Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

A proposal on if and else

12 views
Skip to first unread message

Brent Dax

unread,
Jan 20, 2003, 2:14:35 PM1/20/03
to perl6-l...@perl.org
Many people have pointed out the 'semicolon problem' with if and
else--that is, if Perl intuits a semicolon after every codeblock that
ends a blank line, you would have to cuddle all your elses:

if $cond {
...
} <-- Virtual semicolon here
else {
...
}

My proposed solution to this is to make ALL codeblocks take an optional
'else', accessed by the $code.else attribute. Depending on what sort of
builtin was being used, the else would mean different things:

sub if($cond, &code) {
$cond ?? code() :: &code.else();
}

sub while(&cond, &code) {
if(cond()) {
#There's probably a way to do an
# else without a goto, but...
TOP:
code();
return unless cond();
goto TOP;
}
else {
&code.else();
}
}

sub for(@list is lazy, &code) {
while(@list) {
&code(@list.unshift);
}
else {
&code.else();
}
}

The else on a subroutine declaration might be called if preconditions
(PRE and POST) didn't match, or it might just be ignored.

else would be able to take a single subroutine call instead of a block:

if $cond {
...
}
else if $cond2 {
...
}

Yes, I know this means that we have 'else if' instead of 'elsif', but
it's only two more characters and it makes the grammar cleaner.

--Brent Dax <bren...@cpan.org>
@roles=map {"Parrot $_"} qw(embedding regexen Configure)

>How do you "test" this 'God' to "prove" it is who it says it is?
"If you're God, you know exactly what it would take to convince me. Do
that."
--Marc Fleury on alt.atheism

Rafael Garcia-Suarez

unread,
Jan 20, 2003, 3:31:46 PM1/20/03
to perl6-l...@perl.org
Brent Dax wrote in perl.perl6.language :

> Yes, I know this means that we have 'else if' instead of 'elsif', but
> it's only two more characters and it makes the grammar cleaner.

The tokeniser could send two tokens "else" and "if" whenever it
recognizes the keyword "elsif" -- so this isn't a problem.

Joseph F. Ryan

unread,
Jan 20, 2003, 4:13:31 PM1/20/03
to Rafael Garcia-Suarez, perl6-l...@perl.org
Rafael Garcia-Suarez wrote:

I think the point of having C<if> as a sub rather than as a separate
syntax is so the parser doesn't have to do anything special for
special keywords.

I think the goal was to simplify the compiler, but with the
discussion of recent weeks, it certainly doesn't look like that
happened. :)


Joseph F. Ryan
ryan...@osu.edu

Rafael Garcia-Suarez

unread,
Jan 20, 2003, 4:17:09 PM1/20/03
to perl6-l...@perl.org
Joseph F. Ryan wrote in perl.perl6.language :

>
> I think the point of having C<if> as a sub rather than as a separate
> syntax is so the parser doesn't have to do anything special for
> special keywords.
>
> I think the goal was to simplify the compiler, but with the
> discussion of recent weeks, it certainly doesn't look like that
> happened. :)

Simplify the compiler, yes; but (with my limited knowledge of Perl 6) I
don't expect the tokenizer to be simple. And the hack I just proposed to
the tokenizer is mostly stateless.

--
If strain on the lexer were a design criterion, I blew it long ago.
-- Larry Wall

Joseph F. Ryan

unread,
Jan 20, 2003, 4:59:11 PM1/20/03
to Rafael Garcia-Suarez, perl6-l...@perl.org
Rafael Garcia-Suarez wrote:

>Joseph F. Ryan wrote in perl.perl6.language :
>
>
>>I think the point of having C<if> as a sub rather than as a separate
>>syntax is so the parser doesn't have to do anything special for
>>special keywords.
>>
>>I think the goal was to simplify the compiler, but with the
>>discussion of recent weeks, it certainly doesn't look like that
>>happened. :)
>>
>>
>
>Simplify the compiler, yes; but (with my limited knowledge of Perl 6) I
>don't expect the tokenizer to be simple. And the hack I just proposed to
>the tokenizer is mostly stateless.
>


If the final design stays the way it is now, there really won't be
a "lexer". Instead, a perl6 grammar parses the data, and builds up
a huge match-object as it, well, matches. This match object is then
munged into the optree.

This means the grammar probably won't be anything resembling simple,
since it has to act as both a lexer and a parser at the same time.
However, that's not to say your hack couldn't work; in fact, it would
be easy to implement during the match-object-munging phase.
However, it still treats C<if> as special syntax, which is the real issue
at hand..

I question whether treating C<if> as a function rather than as built-in
syntax will make the parser any simpler if "special block rules" keep
getting added to simply make it work. I'm in favor of keeping a few
"special blocks" if it makes things easier to implement/design in the
long run.


Joseph F. Ryan
ryan...@osu.edu

Rafael Garcia-Suarez

unread,
Jan 20, 2003, 5:14:57 PM1/20/03
to perl6-l...@perl.org
Joseph F. Ryan wrote in perl.perl6.language :
>
> If the final design stays the way it is now, there really won't be
> a "lexer". Instead, a perl6 grammar parses the data, and builds up
> a huge match-object as it, well, matches. This match object is then
> munged into the optree.

Oh, yes, I remember now. Thanks.

> This means the grammar probably won't be anything resembling simple,
> since it has to act as both a lexer and a parser at the same time.
> However, that's not to say your hack couldn't work; in fact, it would
> be easy to implement during the match-object-munging phase.

Indeed.

> However, it still treats C<if> as special syntax, which is the real issue
> at hand..
>
> I question whether treating C<if> as a function rather than as built-in
> syntax will make the parser any simpler if "special block rules" keep
> getting added to simply make it work. I'm in favor of keeping a few
> "special blocks" if it makes things easier to implement/design in the
> long run.

Makes sense. Note that I'm not advocating "elsif", quite an horrible
keyword, that I still mispell as "elseif" sometimes. But I like hacking
on grammars ;-)

Austin Hastings

unread,
Jan 20, 2003, 5:29:55 PM1/20/03
to Joseph F. Ryan, Rafael Garcia-Suarez, perl6-l...@perl.org

--- "Joseph F. Ryan" <ryan...@osu.edu> wrote:
> If the final design stays the way it is now, there really won't be
> a "lexer". Instead, a perl6 grammar parses the data, and builds up
> a huge match-object as it, well, matches. This match object is then
> munged into the optree.
>

With this in mind, I'll say it again:

Let's support separable verbs.

Here's how:

# Note my arbitrary selection of _ as separation indicator. Feel free
to replace this with something more appropriate:

sub if ($test, &block)
_ elsif ($test, &block) is optional is floating is multi
_ elsunless ($test, &block) is optional is floating is multi
_ else (&block) is optional is fixed
{
while (!$args[0].test) shift;
&args[0].block();
}

Where:

1: I'm hacking real hard on the implementation. Better Ideas Welcome.
2: space-underscore-space means "separable bit". Negotiable. BIW.
3: is optional/[dflt: required] means doesn't have to appear.
4: is floating/[dflt: fixed] means can appear in any order.
5: is multi/[dflt: single] means can appear more than once.

The last three (3, 4, 5) are really just match-hints to the rexer for
"here's how to look for me":

/if <arg-bits>
((elsif <arg-bits> | elsunless <arg-bits>)*)
(else <arg-bits>)?/

Instead of, say, requiring all the elsif in front of all the elsunless,
or whatever.

I think this is one of those p6-ish generalizations:

try/catch/finally
do/while
if/elsif/elsunless/else
repeat/until
(arguably: switch/case/default)

are all just separable verbs:

sub try (&block)
_ catch ($e, &block) is optional is multi is fixed
_ finally (&block) is optional is fixed;

sub do (&block)
_ while ($cond); # is single is fixed is required

sub repeat (&block)
_ until ($cond); # is single is fixed is required

sub switch ($cond)
_ case ($val, &block) is multi is required
_ default (&block) is optional;

(Note: This leaves switch statements looking like crap, so I'd really
rather sugar them up. But the point is, you *could* to it that way.)

switch ($x)
case (10) { print 10; }
case (11) { print 11; }
default { print "Something else"; }

=Austin


Brent Dax

unread,
Jan 20, 2003, 6:02:54 PM1/20/03
to Austin_...@yahoo.com, Joseph F. Ryan, Rafael Garcia-Suarez, perl6-l...@perl.org
Austin Hastings:
# Let's support separable verbs.
#
# Here's how:
#
# # Note my arbitrary selection of _ as separation indicator.
# Feel free to replace this with something more appropriate:
#
# sub if ($test, &block)
# _ elsif ($test, &block) is optional is floating is multi
# _ elsunless ($test, &block) is optional is floating is multi
# _ else (&block) is optional is fixed

How do you name one of these suckers?

%::{'if'} #Incomplete, and is there an %::{'elsif'}?
%::{'if_elsif_elsunless_else'} #Could conflict with other symbols
%::{'if _ elsif _ elsunless _ else'} #Depends on ordering

Remember, this also has bearing on importing them from a module.

# {
# while (!$args[0].test) shift;

1. Where did this $args come from?
2. The while syntax is way wrong.
3. How does else's test default to 1?

# &args[0].block();

From this, it's obvious you forgot about sigil invariance.

# }
#
# Where:
#
# 1: I'm hacking real hard on the implementation. Better Ideas Welcome.
# 2: space-underscore-space means "separable bit". Negotiable. BIW.
# 3: is optional/[dflt: required] means doesn't have to appear.
# 4: is floating/[dflt: fixed] means can appear in any order.
# 5: is multi/[dflt: single] means can appear more than once.

5 conflicts with multimethods.

# I think this is one of those p6-ish generalizations:
#
# try/catch/finally
# do/while
# if/elsif/elsunless/else
# repeat/until
# (arguably: switch/case/default)

Except that none of the other ones exist in Perl 6. :^)

try {
...
CATCH {
...
}
}

loop {
...
last unless cond;
}

loop {
...
last if cond;
}

given(topic) {
when cond {
...
}

default {

}
}

IMHO, separable keywords are in general a bad design, so perhaps they
should be grammar-munge hard. We really don't need anything but else
(and possibly its friends) for our purposes, but we want them
everywhere, so I don't see why we shouldn't do it this way.

Austin Hastings

unread,
Jan 20, 2003, 6:37:42 PM1/20/03
to Brent Dax, Austin_...@yahoo.com, Joseph F. Ryan, Rafael Garcia-Suarez, perl6-l...@perl.org
--- Brent Dax <bren...@cpan.org> wrote:
> Austin Hastings:
> # Let's support separable verbs.
> #
> # Here's how:
> #
> # # Note my arbitrary selection of _ as separation indicator.
> # Feel free to replace this with something more appropriate:
> #
> # sub if ($test, &block)
> # _ elsif ($test, &block) is optional is floating is multi
> # _ elsunless ($test, &block) is optional is floating is multi
> # _ else (&block) is optional is fixed
>
> How do you name one of these suckers?
>
> %::{'if'} #Incomplete, and is there an %::{'elsif'}?
> %::{'if_elsif_elsunless_else'} #Could conflict with other symbols
> %::{'if _ elsif _ elsunless _ else'} #Depends on ordering
>
> Remember, this also has bearing on importing them from a module.
>

Full name, with full signature. if_elsif_elsunless_else($c,&b,$c,&b,
$c, &b, &b);

Maybe a special widget in the arglist to denote separability? This
could be important for varargs multimethods.

> # {
> # while (!$args[0].test) shift;
>
> 1. Where did this $args come from?
> 2. The while syntax is way wrong.
> 3. How does else's test default to 1?
>
> # &args[0].block();
>
> From this, it's obvious you forgot about sigil invariance.

I can't even spell sigil invariance. And I'm nowhere close to sure that
it would be valid to use "while" when in the middle of trying to define
"if".

I was "backfilling" the innards after writing the 'outards'. Just a
competence fault on my part.

>
> # }
> #
> # Where:
> #
> # 1: I'm hacking real hard on the implementation. Better Ideas
> Welcome.
> # 2: space-underscore-space means "separable bit". Negotiable. BIW.
> # 3: is optional/[dflt: required] means doesn't have to appear.
> # 4: is floating/[dflt: fixed] means can appear in any order.
> # 5: is multi/[dflt: single] means can appear more than once.
>
> 5 conflicts with multimethods.

s/multi/repeatable/ or whatever. BIW.

>
> # I think this is one of those p6-ish generalizations:
> #
> # try/catch/finally
> # do/while
> # if/elsif/elsunless/else
> # repeat/until
> # (arguably: switch/case/default)
>
> Except that none of the other ones exist in Perl 6. :^)

Because we have not heretofore had a cool syntax for separable verbs.
Now we do. Now it can be possible to say "use pascal;" and get extra
syntax overhead. Rejoice. :-/

>
> try {
> ...
> CATCH {
> ...
> }
> }
>
> loop {
> ...
> last unless cond;
> }
>
> loop {
> ...
> last if cond;
> }
>
> given(topic) {
> when cond {
> ...
> }
>
> default {
>
> }
> }
>
> IMHO, separable keywords are in general a bad design, so perhaps they
> should be grammar-munge hard. We really don't need anything but else
> (and possibly its friends) for our purposes, but we want them
> everywhere, so I don't see why we shouldn't do it this way.

Go us. One step closer to total world domination.

=Austin

Simon Cozens

unread,
Jan 20, 2003, 6:55:05 PM1/20/03
to perl6-l...@perl.org
austin_...@yahoo.com (Austin Hastings) writes:
> Let's support separable verbs.

That (http://dev.perl.org/perl6/rfc/309.html) is a really good idea.

--
Writing software is more fun than working.

Dave Whipp

unread,
Jan 20, 2003, 4:28:38 PM1/20/03
to perl6-l...@perl.org

"Joseph F. Ryan" <ryan...@osu.edu> wrote in message
news:3E2C667B...@osu.edu...

> Rafael Garcia-Suarez wrote:
> >
> >The tokeniser could send two tokens "else" and "if" whenever it
> >recognizes the keyword "elsif" -- so this isn't a problem.
> >
>
> I think the point of having C<if> as a sub rather than as a separate
> syntax is so the parser doesn't have to do anything special for
> special keywords.

The specialness could be generalized, so that its no longer a parser hack:

<proposal rating='NOOOooo'>
#define elsif else if
</idea>

Dave.


Thom Boyer

unread,
Jan 21, 2003, 1:15:17 PM1/21/03
to Rafael Garcia-Suarez, perl6-l...@perl.org
Rafael Garcia-Suarez [mailto:rgarci...@free.fr] wrote:
> The tokeniser could send two tokens "else" and "if" whenever it
> recognizes the keyword "elsif" -- so this isn't a problem.

The primary advantage, to my mind, in using C<elsif>, is that it eliminates
the dangling-else ambiguity -- so splitting it in half removes almost ALL
the value of even having an C<elsif> keyword.

=thom
"More people worry themselves to death than bleed to death." --
_Tunnel_in_the_Sky_, Robert Heinlein

Smylers

unread,
Jan 21, 2003, 4:43:59 PM1/21/03
to perl6-l...@perl.org
Thom Boyer wrote:

> The primary advantage, to my mind, in using C<elsif>, is that it
> eliminates the dangling-else ambiguity -- so splitting it in half
> removes almost ALL the value of even having an C<elsif> keyword.

Surely it's the compulsory braces, even with a single statement, which
eliminates that problem?

These look ambiguous to me, with no C<else if> required:

if test1
if test2
statement_A;
else
statement_B;

if test1
if test2
statement_A;
else
statement_B;

Where as putting the braces in there always disambiguates which C<if>
and C<else> goes with:

if test1 {
if test2 {
statement_A;
}
else {
statement_B;
}
}

if test1 {
if test2 {
statement_A;
}
}
else
{
statement_B;
}

Smylers

Thom Boyer

unread,
Jan 21, 2003, 8:58:46 PM1/21/03
to Smylers, perl6-l...@perl.org
Smylers wrote:
> Thom Boyer wrote:
>>The primary advantage, to my mind, in using C<elsif>, is that it
>>eliminates the dangling-else ambiguity -- so splitting it in half
>>removes almost ALL the value of even having an C<elsif> keyword.
>
>
> Surely it's the compulsory braces, even with a single statement, which
> eliminates that problem?
Almost. The compulsory-braces rule [a Perl 5 syntax decision I applaud]
means that

if test1 {
statement_A;
} elsif test2 {
statement_B;
} elsif test3 {
statement_C;
}

is equivalent in meaning to

if test1 {
statement_A;
} else {
if test2 {
statement_B;
} else {
if test3 {
statement_C;
}
}
}

So if "elsif" becomes "else" followed by "if" in the scanner, the result
is syntactically wrong _because_ the curly braces are required (a point
that I missed in my earlier post):

if test1 {
statement_A;
} else if test2 { # syntax error: missing open brace after 'else'
statement_B;
} else if test3 { # Oops, I did it again
statement_C;
}

And let's not anybody say, "Well, 'elsif' gets converted to 'else'
followed by '{' followed by 'if', then!", because that doesn't work. All
the closing right curly braces would still be missing.

So the compulsory curly braces make for a much more convincing argument
against an "elsif" --> "else if" conversion in the scanner.


Personally, I don't think anybody should be working this hard to make
if/elsif/elsunless/else writeable as a subroutine. I don't think it
should be put in that pigeonhole: it doesn't fit there very well.

If we really need the comfort of knowing that if/else/etc. is writable
in Perl 6, then we can all take comfort that it _is_ always possible (if
not as convenient) using the much more general grammar-extension mechanism.
=thom

Piers Cawley

unread,
Jan 27, 2003, 10:48:51 AM1/27/03
to Austin_...@yahoo.com, Joseph F. Ryan, Rafael Garcia-Suarez, perl6-l...@perl.org
Austin Hastings <austin_...@yahoo.com> writes:

> --- "Joseph F. Ryan" <ryan...@osu.edu> wrote:
>> If the final design stays the way it is now, there really won't be
>> a "lexer". Instead, a perl6 grammar parses the data, and builds up
>> a huge match-object as it, well, matches. This match object is then
>> munged into the optree.
>>
>
> With this in mind, I'll say it again:
>
> Let's support separable verbs.
>
> Here's how:
>
> # Note my arbitrary selection of _ as separation indicator. Feel free
> to replace this with something more appropriate:
>
> sub if ($test, &block)
> _ elsif ($test, &block) is optional is floating is multi
> _ elsunless ($test, &block) is optional is floating is multi
> _ else (&block) is optional is fixed
> {
> while (!$args[0].test) shift;
> &args[0].block();
> }

Mmm... Smalltalk style message specifiers here we come...

method Bool::ifTrue (&trueBlock) _ ifFalse (&falseBlock);

($a == $b).ifTrue { do_this() }
ifFalse { do_that() }

I really like this idea or something like it.

--
Piers

0 new messages