develooper Front page | perl.perl6.language | Postings from February 2005

Re: Slurpy nullary vs nonslurpy nullary

Thread Previous | Thread Next
From:
Larry Wall
Date:
February 18, 2005 08:26
Subject:
Re: Slurpy nullary vs nonslurpy nullary
Message ID:
20050218162626.GA27252@wall.org
On Fri, Feb 18, 2005 at 04:25:49PM +0800, Autrijus Tang wrote:
: After getting Life and Mandel to run on Pugs yesterday (see
: http://svn.perl.org/perl6/pugs/trunk/examples/ ), today I've
: made this version of Quicksort to run:
: 
:     use v6;
: 
:     multi sub quicksort ( ) { () }
: 
:     multi sub quicksort ( *$x, *@xs ) {
: 	my @pre  = @xs.grep{ $_ < $x };
: 	my @post = @xs.grep{ $_ >= $x };

Just as a BTW, that syntax is illegal currently, since those
curlies would be interpreted as hash subscripts.  Method syntax requires
parens if there are any (non-adverbial) arguments.  So you either need
parens for the argument:

	my @pre  = @xs.grep({ $_ < $x });
	my @post = @xs.grep({ $_ >= $x });

or pass an adverbial block:

	my @pre  = @xs.grep:{ $_ < $x };
	my @post = @xs.grep:{ $_ >= $x };

: 	(@pre.quicksort, $x, @post.quicksort);
:     }
: 
:     (1, 5, 2, 4, 3).quicksort.say;
: 
: Note the use of @xs.grep{} above.  Pugs currently has two multisub
: named "grep":
: 
:     * List as invocant, takes a Code arg
:     * Takes two args: Code and List
: 
: It sort of makes sense to me.  Please correct me if it's wrong. :)

As long as the first is always called as single dispatch, and the
second as multiple dispatch, there should be no confusion.

: But anyway.  The real problem is the multisub dispatcher initially
: complained about the () signature, saying that it is "non-slurpy"
: and may not take a list, even though the list eventually flattens
: into an empty list; so I modified the definition to make () explicitly
: slurpy.
: 
: However, that feels wrong, as I'd like to distinguish from a slurpy
: nullnary (something that can take a list, as long as it's empty) and a
: non-slurpy nullary (something that takes no arguments whatsoever).

Right, it's the anchoring problem--but it's really only a problem for
compile time typing, and documenting your intent.  At run time we know
perfectly well that there are 0 arguments.

: I have been wondering whether something like 
: 
:     quicksort( *[] ) 
: 
: Can mean a slurpy nullnary, but I failed to find relevant text in
: Synopses, so here I am. :-)

No, that'd mean a single array reference that has to be empty.

: (PS. Yes, I understand that I can use array unpacking and have
: quicksort always take a single array argument, but I'd still like to
: inquire about slurpy nullary...)

If we decide we need to declare non-anchoring intent (and I'm not
convinced we do), then maybe the final (or only) arg of a multi can
be declared as bare * to indicate it's not anchored to the end of
the argument list.  But the () declaration indicates already that
the function will never match a non-null list, and people might take
(*) to mean that it matches a non-null list and throws away the result.
So I think your initial solution is actually the right one from the
viewpoint of the Perl programmer.  If we need to tweak something,
it's perhaps to document the fact that *$x is required to match an argument,
while *@x isn't required to match any arguments at all.  So if you
had

    multi sub quicksort ( ) { () }
    multi sub quicksort ( *@x ) {

then when dispatching 0 arguments you actually have an ambiguity that
either has to be illegal or solved by ordered matching.  I think
ordered matching is more conducive to a Prolog-like mentality, and
more fail-soft, and slightly righter for Perl.  (But that doesn't say
much about ordering across different modules, does it?)

Larry

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About