Re: Operator sub names are not special
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
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
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
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
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
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