Re: Operator sub names are not special

2005-09-03 Thread Yuval Kogman
On Thu, Sep 01, 2005 at 17:12:51 +, Luke Palmer wrote:
> On 9/1/05, Yuval Kogman <[EMAIL PROTECTED]> wrote:
> > On Wed, Aug 31, 2005 at 13:43:57 -0600, Luke Palmer wrote:
> > > Uh yeah, I think that's what I was saying.  To clarify:
> > >
> > > sub foo (&prefix:<+>) { 1 == 2 }# 1 and 2 in numeric context
> > > foo(&say);   # nothing printed
> > >
> > > But:
> > >
> > > sub foo (&prefix:<+>) { +1 == +2 }
> > > foo(&say);# "1" and "2" printed
> > >
> > > Luke
> > 
> > Furthermore, even if:
> > 
> > sub &infix:<==> ($x, $y) { +$x == +$y }
> > sub foo (&prefix:<+>) { 1 == 2 }
> > 
> > foo(&say); # nothing printed
> > 
> > but if
> > 
> > sub foo (&*prefix:<+>) { 1 == 2 }
> > 
> > then what?
> 
> Um, you can't do that.  You can't lexically bind a global; that's why
> it's global. You could do:
> 
> sub foo (&plus) { temp &*prefix:<+> = +  1 == 2 }
> 
> And then something would be printed... maybe, depending on the
> implementation of == (with your implementation above, it would).

There are some possible problems with going this far...

From an optimizing linker perspective the way to deal with this
relies very heavily on inferrencing possible dynamic scopes...

As I see it the instance of '==' compiled into that foo should have
it's '+' instance resolved, and inferred into the same symbol as the
temp container that 'foo' is creating, so that in effect it's
prebound to the value that isn't there yet.

Furthermore, value inferrencing can let us optimize and hard code
things like

foo(&prefix<+>); # the original

to mean exactly the same thing as

sub foo () { 1 == 2 }

which can then simply reduce the whole call to 'foo' into false.

But...

The things that make this hard:

* what is the definition of &infix:<==>?
* what is the definition of &prefix:<+>?
* where does the line between perl 6 and "builtin" go?
* for the sake of completeness is all of perl 6 defined in perl 6,
* except when inferrence makes it safe to assume that something
can be done with a runtime primitive? This is usually the case.
* what happens if 'eval "temp $opnaame = sub { 'moose' }"'? I
think in this case inferrencing based assumptions are unwinded
and redone.

These behaviors are more than just optimizations, but define the
behavior of the language WRT to runtime modification of the
definition of everything.

As I see it the correct solution is that perl 6 is known to infer
everything and anything as much as possible for reasons of
performance.

If the user annotated types, used traits like 'is read only', or
asked the runtime to close classes, make the metamodel read only, or
disable eval then inferrence can take advantage of this. In any
case, if inferrence can detect a *guaranteed* error, this should be
a compile time error. If the inference engine can detect a possible
error, it should be a user option to make this emit a warning, an
error, or nothing. This choice should be global via command line
switches, as well as lexical via pragmas, with command line switches
overriding everything for the whole program, or just a certain
package or file.

From then, code inferred to be "staticish" can be compiled to use
"native" functions, as provided by the runtime.

At least some of the code must comform to this, or the runtime
cannot execute the PIL because there is no point to get things going
- the definition is circular.

The inferrence is optimistic in the sense that it assumes that
things will not be mucked up at runtime.

Bindings of operators and subs to different values should be an
inferrable thing.

However, runtime loading of unknown code via eval or require (which
are really the same thing) or runtime imports cause the inferrencing
engine to unwind to the last consistent point, and resume from
there.

If errors are found at this stage they are reported via the same
policy as the compile time options - as early as possible, as a
warning, error, or nothing at all.

An implementation strategy for making this work is that all the
operators, functions and whatnot that a bit of code is looking up
and calling become implicit parameters to this bit of code.

From there the call chains are traced from the root of the program
to the lowest level, and implicit parameters are optimized away
where they can be.

Where they cannot, the code is just left as is, with the operator in
question passed in from the calling code, with any side effects like
temporary binding having their effect on the parameter directly.

Symbols that are lexically orthogonal to the call chain, like this:

my &prefix:<+>;
sub bar (&foo) { &prefix:<+> := &foo };
sub moose { 1 == 2 }

don't matter, since the overridden &prefix:<+> is outside of the
scope where == was defined.

Symbols that span multiple call chains like this:

our &*prefix:<+>;
sub bar (&foo) { &prefix:<+> := &foo };

Re: Operator sub names are not special

2005-09-03 Thread Yuval Kogman
On Sat, Sep 03, 2005 at 11:45:33 +0300, Yuval Kogman wrote a lot.

I'd like to summarize:

* if operators are not special than they are defined in perl 6
(maybe)

* if operators are defined in terms of other operators, then
overriding an operator may interfere with the definition of
another operator.

* if all operators are defined in terms of each other, perl 6 is
circular. At some point the loop must be broken, and
functionality has to be delegated to the runtime.

* one way to do this is to infer where operators are not
overridden

* each "builtin" code may have an alternative version in the
native runtime's language

* if a bit of code is kown, by inferrence, to be completely
unaltered, the native could is used instead.

* essentially the role of inferrencing here is to determine
where, and to what extent may the circularity be broken.

* functions which must have a runtime counterpart (like IO) are
defined as stubs. They can be overridden for emulation purposes,
or die as "not yet implemented" when the runtime can't provide a
native version.

This is possibly slow to compile, and possibly dangerous to allow.

I think that the best solution is to allow overriding builtins only
in the current lexical scope, unless this circularity is explicitly
asked for.

-- 
 ()  Yuval Kogman <[EMAIL PROTECTED]> 0xEBD27418  perl hacker &
 /\  kung foo master: /me whallops greyface with a fnord: neeyah!!!



pgpNHHeJGtg0P.pgp
Description: PGP signature


perl6-language@perl.org

2005-09-03 Thread Yuval Kogman
On Fri, Sep 02, 2005 at 17:56:39 +0200, Ingo Blechschmidt wrote:
> Hi,
> 
> multi foo ($a) {...}
> multi foo ($a, $b) {...}
> 
> say &foo.arity;
> # die? warn and return 0? warn and return undef? return 1|2?

A multi sub is a collection of variants, so it doesn't have arity,
each variant has arity.

I'd say it 'fail's.

To get the arity you must tell it which variant yyou mean, either by
providing enough of the prototype, eg

&foo(Any).arity   vs   foo(Any, Any).arity

-- 
 ()  Yuval Kogman <[EMAIL PROTECTED]> 0xEBD27418  perl hacker &
 /\  kung foo master: : neeyah!



pgpJITcejqLNO.pgp
Description: PGP signature


perl6-language@perl.org

2005-09-03 Thread Stuart Cook
On 03/09/05, Yuval Kogman <[EMAIL PROTECTED]> wrote:
> A multi sub is a collection of variants, so it doesn't have arity,
> each variant has arity.
> 
> I'd say it 'fail's.

But if the reason you're calling `&foo.arity` is to answer the
question "Can I call this sub with three arguments?" then that kind of
behaviour isn't going to help very much.

Which leads me to believe that instead of writing

  if &foo.arity == 3 { ... }

you should probably be writing something like this:

  if &foo.accepts(3) { ... }

Implying that you could also write:

  if &foo.accepts(:pos(1..3) :named :code) { ... }

None of this really answers the question "What should &foo.arity
return?", but my point is that most of the time you probably shouldn't
be calling it yourself anyway.  Better to tell the sub what you
actually intend to do, and let it make up its own mind (via its
Signature(s)).

> To get the arity you must tell it which variant yyou mean, either by
> providing enough of the prototype, eg
> 
> &foo(Any).arity   vs   foo(Any, Any).arity

Unfortunately, that particular syntax is going to end up *calling*
&foo (unless of course you make .arity a special form).


Stuart


perl6-language@perl.org

2005-09-03 Thread Yuval Kogman
On Sun, Sep 04, 2005 at 00:27:39 +1000, Stuart Cook wrote:
>   if &foo.accepts(:pos(1..3) :named :code) { ... }

I prefer this api... Arity is ambiguous will multiply variadic args.
We have any number of positionals, nameds, and zero, one or two
slurpies.

> None of this really answers the question "What should &foo.arity
> return?", but my point is that most of the time you probably shouldn't
> be calling it yourself anyway.  Better to tell the sub what you
> actually intend to do, and let it make up its own mind (via its
> Signature(s)).

Yep

> > To get the arity you must tell it which variant yyou mean, either by
> > providing enough of the prototype, eg
> > 
> > &foo(Any).arity   vs   foo(Any, Any).arity
> 
> Unfortunately, that particular syntax is going to end up *calling*
> &foo (unless of course you make .arity a special form).

There was a syntax to disambiguate multis to .assuming... I meant
that.

-- 
 ()  Yuval Kogman <[EMAIL PROTECTED]> 0xEBD27418  perl hacker &
 /\  kung foo master: /me sushi-spin-kicks : neeyah



pgpxBzmLCxxY1.pgp
Description: PGP signature


perl6-language@perl.org

2005-09-03 Thread Luke Palmer
On 9/3/05, Stuart Cook <[EMAIL PROTECTED]> wrote:
> On 03/09/05, Yuval Kogman <[EMAIL PROTECTED]> wrote:
> > A multi sub is a collection of variants, so it doesn't have arity,
> > each variant has arity.
> >
> > I'd say it 'fail's.
> 
> But if the reason you're calling `&foo.arity` is to answer the
> question "Can I call this sub with three arguments?" then that kind of
> behaviour isn't going to help very much.
> 
> Which leads me to believe that instead of writing
> 
>   if &foo.arity == 3 { ... }
> 
> you should probably be writing something like this:
> 
>   if &foo.accepts(3) { ... }

That's a nice reformulation.  However, .arity is still important.  But
maybe .arity doesn't exist, and all you get are .accepts, .min_arity,
and .max_arity.  After all, "for" has to know how many things to take
off of the list, and doing:

my @pass;
given ({ &foo.accepts($_) }) {
when 1 { @pass = @args.shift(0,1) }
when 2 { @pass = @args.splice(0,2) }
...
}

Is unacceptable.  But *the* arity of a function in Perl is rather ill-defined.

(As a matter of fact, I use the existence numeric casing to determine
when a language is not general enough in a particular area;  C++ had
to do numeric casing to implement typelists, Haskell has to do numeric
casing to implement variadic functions and lifts, etc.   So far, I've
never had to do it in Perl. :-)

Luke