Hello, Please forgive my ignorance of perl6 and of proper procedures for this kind of thing. Below I describe an operator (or syntax really) I've been pining for under perl5. I already know the syntax proposal is obsolete in the context of perl6 syntax, but perhaps somebody with more understanding could adapt the concept to fit the current state-of-the-art.
Cheers, Lyren Brown =head1 TITLE Conditional, Short-Circuiting Dereference Operator C<&&-E<gt>>. =head1 VERSION Maintainer: Lyren Brown <[EMAIL PROTECTED]> Date: 1 Mar 2002 Version: 1 Mailing List: perl6-language Number: 1 =head1 ABSTRACT An operator for conditionally dereferencing a scalar based on whether it is a valid reference. The operator is short-circuiting to avoid unwanted or unnecessary auto-vivification or symbolic dereferencing. It returns the scalar if the scalar is not a reference. =head1 DESCRIPTION The C<&&-E<gt>> dereferencing syntax can be used instead of C<-E<gt>> for any type of dereferencing. =head2 Examples my $ref = []; my $foo = $ref->[0]{bar}{baz}; # $foo is undef. Because of auto-vivification, the array that C<$ref> references now has an element 0 which is a one-element anonymous hash which has a key "bar" whose value is a zero-element anonymous hash. my $ref = []; my $foo = $ref&&->[0]&&->{bar}&&->{baz}; # $foo is undef. Because if its short-circuiting nature, the C<&&-E<gt>> operator prevents auto-vivification. So the array that C<$ref> references continues to have zero elements. $ref->[0] = 3; $foo = $ref&&->[0]&&->{bar}&&->{baz}; # $foo is 3. Unlike C<-E<gt>>, C<&&-E<gt>> never attempts to symbolically dereference, so the setting of strict refs is irrelevant. $ref->[0]{bar} = 'hello'; $foo = $ref&&->[0]&&->{bar}&&->{baz}; # $foo is "hello". $ref->[0]{bar}[0] = 'test'; $foo = $ref&&->[0]&&->{bar}&&->{baz}; # Error: Not a HASH reference. The C<&&-E<gt>> operator also works for closure references and method calls. my $ref = sub { shift }; my $foo = $ref&&->('info')&&->('msg'); # $foo is "info". $ref = sub { my $type = shift; sub { "$type: @_" } }; $foo = $ref&&->('info')&&->('msg'); # $foo is "info: msg". $ref = undef; $foo = $ref&&->get('blah'); # $foo is undef; $ref = new Foo; $foo = $ref&&->get('blah'); # $foo is result of get() method. =head2 Short-Hand Braces without an arrow use either C<-E<gt>> or C<&&-E<gt>> semantics depending on which was used latest in the dereferencing expression. my $foo = $ref&&->[0]&&->{bar}&&->{baz}; my $foo = $ref&&->[0]{bar}{baz}; # Equivalent to previous line. my $foo = $ref->[0]&&->{bar}->{baz}; # Use &&-> just for 'bar' lookup. =head2 Perl5 Alternatives There are many ways to get around the absence of an operator like C<&&-E<gt>> in Perl5, but none are as clear, concise and potentially efficient as C<&&-E<gt>>. Take the following example: my $foo = $r&&->('bar')&&->[0]{baz}; If we maintain as an invariant that intermediate nodes either evaluate to false (e.g. C<undef>) or are a reference of the right type, then the following Perl5 idiom can be used: my $foo = $r && $r->('bar') && $r->('bar')->[0] && $r->('bar')->[0]{baz}; Or using temporary variables: my $foo = do { my ($r1, $r2); $r && ($r1 = $r->('bar')) && ($r2 = $r1->[0]) && $r2->{baz} }; We can add the is-a-reference check that C<&&-E<gt>> provides as follows: my $foo = do { my ($r1, $r2); ref $r ? ref ($r1 = $r->('bar')) ? ref ($r2 = $r1->[0]) ? $r2->{baz} : $r2 : $r1 : $r }; We can use closures to abstract some of the code and avoid temporary variables while retaining the short-circuiting semantics. sub da (&$$) { ref $_[1] ? $_[0]->($_[1]->[$_[2]]) : $_[1] } sub dh (&$$) { ref $_[1] ? $_[0]->($_[1]->{$_[2]}) : $_[1] } sub dc (&$@) { ref $_[1] ? $_[0]->($_[1]->(@_[2..$#_])) : $_[1] } sub dm (&$$@) { ref $_[1] ? $_[0]->($_[1]->${\$_[2]}(@_[3..$#_])) : $_[1] } my $foo = dc { da { dh { shift } shift, 'baz' } shift, 0 } $r, 'bar'; =head1 IMPLEMENTATION Unknown. =head1 REFERENCES RFC 177: A Natural Syntax Extension For Chained References (aka Multidimensional Arrays/Hashes) L<Hash::NoVivify> http:[EMAIL PROTECTED]/msg47001.html http://www.perl.com/pub/a/2001/07/25/onion.html "What is now $foo->[$a] will be reduced to $foo[$a] in Perl 6." =cut