Re: Sane (less insane) pair semantics
Hi, TSa wrote: Ingo Blechschmidt wrote: Exactly. I'd like to add that, under the proposal, you always know what things are passed how, only by looking for a *. foo $var;# always positionally, even if $var isa Pair foo *$pair; # always named But where is the name? Is it 'pair'? Like in foo :pair($pair); No. or dynamically through foo $pair.key = $pair.value; Yep. assuming that precedence of = is tighter than foo's. I think it is. As I lengthyly ranted elsewhere in this thread the splat should just defer the structural callability check until runtime. Well, and since everybody seems to be happy with .$pair denoting a call through a hardref stored in $pair, I don't understand why :$pair is not (yet) denoting a hard pairref. Both forms beeing interpreted in the context of the term to Um, sorry, I don't understand... The only syntax I know of where a $ follows a . is calling method references: my $meth = method (Foo $self: ...) {...}; $foo.$meth(...); (But this syntax doesn't have, obviously, anything to do with magical/non-magical pairs.) If full uncertainty isn't your thing, you might instruct the type system to make sure that $pair at least doesn't fail you on pairhood my Pair $pair; Yep. foo $pair; # syntactically an item, thus a positional call foo *$pair; # guarranteed pair after splatting foo [EMAIL PROTECTED]; # always positionally This makes perfect sense to me if you mean that the positionals that foo requests are satisfied in the order provided by @array without exceptions for pairs, not to mention subtypes of pairs or things that do the Pair role etc. Yep, it's very important that Pairs are not exceptions. foo *%hash; # always named (hash keys taken as parameter names) So that shall fail at compile time if foo has *anonymous* positionals? Assuming that anonymous positionals exist, yes, I think so. Previously, you wasn't able to know whether you passed something positionally or by name: sub bar ($x) { grtz $x } bar 42; # 42 passed to grtz positionally bar a = 42; # either the pair (a = 42) passed to grtz # positionally or the number 42 passed by name Under the new proposal, grtz $x always passes $x positionally. You don't need grtz's signature, nor do you need to know $x's type (is $x a Pair?). Yep. But you could attempt to dispatch .key on $x in grtz: sub grtz ($item) { say $x.key; } and get a printout of 'Undef of Key' or so and 'a' respectively. HiHi, or a 'method not understood' exception if .key is not applicable to 42 ;) Yep, of course. Pairs are, when not splatted with *, normal instances of normal classes. (And when pairs are splatted, they are no longer pairs, but syntactical constructs. (This might of course be implemented using some class in the compiler, but this is an implementation detail.)) Stuart Cook wrote: And look, if you really wanted to, you could define your own splat-style operator that works exactly as you describe. But I don't think it should be the default. I think that is difficult *without* parser support because a purely prefix thingy doesn't get the coderef the flattened array goes to. Right, also prefix:* can be faked as a normal subroutine (the PIL to JavaScript compiler does this currently [1]), it has to be some kind of grammatical rule or perhaps a macro if we want it to be implemented properly. Right. Under the proposal, you can -- *if you want to* -- use pairs stuffed in arrays as named arguments: foo *hash(@array_of_pairs); # @array_of_pairs's pairs used as named args This hash function there is hardly the same as the one from S06, that takes every other pair from @array_of_pairs, converts *the pair* to a key---which might preserve the key actually---and combines it with the next entry from the array as value? Hm. I thought the hash() sub would be a bit more DWIMmy, so it can be used for desugaring: my %hash = (a = 1, b,2, c); # desugared to my %hash = hash(a = 1, b,2, c); # which means my %hash = (a = 1, b = 2, c = undef); # thus: sub hash ([EMAIL PROTECTED]) returns Hash { my %hash; while shift @things - $thing { given $thing { when Pair { %hash{$thing.key} = $thing.value } default { my $value = shift @things; %hash{$thing} = $value; } } } %hash; } But, looking at S06, the reference implementation of S06 isn't that DWIMmy. Dunno whether this is simply a oversight in S06 or whether it has been purposefully left out. @AoP = (a = 'a', b = 'b', c = 'c', d = 'd'); %hash = hash @AoP; # = (AoP[0] = AoP[1], AoP[2] = AoP[3]); # = ( a = 'b' , c = 'd' ); +%hash == 2; # true? With my hash, +%hash would be 4. But if we made
Re: Sane (less insane) pair semantics
Ingo Blechschmidt wrote: Juerd wrote: Ingo Blechschmidt skribis 2005-10-10 20:08 (+0200): Named arguments can -- under the proposal -- only ever exist in calls. Which leaves us with no basic datastructure that can hold both positional and named arguments. This is a problem because in a call, they can be combined. Very true. This is why we need Luke's Tuple proposal [1]. Luke's Tuple proposal, aka Luke's Grand Unified Object Model, is way not what we need for this. As far as I can see, LGUOM is an expression of Haskell envy of brobdingnagian proportion. A rule that says splatting a list coerces all pairs into named args works just fine. The corresponding rule, accessing the parameters to your sub as a list (not using *%args) coerces all named args to pairs. Presto! Reversible, etc. An alternative might be PHP-style arrays. But nobody wants that. Basically: my $tuple = (a = 1, (b = 2)):{ ...block... }; # $tuple.isa(Tuple) # Tuples are ordinary objects -- they can be stored # in scalars, arrays, etc. # But splatting tuples unfolds their magic: foo(*$tuple); # same as foo(a = 1, (b = 2)):{ ...block...}; # named arg a, positional pair (b = 2), # adverbial block { ...block... } # (Yep, under the current proposal, tuple construction conflicts # with list/array construction. FWIW, I'd be fine with # using Tuple.new(...) as the tuple constructor.) --Ingo [1] http://svn.openfoundry.org/pugs/docs/notes/theory.pod Tuple construction conflicts with a lot of things. Given the amount of new (to me, anyways) syntax proposed in the rest of the document, I'm surprised that LQe didn't unify lists and tuples (or push list construction elsewhere). =Austin
Re: Sane (less insane) pair semantics
On 11/10/05, Austin Hastings [EMAIL PROTECTED] wrote: Luke's Tuple proposal, aka Luke's Grand Unified Object Model, is way not what we need for this. As far as I can see, LGUOM is an expression of Haskell envy of brobdingnagian proportion. The reason I refrained from linking to theory.pod was that I didn't want people getting distracted by a document that's 90% irrelevant to what we're discussing here. That other 10%, though, is Tuples--and they're exactly what's needed for representing an argument-'list' in its entirety. That is, after all, a large part of what they were designed for. A rule that says splatting a list coerces all pairs into named args works just fine. The corresponding rule, accessing the parameters to your sub as a list (not using *%args) coerces all named args to pairs. Presto! Reversible, etc. 1) What happens if that list is lazy? You'd have to force the entire thing, just to check if there were any pairs hiding in it. What if it's an infinite list? What if you can't know whether it's infinite or not? 2) What if the list contains pairs, but you want to pass them as positionals? What if it might contain pairs, but you're not sure? What if you introduce a new named parameter (or change a parameter name), and what you thought was a positional pair now becomes a named arg? Your suggestion would involve re-introducing some of the 'magic' that real experience suggests we should be trying desperately to get away from. And look, if you really wanted to, you could define your own splat-style operator that works exactly as you describe. But I don't think it should be the default. An alternative might be PHP-style arrays. But nobody wants that. The key difference is that while a PHP-style array can't decide whether it's an array or a hash, a Tuple *knows* that it has to be both (and more), in order to accurately represent the full power of Perl 6's argument system. (Also, Tuples might end up being immutable, but don't quote me on that.) Tuple construction conflicts with a lot of things. Given the amount of new (to me, anyways) syntax proposed in the rest of the document, I'm surprised that LQe didn't unify lists and tuples (or push list construction elsewhere). He very nearly does, actually (albeit with a handwave). But Tuple syntax (and the rest of theory.pod) is largely irrelevant here. (I personally think Ingo's `Tuple.new` might be sufficient.) Stuart
Re: Sane (less insane) pair semantics
Hi, Stuart Cook wrote: On 11/10/05, Austin Hastings [EMAIL PROTECTED] wrote: A rule that says splatting a list coerces all pairs into named args works just fine. The corresponding rule, accessing the parameters to your sub as a list (not using *%args) coerces all named args to pairs. Presto! Reversible, etc. 2) What if the list contains pairs, but you want to pass them as positionals? What if it might contain pairs, but you're not sure? What if you introduce a new named parameter (or change a parameter name), and what you thought was a positional pair now becomes a named arg? Your suggestion would involve re-introducing some of the 'magic' that real experience suggests we should be trying desperately to get away from. Exactly. I'd like to add that, under the proposal, you always know what things are passed how, only by looking for a *. foo $var;# always positionally, even if $var isa Pair foo *$pair; # always named foo [EMAIL PROTECTED]; # always positionally foo *%hash; # always named (hash keys taken as parameter names) Previously, you wasn't able to know whether you passed something positionally or by name: sub bar ($x) { grtz $x } bar 42; # 42 passed to grtz positionally bar a = 42; # either the pair (a = 42) passed to grtz # positionally or the number 42 passed by name Under the new proposal, grtz $x always passes $x positionally. You don't need grtz's signature, nor do you need to know $x's type (is $x a Pair?). Compare this with the old semantics: grtz $x; # $x is not a Pair? == $x passed positionally # else == # grtz expects a Pair as its first positional parameter? # == $x passed positionally # else == # grtz's signature lists a parameter named $x.key? #== $x.value passed by name # else # == $x passed positionally And look, if you really wanted to, you could define your own splat-style operator that works exactly as you describe. But I don't think it should be the default. Right. Under the proposal, you can -- *if you want to* -- use pairs stuffed in arrays as named arguments: foo *hash(@array_of_pairs); # @array_of_pairs's pairs used as named args foo [EMAIL PROTECTED]; # @array_of_pairs's pairs used positionally But if we made [EMAIL PROTECTED] mean that... * [EMAIL PROTECTED]'s pairs are always taken as named arguments, there wouldn't be a simple way to pass pairs positionally. * [EMAIL PROTECTED]'s pairs are always taken as pairs, there wouldn't be a simple way to use the pairs as named arguments. * [EMAIL PROTECTED]'s pairs are taken as pairs or named arguments, depending on the called subroutine (does it accept named params? Do some parameters specifically want a Pair? etc.), we'd introduce non-local non-determinism to a quite important part of the language. --Ingo
Re: Sane (less insane) pair semantics
HaloO, Larry Wall wrote: It still has to figure out how to reconcile the named arguments with the positional parameters, of course, unless someone has made sufficient representation to the compiler that all calls to a particular short name have particular named parameters that are guaranteed to be in the same position everywhere, in which case the compiler is allowed to simply translate them to positionals on the call end. Does that mean that a named binding excludes a positional one and vice versa? I would consider that too much of a burden that tries to solve the unsolvable problem of meeting unstated assumptions ;) The thing I try to get at is the unification of classes and their instances on the one hand and subs and their invocations on the other. Let's take the four sigiled vars $_, @_, %_ and _ and assume that they always contain the current state of affairs. Let's say they are the registers of the virtual machine. Everything else is the memory that refers to itself in a what not messy way. Memory locations not rooted in the four registers are garbage collected eventually. Making a goto kind of call just means putting a new address into _. At the statement level there's of course an automatic goto to the next instruction. A sub kind of call with parameters means messing with $_, @_ and %_ prior to making the jump. The return values are passed out by messing with $_, @_ and %_ in the sub. With CPS there actually is no returning. It's just the next jump. Well, the handling of the four magicals is more complicated than that. There'll be lexical binding, temping etc. And how about rules and grammars? Is there a $/, @/, %/ and / quadriga? Method dispatch means basing the selection of the address to be put into _ on the content of $_, @_ and %_. Not considering dispatch and the topic for now I come back to the problem of this thread: the constructor call for an invocation of a sub stored in _. The task of the compiler is to output code that doesn't violate structural type constraints extracted from the source while preserving unspecificity as much as possible. The first set of constraints comes from the signature of _ and the second from the *syntactical* structure of the arguments. The left to right order gives the positional structure while the adverbial pairs and the autoquoting version of fat arrow give the named or keyed structure. Splatted terms are actually lazily evaluated code fragments that insert information into the magicals prior to this matching. Double splat does so eagerly. The prefix fundamental type enforcers ?, + and ~ also produce structural items as a side effect. So do most circumfix operators like [], '' or . The parens are for grouping only, they are transparent to structural typing! The loose precedence separators , and ; never take keyed args. I think it makes sense to exclude them from overloading. They might be a context sensitive parser concept, actually. Well, and at some point prior to bindind the args to the params the trait blocks like ENTER and PRE are called. And I wonder how labels inside the sub's block can be used to enter it through different paths: sub through { first: say first; return; second: say second; return; third: say third; return; } through :third; # prints third? through;# prints first? Obviously neither the compiler nor the virtual machine will have difficulties with the above procedure. Also the programmers can shy away from beeing specific on the caller side or the callee side by splatting. Note that what I call structural type match is only an arity and key match. Type constraints are checked only if the structure fits! From this thread I gather that the case of a pair hidden in an array is the most debated one: my @array = ( 1, two = 2, 3 ); I hope, we all agree that [EMAIL PROTECTED] == 3. But is @arraytwo == 2? If yes, what shall happen with foo( [EMAIL PROTECTED] ); when foo requires exactly three params? sub foo ($x, $y, $z) {...} And how shall the arity 2..3 be handled? sub foo ($x, $y, ?$z) # structure is foo:($,$,?$) without param names { $x eqv 1; # yes $y eqv (two = 2) $z eqv 3; # this? $y eqv 3 $z eqv undef; # or this? } How about a named optional with my preferred keyed item twigil :$ where actually the key and variable name might differ as in :two$z? Perhaps that might be spelled :two($z) and allow the fat arrow syntax two = $z as well. sub foo ($x, $y, :$two) # structure is foo:($,$,:two) without param names # S06: ($x, $y, +$two) # ($x, $y, two = $z) { $x eqv 1; # yes $y eqv (two = 2) $two eqv 2; # this? $y eqv 3 $two eqv 2; # or this? } My 'Seven Sigils of Perl6' idea also nicely delivers an invocant markup in methods: method foo (.$self, $x, $y, two = $z) {...} Without the multi prefix method blahh ( .$first, .$second ) {...} # perhaps without comma? # S12: ( $first:
Re: Sane (less insane) pair semantics
(It seems you're confused about my position because I was sloppy presenting it. My apologies; hopefully this will clear a few things up.) On 10/10/05, Uri Guttman [EMAIL PROTECTED] wrote: Stuart Cook [EMAIL PROTECTED] writes: The think I don't like about `foo( *$bar )` is that it's not clear whether you're splatting a pair, or a hash, or an array, or a complete argument-list object. This is probably fine for quick-'n'-dirty code, but I'd like to encourage a more explicit style: but perl will know the type of the value in $bar and expand/splat it accordingly. I realise that perl can cope with it--my concern was more for the person reading the code. Just like perl can cope without explicit type annotations, but some of us will choose to write them anyway. The idea is that when you (the human) see *%, you _know_ it's a named splat, and when you see *@ you _know_ it's a positional splat. With *$, it could be either, depending on what's in the variable. I agree that sensible variable names and type annotations should make this a minor issue, it's just that I'd sometimes like to add an extra sigil for additional clarity. And to clarify, as far as I'm aware, nothing I suggested here is new syntax--just ways of combining existing explicit-deref syntax with (*) to produce more self-descriptive code. my $pair = a='b'; foo( *%$pair ); # view the pair as a 1-elem hash, and splat that the % there isn't a hash. perl can see the single pair and deal with that. the way to make this more readable is to use better variable names. $pair here is fine and *$pair would mean to splat it into the named arguments. My understanding (possibly incorrect) was that the % 'derefs' the pair into a one-element hash, in much the same way that %$href derefs a hashref into a hash. From there, *%$pair is exactly the same as: # there's probabaly a shorter way of writing this first line, but I'm shooting for clarity :) my %hash = ($pair.key = $pair.value); foo( *%hash ); sub returns_a_hash { ... } foo( *%{returns_a_hash} ); # call the sub, view the result as a hash, and splat that isn't that what hash() is for? what is returns_a_hash really returning, a list or a hash ref because you can't return a hash (or can you this week? :). My sloppy language again--the idea was that returns_a_hash produces a hashref, which is dereffed by %{}, and finally splatted. sub returns_an_array { ... } foo( [EMAIL PROTECTED] ); # call the sub, view the result as a hash, and splat that where is the hash? wouldn't you want %{} in your system? and %{} derefs a hash and doesn't convert a list to a hash. that is what hash() does. Sorry, that was meant to say view the result as an array. (I swear I proofread that post!) In summary: 1) I believe all my suggestions use currently-existing syntax (modulo errors on my part) 2) Yes, the extra sigils/derefs are redundant, but sometimes we want to be explicit 3) I don't particularly object to `foo( *$pair )` also working; this is meant as an extra option Stuart
Re: Sane (less insane) pair semantics
On 10/10/05, Austin Hastings [EMAIL PROTECTED] wrote: So to pass a hash that has one element requires using the chash/c keyword? I don't see a hash in your example, so I'm not sure what you're referring to here. Specifically, if I say: @args = (a = 1, get_overrides()); Then can I say foo([EMAIL PROTECTED]); Not if you want that a=1 to be a named argument. Under the proposal, the only ways to pass a named argument are: 1) By using a literal pair in the syntactic top-level of the arg list 2) By splatting a pair, hash, or arg-list-object Or will I, in the case of no overrides, get a positional pair instead of named a =1 ? The overrides have nothing to do with it. That a=1 will *always* be a positional, because by the time it reaches the argument list, it's a value (not a syntactic form). The only way to use a pair-value as a named argument is to splat it directly, or splat a hash or arg-list-object containing it. Splatting an array *never* introduces named arguments, only positionals. Stuart
Re: Sane (less insane) pair semantics
Stuart Cook skribis 2005-10-10 22:58 (+1100): @args = (a = 1, get_overrides()); foo([EMAIL PROTECTED]); Not if you want that a=1 to be a named argument. Under the proposal, the only ways to pass a named argument are: 1) By using a literal pair in the syntactic top-level of the arg list 2) By splatting a pair, hash, or arg-list-object I find this counterintuitive, and also want arrays to be included in option 2. It is consistent with the idea that * expands its RHS and evaluate it as if it was written literally. I'd like @_ or @?ARGS or something like that to be a *-able array that will be guaranteed to be compatible with the current sub's signature. Juerd -- http://convolution.nl/maak_juerd_blij.html http://convolution.nl/make_juerd_happy.html http://convolution.nl/gajigu_juerd_n.html
Re: Sane (less insane) pair semantics
Miroslav Silovic skribis 2005-10-10 15:04 (+0200): Under the proposal, the only ways to pass a named argument are: 1) By using a literal pair in the syntactic top-level of the arg list 2) By splatting a pair, hash, or arg-list-object I find this counterintuitive, and also want arrays to be included in How would you splat an array of pairs if you want to preserve the pairs? By adding parens, because by this proposal (if I read it correctly), only pairs on the topmost level of arguments (not in any parens) are parsed as named arguments. foo(([EMAIL PROTECTED])); foo ([EMAIL PROTECTED]); This doesn't allow for combining named and positional pairs. I do not think that is necessary at all, for arrays. I think that combining the two on the same level is a recipe for disaster anyway, and should perhaps even emit a warning. Juerd -- http://convolution.nl/maak_juerd_blij.html http://convolution.nl/make_juerd_happy.html http://convolution.nl/gajigu_juerd_n.html
Re: Sane (less insane) pair semantics
Juerd skribis 2005-10-10 15:20 (+0200): only pairs on the topmost level of arguments (not in any parens) are s/not in any parens/not in any grouping parens/, to exclude .() Juerd -- http://convolution.nl/maak_juerd_blij.html http://convolution.nl/make_juerd_happy.html http://convolution.nl/gajigu_juerd_n.html
Re: Sane (less insane) pair semantics
[EMAIL PROTECTED] wrote: Stuart Cook skribis 2005-10-10 22:58 (+1100): @args = (a = 1, get_overrides()); foo([EMAIL PROTECTED]); Not if you want that a=1 to be a named argument. Under the proposal, the only ways to pass a named argument are: 1) By using a literal pair in the syntactic top-level of the arg list 2) By splatting a pair, hash, or arg-list-object I find this counterintuitive, and also want arrays to be included in option 2. How would you splat an array of pairs if you want to preserve the pairs? It is consistent with the idea that * expands its RHS and evaluate it as if it was written literally. I'd like @_ or @?ARGS or something like that to be a *-able array that will be guaranteed to be compatible with the current sub's signature. This sounds nice, though. Maybe it suggests that the 'named splat' should be something other than *? Miro
Re: Sane (less insane) pair semantics
Interestingly, I had already written almost exactly the same thing into my version of S06, but I've been holding off on checking it in while I mull over Luke's theory theory. Regardless of the actual syntax we end up with, I think everyone can assume that the compiler will be able to determine at compile time which pairs are intended to be named arguments and which ones positional parameters, and pass them as separate entities through whatever structure supplies all the arguments to a call so that the caller doesn't have to worry about making the distinction based on type. It still has to figure out how to reconcile the named arguments with the positional parameters, of course, unless someone has made sufficient representation to the compiler that all calls to a particular short name have particular named parameters that are guaranteed to be in the same position everywhere, in which case the compiler is allowed to simply translate them to positionals on the call end. Perhaps it would be useful to allow a stubbed multi to declare the required names of positional parameters in some scope or other. This might be generalized to a translation service for calls outside the scope, where the current scope could even be the current language as a whole. That might alleviate cultural differences if one language always uses $left and $right where another uses x and y, for instance. Of course, I haven't eaten breakfast yet, so maybe that's impossible. Larry
Re: Sane (less insane) pair semantics
Stuart Cook wrote: On 10/10/05, Austin Hastings [EMAIL PROTECTED] wrote: The overrides have nothing to do with it. That a=1 will *always* be a positional, because by the time it reaches the argument list, it's a value (not a syntactic form). The only way to use a pair-value as a named argument is to splat it directly, or splat a hash or arg-list-object containing it. Splatting an array *never* introduces named arguments, only positionals. That seems like a huge error. Arrays are the only thing (that I know of) that can store the positional part of an arglist as well as storing the pairs. If there's not some mechanism for getting the entire arglist, and if there's not some simple inversion of that simple mechanism for passing the args along to some other victim, then ... well ... I don't know. But it's bad! So since you keep saying arg-list-object as though it was something not an array, I'll bite: What's an arg-list-object, and how is it different from an array? =Austin
Re: Sane (less insane) pair semantics
Miroslav Silovic wrote: [EMAIL PROTECTED] wrote: * expands its RHS and evaluate it as if it was written literally. I'd like @_ or @?ARGS or something like that to be a *-able array that will be guaranteed to be compatible with the current sub's signature. This sounds nice, though. Maybe it suggests that the 'named splat' should be something other than *? How about perl should DWIM? In this case, I'm with Juerd: splat should pretend that my array is a series of args. So if I say: foo [EMAIL PROTECTED]; or if I say: foo([EMAIL PROTECTED]); I still mean the same thing: shuck the array and get those args out here, even the pairs. It's worth pointing out that perl does know the list of declared named args, though that may not be enough. If the pair.key matches an expected arg, then splat should collapse it for sure. If it doesn't match...I dunno. Is there a list() operator for converting hashes into lists of pairs? That might make parsing foo([EMAIL PROTECTED], *%_) more palatable, but I'd still prefer to get pairs in @_ if I don't explicitly ask for *%_... =Austin
Re: Sane (less insane) pair semantics
Hi, Austin Hastings wrote: How about perl should DWIM? In this case, I'm with Juerd: splat should pretend that my array is a series of args. Yep. So if I say: foo [EMAIL PROTECTED]; or if I say: foo([EMAIL PROTECTED]); I still mean the same thing: shuck the array and get those args out here, even the pairs. Right, you name it: you get *pairs* out of the array, not named parameters. Under the proposal, a Pair object doesn't have any special magic -- it's simply class Pair { has $.key; has $.value is rw } Thus: my @array = (42, hi, (a = 23)); foo [EMAIL PROTECTED]; # same as foo 42, hi, (a = 23); # three positional params (Int, Str, Pair) It's worth pointing out that perl does know the list of declared named args, though that may not be enough. If the pair.key matches an expected arg, then splat should collapse it for sure. If it doesn't match...I dunno. But that's exactly the problem. You shouldn't have to worry about any special magic when dealing with [EMAIL PROTECTED] Consider: sub foo ($a, $b, $c, ?$d) {...} my @array = (1, 2, (key = value)); foo [EMAIL PROTECTED]; # fine, no problem, $c will receive (key = value) my @array = (1, 2, (d = value)); foo [EMAIL PROTECTED]; # oops! $a = 1, $d = value # Required argument 'c' not given! Is there a list() operator for converting hashes into lists of pairs? my @array_of_pairs = %hash; # short for my @array_of_pairs = list %hash; --Ingo
Re: Sane (less insane) pair semantics
Austin Hastings wrote: How about perl should DWIM? In this case, I'm with Juerd: splat should pretend that my array is a series of args. So if I say: foo [EMAIL PROTECTED]; or if I say: foo([EMAIL PROTECTED]); I still mean the same thing: shuck the array and get those args out here, even the pairs. The trouble is, an array doesn't contain enough information: Compare: foo( (a=1), b=2 ); With @args = ( (a=1), b=2 ); foo( [EMAIL PROTECTED] ); If we have an arglist ctor, then we could have @args = arglist( (a=1), b=2 ); foo( [EMAIL PROTECTED]); say @args.perl ## ( ## (a=1) but is_positional, ## (b=2) but is_named, ## ) but without such a constructor, it would be difficult to DWIM correctly. Of course, for the case of $?ARGS, constructing the array with appropriate properties wouldn't be a problem.
Re: Sane (less insane) pair semantics
On 2005-10-10 13:36, Ingo Blechschmidt [EMAIL PROTECTED] wrote: Under the proposal, a Pair object doesn't have any special magic Right. So under this proposal, the key = value syntax is overloaded: in some contexts it creates a Pair object, and in others it assigns a value to a named parameter, and parentheses are the disambiguating mechanism to get the former behavior in the latter context. Meanwhile, a reference to a Pair object occurring in an argument list does not interact with the named-parameter mechanism at all. At least, not by default. It would be desirable to have a way to flatten a hash/list of Pairs/whatever in such a way that it *does* map key names to named parameters.
Re: Sane (less insane) pair semantics
Ingo Blechschmidt skribis 2005-10-10 19:36 (+0200): my @array = (42, hi, (a = 23)); It is worth pointing out that the inner parens here are merely for grouping: this information is lost afterwards, hence this: foo [EMAIL PROTECTED]; # same as shouldn't be foo 42, hi, (a = 23); # three positional params (Int, Str, Pair) but instead foo 42, hi, a = 23 # two positional args, one named. OR pairs need to remember whether they were originally in parens. This is very doable, but whether we want or need it is very arguable. (Very little sidenote: parameters are expected, arguments are passed. In the signature, you have parameters, in the call, you have arguments. However, in the case of a named argument, it does make some sense to call the name parameter and the value argument, resulting in having both in the call.) Juerd -- http://convolution.nl/maak_juerd_blij.html http://convolution.nl/make_juerd_happy.html http://convolution.nl/gajigu_juerd_n.html
Re: Sane (less insane) pair semantics
Hi, Mark Reed wrote: On 2005-10-10 13:36, Ingo Blechschmidt [EMAIL PROTECTED] wrote: Under the proposal, a Pair object doesn't have any special magic Right. So under this proposal, the key = value syntax is overloaded: in some contexts it creates a Pair object, and in others it assigns a value to a named parameter, and parentheses are the disambiguating mechanism to get the former behavior in the latter context. Meanwhile, a reference to a Pair object occurring in an argument list does not interact with the named-parameter mechanism at all. Exactly. At least, not by default. It would be desirable to have a way to flatten a hash/list of Pairs/whatever in such a way that it *does* map key names to named parameters. Yep: foo *%hash; # keys of %hash taken as named parameters foo *hash(@array_of_pairs); # @array_of_pairs's pairs taken as named parameters --Ingo
Re: Sane (less insane) pair semantics
Hi, Dave Whipp wrote: Austin Hastings wrote: How about perl should DWIM? In this case, I'm with Juerd: splat should pretend that my array is a series of args. So if I say: foo [EMAIL PROTECTED]; or if I say: foo([EMAIL PROTECTED]); I still mean the same thing: shuck the array and get those args out here, even the pairs. The trouble is, an array doesn't contain enough information: Compare: foo( (a=1), b=2 ); With @args = ( (a=1), b=2 ); foo( [EMAIL PROTECTED] ); my @args = ( (a = 1), b = 2 ); # is sugar for my @args = ( (a = 1), (b = 2) ); # We can't stuff named arguments into an array, only pairs. # Named arguments are neither objects nor some other data type, # they're purely syntactical. If we have an arglist ctor, then we could have @args = arglist( (a=1), b=2 ); foo( [EMAIL PROTECTED]); say @args.perl ## ( ## (a=1) but is_positional, ## (b=2) but is_named, ## ) but without such a constructor, it would be difficult to DWIM correctly. Yep, see Luke's tuple proposal [1]: my $tuple = ( (a = 1), b = 2 ); foo *$tuple; # same as foo( (a = 1), b = 2 ); # one positional argument (a Pair) and # the named parameter b --Ingo [1] http://svn.openfoundry.org/pugs/docs/notes/theory.pod /Tuples
Re: Sane (less insane) pair semantics
Hi, Juerd wrote: Ingo Blechschmidt skribis 2005-10-10 19:36 (+0200): my @array = (42, hi, (a = 23)); It is worth pointing out that the inner parens here are merely for grouping: this information is lost afterwards, hence this: foo [EMAIL PROTECTED]; # same as shouldn't be foo 42, hi, (a = 23); # three positional params (Int, Str, Pair) but instead foo 42, hi, a = 23 # two positional args, one named. OR pairs need to remember whether they were originally in parens. This is very doable, but whether we want or need it is very arguable. Luckily, this is not needed, see my response to Dave [1]: Because named arguments are purely syntactic (i.e., they are not objects or some other kind of data type), you can't stuff them into an array (or a scalar, for that matter). # (assuming = binds thighter than =) my $scalar = a = 1; # sugar for my $scalar = (a = 1); my @array = (42, a = 1); # sugar for my @array = (42, (a = 1)); Named arguments can -- under the proposal -- only ever exist in calls. --Ingo [1] http://www.nntp.perl.org/group/perl.perl6.language/23438
Re: Sane (less insane) pair semantics
Ingo Blechschmidt skribis 2005-10-10 20:08 (+0200): Named arguments can -- under the proposal -- only ever exist in calls. Which leaves us with no basic datastructure that can hold both positional and named arguments. This is a problem because in a call, they can be combined. An array could hold both, but with only one small and minor inconvenience: pairs are either all positional, or all named. I sincerely believe that this is a feature, not a problem, because arrays are singledimensional, and having pairs mean two different things on the same level is, as this new proposal also indicates, confusing at best. Juerd -- http://convolution.nl/maak_juerd_blij.html http://convolution.nl/make_juerd_happy.html http://convolution.nl/gajigu_juerd_n.html
Re: Sane (less insane) pair semantics
Ingo Blechschmidt skribis 2005-10-10 19:59 (+0200): my @args = ( (a = 1), b = 2 ); # is sugar for my @args = ( (a = 1), (b = 2) ); Please, no. Please let the pair constructor be =, not (=). There is really no need for this operator to consist of both infix and circumfix parts. Please leave the parens for grouping (and in calls: breaking recognition). Juerd -- http://convolution.nl/maak_juerd_blij.html http://convolution.nl/make_juerd_happy.html http://convolution.nl/gajigu_juerd_n.html
Re: Sane (less insane) pair semantics
Hi, Juerd wrote: Ingo Blechschmidt skribis 2005-10-10 19:59 (+0200): my @args = ( (a = 1), b = 2 ); # is sugar for my @args = ( (a = 1), (b = 2) ); Please, no. Please let the pair constructor be =, not (=). There is really no need for this operator to consist of both infix and circumfix parts. Please leave the parens for grouping (and in calls: breaking recognition). Err, of course! The parens around b = 2 should make clear that b = 2 is not a named argument, but a pair. Outside of calls, the parens are only for grouping: my @args = (b = 2);# same as my @args = ((b = 2)); # same as my @args = b = 2; --Ingo
Re: Sane (less insane) pair semantics
J == Juerd [EMAIL PROTECTED] writes: J Ingo Blechschmidt skribis 2005-10-10 19:59 (+0200): my @args = ( (a = 1), b = 2 ); # is sugar for my @args = ( (a = 1), (b = 2) ); J Please, no. Please let the pair constructor be =, not (=). There is J really no need for this operator to consist of both infix and circumfix J parts. Please leave the parens for grouping (and in calls: breaking J recognition). he isn't saying that. the example shows the b = 2 is fine and will be parsed as if it were ( b = 2 ). the point is how pairs in an array are splatted or not to names args. and if i get it right, *hash( @args ) is what is needed to convert an array of pairs to be used as named params. uri -- Uri Guttman -- [EMAIL PROTECTED] http://www.stemsystems.com --Perl Consulting, Stem Development, Systems Architecture, Design and Coding- Search or Offer Perl Jobs http://jobs.perl.org
Re: Sane (less insane) pair semantics
Hi, Juerd wrote: Ingo Blechschmidt skribis 2005-10-10 20:08 (+0200): Named arguments can -- under the proposal -- only ever exist in calls. Which leaves us with no basic datastructure that can hold both positional and named arguments. This is a problem because in a call, they can be combined. Very true. This is why we need Luke's Tuple proposal [1]. Basically: my $tuple = (a = 1, (b = 2)):{ ...block... }; # $tuple.isa(Tuple) # Tuples are ordinary objects -- they can be stored # in scalars, arrays, etc. # But splatting tuples unfolds their magic: foo(*$tuple); # same as foo(a = 1, (b = 2)):{ ...block...}; # named arg a, positional pair (b = 2), # adverbial block { ...block... } # (Yep, under the current proposal, tuple construction conflicts # with list/array construction. FWIW, I'd be fine with # using Tuple.new(...) as the tuple constructor.) --Ingo [1] http://svn.openfoundry.org/pugs/docs/notes/theory.pod
Re: Sane (less insane) pair semantics
IB == Ingo Blechschmidt [EMAIL PROTECTED] writes: IB * (key = $value) (with the parens) is always a positionally passed IB Pair object. key = $value (without the parens) is a named IB parameter: IB sub foo ($a) {...} IB * Unary * makes a normal pair variable participate in named binding: IB foo(*$pair); # named parameter a, $a will be 42 IB * Same for hashes: IB my %hash = (a = 1, b = 2, c = 3); IB foo(%hash); # positional parameter, $a will be \%hash IB foo(*%hash); # three named parameters IB Opinions? works for me. but what about lists and arrays? my @z = ( 'a', 1 ) ; foo( @z ) # $a = [ 'a', 1 ] ?? my @z = ( a = 1 ) ; foo( @z ) # $a = pair( a = 1 ) or does that need * too? same questions for lists (this shows a nested sub call) sub bar { return ( a = 1 ) } foo( bar() )# i would expect $a == ( a = 1 ) since there is # no * foo( *bar() ) # i would expect $a == 1 i think i covered most/all of the variations. but this needs to be hammered down for all of them. thanx, uri -- Uri Guttman -- [EMAIL PROTECTED] http://www.stemsystems.com --Perl Consulting, Stem Development, Systems Architecture, Design and Coding- Search or Offer Perl Jobs http://jobs.perl.org
Re: Sane (less insane) pair semantics
Hi, Uri Guttman wrote: IB == Ingo Blechschmidt [EMAIL PROTECTED] writes: IB * (key = $value) (with the parens) is always a positionally passed IB Pair object. key = $value (without the parens) is a named IB parameter: IB sub foo ($a) {...} IB * Unary * makes a normal pair variable participate in named binding: IB foo(*$pair); # named parameter a, $a will be 42 IB * Same for hashes: IB my %hash = (a = 1, b = 2, c = 3); IB foo(%hash); # positional parameter, $a will be \%hash IB foo(*%hash); # three named parameters IB Opinions? works for me. Great! :) but what about lists and arrays? my @z = ( 'a', 1 ) ; foo( @z ) # $a = [ 'a', 1 ] ?? Yep. my @z = ( a = 1 ) ; foo( @z ) # $a = pair( a = 1 ) or does that need * too? No. Even foo([EMAIL PROTECTED]) would cause $a to be the Pair (a = 1). If you really wanted to have an array of pairs participate in named binding, you'd have to write: foo(*hash(@z)); # (which is short for) my %hash = @z; foo(*%hash); same questions for lists (this shows a nested sub call) sub bar { return ( a = 1 ) } foo( bar() ) # i would expect $a == ( a = 1 ) since there is # no * Yep. foo( *bar() ) # i would expect $a == 1 Yep. --Ingo
Re: Sane (less insane) pair semantics
On Sun, Oct 09, 2005 at 20:22:59 +0200, Ingo Blechschmidt wrote: Opinions? Yes! -- () Yuval Kogman [EMAIL PROTECTED] 0xEBD27418 perl hacker /\ kung foo master: *shu*rik*en*sh*u*rik*en*s*hur*i*ke*n*: neeyah pgpPtAVtx26AP.pgp Description: PGP signature
Re: Sane (less insane) pair semantics
On 10/9/05, Uri Guttman [EMAIL PROTECTED] wrote: IB == Ingo Blechschmidt [EMAIL PROTECTED] writes: IB sub foo ($a) {...} works for me. but what about lists and arrays? my @z = ( 'a', 1 ) ; foo( @z ) # $a = [ 'a', 1 ] ?? Yep. my @z = ( a = 1 ) ; foo( @z ) # $a = pair( a = 1 ) or does that need * too? $a = [ a = 1 ] You passed an array. The parameter gets an array. same questions for lists (this shows a nested sub call) sub bar { return ( a = 1 ) } foo( bar() )# i would expect $a == ( a = 1 ) since there is # no * foo( *bar() ) # i would expect $a == 1 Yeah, I think your expectations are correct. Basically, * takes whatever kind of object it is (array, hash, pair) and pretends that you wrote its contents literally into the argument list. Luke
Re: Sane (less insane) pair semantics
LP == Luke Palmer [EMAIL PROTECTED] writes: LP On 10/9/05, Uri Guttman [EMAIL PROTECTED] wrote: IB == Ingo Blechschmidt [EMAIL PROTECTED] writes: IB sub foo ($a) {...} works for me. but what about lists and arrays? my @z = ( 'a', 1 ) ; foo( @z ) # $a = [ 'a', 1 ] ?? LP Yep. my @z = ( a = 1 ) ; foo( @z ) # $a = pair( a = 1 ) or does that need * too? LP $a = [ a = 1 ] LP You passed an array. The parameter gets an array. right. and it has one pair inside. same questions for lists (this shows a nested sub call) sub bar { return ( a = 1 ) } foo( bar() )# i would expect $a == ( a = 1 ) since there is # no * foo( *bar() ) # i would expect $a == 1 LP Yeah, I think your expectations are correct. LP Basically, * takes whatever kind of object it is (array, hash, pair) LP and pretends that you wrote its contents literally into the argument LP list. that is a succinct statement of how * work but you also have to describe the cases with pairs and such and no *. and what about the case that ingo said needed *hash()? i think a list of all the know variations (* and no *) should be done to keep the behavior clear to all. just more of the examples we have so far and what gets set in the args for each. it will also make it easier to create tests for these and to get this into pugs. uri -- Uri Guttman -- [EMAIL PROTECTED] http://www.stemsystems.com --Perl Consulting, Stem Development, Systems Architecture, Design and Coding- Search or Offer Perl Jobs http://jobs.perl.org
Re: Sane (less insane) pair semantics
The think I don't like about `foo( *$bar )` is that it's not clear whether you're splatting a pair, or a hash, or an array, or a complete argument-list object. This is probably fine for quick-'n'-dirty code, but I'd like to encourage a more explicit style: my %hash = (a='b', c='d'); foo( *%hash ); # splat a hash as named arguments # = foo( a='b', c='d' ); my $pair = a='b'; foo( *%$pair ); # view the pair as a 1-elem hash, and splat that my $href = \%hash; # or just %hash foo( *%$href ); # view the hashref as a hash, and splat that sub returns_a_hash { ... } foo( *%{returns_a_hash} ); # call the sub, view the result as a hash, and splat that my @array = (1, 2, 3); foo( [EMAIL PROTECTED] ); # splat an array as positional arguments # = foo( 1, 2, 3 ); my $aref = [EMAIL PROTECTED]; # or just @array foo( [EMAIL PROTECTED] ); # view the arrayref as an array, and splat that sub returns_an_array { ... } foo( [EMAIL PROTECTED] ); # call the sub, view the result as a hash, and splat that In this style, the splat character (*) is always next to a sigil (% or @) telling you exactly how the arguments are being substituted (named or positional). I'm also a little wary of giving parens the power to change pair behaviour, but the rules are simple enough that I can probably get over it. The other proposal, IIRC, was to have `named()` and `pair()` special-forms for forcing the desired behaviour; these would only be valid in argument lists. Stuart
Re: Sane (less insane) pair semantics
Ingo Blechschmidt wrote: Hi, while fixing bugs for the imminent Pugs 6.2.10 release, we ran into several issues with magical pairs (pairs which unexpectedly participate in named binding) again. Based on Luke's Demagicalizing pairs thread [1], #perl6 refined the exact semantics [2]. The proposed changes are: * (key = $value) (with the parens) is always a positionally passed Pair object. key = $value (without the parens) is a named parameter: sub foo ($a) {...} foo(a = 42);# named parameter a, $a will be 42 foo(:a(42)); # same foo((a = 42)); # positional parameter (a pair), # $a will be the Pair (a = 42) foo((:a(42))); # same What about whitespace? foo (a = 42); # Note space Is that the first case (subcall with named arg) or the second case (sub with positional pair)? * Passing a variable containing a Pair is always passed positionally: my $pair = (a = 42); # or :a(42) foo($pair); # positional parameter, $a will be the Pair (a = 42) * Unary * makes a normal pair variable participate in named binding: foo(*$pair); # named parameter a, $a will be 42 * Same for hashes: my %hash = (a = 1, b = 2, c = 3); foo(%hash); # positional parameter, $a will be \%hash foo(*%hash); # three named parameters Opinions? --Ingo [1] http://article.gmane.org/gmane.comp.lang.perl.perl6.language/4778/ [2] http://colabti.de/irclogger/irclogger_log/perl6?date=2005-10-09,Sunsel=528#l830 What's the most complete way to get the sub's arguments? That is, for a sub that takes positional, optional, named, and variadic (*) arguments, what's the best mechanism for grabbing the entire call? Your reply to Uri: Uri Guttman wrote: but what about lists and arrays? my @z = ( 'a', 1 ) ; foo( @z ) # $a = [ 'a', 1 ] ?? Yep. Suggests that I cannot pass along parameters in the usual way: sub foo(...) { bar(@_); } Does that work if I code it as bar @_; (which is huffmanly, but hardly intuitive). =Austin
Re: Sane (less insane) pair semantics
On 10/10/05, Austin Hastings [EMAIL PROTECTED] wrote: What about whitespace? foo (a = 42); # Note space Is that the first case (subcall with named arg) or the second case (sub with positional pair)? Sub with positional pair, since the parens aren't call-parens (because of the space), so they protect the pair. It would probably be prudent to emit a warning in this case, for obvious reasons. (Actually, this is one of the major problems with using parens to protect pair args.) What's the most complete way to get the sub's arguments? That is, for a sub that takes positional, optional, named, and variadic (*) arguments, what's the best mechanism for grabbing the entire call? As far as I know there currently *isn't* a concise way to capture/forward all (or some) of a sub's arguments; the closest thing is: sub foo([EMAIL PROTECTED], *%named) { bar([EMAIL PROTECTED], *%named) } Which is ugly and unwieldy. I believe Luke was considering some kind of 'unified arg-list object' which you could use to slurp and splat entire argument lists, like so: sub foo(*$args) { bar(*$args) } But I don't think it's been posted to the list yet. Stuart
Re: Sane (less insane) pair semantics
SC == Stuart Cook [EMAIL PROTECTED] writes: SC The think I don't like about `foo( *$bar )` is that it's not clear SC whether you're splatting a pair, or a hash, or an array, or a complete SC argument-list object. This is probably fine for quick-'n'-dirty code, SC but I'd like to encourage a more explicit style: but perl will know the type of the value in $bar and expand/splat it accordingly. SC my $pair = a='b'; SC foo( *%$pair ); # view the pair as a 1-elem hash, and splat that the % there isn't a hash. perl can see the single pair and deal with that. the way to make this more readable is to use better variable names. $pair here is fine and *$pair would mean to splat it into the named arguments. SC my $href = \%hash; # or just %hash SC foo( *%$href ); # view the hashref as a hash, and splat that same as above. perl sees the href and will just DWIM. SC sub returns_a_hash { ... } SC foo( *%{returns_a_hash} ); # call the sub, view the result as a SC hash, and splat that isn't that what hash() is for? what is returns_a_hash really returning, a list or a hash ref because you can't return a hash (or can you this week? :). SC my $aref = [EMAIL PROTECTED]; # or just @array SC foo( [EMAIL PROTECTED] ); # view the arrayref as an array, and splat that again, autoderef would work fine here. i don't see the benefit of the extra @. SC sub returns_an_array { ... } SC foo( [EMAIL PROTECTED] ); # call the sub, view the result as a SC hash, and splat that where is the hash? wouldn't you want %{} in your system? and %{} derefs a hash and doesn't convert a list to a hash. that is what hash() does. uri -- Uri Guttman -- [EMAIL PROTECTED] http://www.stemsystems.com --Perl Consulting, Stem Development, Systems Architecture, Design and Coding- Search or Offer Perl Jobs http://jobs.perl.org
Re: Sane (less insane) pair semantics
Stuart Cook wrote: On 10/10/05, Austin Hastings [EMAIL PROTECTED] wrote: What about whitespace? foo (a = 42); # Note space Is that the first case (subcall with named arg) or the second case (sub with positional pair)? Sub with positional pair, since the parens aren't call-parens (because of the space), so they protect the pair. It would probably be prudent to emit a warning in this case, for obvious reasons. (Actually, this is one of the major problems with using parens to protect pair args.) So to pass a hash that has one element requires using the chash/c keyword? Specifically, if I say: @args = (a = 1, get_overrides()); Then can I say foo([EMAIL PROTECTED]); Or will I, in the case of no overrides, get a positional pair instead of named a =1 ? What's the most complete way to get the sub's arguments? That is, for a sub that takes positional, optional, named, and variadic (*) arguments, what's the best mechanism for grabbing the entire call? As far as I know there currently *isn't* a concise way to capture/forward all (or some) of a sub's arguments; the closest thing is: sub foo([EMAIL PROTECTED], *%named) { bar([EMAIL PROTECTED], *%named) } Which is ugly and unwieldy. I believe Luke was considering some kind of 'unified arg-list object' which you could use to slurp and splat entire argument lists, like so: sub foo(*$args) { bar(*$args) } But I don't think it's been posted to the list yet. It seems like positionals, if specified, should appear as pairs in [EMAIL PROTECTED] unless a hash is also present. That is, @_ or its replacement as the collection-of-all-arguments-given should be a list, for positionalness, and should include pairs when necessary. =Austin