Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bless $x, undef to unbless #14684

Closed
p5pRT opened this issue Apr 30, 2015 · 28 comments
Closed

bless $x, undef to unbless #14684

p5pRT opened this issue Apr 30, 2015 · 28 comments

Comments

@p5pRT
Copy link

p5pRT commented Apr 30, 2015

Migrated from rt.perl.org#124428 (status was 'rejected')

Searchable as RT124428$

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2015

From @epa

Created by @epa

Sometimes you need to unbless a scalar. Various CPAN modules exist to
do this and various whimsical names such as 'curse' and 'smite', but
it deserves to be in the core language. No new keyword is needed;
instead you should be able to just

  bless $x, undef;

to unbless scalar $x.

Note that this is not the same thing as

  bless $x;

which should continue to bless into the current package.

Perl Info

Flags:
    category=core
    severity=wishlist

Site configuration information for perl 5.18.4:

Configured by Red Hat, Inc. at Thu Apr  2 16:17:20 UTC 2015.

Summary of my perl5 (revision 5 version 18 subversion 4) configuration:
   
  Platform:
    osname=linux, osvers=3.19.1-201.fc21.x86_64, archname=x86_64-linux-thread-multi
    uname='linux buildvm-23.phx2.fedoraproject.org 3.19.1-201.fc21.x86_64 #1 smp wed mar 18 04:29:24 utc 2015 x86_64 x86_64 x86_64 gnulinux '
    config_args='-des -Doptimize=-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches  -m64 -mtune=generic -Dccdlflags=-Wl,--enable-new-dtags -Dlddlflags=-shared -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches  -m64 -mtune=generic -Wl,-z,relro  -Dshrpdir=/usr/lib64 -DDEBUGGING=-g -Dversion=5.18.4 -Dmyhostname=localhost -Dperladmin=root@localhost -Dcc=gcc -Dcf_by=Red Hat, Inc. -Dprefix=/usr -Dvendorprefix=/usr -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl5 -Dsitearch=/usr/local/lib64/perl5 -Dprivlib=/usr/share/perl5 -Dvendorlib=/usr/share/perl5/vendor_perl -Darchlib=/usr/lib64/perl5 -Dvendorarch=/usr/lib64/perl5/vendor_perl -Darchname=x86_64-linux-thread-multi -Dlibpth=/usr/local/lib64 /lib64 /usr/lib64 -Duseshrplib -Dusethreads -Duseithreads -Dusedtrace=/usr/bin/dtrace -Duselargefiles -Dd_semctl_semun -Di_db -Ui_ndbm -Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Duseperlio -Dinstallusrbinperl=n -Ubincompat5005 -Uversiononly -Dpager=/usr/bin/less -isr -Dd_gethostent_r_proto -Ud_endhostent_r_proto -Ud_sethostent_r_proto -Ud_endprotoent_r_proto -Ud_setprotoent_r_proto -Ud_endservent_r_proto -Ud_setservent_r_proto -Dscriptdir=/usr/bin -Dusesitecustomize'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=define, usemultiplicity=define
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=define, use64bitall=define, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='gcc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
    ccversion='', gccversion='4.8.3 20140911 (Red Hat 4.8.3-7)', gccosandvers=''
    intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='gcc', ldflags =' -fstack-protector'
    libpth=/usr/local/lib64 /lib64 /usr/lib64
    libs=-lresolv -lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lpthread -lc -lgdbm_compat
    perllibs=-lresolv -lnsl -ldl -lm -lcrypt -lutil -lpthread -lc
    libc=, so=so, useshrplib=true, libperl=libperl.so
    gnulibc_version='2.18'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,--enable-new-dtags'
    cccdlflags='-fPIC', lddlflags='-shared -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -Wl,-z,relro '

Locally applied patches:
    Fedora Patch1: Removes date check, Fedora/RHEL specific
    Fedora Patch3: support for libdir64
    Fedora Patch4: use libresolv instead of libbind
    Fedora Patch5: USE_MM_LD_RUN_PATH
    Fedora Patch6: Skip hostname tests, due to builders not being network capable
    Fedora Patch7: Dont run one io test due to random builder failures
    Fedora Patch9: Fix find2perl to translate ? glob properly (RT#113054)
    Fedora Patch10: Update h2ph(1) documentation (RT#117647)
    Fedora Patch11: Update pod2html(1) documentation (RT#117623)
    Fedora Patch12: Disable ornaments on perl5db AutoTrace tests (RT#118817)
    Fedora Patch14: Do not use system Term::ReadLine::Gnu in tests (RT#118821)
    Fedora Patch15: Define SONAME for libperl.so
    Fedora Patch16: Install libperl.so to -Dshrpdir value
    Fedora Patch18: Fix crash with \\&$glob_copy (RT#119051)
    Fedora Patch19: Fix coreamp.t rand test (RT#118237)
    Fedora Patch20: Reap child in case where exception has been thrown (RT#114722)
    Fedora Patch21: Fix using regular expressions containing multiple code blocks (RT#117917)
    Fedora Patch22: Create site paths by cpan for the first time (CPAN RT#99905)
    Fedora Patch200: Link XS modules to libperl.so with EU::CBuilder on Linux
    Fedora Patch201: Link XS modules to libperl.so with EU::MM on Linux


@INC for perl 5.18.4:
    /home/eda/lib/perl5/
    /home/eda/lib64/perl5/
    /usr/local/lib64/perl5
    /usr/local/share/perl5
    /usr/lib64/perl5/vendor_perl
    /usr/share/perl5/vendor_perl
    /usr/lib64/perl5
    /usr/share/perl5
    .


Environment for perl 5.18.4:
    HOME=/home/eda
    LANG=en_GB.UTF-8
    LANGUAGE (unset)
    LC_COLLATE=C
    LC_CTYPE=en_GB.UTF-8
    LC_MESSAGES=en_GB.UTF-8
    LC_MONETARY=en_GB.UTF-8
    LC_NUMERIC=en_GB.UTF-8
    LC_TIME=en_GB.UTF-8
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/eda/bin:/home/eda/bin:/usr/local/bin:/usr/bin:/sbin:/usr/sbin:/sbin:/usr/sbin
    PERL5LIB=/home/eda/lib/perl5/:/home/eda/lib64/perl5/
    PERL_BADLANG (unset)
    SHELL=/bin/bash

-- 
Ed Avis <eda@waniasset.com>


This email is intended only for the person to whom it is addressed and may contain confidential information. Any retransmission, copying, disclosure or other use of, this information by persons other than the intended recipient is prohibited. If you received this email in error, please contact the sender and delete the material. This email is for information only and is not intended as an offer or solicitation for the purchase or sale of any financial instrument. Wadhwani Asset Management LLP is a Limited Liability Partnership registered in England (OC303168) with registered office at 40 Berkeley Square, 3rd Floor, London, W1J 5AL. It is authorised and regulated by the Financial Conduct Authority.

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2015

From @kentfredric

On 1 May 2015 at 01​:35, Ed Avis <perlbug-followup@​perl.org> wrote​:

bless $x\, undef;

to unbless scalar $x.

Incidentally, Acme​::Damn makes that syntax available​:

https://metacpan.org/pod/Acme::Damn#bless-reference-undef

Unfortunately, its not presently an "error" if somebody does this without
it, and so​:

  bless $x, undef
  bless $x, ''

Are both equivalent to

  bless $x, "main"

perl -MData​::Dump=pp -wE 'package Boss; my $x = bless {}, undef;
Data​::Dump​::pp $x'
Use of uninitialized value in bless at -e line 1.
Explicit blessing to '' (assuming package main) at -e line 1.
bless({}, "main")

Other than that, the proposal seems simple enough that I'm in favour of it.

I just can't tell the scope of if any code is foolishly relying on this
existing behaviour, because grepping for it without a full parse is hard. (
And also, writing a critic policy to match this expression might be fun )​:
http​://grep.cpan.me/?q=bless\W.{0%2C500}%3F%2C\s*undef

Obviously you can do damage prevention by making it a feature.

--
Kent

*KENTNL* - https://metacpan.org/author/KENTNL

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2015

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2015

From @epa

  bless $x, undef

will currently generate two warnings, if warnings are enabled​:

  Use of uninitialized value in bless
  Explicit blessing to '' (assuming package main)

For that reason I felt that changing the semantics would be reasonable. Oneliners may be written without warnings, but they rarely bless objects.

For backwards compatibility I guess that

  bless $x, ''

could continue to do what it does currently; only an explicit undef would cause the unblessing.

--
Ed Avis <eda@​waniasset.com>

This email is intended only for the person to whom it is addressed and may contain confidential information. Any retransmission, copying, disclosure or other use of, this information by persons other than the intended recipient is prohibited. If you received this email in error, please contact the sender and delete the material. This email is for information only and is not intended as an offer or solicitation for the purchase or sale of any financial instrument. Wadhwani Asset Management LLP is a Limited Liability Partnership registered in England (OC303168) with registered office at 40 Berkeley Square, 3rd Floor, London, W1J 5AL. It is authorised and regulated by the Financial Conduct Authority.

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2015

From @avar

On Thu, Apr 30, 2015 at 3​:51 PM, Ed Avis <eda@​waniasset.com> wrote​:

bless $x\, undef

will currently generate two warnings, if warnings are enabled​:

Use of uninitialized value in bless
Explicit blessing to '' \(assuming package main\)

For that reason I felt that changing the semantics would be reasonable. Oneliners may be written without warnings, but they rarely bless objects.

For backwards compatibility I guess that

bless $x\, ''

could continue to do what it does currently; only an explicit undef would cause the unblessing.

The main problem with this proposal is that now this code that warned
before would silently unbless​:

  bless $what{object}, $what{__PACKAGE__};

We could I guess generate a warning for trying to unbless an already
unblessed thing, but are we going to add one too for​:

  bless {} => "main" for 1..2

?

I think this makes more sense as a new function Scalar​::Util or something.

Or maybe we could just ship Acme​::Damn ?​:)

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2015

From @epa

Ævar Arnfjörð Bjarmason <avarab <at> gmail.com> writes​:

The main problem with this proposal is that now this code that warned
before would silently unbless​:

bless $what{object}, $what{__PACKAGE__};

The cautious approach would be to make a hard deprecation cycle.
(1) blessing to undef becomes a runtime error (rather than just a warning
as now). (2) a couple of releases later, blessing to undef gets the semantics
of unblessing.

I do think that C<bless $x, undef> is the logical way to express it and it
shouldn't linger forever in Obscure​::Scalar​::Utils or Acme​::Whatever.

--
Ed Avis <eda@​waniasset.com>

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2015

From @leonerd

On Thu, 30 Apr 2015 16​:26​:43 +0200
Ævar Arnfjörð Bjarmason <avarab@​gmail.com> wrote​:

I think this makes more sense as a new function Scalar​::Util or
something.

As Scalar​::Util's current maintainer, if anyone wants to throw me the
obvious ~3 line XS patch + PP docs to make

  use Scalar​::Util 'unbless';

I'll happily merge it.

--
Paul "LeoNerd" Evans

leonerd@​leonerd.org.uk
http​://www.leonerd.org.uk/ | https://metacpan.org/author/PEVANS

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2015

From @epa

unbless is already part of Data​::Structure​::Util (and other modules).
Although the implementation there is a bit funky in that it recursively
unblesses everything in the data structure - not what I would have done :-(
That does mean that the name 'unbless' is already taken in some sense.

--
Ed Avis <eda@​waniasset.com>

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2015

From @avar

On Thu, Apr 30, 2015 at 4​:30 PM, Ed Avis <eda@​waniasset.com> wrote​:

Ævar Arnfjörð Bjarmason <avarab <at> gmail.com> writes​:

The main problem with this proposal is that now this code that warned
before would silently unbless​:

bless $what{object}, $what{__PACKAGE__};

The cautious approach would be to make a hard deprecation cycle.
(1) blessing to undef becomes a runtime error (rather than just a warning
as now). (2) a couple of releases later, blessing to undef gets the semantics
of unblessing.

I do think that C<bless $x, undef> is the logical way to express it and it
shouldn't linger forever in Obscure​::Scalar​::Utils or Acme​::Whatever.

Aside from backwards compatibility concerns I don't like this API design.

We have tie() and untie(), not untying as some special parameter to
tie(), similarly for link() and unlink() or mkdir() and rmdir() for
that matter.

I know there's good reasons for why some of those couldn't get extra
parameters or special parameters like bless() could, but I find
unbless() to be more logical. We already have the logical equivalent
of do() an undo() functions, not undo() as some special parameter to
do().

Also what should a function like this do? Objects are opaque and while
we can just remove the blessedness I think if the core introduced
something like this it would make more sense to make​:

  unbless($obj); # or bless($obj, undef); ....

Be​:

  $obj = $obj->UNBLESS; # Or is that already ->FREEZE

Which perhaps would fall back on a core method that would just remove
the blessed flag if no "UNBLESS" sub was available. That way we could
generalize "as_hash" and other "remove private garbage and return
something sensible to reconstruct the object" which exists in almost
any non-trivial Perl program.

You could argue that it should do exactly nothing except remove the
blessed flag, but the absence of this feature in Perl now means people
don't expect their objects to go back to non-objects unless they
explicitly have some "object export" feature. A core API change like
this would have an effect on future code.

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2015

From @kentfredric

On 1 May 2015 at 02​:30, Ed Avis <eda@​waniasset.com> wrote​:

I do think that C<bless $x, undef> is the logical way to express it and it
shouldn't linger forever in Obscure​::Scalar​::Utils or Acme​::Whatever.

Another thought against​: making undef remove bless instead of casting it
could be seen as special-casing.

A type of special casing that might put more burden on people using

  bless $x, $somename

Due to the need to propagate the special case when $somename is not defined
by them.

Imagine​:

  sub foo {
  my $class = shift;
  my $structure = bless {@​_} , $class;
  die "unsupported" unless $x->can("foo") or $x->isa("Bar");
  }

Given that currently, that would mean

  foo(undef, @​args );

Would presently create a valid object, allbeit one they've got handling
code for it being invalid.

The new behaviour would create a non-object, which might croak/bail in
confusing ways which requires additional handling.

That would be a step backwards.

--
Kent

*KENTNL* - https://metacpan.org/author/KENTNL

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2015

From @leonerd

On Thu, 30 Apr 2015 14​:46​:49 +0000 (UTC)
Ed Avis <eda@​waniasset.com> wrote​:

unbless is already part of Data​::Structure​::Util (and other modules).
Although the implementation there is a bit funky in that it
recursively unblesses everything in the data structure - not what I
would have done :-( That does mean that the name 'unbless' is already
taken in some sense.

That's OK - perl's naming structure means that two different packages
can provide the same named function with different implementations.

unbless is the sensible name for this function.

Also it would be "surprising" to users if a "core"-style
Scalar​::Util​::unbless were to recurse, so better to do the simple
3liner.

--
Paul "LeoNerd" Evans

leonerd@​leonerd.org.uk
http​://www.leonerd.org.uk/ | https://metacpan.org/author/PEVANS

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2015

From @kentfredric

On 1 May 2015 at 02​:48, Ævar Arnfjörð Bjarmason <avarab@​gmail.com> wrote​:

Be​:

$obj = $obj\->UNBLESS; \# Or is that already \->FREEZE

A disadvantage of that approach is that it would be unsafe to use on
non-blessed values, leading to people needing to do one of the following​:

  my $ref = blessed $original ? $original->UNBLESS : $original # ew

  my $ref = UNIVERSAL​::UNBLESS( $original ) ; # ew

  use Safe​::Unbless;

  my $ref = $original->$_unbless;

That would still be the case if we defined unbless not to work on already
unblessed objects.

But seeing bless works on already blessed objects, it would break the
parity.

--
Kent

*KENTNL* - https://metacpan.org/author/KENTNL

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2015

From @epa

Ævar Arnfjörð Bjarmason <avarab <at> gmail.com> writes​:

make​:

 unbless\($obj\); \# or bless\($obj\, undef\); \.\.\.\.

Be​:

$obj = $obj\->UNBLESS; \# Or is that already \->FREEZE

If you introduce that, then the UNBLESS method would also have to be called
when an existing blessed object is re-blessed into a different class.

Personally I would just like to set or unset the blessed field on the
scalar, without any hidden methods being called.

You could argue that it should do exactly nothing except remove the
blessed flag, but the absence of this feature in Perl now means people
don't expect their objects to go back to non-objects unless they
explicitly have some "object export" feature. A core API change like
this would have an effect on future code.

I don't quite understand what you are getting at here. After all, an object
can already be re-blessed into a different class such that none of the
original methods (not even DESTROY) will be called. How is unblessing
any worse than reblessing into RandomUnrelatedPackage?

  package Foo;
  sub DESTROY { say 'destroy' }
  sub new { bless {} }
  package Bar;
  package main;
  my $f = new Foo;
  bless $f, 'Bar';

--
Ed Avis <eda@​waniasset.com>

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2015

From @rjbs

* Ævar Arnfjörð Bjarmason <avarab@​gmail.com> [2015-04-30T10​:48​:39]

Aside from backwards compatibility concerns I don't like this API design.

I agree with all of Ævar's objections.

$obj = $obj\->UNBLESS; \# Or is that already \->FREEZE

Which perhaps would fall back on a core method that would just remove
the blessed flag if no "UNBLESS" sub was available. That way we could
generalize "as_hash" and other "remove private garbage and return
something sensible to reconstruct the object" which exists in almost
any non-trivial Perl program.

I was really not sure about this, but the more I thought about it, the more
that something like this seems important to provide. It's also plausible that
the right solution is that UNIVERSAL​::UNBLESS just calls Scalar​::Util​::unbless,
and now you have a toolkit.

I haven't given it a lot of thought (yet?).

--
rjbs

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2015

From @epa

An alternative proposal would be first to move Scalar​::Util​::blessed
into the core language, and then make it an lvalue.

  blessed($x) = 'Foo'; # blesses $x into package Foo
  blessed($x) = undef; # unblesses $x

But both this and C<bless $x, undef> work on a single scalar.

One advantage of adding 'unbless' is that it can work on a list​:

  unbless @​a; # unblesses each element

As it happens that is the use case I am thinking of - and it is in a hot
path of my program, so if I could call a single builtin to deal with the
whole list that would be better than writing a loop.

So on reflection I think adding 'unbless' may be the best way.

--
Ed Avis <eda@​waniasset.com>

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2015

From @epa

I wouldn't necessarily want to call a method every time I unbless an object.
Sure, that can be the default, but just as bless is purely a builtin
operation, there should be some kind of raw_unbless which is equally
simple and fast, and does nothing except unset the field on the scalar.

I don't buy the argument that adding raw_unbless will somehow violate the
language's contract with object-oriented libraries that don't expect their
objects to suddenly get downgraded to ordinary references, because (a)
there are already unbless implementations on CPAN, and (b) you can already
rebless any existing object into some random other class.

--
Ed Avis <eda@​waniasset.com>

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2015

From @leonerd

On Thu, 30 Apr 2015 15​:01​:54 +0000 (UTC)
Ed Avis <eda@​waniasset.com> wrote​:

An alternative proposal would be first to move Scalar​::Util​::blessed
into the core language, and then make it an lvalue.

blessed\($x\) = 'Foo';    \# blesses $x into package Foo
blessed\($x\) = undef;    \# unblesses $x

It doesn't need to be moved to be lvalue'able. It can have lvalue
semantics just fine where it lives now.

(I would prefer that it didn't though because Real Soon Now I'm going
to make a super-optimised custom-op version of blessed that would then
remove the ENTERSUB/XS call overhead; see

  https://github.com/Scalar-List-Utils/Scalar-List-Utils/tree/pevans-custom-ops
)

--
Paul "LeoNerd" Evans

leonerd@​leonerd.org.uk
http​://www.leonerd.org.uk/ | https://metacpan.org/author/PEVANS

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2015

From @kentfredric

On 1 May 2015 at 03​:07, Ed Avis <eda@​waniasset.com> wrote​:

I wouldn't necessarily want to call a method every time I unbless an
object.
Sure, that can be the default, but just as bless is purely a builtin
operation, there should be some kind of raw_unbless which is equally
simple and fast, and does nothing except unset the field on the scalar.

I don't buy the argument that adding raw_unbless will somehow violate the
language's contract with object-oriented libraries that don't expect their
objects to suddenly get downgraded to ordinary references, because (a)
there are already unbless implementations on CPAN, and (b) you can already
rebless any existing object into some random other class.

I posit the frequency of using unbless is already low, and the desire for
unbless to imply DESTROY is even lower.

Conflating those 2 behaviours together just means if you want one without
the other, you don't have the choice, and we're back at square one.

The last thing you want is do go "ok, I'm going to just unbless things so
they can be serialized" going "uh. ,.... and now the data is gone, great".

Similarly, using unbless on a list of objects seems infrequent enough that
it would require evidence of a real usecase to justify that being there by
design. ( Because it breaks parity, and limits future options ).

For instance, if unbless always took a list, then you're limiting your
options later if you decide unbless can take parameters. ( Also not
something I'd want, due to parity breaking , but just for example ).

  my $hash = unbless $ref, { destroy => 1 };

^ would not be an option if​:

- unbless supported a list
- unbless allowed passthrough of non-blesed objects ( similar to how bless
doesnt' barf on blessed objects ).

--
Kent

*KENTNL* - https://metacpan.org/author/KENTNL

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2015

From @demerphq

On 30 April 2015 at 17​:03, Ricardo Signes <perl.p5p@​rjbs.manxome.org> wrote​:

* Ævar Arnfjörð Bjarmason <avarab@​gmail.com> [2015-04-30T10​:48​:39]

Aside from backwards compatibility concerns I don't like this API design.

I agree with all of Ævar's objections.

$obj = $obj\->UNBLESS; \# Or is that already \->FREEZE

Which perhaps would fall back on a core method that would just remove
the blessed flag if no "UNBLESS" sub was available. That way we could
generalize "as_hash" and other "remove private garbage and return
something sensible to reconstruct the object" which exists in almost
any non-trivial Perl program.

I was really not sure about this, but the more I thought about it, the more
that something like this seems important to provide. It's also plausible that
the right solution is that UNIVERSAL​::UNBLESS just calls Scalar​::Util​::unbless,
and now you have a toolkit.

I haven't given it a lot of thought (yet?).

I am opposed to $obj->UNBLESS; Methods are overridable, and I would
consider a method call to "touch" the object, which could have any
sort of consequence. If we think we want this we should just add
unbless to the language like we have untie. IMO unbless should be
usable on something like Object​::Deadly without triggering any method
calls. Also, I thing its weird to have a method call change the type
of its invocant like this, not entirely unheard of, but weird.

Also unblessing is a strange thing given that the *referent* not the
reference is blessed, consider the action at a distance involved. One
part of the code might accept an object, validate that it has indeed
received an object, but then at some far distant point in the code the
object could be unblessed, leaving a non-object in memory, resulting
in strange consequences. Of course this also applies to *reblessing*
too, but still, we already have that problem, we dont "officially"
have the problem of unbless.

Yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2015

From @demerphq

On 30 April 2015 at 20​:21, demerphq <demerphq@​gmail.com> wrote​:

On 30 April 2015 at 17​:03, Ricardo Signes <perl.p5p@​rjbs.manxome.org> wrote​:

* Ævar Arnfjörð Bjarmason <avarab@​gmail.com> [2015-04-30T10​:48​:39]

Aside from backwards compatibility concerns I don't like this API design.

I agree with all of Ævar's objections.

$obj = $obj\->UNBLESS; \# Or is that already \->FREEZE

Which perhaps would fall back on a core method that would just remove
the blessed flag if no "UNBLESS" sub was available. That way we could
generalize "as_hash" and other "remove private garbage and return
something sensible to reconstruct the object" which exists in almost
any non-trivial Perl program.

I was really not sure about this, but the more I thought about it, the more
that something like this seems important to provide. It's also plausible that
the right solution is that UNIVERSAL​::UNBLESS just calls Scalar​::Util​::unbless,
and now you have a toolkit.

I haven't given it a lot of thought (yet?).

I am opposed to $obj->UNBLESS; Methods are overridable, and I would
consider a method call to "touch" the object, which could have any
sort of consequence. If we think we want this we should just add
unbless to the language like we have untie. IMO unbless should be
usable on something like Object​::Deadly without triggering any method
calls. Also, I thing its weird to have a method call change the type
of its invocant like this, not entirely unheard of, but weird.

Also unblessing is a strange thing given that the *referent* not the
reference is blessed, consider the action at a distance involved. One
part of the code might accept an object, validate that it has indeed
received an object, but then at some far distant point in the code the
object could be unblessed, leaving a non-object in memory, resulting
in strange consequences. Of course this also applies to *reblessing*
too, but still, we already have that problem, we dont "officially"
have the problem of unbless.

I should have added, that DDS, which is Object​::Deadly proof, achieves
the same result by blessing an object into a namespace known to have
only "safe" methods. I did not need unbless to deal with
Object​::Deadly.

Yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2015

From @ap

* Ed Avis <perlbug-followup@​perl.org> [2015-04-30 15​:40]​:

Sometimes you need to unbless a scalar. Various CPAN modules exist to
do this and various whimsical names such as 'curse' and 'smite', but
it deserves to be in the core language.

I’ve wished at various times that it existed, yes.

No new keyword is needed; instead you should be able to just

bless $x\, undef;

to unbless scalar $x.

Note that this is not the same thing as

bless $x;

which should continue to bless into the current package.

Opposed.

There is absolutely no advantage to shoe-horning this into `bless`.

* Ævar Arnfjörð Bjarmason <avarab@​gmail.com> [2015-04-30 16​:30]​:

This makes more sense as a new function Scalar​::Util or something.

Aye.

* Ævar Arnfjörð Bjarmason <avarab@​gmail.com> [2015-04-30 16​:50]​:

We have tie() and untie(), not untying as some special parameter to
tie(), similarly for link() and unlink() or mkdir() and rmdir() for
that matter.

Good point.

Also what should a function like this do? Objects are opaque and while
we can just remove the blessedness I think if the core introduced
something like this it would make more sense to make​:

 unbless\($obj\); \# or bless\($obj\, undef\); \.\.\.\.

Be​:

$obj = $obj\->UNBLESS; \# Or is that already \->FREEZE

Which perhaps would fall back on a core method that would just remove
the blessed flag if no "UNBLESS" sub was available. That way we could
generalize "as_hash" and other "remove private garbage and return
something sensible to reconstruct the object" which exists in almost
any non-trivial Perl program.

You could argue that it should do exactly nothing except remove the
blessed flag, but the absence of this feature in Perl now means people
don't expect their objects to go back to non-objects unless they
explicitly have some "object export" feature. A core API change like
this would have an effect on future code.

These issues are orthogonal.

You are talking about the case in which encapsulation matters, i.e.
I have some random object that I want to peel the blessedness off of.

But there is just as legitimately the case where I have an object from
a class I control, and I want an efficient way to get at its guts.

Both are valid use cases with different requirements, so arguing against
one based on the other is an instance of confusion, and choosing one of
them as preferable would be a mistake.

* Ed Avis <eda@​waniasset.com> [2015-04-30 17​:10]​:

An alternative proposal would be first to move Scalar​::Util​::blessed
into the core language, and then make it an lvalue.

blessed\($x\) = 'Foo';    \# blesses $x into package Foo
blessed\($x\) = undef;    \# unblesses $x

But both this and C<bless $x, undef> work on a single scalar.

Again with the shoe-horning. Why would you want to?

One advantage of adding 'unbless' is that it can work on a list​:

unbless @&#8203;a;    \# unblesses each element

As it happens that is the use case I am thinking of - and it is in
a hot path of my program, so if I could call a single builtin to deal
with the whole list that would be better than writing a loop.

So on reflection I think adding 'unbless' may be the best way.

That is way low on the list of reasons to prefer a separate function,
but sure, I can go with that.

* Ed Avis <eda@​waniasset.com> [2015-04-30 16​:50]​:

unbless is already part of Data​::Structure​::Util (and other modules).
Although the implementation there is a bit funky in that it
recursively unblesses everything in the data structure - not what
I would have done :-( That does mean that the name 'unbless' is
already taken in some sense.

So having some random function called “unbless” in some random non-core
never-heard-of-it-before CPAN module means the name and semantics are
taken and set in stone…

… whereas having had `bless $thing, undef` as part of the language and
already having had a particular meaning forever and ever means it’s up
for grabs?

I don’t understand this conception of “taken”.

(And similarly with `blessed`, though much less strongly.)

Mauve regards,
--
Aristotle Pagaltzis // <http​://plasmasturm.org/>

@p5pRT
Copy link
Author

p5pRT commented May 1, 2015

From @epa

C<bless $x, undef> produces two warnings if used. It is not documented in
perlfunc (the single-arg case is, but not an explicit undef). To me, that
suggests that the current behaviour is an implementation accident rather than
a settled part of the language.

The consensus seems to have converged on adding 'unbless' for other reasons,
which is fine by me.

If you think that C<bless $x, undef> is truly part of the language and
should stay with its current semantics, I suggest documenting it in perlfunc
and removing the two warnings which it currently produces.

--
Ed Avis <eda@​waniasset.com>

@p5pRT
Copy link
Author

p5pRT commented Dec 6, 2017

From zefram@fysh.org

bless($x, undef) already has a defined meaning, and should not be changed.
Its behaviour, including the warnings, arises naturally from the usual
treatment of undef when a string is desired and from the behaviour of
bless on an empty string. There is no need for specific documentation
of this behaviour.

The appropriate way to invoke unblessing is as a subroutine supplied by
a module. As noted, this is already available. There is no need for
the core to supply an unblessing facility.

This ticket should be closed.

-zefram

@p5pRT
Copy link
Author

p5pRT commented Dec 6, 2017

@cpansprout - Status changed from 'open' to 'rejected'

@p5pRT p5pRT closed this as completed Dec 6, 2017
@p5pRT
Copy link
Author

p5pRT commented Dec 6, 2017

From @epa

bless($x, undef) already has a defined meaning,

Could this be made a bit more explicit in perlfunc, not just for undef, but for blessing into the empty string too? I would use some wording like

  If CLASSNAME is omitted, the current package is used. An empty string (or undef)
  for CLASSNAME is the same as 'main'.

This is worth documenting since it's the one case where the string you get back
from ref($x) is not the same as the string $s you passed to bless($x, $s).

I would also add a note

  To unbless a scalar, see the Data​::Structure​::Util module on CPAN.

either in the perlfunc section above, or somewhere in perlfaq.

@p5pRT
Copy link
Author

p5pRT commented Dec 6, 2017

From @epa

P.S. perhaps the note 'make sure that CLASSNAME is a true value' should also be revisited, given that bless($x, undef) has a defined meaning and undef is not a true value.

@p5pRT
Copy link
Author

p5pRT commented Dec 6, 2017

From zefram@fysh.org

Doc clarifications in commit b3893bf.

-zefram

@p5pRT
Copy link
Author

p5pRT commented Dec 6, 2017

From @epa

Thanks for making the documentation changes.

@p5pRT p5pRT added the Wishlist label Oct 19, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant