[Kc] proposal: functional C<if>

David Nicol davidnicol at gmail.com
Wed Apr 25 14:27:38 PDT 2012


On Wed, Apr 25, 2012 at 3:34 PM, Jesse Luehrs <doy at tozt.net> wrote:
> On Wed, Apr 25, 2012 at 02:58:07AM -0500, David Nicol wrote:
>> On Tue, Apr 24, 2012 at 1:18 PM, Jesse Luehrs <doy at tozt.net> wrote:
>>
>> > I have on occasion wished for a more functional programming-style if
>> > statement:
>> >
>> >  my $foo = if ($foo->bar) { $bar } else { $baz };
>> >
>> > It is a lot more readable than ?: when the expressions get more
>> > complicated.
>>
>> C<do> is very handy and will let you do that:
>>
>> $ perl -le 'my $X = do { if ( 0 ) { 27 } else { 33 }};print $X'
>> 33
>>
>> $ perl -le 'my $X = do { if ( 1 ) { 27 } else { 33 }};print $X'
>> 27
>
> Sure, but if I didn't care about it being pretty, ?: already works too(:

This proposal is separate from "overridable keywords."

The proposal appears to be, allow

     if ( BOOLEAN ) { TRUE BRANCH } else { FALSE BRANCH }

and variations (unless, elsif, elsunless (do we even have that?) and so on)

to act as R-values in assignment and elsewhere. In effect, making that
syntax exactly a long way to write the ternary operator.

An if-statement already sort of returns a value, but it can only be
captured by enclosing the if-statement in a block of some kind, so the
value gets returned
according the "value of a block is the value of the last expression
executed" rule.

Currently, attempts to use if-statements as R-values are syntax
errors. They are not misinterpreted as trailing conditionals.

It seems that there is no syntactic ambiguity between R-value
if-statement and trailing if-statement, but differentiating may
require looking ahead several tokens, as the signifiers


Challenge: Can anyone come up with an ambiguous expression where it is
not clear if the expression is supposed to be an R-value if-statement
(were such things allowed) or a trailing conditional?

I imagine it would be pretty tricky to modify perl so the if and
unless keywords are reclassified into animals that can be r-values,
since they are already the subject of some ambiguity. But maybe it
isn't, as regular and trailing versions never appear at the same place
in the parsing state machine.

here we've got an "if" where only an r-value will make sense:

$ perl -le '$X = if (1) { "T" } else { "F" }; print $X'
syntax error at -e line 1, near "= if"
Execution of -e aborted due to compilation errors.
$ perl -le '$X = (if (1) { "T" } else { "F" }); print $X'
syntax error at -e line 1, near "(if"
Execution of -e aborted due to compilation errors.

those might become valid by simply allowing C<if> to be an r-value, in
an identified and enumerated set of r-value-only situations, such as
on the right side of an assignment operator, or as the first thing
after a left round, (and also what? )


here we've got a left curly after a trailing conditional if:

$ perl -le 'print if (1) { "T" } else { "F" }'
syntax error at -e line 1, near ") {"
Execution of -e aborted due to compilation errors.
$ perl -le 'print if (1) { "T" }'
syntax error at -e line 1, near ") {"
Execution of -e aborted due to compilation errors.

Making those valid would require looking ahead to determine whether
the C<if> is a trailer or a returner. The differentiator appears to
be, the returner has both (1) parentheses around the thing following
the keyword and (2) an opening curly following the parenthesized
predicate, while the trailer's predicate may have parentheses, they
are never directly.followed by an opening curly.


More information about the kc mailing list