Re: new Capture behavior (Was: Re: r25685 - docs/Perl6/Spec)

2009-03-06 Thread Daniel Ruoso
Em Qui, 2009-03-05 às 18:43 -0800, Jon Lang escreveu:
 OK; let me get a quick clarification here.  How does:
 say Hello, World!;

This is the equivalent to

 say.postcircumfix:( )( \(Hello, World) );

 differ from:
 Hello, World!.say;

This is just

  Hello, World!.say;

Meaning, the first dispatch is private to the sub, the second to the
object.

 or:
 say $*OUT: Hello, World!;

  $*OUT.say(Hello, World!);

dispatch is private to $*OUT...

 And more generally, would there be a
 reasonable way to write a single routine (i.e., implementation) that
 could be invoked by a programmer's choice of these calling
 conventions, without redirects (i.e., code blocks devoted to the sole
 task of calling another code block)?

This is exactly what this change has enabled. Now it doesn't matter if
your signature had an invocant or not, if that code is available as a
method it can be dispatched as a method, if it is available as a sub, it
can be dispatched as a sub, which means that you can install a sub as a
method and a method as a sub, it doesn't mattter...

 Could you use binding?
 my sub say (String *$first, String *...@rest, OStream :$out = $*OUT,
 OStream :$err = $*ERR)
 { ... }
 role String {
 has say:(String $first: String *...@rest, OStream :$out = $*OUT,
 OStream :$err = $*ERR)
 := OUTER::say;
 }

semantically, yes... but I don't think there's a syntax to bind a sub as
a method... You need to do it through the meta api at this moment...

maybe we could have something in the lines of

  method bar ::= bar;

or even

  method bar is external bar;

daniel



Re: new Capture behavior (Was: Re: r25685 - docs/Perl6/Spec)

2009-03-06 Thread TSa

HaloO,

Daniel Ruoso wrote:

Em Qui, 2009-03-05 às 18:43 -0800, Jon Lang escreveu:

And more generally, would there be a
reasonable way to write a single routine (i.e., implementation) that
could be invoked by a programmer's choice of these calling
conventions, without redirects (i.e., code blocks devoted to the sole
task of calling another code block)?


This is exactly what this change has enabled. Now it doesn't matter if
your signature had an invocant or not, if that code is available as a
method it can be dispatched as a method, if it is available as a sub, it
can be dispatched as a sub, which means that you can install a sub as a
method and a method as a sub, it doesn't mattter...

[..]

semantically, yes... but I don't think there's a syntax to bind a sub as
a method... You need to do it through the meta api at this moment...


With this nice unification of sub and method as far as the binder
is concerned I wonder how one implements methods for classes one
is supertyping from without an is also clause. With the venerable
example of Complex supertyping Num we should have

   method im (Num $x:) { return 0 }
   method re (Num $x:) { return $x }

outside of any class and nonetheless allow the method invocation
syntax 3.im without the object slot dispatcher complaining. That
is I want to avoid

   class Num is also
   {
  method im { return 0 }
  method re { return self }
   }

at least as syntactical form. I think in the end the class Num
gets the additional methods one way or another. But it seems
open classes have acquired a design smell of late. Or why is
the process called monkey patching?


Regards, TSa.
--

The unavoidable price of reliability is simplicity -- C.A.R. Hoare
Simplicity does not precede complexity, but follows it. -- A.J. Perlis
1 + 2 + 3 + 4 + ... = -1/12  -- Srinivasa Ramanujan


Re: new Capture behavior (Was: Re: r25685 - docs/Perl6/Spec)

2009-03-05 Thread Daniel Ruoso
Em Qui, 2009-03-05 às 12:58 -0300, Daniel Ruoso escreveu:
 What really got me confused is that I don't see what problem this change
 solves, since it doesn't seem that a signature that expects an invocant
 (i.e.: cares about invocant) will accept a call without an invocant, so
 method foo($b,$c) is export still need to have a transformed signature
 in the sub version of foo.

Thinking again,

Unless that actually means that we're really removing all the runtime
semantics around the invocant... and methods implicitly do my $self =
shift all the time...

That'd be sad... we loose invocant semantics... SMOP will require a
HUGE refactoring... :(

daniel



Re: new Capture behavior (Was: Re: r25685 - docs/Perl6/Spec)

2009-03-05 Thread Jon Lang
Daniel Ruoso wrote:
 Daniel Ruoso escreveu:
 What really got me confused is that I don't see what problem this change
 solves, since it doesn't seem that a signature that expects an invocant
 (i.e.: cares about invocant) will accept a call without an invocant, so
 method foo($b,$c) is export still need to have a transformed signature
 in the sub version of foo.

 Thinking again,

 Unless that actually means that we're really removing all the runtime
 semantics around the invocant... and methods implicitly do my $self =
 shift all the time...

 That'd be sad... we loose invocant semantics... SMOP will require a
 HUGE refactoring... :(

Remember that Captures are also being used as Perl 6's answer to
references.  When used in that way, problems arise when you treat a
single item as being fundamentally different from a one-item list.

-- 
Jonathan Dataweaver Lang


Re: new Capture behavior (Was: Re: r25685 - docs/Perl6/Spec)

2009-03-05 Thread Larry Wall
On Thu, Mar 05, 2009 at 12:58:21PM -0300, Daniel Ruoso wrote:
: Em Qua, 2009-03-04 às 20:21 +0100, pugs-comm...@feather.perl6.nl
: escreveu:
:  Simplify meaning of Capture and Match in item context to preserve sanity
:  (an object in item context is always just itself, never a subpart)
: 
:   sub foo { return 1 }
:   my $a = foo();
: 
: That is currently expressed as taking the capture (in this case \(1))
: and coerce it to the appropriate context, in order for that to work,
: Capture need to do some DWIMmery when used in item context.
: 
: What I have in mind is:
: 
:   A capture in item context returns the first positional argument if 
:   there is only one (named or positional), otherwise it returns itself 
:   (so it can be used as both an array and a hash).

That's fine, and consistent with the interpolation of captures into list
context when you say my @a = foo().

:  The invocant (if any) of a Capture is now always considered 1st positional.
: 
: Unless you're a method, then it's really an invocant...
: 
: That seems to mean that you actually have two different APIs to talk to
: a capture, which are:
: 
:   * I don't care about invocant, gimme the positional args
:   * I do care about invocant, gimme the positional args

Refactor that the other way.

* Give me the arguments
* Did the first argument have a colon after it instead of comma?

: So, if you don't care about invocant, it is just a regular positional
: argument, but if you do care, it is not a positional argument. It looks
: like the old my $self = shift...

You use the P5 formulation there to make it sound bad, but it isn't.
The invocant is always passed as an argument anyway.  It has to be availble
as self, whether or not it gets bound to a user-defined variable.

: What really got me confused is that I don't see what problem this change
: solves, since it doesn't seem that a signature that expects an invocant
: (i.e.: cares about invocant) will accept a call without an invocant, so
: method foo($b,$c) is export still need to have a transformed signature
: in the sub version of foo.

This is simplifying the invocation semantics.  We don't invoke subs
and methods differently.  Binding doesn't give a rip about invocants.

The : in a signature merely tells the compiler that it doesn't need to
supply its own implicit $: on the front of the actual signature.  When
you ask a method for its signature, it always reports something with
an invocant on the front, ($: $a,$b,$c) if it's implicit.  Binding
sees that merely as ($, $a,$b,$c).  There's no extra shifting going on;
there's no array being mutated.

In implementation, there is no difference between a sub and a method.
The signature of a method will always have its first argument marked
as invocant, but binding doesn't care, so when we export as a sub,
the signature stays with the colon on the front, and the multi
dispatcher just ignores that.  If it decides to call the aliased
method, it just calls it as an ordinary subroutine, and the binding
in the method again just ignores whether there were colons in
either the capture or the signature.  The first argument is
simply bound to whatever the signature asks for.

An interesting corollary is that self is potentially legal in
an ordinary sub; it just means the first argument that was passed,
regardless of how it was bound.

Another corollary is that, in addition to exporting methods as subs,
you can go the other way and import methods from subs.  If you
install a sub as body of a method, it just gets invoked the same way,
and the invocant is bound as the first argument to the function.

So what's the difference between a function and a method then?
Nothing on the implementation end.  The only difference is in the
call end; we have different calling notations that invoke different
dispatchers.  Each of those dispatchers resolves the membership
and ordering of its multiple candidates in its own way, using some
combination of namespace and type filtering, but not the presence or
absence of a ':' in either the Capture or the Signature.

Once the candidate list is resolved down to individual Code entries,
however, the dispatchers are identical in how they dispatch to the
individual functions/methods.  If necessary we can install a call
primitive that requires a singular code object and invokes it as a
function, rather than relying on foo() to do both multiple dispatch
and low-level invocation.  Or maybe we just define .() to mean that,
and make ()/.() inconsistent with other dotless/dotty postfixes.

Larry


Re: new Capture behavior (Was: Re: r25685 - docs/Perl6/Spec)

2009-03-05 Thread Darren Duncan

Larry Wall wrote:
snip

So what's the difference between a function and a method then?
Nothing on the implementation end.  The only difference is in the
call end; we have different calling notations that invoke different
dispatchers.  Each of those dispatchers resolves the membership
and ordering of its multiple candidates in its own way, using some
combination of namespace and type filtering, but not the presence or
absence of a ':' in either the Capture or the Signature.

snip

This all sounds reasonable to me, but I'm wondering how to make it work in 
certain ways that I would like.


Case in point, with my Set::Relation module.  That module is an object-oriented 
derivation of a module design that was originally just functional, having a 
collection data type as its main operand and all of its routines originally just 
being functions.  The object-oriented Set::Relation is somewhat unnatural 
because its functionality is not supposed to consider any particular routine 
argument as special, that is an invocant.  The reason I made it OO was so users 
wouldn't have  to use Package.func syntax and wouldn't have to import the 
routines.  Now, perhaps one solution is to make this non-OO and export its 
routines, but I figure people may want to say $arg1.foo($arg2) or whatever.


Here's a question:

Say I had an N-adic routine where in OO terms the invocant is one of the N 
terms, and which of those is the invocant doesn't matter, and what we really 
want to have is the invocant automatically being a member of the input list.


For example, say we had method natural_join of R (R $topic: Array of R 
$others) but what we really want is method natural_join of R (Array of R 
$topic) so that within the natural_join method we can simply refer to the array 
$topic and the invocant just happens to be one of its elements, as if 
natural_join were just a function with no invocant.


So, is there some way, or is it reasonable for there to be, to declare a method 
in Perl 6 such that say it is declared with say an Array of R or Set of R etc 
parameter and that parameter is marked somehow, maybe with a trait, to say it 
automatically gains the invocant as one of its elements?  This is sort of the 
opposite of unpacking array parameters.  Maybe something like method 
natural_join of R (Array of R $topic is enveloping self), but keep in mind that 
it should work if the parameters in question are named instead.  Then one could 
invoke it with say $r1.natural_join( [$r2, $r3] ) or some such.


I'm thinking maybe there was an answer to this in Synopsis 6 but I didn't see 
it.

Thank you. -- Darren Duncan


Re: new Capture behavior (Was: Re: r25685 - docs/Perl6/Spec)

2009-03-05 Thread Jon Lang
Darren Duncan wrote:
 Here's a question:

 Say I had an N-adic routine where in OO terms the invocant is one of the N
 terms, and which of those is the invocant doesn't matter, and what we really
 want to have is the invocant automatically being a member of the input list.

How about allowing submethods to be declared outside of classes and
roles as well as inside them?  When declared inside a class or role,
it is declared in has scope, and works as described; when declared
elsewhere, it is declared in my scope, and works just like a sub,
except that you're forced to specify an invocant in the signature(s).
You could then use the same sort of tricks that subs can use to
specify alternate signatures, including the one that lets the
positional arguments be filled out in any order.

-- 
Jonathan Dataweaver Lang


Re: new Capture behavior (Was: Re: r25685 - docs/Perl6/Spec)

2009-03-05 Thread Darren Duncan

Darren Duncan wrote:
So, is there some way, or is it reasonable for there to be, to declare a 
method in Perl 6 such that say it is declared with say an Array of R or 
Set of R etc parameter and that parameter is marked somehow, maybe with 
a trait, to say it automatically gains the invocant as one of its 
elements?  This is sort of the opposite of unpacking array parameters.  
Maybe something like method natural_join of R (Array of R $topic is 
enveloping self), but keep in mind that it should work if the 
parameters in question are named instead.  Then one could invoke it with 
say $r1.natural_join( [$r2, $r3] ) or some such.


I should further qualify my question/request, which should also bring it more on 
topic with the thread, is that ideally the same single routine declaration would 
DWIM regardless of whether it is invoked as $obj.meth syntax or whether the 
routine is exported and called with meth($obj) syntax.  Larry said essentially 
that the invocant is just another parameter for the most part.  And what I'm 
asking is a way that the invocant could be combined into a distinct 
Array|Set|etc parameter when an invocant exists, and the parameter is just 
itself otherwise. -- Darren Duncan


Re: new Capture behavior (Was: Re: r25685 - docs/Perl6/Spec)

2009-03-05 Thread Jon Lang
OK; let me get a quick clarification here.  How does:

say Hello, World!;

differ from:

Hello, World!.say;

or:

say $*OUT: Hello, World!;

in terms of dispatching?  And more generally, would there be a
reasonable way to write a single routine (i.e., implementation) that
could be invoked by a programmer's choice of these calling
conventions, without redirects (i.e., code blocks devoted to the sole
task of calling another code block)?

Could you use binding?

my sub say (String *$first, String *...@rest, OStream :$out = $*OUT,
OStream :$err = $*ERR)
{ ... }

role String {
has say:(String $first: String *...@rest, OStream :$out = $*OUT,
OStream :$err = $*ERR)
:= OUTER::say;
}

That (or something like it) might be doable.  But in the spirit of
TIMTOWTDI, I'd like to explore another possibility: what difficulties
would arise from allowing subs to have signatures with invocants,
which in turn allow the sub to be called using method-call syntax
(though possibly not method dispatch semantics)?  In effect, allow
some syntactic sugar that allows properly-sigged subs outside of a
role to masquerade as methods of that role.

-- 
Jonathan Dataweaver Lang