Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

RFC: Perl5 Language Extension: Definedness-Triggered Shortcut Operators

by martin (Friar)
on Mar 17, 2012 at 09:20 UTC ( [id://960147]=perlmeditation: print w/replies, xml ) Need Help??

The defined-or operator, available since perl5.10, is an example of shortcut behaviour triggered on definedness: If the left hand side is defined, leave it at that, otherwise evaluate the right hand side.

Shortcut behaviour in general can help to make code more expressive, in that it combines control flow and expression evaluation in a very intuitive way. Without it, more ifs and elses and variables to store intermediate results would clutter code that has to deal with conditional evaluations.

Defined-or, therefore, demonstrates a useful concept. It could be taken much further, though, with a little bit of generalization. In light of that, we might also give the choice of its symbol a second thought.

I suggest a new family of logical shortcut operators looking at definedness.

  • Defined-or, as we already know it, gets a new symbol and a low-precedence counterpart.
  • Defined-and is added with high- and low-precedence variants.
  • Defined-dereference is added.

I'll briefly explain syntax and semantics of each of those.

A :|| B
A dor B
(Defined-or) Evaluate A. If the result is defined, return it. Otherwise, evaluate B and return its result. :|| has the same precedence as || and dor has the same precedence as or. There is also an assignment operator variant :||= in analogy to ||=.
A :&& B
A dand B
(Defined-and) Evaluate A. If the result is undef, return undef. Otherwise, evaluate B and return its result. :&& has the same precedence as && and dand has the same precedence as and. There is also an assignment operator variant :&&= in analogy to &&=.
A :-> B
(Defined-dereference) Evaluate A. If the result is undef, return undef. Otherwise, evaluate B and return what would have been returned if the symbol was an ordinary arrow. B can be a method call as well as an arrayref index or hashref index or a coderef parameter list. There is no assignment variant like there is none with a normal arrow.

As to the symbol for defined-or, I consider the current choice somewhat unfortunate in that slash and double-slash already had enough other meanings and don't easily lead to generalizations either. It could stay in the language like other redundancies but gradually fade into deprecation.

Note that defined-dereference is a bit less trivial to implement than it might seem at first glance, since there is no other operator yet with shortcut behaviour whose shortcut-condition only has to be adapted. I included it anyway as I consider it useful in similar situations as defined-and, where undef may indicate some sort of failure we want to take care of early in an expression. I sometimes wished to have such an operator to chain method calls returning their object on success.

Clearly, there are situations where traditional "and" and "defined-and" would amount to the same effect. Being able to distinguish definedness from boolean truth, however, has its applications, or nobody would have cared to implement defined-or. I am now suggesting to act on that insight a bit more consequently.

I may even have a go at the patch myself if the perl5 porters gang neither veto the idea nor want to take it up from here. It may take me a while though, as I'd hate to make a blunder of my first patch that is more than a bugfix.

Fellow monks, what is your opinion on (a) the concept, (b) the proposed syntax?

Update:Put RFC: in the title.

  • Comment on RFC: Perl5 Language Extension: Definedness-Triggered Shortcut Operators

Replies are listed 'Best First'.
Re: Perl5 Language Extension: Definedness-Triggered Shortcut Operators
by moritz (Cardinal) on Mar 17, 2012 at 12:09 UTC

    I very much like the spirit behind this proposal, though I'm not sure if : is a good choice as "defined"-modifier. It doesn't have any definedness connotation for me.

    Maybe just stick with d? There's no rule that says operators need to be either word or non-word character only: A d|| B etc.

    And while you're at it, you can also introduce a prefix meta operator for exists instead of defined: e|| and e&&

    FWIW I don't see any problems with having multiple names for the same operator; it's a good way to deal with language change and graceful deprecation.

    Update: I should add that Perl 6 has long taken the road of having meta operators, and even type prefixed operators. For example bitwise AND behaves different from strings and numbers, which is there are two operators for them: +& and ~& (the ~ generally stands for strings in Perl 6, concatenation is infix ~, and string context is prefix ~).

    Meta operators are more general than that. For example the Z meta op can be applied to infix operators, making them "zip" two lists together:

    my @sums = 1, 2, 3 Z+ 30, 20, 10; # 31, 22, 13;

    It's a case where an operator consists of both word and non-word characters, and it's not particularly hard to read.

      Using a letter such as "d" might allow a prototype to be written using Devel::Declare.

      perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
Re: Perl5 Language Extension: Definedness-Triggered Shortcut Operators
by ikegami (Patriarch) on Mar 17, 2012 at 10:06 UTC

    You're putting the horse before the cart. Before you start worrying about the exact implementation, one needs to show the reason and purpose for the feature in the first place. You didn't provide any justification whatsoever for these changes, or mentioned any thoughts on the effects of the changes.

    You even pretend that // doesn't exist. Don't you think people will have a problem with two names for the same operator? The word "teachability" has come up in discussions about new features. Having two operators with the same name would detract from teachability, for one.

    The low-precedence version (to be named dor or err) was intentionally rejected (for reasons unknown to me). Do you have any new arguments that was presented then?

Re: Perl5 Language Extension: Definedness-Triggered Shortcut Operators
by tobyink (Canon) on Mar 17, 2012 at 13:04 UTC

    For defined-or we already have //.

    As far as the other two go, take a look at PerlX::Perform which I believe should allow you to do defined-and and defined-dereference, albeit with more verbose syntax.

    For example, imagine that $bob->spouse might return a Person object, or might return undef if Bob isn't married. Then PerlX::Perform allows:

    $bobs_wifes_name = perform { $_->name } wherever $bob->spouse;

    If the wherever expression evaluates to undefined, then the perform keyword returns undef (or the empty list if called in list context). If the wherever expression evaluates to a defined value (even if that value is false) then that value is assigned to $_ and the perform block is triggered.

    PerlX::Perform also offers an alternative syntax which works more or less the same way. Note that the alternative syntax uses a comma, whereas the syntax above does not.

    $bobs_wifes_name = wherever $bob->spouse, perform { $_->name };

    So your A :&& B can be written as:

    wherever A, perform {B}

    And your A:->B can be written as:

    wherever A, perform {$_->B}

    Do give PerlX::Perform a try. Patches for improved performance, or more sugary syntax are likely to be accepted.

    perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
Re: Perl5 Language Extension: Definedness-Triggered Shortcut Operators
by jwkrahn (Abbot) on Mar 17, 2012 at 10:17 UTC
    The defined-or operator, available since perl5.10, is an example of shortcut behaviour triggered on definedness: If the left hand side is defined, leave it at that, otherwise evaluate the right hand side.

    The defined-or operator, available since perl5.10, is an example of shortcut behaviour triggered on definedness and truth: If the left hand side is defined and true, leave it at that, otherwise evaluate the right hand side.

      The defined-or operator, available since perl5.10, is an example of shortcut behaviour triggered on definedness and truth: If the left hand side is defined and true, leave it at that, otherwise evaluate the right hand side.

      Are you sure? The defined-or operator in my perls test only for definedness, not for truth:

      >perl -E '$x=undef; $y=$x // warn "RHS evaluated"; say $y' RHS evaluated at -e line 1. 1 >perl -E '$x=""; $y=$x // warn "RHS evaluated"; say $y' >perl -E '$x=0; $y=$x // warn "RHS evaluated"; say $y' 0 >perl -E '$x="true"; $y=$x // warn "RHS evaluated"; say $y' true >perl -E '$x=42; $y=$x // warn "RHS evaluated"; say $y' 42 >perl -V Summary of my perl5 (revision 5 version 12 subversion 3) configuration +: Platform: osname=linux, osvers=2.6.35.10, archname=x86_64-linux-thread-multi uname='linux midas64 2.6.35.10 #2 smp thu jan 6 19:06:19 cst 2011 +x86_64 amd athlon(tm) ii x2 235e processor authenticamd gnulinux ' config_args='-de -Dprefix=/usr -Dvendorprefix=/usr -Dcccdlflags=-f +PIC -Dinstallprefix=/usr -Dlibpth=/usr/local/lib64 /usr/lib64 /lib64 +-Doptimize=-O2 -fPIC -Dusethreads -Duseithreads -Dpager=/usr/bin/less + -isr -Dinc_version_list=5.12.2 5.12.1 5.12.0 5.10.1 5.10.0 5.8.8 5.8 +.7 5.8.6 5.8.5 5.8.4 5.8.3 5.8.2 5.8.1 5.8.0 -Darchname=x86_64-linux' hint=recommended, useposix=true, d_sigaction=define useithreads=define, usemultiplicity=define useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=und +ef use64bitint=define, use64bitall=define, uselongdouble=undef usemymalloc=n, bincompat5005=undef Compiler: cc='cc', 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 -fPIC', cppflags='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -f +stack-protector -I/usr/local/include' ccversion='', gccversion='4.5.2', gccosandvers='' intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=1 +6 ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', + lseeksize=8 alignbytes=8, prototype=define Linker and Libraries: ld='cc', ldflags =' -fstack-protector' libpth=/usr/local/lib64 /usr/lib64 /lib64 libs=-lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lpthread -lc perllibs=-lnsl -ldl -lm -lcrypt -lutil -lpthread -lc libc=/lib64/libc-2.12.2.so, so=so, useshrplib=false, libperl=libpe +rl.a gnulibc_version='2.12.2' Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E' cccdlflags='-fPIC', lddlflags='-shared -O2 -fPIC -fstack-protector +' Characteristics of this binary (from libperl): Compile-time options: MULTIPLICITY PERL_DONT_CREATE_GVSV PERL_IMPLICIT_CONTEXT PERL_MALLOC_WRAP USE_64_ +BIT_ALL USE_64_BIT_INT USE_ITHREADS USE_LARGE_FILES USE_PERLIO USE_PERL_ATOF USE_REENTRANT_API Built under linux Compiled at Jan 26 2011 12:39:46 %ENV: PERL_UNICODE="SDL" @INC: /usr/lib64/perl5/site_perl/5.12.3/x86_64-linux-thread-multi /usr/lib64/perl5/site_perl/5.12.3 /usr/lib64/perl5/vendor_perl/5.12.3/x86_64-linux-thread-multi /usr/lib64/perl5/vendor_perl/5.12.3 /usr/lib64/perl5/5.12.3/x86_64-linux-thread-multi /usr/lib64/perl5/5.12.3 /usr/lib64/perl5/site_perl /usr/lib64/perl5/vendor_perl .

      This is also consistent with the documentation of Perl 5.10.0:

      Although it has no direct equivalent in C, Perl's // operator is related to its C-style or. In fact, it's exactly the same as ||, except that it tests the left hand side's definedness instead of its truth. Thus, $a // $b is similar to defined($a) || $b (except that it returns the value of $a rather than the value of defined($a)) and is exactly equivalent to defined($a) ? $a : $b.

      Alexander

      --
      Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
      I doubt it:
      perl -E 'my $x = 0 ; say $x // "true" ' 0
        And, explained by aaron_baugher, below:
        C:\>perl -E "my $x = 0 ; say $x // 'true'; my $y = 1; say $y // 'true' +;$x = undef; my $a=$x // warn 'RHS evaluated'; say $a;" 0 1 RHS evaluated at -e line 1. 1
        updated.
Re: Perl5 Language Extension: Definedness-Triggered Shortcut Operators
by JavaFan (Canon) on Mar 17, 2012 at 21:58 UTC
    Fellow monks, what is your opinion on (a) the concept, (b) the proposed syntax?
    None of your proposals hasn't been proposed on p5p one or more times the last 12 years (although, I grant you, you proposed syntax is new to me -- but that's probably because Larry gets the colon, and you ain't no Larry).

    Why don't you start by digging into the p5p archives, and refute the reasons why of all the proposals, only // survived? And while you are at it, explain why we need a :|| identical to //.

      Why don't you start by digging into the p5p archives, and refute the reasons why of all the proposals, only // survived? And while you are at it, explain why we need a :|| identical to //.

      Twelve years worth of p5p is a lot of ground to dig through, so I have only just begun. Here is a summary of what I have found so far.

      • There has indeed been debate about quite a number of operators looking at definedness.
      • Objections mostly address syntactical issues. Opinions stating that it was bad to have such operators at all seem to be very rare.
      • The "safe arrow" operator in particular has got a lot of support, though its symbol is not quite settled yet. One of its benefits I did not mention in my first post is that it can disable auto-vivification.
      • The double-slash symbol seems to have made it because of high demand for expressions with default values and it being the syntax proposed by Larry Wall for Perl 6.
      • Low-precedence defined-or was initially called "err", but its naming was later challenged. Larry himself did not like "dor" either, and he pointed out that "orelse", which is what "err" evolved into in Perl 6, has different semantics now that would not easily fit into Perl 5.
      • My primary concerns, i.e. the usefulness of short-cutting expression evaluation and the intent to provide more general solutions than an isolated exotic operator, don't seem to have played a major role in the discussion lately.
      • Colons indeed seem to be some sort of holy ground nobody dares to touch.
      • Points made in favour of a new syntax are often among these: (a) Has the new syntax been illegal before, so that old code is not likely to get hurt? (b) Do similar things look similar and dissimilar things look different? (c) Is the new syntax easy to use and remember? (d) Does it fit in the general look-and-feel of the language? (e) Are names free of different meanings or possible misunderstandings? (f) Is the impact on the existing language parser(s) limited?

      As to the coexistence of different symbols, I have already tried to convey that one of them should be preferred but the other one cannot suddenly be made illegal. This has precedents, like tr versus y, or version objects versus v-strings.

        Opinions stating that it was bad to have such operators at all seem to be very rare.
        There's always the fact that "adding features means more complexity of the implemenation, and hence more work on maintenance". Since this is an opinion carried forward by the handful of people that actually do significant maintenance work, this opinion carries a lot of weight.
        The "safe arrow" operator in particular has got a lot of support, though its symbol is not quite settled yet.
        But it wasn't hung just on syntax. And noone cared enough to restart the discussion. Which, to me, seems it's not an itch that bothers a lot of people.
        The double-slash symbol seems to have made it because of high demand for expressions with default values and it being the syntax proposed by Larry Wall for Perl 6.
        Right. So.... what's your argument to have an :|| as well?
        Low-precedence defined-or was initially called "err", but its naming was later challenged. Larry himself did not like "dor" either, and he pointed out that "orelse", which is what "err" evolved into in Perl 6, has different semantics now that would not easily fit into Perl 5.
        5.9.x had err for sometime (as the low priority version of //). It was decided it was better not to have it. What makes you think the time is right now, and what are your arguments that the concerns of a few years ago aren't concerns anymore?
        My primary concerns, i.e. the usefulness of short-cutting expression evaluation and the intent to provide more general solutions than an isolated exotic operator, don't seem to have played a major role in the discussion lately.
        I don't think there's much disagreement that having more features in the language has a value. But unless said value exceeds the costs it's not going to happen. And even if the value exceeds the costs, someone has to do the work first. Perlmonks is wrong forum to discuss this. Of course, 99.9% of the people here will say "Good idea. When can I have it"? Go pitch your idea on p5p.
        Has the new syntax been illegal before, so that old code is not likely to get hurt?
        That rules out any named operator like err, dor or dand -- unless you make them weak keywords or enable them using features.
Re: Perl5 Language Extension: Definedness-Triggered Shortcut Operators
by martin (Friar) on Mar 18, 2012 at 11:57 UTC

    One syntactical alternative I could think of is:

    A &&& B # defined-and A ||| B # defined-or A >>> B # safe arrow

    This would be a systematic approach reminiscent of the role of undef in ternary logic -- triple sign, third kind of truth value involved.

    I am not sure whether a whole lot of other similar symbols like ^^^ would make as much sense, though, which means we then had to explain why only those mentioned above were there.

      A &&& B   # defined-and
      You're not the first. Here's the reason why it's a bad idea:
      $ perl -ce 'A &&& B' -e syntax OK
      It's not worth breaking backwards compatability for this.

        You are right, triple ampersand parses as "boolean and" followed by a "subroutine call sigil". Too bad.

Re: Perl5 Language Extension: Definedness-Triggered Shortcut Operators
by Anonymous Monk on Mar 17, 2012 at 13:30 UTC
    You really can't change it now... it's already here once, and doesn't need to be here twice. Let a programming language get defined by a committee, and whaddaya get? Java, COBOL, or Ada. Pick your poison.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://960147]
Approved by Corion
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (5)
As of 2024-04-25 14:50 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found