Re: Proposal: split ternary ?? :: into binary ?? and //
On Tue, Sep 06, 2005 at 07:26:37AM +1000, Damian Conway wrote: > Thomas Sandlass wrote: > > >I'm still contemplating how to get rid of the :: in the > >ternary > > > >Comments? > I believe that the single most important feature of the ternary operator is > that it is ternary. That is, unlike an if-else sequence, it's impossible to > leave out the "else" in a ternary operation. Splitting the ternary destroys > that vital characteristic, which would be a very bad outcome. At OSCON I was also thinking that it'd be really nice to get rid of the :: in the ternary and it occurred to me that perhaps we could use something like '?:' as the 'else' token instead: (cond) ?? (if_true) ?: (if_false) However, I'll freely admit that I hadn't investigated much further to see if this might cause other syntax ambiguities. Pm
RE: Proposal: split ternary ?? :: into binary ?? and //
HaloO, Luke wrote: > > > ?? !! ain't bad either. > > > > It's definitely much better that sabotaging the > > (highly useful) // operator > > within (highly useful) ternaries. > > I guess the thing that I really think is nice is getting :: out of > that role and into the type-only domain. Right. To make :: indicate type or meta was my primary concern. So I see the following situation: unwanted ?? :: ASCII replacements ?? //# two binaries ?? \\# I would like it as chaining binary nor ?? !!# wasn't binary ! the none() constructor # and !! the binary nor---at least in Pugs? Latin1 replacements ?? ¦¦ ?? ¡¡ ?? ¿¿ @Larry's choice? -- TSa
Re: Proposal: split ternary ?? :: into binary ?? and //
On 9/6/05, Thomas Sandlass <[EMAIL PROTECTED]> wrote: > Right. To make :: indicate type or meta was my primary concern. Okay, now why don't you tell us about this new binary :: you're proposing. Luke
perl6-language@perl.org
H. The arity of a given multi might be 3 or 4 or 5. If *only* there were a way to return a single value that was simultaneously any of 3 or 4 or 5. Oh, wait a minute... Damian
perl6-language@perl.org
On 9/3/05, Damian Conway <[EMAIL PROTECTED]> wrote: > H. The arity of a given multi might be 3 or 4 or 5. > > If *only* there were a way to return a single value that was simultaneously > any of 3 or 4 or 5. > > Oh, wait a minute... Well, we'd better document that pretty damn well then, and provide min_arity and max_arity, too. This is one of those places where Yuval is spot on about autothreading being evil. This is also one of those places where I am spot on about Junctive logic being evil. It looks like returning a junction is the dwimmiest thing we can do here: given &code.arity { when 1 { code(1) } when 2 { code(1,2) } } So if &code is a multimethod that has variants that take two parameters or three parameters, great, we call it with (1,2), which will succeed. And if it has variants that take one parameter or three parameters, great, we call it with (1), which will succeed. And if it has variants that take one parameter or two parameters, um..., great, we call it with (1), which will succeed. In that last case though, this is not equivalent to the above: given &code.arity { when 2 { code(1,2) } when 1 { code(1) } } That may be a little... surprising. Still, it's fixed to succeed either way, so that's probably okay, right? But let's do a little thinking here. You're asking a code reference for its arity. It's pretty likely, that unless you are doing dwimminess calculations (which aren't that uncommon, especially in Damian's modules), that you have no idea what the arguments are either. An example of a function that uses arity is &map. sub map (&code, [EMAIL PROTECTED]) { gather { my @args = @list.splice(0, &code.arity); take &code([EMAIL PROTECTED]); } } In the best case (depending on our decision), this fails with "can't assign a junction to an array". In the worst case, it autothreads over splice, returning a junction of lists, makes @args a junction of lists, and then returns a list of junctions for each arity the multimethod could have taken on. I don't think that's correct... at all. The correct way to have written that function is: sub map (&code, [EMAIL PROTECTED]) { gather { my @args = @list.splice(0, min(grep { ?$_ } &code.arity.states)); take &code([EMAIL PROTECTED]); } } Not quite so friendly anymore. In order to use this, we had to access the states of the junction explicitly, which pretty much killed the advantage of it being a junction. Junctions are logical travesty, and it seems to me that they cease to be useful in all but the situations where the coder knows *everything*. But I still like them. Here's how I'm thinking they should work. This is a minimalistic approach: that is, I'm defining them in the safest and most limited way I can, and adding useful cases, instead of defining them in the richest and most general way possible and forbidding cases that are deemed "unsafe". Throw out all your notions about how Junctions work. We're building from scratch. Things that come on the right side of smart match do a role called Pattern, which looks like this: role Pattern { method match(Any --> Bool) {...} } Among the things that do pattern are Numbers, Strings, Arrays, ... (equivalence); Types, Sets, Hashes (membership); Bools, Closures (truth); and Junctions (pattern grep). That is, a Junction is just a collection of Patterns together with a logical operation. It, in turn, is a pattern that can be smart-matched against. Therefore, we sidestep the issue of the existence of junctions making every ordered set have exactly one element[1]. because there is nothing illogical against testing against a pattern. You can also safely pass it to functions, and they can use it in their smart matches, and everything is dandy. That's it for the base formulation. A junction is just a pattern, and it makes no sense to use it outside of the smart-match operator. But that means that we have to change our idioms: if $x == 1 | 2 | 3 {...} # becomes if $x ~~ 1 | 2 | 3 {...}# not so bad if $x < $a | $b {...} # becomes if ($x ~~ { $_ < $a } | { $_ < $b }) {...} # eeeyuck if $x < $a || $x < $b {...} # back to square one # from E06 if any(@newvals) > any(@oldvals) { say "Already seen at least one smaller value"; } # becomes if (grep { my $old = $_; grep { $_ > $old } @newvals } @oldvals) { say "I don't remember what I was going to say because the condition took so long to type" } So, that sucks. But I'm beginning to wonder whether we're really stuck there. The two yucky examples above can be rewritten, once we take advantage of some nice properties of orderings: if $x < max($a, $b) {...} if min(@newvals) > min(@oldvals) {...} But that's a solution to the specific comparison problems, not the general threaded
perl6-language@perl.org
Luke Palmer skribis 2005-09-06 13:28 (+): > Well, we'd better document that pretty damn well then, and provide > min_arity and max_arity, too. Won't junctions do Array, then? I think &foo.arity.max would be very intuitive, and likewise, for @&foo.arity { ... } Juerd -- http://convolution.nl/maak_juerd_blij.html http://convolution.nl/make_juerd_happy.html http://convolution.nl/gajigu_juerd_n.html
RE: Proposal: split ternary ?? :: into binary ?? and //
HaloO, Luke wrote: > Okay, now why don't you tell us about this new binary :: you're proposing. Well, not a new one. Just plain old foo::bar::blahh and 'my ::blubb $x' with relaxed whitespace rules. The ternary ?? :: is a splinter in my mind's eye because it is not a compile time or symbol lookup construct. The driving idea is to let tokens always mean the same or at least very similar things in different contexts. And I thought that is your rating as well. For :: that should be 'symbol table management'. E.g. ::= fits that notion perfectly while the alternative separation of the ternary doesn't. There's yet another approach, to make ternary listfix: $val = $cond ?? "true" ?? "false"; and perhaps we change it from ternary to (n > 2)-ary: $val = $tested_only ?? $val_or_test ?? $other_or_test ?? $final; But in both ways, recursive "ternary" needs parens. Which can be regarded as a good thing. This listfix ?? behaves more like a rhs returning ||. As the RegularityGuy(TM) I like the chaining triple // || \\ where // returns the first defined, || returns the first true and \\ returns the first false. And of course there are low precedence counterparts err, or, nor. And the binary \ for none() construction. BTW is (\) indicating the relative complement of the set operators? Even the unary ref prefix makes sense as \ because it means 'not the value' or 'not right here but keep for later reference'. -- TSa
perl6-language@perl.org
On Tue, Sep 06, 2005 at 13:28:24 +, Luke Palmer wrote: This should still work: > sub map (&code, [EMAIL PROTECTED]) { > gather { > my @args = @list.splice(0, &code.arity); > take &code([EMAIL PROTECTED]); > } > } multi sub foo ( ... ) { ... } multi sub foo ( ... ) { ... } my @mapped = map &foo ...; I think this is inconsistent. There is another option though: sub map (&code, [EMAIL PROTECTED]) { gather { take &code.mutably_bind_some(@list); # removes stuff # from @list } } The code object can then look for suitable multimethod alternatives for the arguments in question, avoid that alltogether, dispatch based on the arity of the first alternative, dispatch based on the arity of the most general alternative, or whatever. I would be careful though, and only pass singly bindable, non slurpy code refs into map in my code, in which case i'd expect 'mutably_bind_some(@list)' to be along these lines: method mutably_bind_some ([EMAIL PROTECTED] is rw) { my @bound_params = map { pop @params } 1 .. $?SELF.arity; $?SELF.bind_params(@bound_params); } -- () Yuval Kogman <[EMAIL PROTECTED]> 0xEBD27418 perl hacker & /\ kung foo master: /me supports the ASCII Ribbon Campaign: neeyah!!! pgpZ6GyiTREuw.pgp Description: PGP signature
Re: Proposal: split ternary ?? :: into binary ?? and //
On Tue, Sep 06, 2005 at 04:57:30PM +0200, Thomas Sandlass wrote: > There's yet another approach, to make ternary listfix: > > $val = $cond ?? "true" ?? "false"; So ^^ that one doesn't do the same thing as ^^ that one? I'd find that confusing in itself. And that's without considering the change from the C of C and Perl 5. [contents of this message may settle in transit, particularly if your mail reader uses a proportional font.] Nicholas Clark
perl6-language@perl.org
On a related note: Suppose I have a function with a non-obvious arity: I might, in a desperate attempt to find billable hours, describe the arity as a trait: sub sandwich($bread, $meat, $cheese, $condiment1, $qty1, ...) does arity ({ 3 + 2 * any(1..Inf); }); That's easy enough for trivial cases like this, but is there a way to use C for the more difficult cases? Specifically, and obviously, printf-and-friends: my &example := &printf.assuming(format => "%s %s %n\n"); say &example.arity(); The obvious output is any(1..Inf), since who's going to code the arity function? But: 1. Is it possible to code an arity trait as a run-time block? (I assume yes) 2. Could this, or any, trait take advantage of assumed parameters? If so, how? (Of course, after the arity function is written, it seems obvious to die unless the current function's arity is le the number of arguments...) =Austin
\(...)?
Hi, # Perl 5 my @array_of_references = \($foo, $bar, $baz); print [EMAIL PROTECTED];# prints 3 print ${ $array_of_references[1] }; # prints $bar # Perl 6 my @array = \($foo, $bar, $baz); say [EMAIL PROTECTED]; # 3 (like Perl 5)? # Or 1, making \(...) similar to [...]? If \(...) still constructs a list of references, are the following assumptions correct? \(@array); # same as [EMAIL PROTECTED]; # (As () is only used for grouping in this case.) # Correct? \(@array,); # same as map { \$_ } @array; # (As &postcircumfix:{'\\(', ')'} is called here.) # Correct? --Ingo -- Linux, the choice of a GNU | Row, row, row your bits, gently down generation on a dual AMD | the stream... Athlon!|
Packages, Modules and Classes
Hey all, I recently added Package and Module into the MetaModel (2.0) so that Package is an Object Module is a Package Class is a Module as mentioned here http://article.gmane.org/gmane.comp.lang.perl.perl6.language/4599. Currently Packages have names and Modules add version and authority information, but I have nothing yet in place to represent package symbol tables. Which brings me to my questions. I assume that each symbol table entry has the following slots; SCALAR, ARRAY, HASH, SUB, METH. I base this off the AUTO* hooks described in S10. I assume too that the METH slot is only valid for Classes, and not appropriate for Packages and Modules. This would mean that given this code: package Foo; our $baz; sub bar { ... } %Foo::{'bar'}{SUB} is a ref to the &bar sub, and %Foo::{'baz'}{SCALAR} is a ref to the scalar $baz. The same, I would assume, would apply for Modules, so that: module Foo; our $baz; sub bar { ... } is pretty much interchangable with the first example. But I think it's a little trickier when we get to Classes. Given this code: class Foo; our $baz; sub bar { ... } I would expect it to behave just as it does for a Package or Module. But when we start to introduce methods and attributes, I am unsure of how things will work. class Foo; has $.baz; method bar { ... } Can I get to $.baz? If I can, what will I get? I expect that %Foo::{'bar'}{METH} will give me a method ref, but what happens when I try to store something in it? Does that perform some kind of meta-model actions (Foo.meta.change_method(...) or somesuch)? What if I delete the symbol table entry, what happens then (more meta-trickery)? Thanks, Stevan
Re: \(...)?
Ingo Blechschmidt skribis 2005-09-06 19:46 (+0200): > If \(...) still constructs a list of references, are the following > assumptions correct? IIRC, the RHS of \ is in scalar context, and the comma in scalar context (the parens are just for precedence), creates an arrayref. Which is interesting (and imho, a bad idea), because: > \(@array); # same as \(@array) and [EMAIL PROTECTED] are the same thing > \(@array,); # same as \(@array,) is [ @array ], NOT map { \$_ } @array Juerd -- http://convolution.nl/maak_juerd_blij.html http://convolution.nl/make_juerd_happy.html http://convolution.nl/gajigu_juerd_n.html
Re: \(...)?
Hi, Juerd wrote: > Ingo Blechschmidt skribis 2005-09-06 19:46 (+0200): >> If \(...) still constructs a list of references, are the following >> assumptions correct? > > IIRC, the RHS of \ is in scalar context, and the comma in scalar > context (the parens are just for precedence), creates an arrayref. > > Which is interesting (and imho, a bad idea), because: > >> \(@array); # same as > > \(@array) and [EMAIL PROTECTED] are the same thing Agreed. >> \(@array,); # same as > > \(@array,) is [ @array ], NOT map { \$_ } @array I'm not sure of the []s, remember &postcirumfix:<[ ]> creates *new* containers: [EMAIL PROTECTED] = $bar; # @array[0] unchanged Compare this to: (@array,)[0] = $bar; # @array[0] changed to $bar So, I think, if we ditch Perl 5's special \(...), \(@array,); # should be the same as \do { (@array,) }; This has the consequence that (\(@array,))[0] = $bar; changes @array[0]. --Ingo -- Linux, the choice of a GNU | Mr. Cole's Axiom: The sum of the generation on a dual AMD | intelligence on the planet is a constant; Athlon!| the population is growing.
perl6-language@perl.org
Luke wrote: > Well, we'd better document that [junctive arity values] pretty damn > well then, and provide min_arity and max_arity, too. Unnecessary. The C and C builtins should be overloaded to Just Work on junctive values: if min &code.arity < 2 {...} > This is one of those places where Yuval is spot on about autothreading > being evil. This is also one of those places where I am spot on about > Junctive logic being evil. No. Neither autothreading nor junctive logic is "evil". They're just "different". I know that many people can't tell the difference between "evil" and "different", but you two are smart enough to be able to. > It looks like returning a junction is the dwimmiest thing we can do here: > > given &code.arity { > when 1 { code(1) } > when 2 { code(1,2) } > } > > So if &code is a multimethod that has variants that take two > parameters or three parameters, great, we call it with (1,2), which > will succeed. And if it has variants that take one parameter or three > parameters, great, we call it with (1), which will succeed. And if it > has variants that take one parameter or two parameters, um..., great, > we call it with (1), which will succeed. > > In that last case though, this is not equivalent to the above: > > given &code.arity { > when 2 { code(1,2) } > when 1 { code(1) } > } > > That may be a little... surprising. Still, it's fixed to succeed > either way, so that's probably okay, right? It's not surprising at all. The order of C tests (usually) matters, because a series of C statements (usually) short-circuits. > But let's do a little thinking here. You're asking a code reference > for its arity. It's pretty likely, that unless you are doing > dwimminess calculations (which aren't that uncommon, especially in > Damian's modules), that you have no idea what the arguments are > either. An example of a function that uses arity is &map. > > sub map (&code, [EMAIL PROTECTED]) { > gather { > my @args = @list.splice(0, &code.arity); > take &code([EMAIL PROTECTED]); > } > } > > In the best case (depending on our decision), this fails with "can't > assign a junction to an array". In the worst case, it autothreads > over splice, returning a junction of lists, makes @args a junction of > lists, and then returns a list of junctions for each arity the > multimethod could have taken on. I don't think that's correct... at > all. The correct way to have written that function is: > > sub map (&code, [EMAIL PROTECTED]) { > gather { > my @args > = @list.splice(0, min(grep { ?$_ } &code.arity.states)); BTW, that should be &code.arity.values, not &code.arity.states. > take &code([EMAIL PROTECTED]); > } > } > > Not quite so friendly anymore. Only because you're doing it the unfriendly way. Instead of, for example: sub map (&code, [EMAIL PROTECTED]) { gather { my @args = @list.splice(0, min &code.arity); take &code([EMAIL PROTECTED]); } } which is perfectly friendly, and also clearer. Or, perhaps more usefully, a multi should be illegal as a map block: sub map (&code, [EMAIL PROTECTED]) { croak "Can't use multi as map block" if &code.arity.values > 1; gather { my @args = @list.splice(0, &code.arity); take &code([EMAIL PROTECTED]); } } > Junctions are logical travesty, Well, that's very emotive, but I don't believe it's either a useful or an accurate characterization. I would agree that junctions can be logically *sophisticated*, but then I'd argue that *all* programming constructs are that. > and it seems to me that they cease to be useful in all but the > situations where the coder knows *everything*. What does that mean, exactly? How can anyone *ever* write sensible code without knowing what kind of values they're processing? > But I still like them. > > Here's how I'm thinking they should work. This is a minimalistic > approach: that is, I'm defining them in the safest and most limited > way I can, and adding useful cases, instead of defining them in the > richest and most general way possible and forbidding cases that are > deemed "unsafe". > > Throw out all your notions about how Junctions work. We're building > from scratch. > > Things that come on the right side of smart match do a role called > Pattern, which looks like this: > > role Pattern { > method match(Any --> Bool) {...} > } > > Among the things that do pattern are Numbers, Strings, Arrays, ... > (equivalence); Types, Sets, Hashes (membership); Bools, Closures > (truth); and Junctions (pattern grep). That is, a Junction is just a > collection of Patterns together with a logical operation. It, in > turn, is a pattern that can be smart-matched against. Therefore, we > sidestep the issue of th