Generate "apply defaults when condition" syntax #48

schwern opened this Issue Aug 11, 2012 · 9 comments


None yet

3 participants

schwern commented Aug 11, 2012

@thoughtstream mused...

Maybe we can have:

sub foo ($arg = 'default')               # existence test
sub foo ($arg = 'default' when undef)    # default if $arg ~~ undef
sub foo ($arg = 'default' when '')       # default if $arg ~~ ''
sub foo ($arg = 'default' when 0)        # default if $arg ~~ 0
sub foo ($arg = 'default' when * < 0 )   # default if $arg < 0

Note that I later withdrew the final (Perl6y) suggestion:

sub foo ($arg = 'default' when * < 0 )   # default if $arg < 0

and replaced it with the Perl5ish:

sub foo ($arg = 'default' when {$_ < 0} )   # default if $arg < 0

My most recent patch implements the latter, not the former.


I think the when thing is a great idea. It's @schwern's original idea from #45, right? (See first schwern comment in that issue.) It covers @ruz's use case and is easily extensible. Since we're using PPI for the parsing, it's not hard to do (as @thoughtstream has demonstrated), and it should be moderately easy to keep from interfering with other stuff (e.g. where). Unless we're concerned about the possibility of breaking new ground here (if Perl 6 has a when, I'm not familiar with it), I can't see a downside.

I also agree with @thoughtstream's corrected patch (i.e. $_ over *).


Note that I am currently working (in my copious free time) on a v3 patch
that uses PPI to parse all the components after the type and parameter name.
That is:

func (Type $param where /whatever/ = $DEFAULT when { cond() }) {...}
                  \___________________  ____________________/
                               Parsed using PPI

This will (very nearly) solve the problem of correctly handling arbitrarily
complex code as the operands of where, of =, and of when
(i.e. solve it as far any static analyser, such as PPI, is able to).

It's relatively trivial, if a little tedious to implement, but if we're
eventually going ahead with these features (and soon, I hope!),
it will be worth waiting for, I think.

I'll implement it to also support //= as a shortcut for when undef
(as per Schwern's ruling), but I still think that's multiplying entities

And, more importantly, I fear that it's the thin edge of an undesirable wedge:
I'd rather not have //= at all and have to write when undef everywhere
if the exclusion of //= also serves to prevent the subsequent addition of
still more defaulting operators, such as ||= or ''= or (gods help us!) 0=.

schwern commented Aug 16, 2012

@thoughtstream Converting the signature parsing to PPI is extremely welcome! Its been a niggling problem for a while now. I've made you a collaborator (IT'S A TRAP). Make a branch for the PPI work and push it as you go so we can see where you're going with this?

WRT the slippery slope of assignment operators, it's a good thing there are people designing this thing who can make thoughtful decisions! I've never been swayed by the "if we do X good thing, people will want similar looking Y bad thing, so let's not do X because it will lead to Y" argument. We know Y is bad, so don't do it.

The nice part about having the generic when operator in addition to the specific ones is when acts as a test bed for what sort of defaults people need. We're pretty sure when undef is going to be common (if you don't think so, that's a whole different story). If it turns out that when 0 is common then we will consider 0= with all the consideration due to coining a new assignment operator.

Though how does one express the equivalent to ||= with when? That is "when this is false".


Though how does one express the equivalent to ||= with when? That is "when this is false".

From my understanding of @thoughtstream's syntax, it would be: when !$_ .

schwern commented Aug 16, 2012

@thoughtstream PS If you don't want to implement //= you don't have to. You can just do when and somebody else (maybe me since I seem to be the biggest proponent) will do it. when and //= are orthogonal problems.

@barefootcoder Ok, that's cool. Probably worth putting in the docs.


Re branching repo: Probably won't. Expect annoyingly complete patches.
(I know. Not properly social. Not a team player. Not git-ish.
But also not a new phenomenon. Every single report card I ever
received included some variation of: "Does not play well with others".)

Re expressing ||= via when: that's just:

sub foo ($arg = 'default' when {!$_}) {...}

Note that:

sub foo ($arg = 'default' when !$_) {...}

won't be allowed (at least, not under my patch), because:

$arg ~~ !$_

is one of the eight evil special cases of Perl 5 smartmatching that
(gods willing!) are soon going away, so no point in encouraging it now.
That kind of auto-thunking was a mistake; one we should avoid

Alternatively, if you want the full extent of your folly revealed to the world,
you could express ||= as:

func overbool ($arg) { eval{ overload::Method($arg,'bool')->($arg) }}
func overnot  ($arg) { eval{ overload::Method($arg, '!'  )->($arg) }}

func foo ($arg = 'default' when [ "", 0, 0.0, "0", undef, \&overbool, \&overnot ]) {...}



@thoughtstream: Don't sweat it. I'll take your patch and put it on a branch. Do I have the latest, or do you want to email me a newer one?

... won't be allowed (at least, not under my patch), because: ...

Ah, okay, braces required. Sure, nothing wrong with that, especially if it makes the parsing easier. I'll just think of it like map (which I never use the EXPR form of, due to the fact that I think it would cross at least one of my eyes).


Fixed in version 20121201.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment