I don't know if this I bring up deserves the name "meditation", but I can't figure out a better place to post it than here. It's motivated by a recent thread in clpm.

Perl has handy constructs for creating references to anonymous arrays and hashes, but no such facility for scalars. One could argue that \3 is an anonymous reference to a scalar, since the location that it points to is not associated with any "name" (i.e. variable). But \3 is immutable, which makes it qualitatively different from [3] and +{ 3 => undef }.

I am sure there are excellent reasons behind the decision not to include in Perl an easy way to construct refs to a mutable anonymous scalar. But I have an aesthetic need to be able to invoke to the smallest unit of referencehood, or rather, of anonymous-mutable-referencehood. (Yes, I have strange needs; I'm working on it.)

Among the proposals that came up in the aforementioned thread, the one I liked the most was \"$_". Actually, this is my own minor (I believe) modification of the original proposal, which, in the thread's context was

bless \ "$_", 'Foo' for 3;

Perhaps an even better would be \"$$", whose contents are less potential for variation (as befits anything aspiring to the status of the canonical) than those of $_.

Whence this need to invoke the smallest unit of anonymous-mutable-referencehood? One situation is when defining an object that is not supposed to have any state, but just exist and do all its work through methods. Maybe objects of this class only serve to update the state of the class. I find it distasteful to implement such objects as empty array or hash refs, because the semantics of the implementation are not in harmony with the true nature of the objects. More harmonious, it seems to me, would be to bring such an object to life with a line like

bless "\$$", 'Foo';
which makes it clear (or at least clearer) that the purpose of this reference is purely ceremonial.

I welcome your thoughts.

the lowliest monk

Replies are listed 'Best First'.
Re: On References to the Unnamed
by jdporter (Paladin) on Mar 15, 2005 at 17:29 UTC

    But  bless \"$_", 'Foo' doesn't even work: Modification of a read-only value attempted...

    You could make a "factory" for scalar refs:

    sub new_scalar_ref { my $x; \$x }
    Of course, this technique can be used in-line with do, if you prefer.

    Another idea you could consider is to bless an anonymous sub. That, at least, will throw an exception if a client ever tries to deref it as data.

      Golfed:

      sub new_scalar_ref { \(my $x) }

      This is one of The Few Places Where \() Syntax is UsefulTM. Another favorite is DBI->bind_columns().

        Another is in Getopt::Long (example slightly golfed)

        GetOptions('in|i=s' => \my $indir, 'out|o=s' => \my $outfile, 'log|l=s' => \my $logfile, 'cp|c=s' => \my $cp, 'help|?' => \my $help, man => \my $man) or pod2usage(2);

        ...it is better to be approximately right than precisely wrong. - Warren Buffet

      What??? It works perfectly well on my system (Linux), both with Perl 5.6.1 and Perl 5.8.4. No error messages at all.

      Perl is an endless source of wonderment...

      the lowliest monk

Re: On References to the Unnamed
by Anonymous Monk on Mar 15, 2005 at 17:42 UTC
    I find it quite surprising that \"$a" creates a reference to an lvalue, since "$a" isn't an lvalue. This might be a bug, or an artifact of the implementation of perl. Unless I'd find a place where this is documented, I wouldn't count on it working on a next version of perl.

    If I want a scalar to an anonymous scalar, I use:

    \do {my $foo}; # Or do {\my $foo};
    which is an well-known technique, and before we had auto-vivifying filehandles, similar to how we created references to filehandles (\do {local *FOO}).

    As for sizes, \"$$" takes 2.5 times the memory \do {my $foo} takes. And even \"" takes more than twice the memory. This is because \do {my $foo} is just an SV, pointing to nothing. (The flag ROK says it's a reference). But \"" still has to point to something.

    #!/usr/bin/perl use strict; use warnings; use Devel::Size 'total_size'; use Devel::Peek; my $a = \"$$"; my $b = \""; my $c = \do {my $foo}; print total_size($a), "\n"; print total_size($b), "\n"; print total_size($c), "\n"; print "-----\n"; print Dump($a); print Dump($c); __END__ 30 25 12 ----- SV = RV(0x81c1df4) at 0x8191e58 REFCNT = 1 FLAGS = (PADBUSY,PADMY,ROK) RV = 0x8184180 SV = PV(0x8184494) at 0x8184180 REFCNT = 1 FLAGS = (POK,pPOK) PV = 0x8189cf8 "23192"\0 CUR = 5 LEN = 6 SV = RV(0x81c1dfc) at 0x8191eac REFCNT = 1 FLAGS = (PADBUSY,PADMY,ROK) RV = 0x8191f84 SV = NULL(0x0) at 0x8191f84 REFCNT = 2 FLAGS = (PADBUSY,PADMY)
Re: On References to the Unnamed
by Juerd (Abbot) on Mar 15, 2005 at 21:01 UTC

    Wouldn't it be much easier to just introduce a perlvar that each time it's used, is a new scalar? I suggest $^N, New scalar.

    bless \$^N, $class; bless \($^N = "some value"), $class;
    I don't really see why this is needed, though. I can live with
    bless \my $dummy, $class;
    or, if for some strange reason I don't want to pollute the lexical scope with a $dummy,
    bless \do { my $dummy }, $class;

    Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

      No need for $dummy:
      sub new { my $class = shift; bless \$class, $class; }

      $^N is already taken.

      ihb

      See perltoc if you don't know which perldoc to read!

Re: On References to the Unnamed
by hardburn (Abbot) on Mar 15, 2005 at 20:08 UTC

    Quoting is not an identity function in Perl. Don't treat it like one or you'll eventually get bitten.

    Make a proper identity function instead (simplified to only return the first arg instead of all of them):

    sub ident { shift } bless \(ident($_)) => 'Foo' for 3;

    A little more typing? Yes. Avoids subtle bugs? Yes :)

    "There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.

      Quoting is not an identity function in Perl.
      That's the point of \"$_", isn't?

        Right. People expect "$_" to return the same data (i.e., an identity function). But that's not strictly true in Perl, due to the way Perl does implicit conversions.

        "There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.

Re: On References to the Unnamed
by Roy Johnson (Monsignor) on Mar 16, 2005 at 15:40 UTC
    This generates a list of anonymous scalars:
    \@{[]}[0..49]
    Taking a reference to a slice yields a reference to each member (it's \ operating on a list). Generating one ref requires the same number of chars as Larry's, and is substantially slower. But if you ever need to generate a substantial list of scalar refs (it catches up at around 20, compared to using map with Larry's), this would be the way to go.

    And with all due respect to Larry, here's a golfier way to get a single scalar ref:

    \[]->[0]
    Now, for the case you mention, in which you merely need a stateless object...well, you don't need an object. You just do everything through class methods. But taking a reference to a constant would work. You don't need an anonymous scalar, because you're not going to modify the contents.

    You'd want a scalar when you have an object with only one property. In that case, you'd just declare a lexical scalar in your constructor, and bless a reference to it. So you still don't need anonymous scalars.


    Caution: Contents may have been coded under pressure.
    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: On References to the Unnamed
by mstone (Deacon) on Mar 16, 2005 at 19:48 UTC

    You could always use a simplified version of the trick from Glob.pm:

    sub anon_ref { $N ||= 1; my $name = sprintf "var%04d", $N; my $ref = \${ 'NAMESPACE::' . $name }; delete $NAMESPACE{ $name }; $N++; return ($ref); }

    It does use a name to create the variable, but then deletes that name from the symbol table, which arguably results in an anonymous scalar.

    In an object constructor, it would looks like so:

    sub My_object::new { my ($type, @data) = @_; $N ||= 1; my $name = sprintf "var%04d", $N; my $object = \${ 'NAMESPACE::' . $name }; delete $NAMESPACE{ $name }; $N++; bless $object, $type; $object->configure_with (@data); return ($object); }

    or you can factor the ref code out into a separate function and just use:

    sub My_object::new { my $O = bless anon_ref(), shift; $O->configure_with (@_); return ($O); }

    By tweaking the specific kind of ref you create in anon_ref(), you can make it return scalars, lists, hashes, or entire globs. Most of the File:: classes use anonymous globs to store their filehandles, in fact..

Re: On References to the Unnamed
by eyepopslikeamosquito (Archbishop) on May 28, 2005 at 13:49 UTC

    I noticed today that TheDamian posted another way to do it namely:

    $anon_scalar_ref = \eval{undef}; # or ... $anon_scalar_ref = \eval{ $init_val }; # if you prefer anon scalar in +itialized

    Running:

    #!/usr/bin/perl use strict; use warnings; use Devel::Size 'total_size'; use Devel::Peek; my $a = \"$$"; my $b = \""; my $c = \do {my $foo}; my $d = \eval{undef}; print total_size($a), "\n"; print total_size($b), "\n"; print total_size($c), "\n"; print total_size($d), "\n"; print "-----\n"; print Dump($a); print Dump($c); print Dump($d);
    produced:
    29 25 12 12 ----- SV = RV(0x1865b28) at 0x18242d8 REFCNT = 1 FLAGS = (PADBUSY,PADMY,ROK) RV = 0x224f08 SV = PV(0x2251fc) at 0x224f08 REFCNT = 1 FLAGS = (POK,pPOK) PV = 0x1834234 "3484"\0 CUR = 4 LEN = 5 SV = RV(0x1865b30) at 0x18242e4 REFCNT = 1 FLAGS = (PADBUSY,PADMY,ROK) RV = 0x186168c SV = NULL(0x0) at 0x186168c REFCNT = 2 FLAGS = (PADBUSY,PADMY) SV = RV(0x1865b34) at 0x18247a4 REFCNT = 1 FLAGS = (PADBUSY,PADMY,ROK) RV = 0x224fbc SV = NULL(0x0) at 0x224fbc REFCNT = 1 FLAGS = ()