Re: S08 Draft questions (Captures and Signatures)
I can't comment on most of your questions, but the few that I can answer are inline below... Jon Lang wrote: > Yes, I know that there is no S08. I'm working on writing one, ++ > * What types are you allowed to assign to an invocant? Whatever the type constraint says. When you write class Foo { method bar ($x, $y) }, then bar's signature gets an invocant of type Foo implicitly. If you write ... method bar (A $s:, $x, $y), then the type constraint is A. > * Are placeholder parameters ever considered to be part of a > function's longname? (I'm expecting that they aren't: if you want a > longname, you ought to specify it in a formal signature.) I expect they are; to me placeholder variables are just a different way to write a signature, spread out all over the block. 08:41 <@moritz_> rakudo: say {$^a + $^b}.arity 08:41 < p6eval> rakudo 78cb4c: OUTPUT«2» So they already count towards the arity (which makes sense, otherwise map, reduce etc. couldn't work with it); why should they be omitted from the longname then? > * does the use of placeholder parameters interfere with the use of the > slurpy parameters normally provided by the default signature (i.e., > *...@_ and *%_)? I'm guessing not. As far as I understand, you can only use placeholder parameters on a sub or a block with no explicit signature. When you use them, you give them a signature. *...@_ and *%_ are not part of that signature. (so yes, the interfere). Cheers, Moritz
simultaneous conditions in junctions
Thinking about Jon Lang's -1|+1 example in another way, I wondered about simultaneous conditions. Consider $x = any (1,2,5,6) How do we compose a conditional that asks if any of this set of eigenstates are simultaneously both > 2 and < 5? Clearly the desired answer for $x is False, but my $x = any(1,2,5,6); say ?( 2 < $x < 5); # true Is there some combination of any/all that will achieve this? Here it would seem that we would want to have some sieving, so that eigenstates that are true for one test can be given to another test.
Re: simultaneous conditions in junctions
Richard (>): > Consider > > $x = any (1,2,5,6) > > How do we compose a conditional that asks if any of this set of eigenstates > are simultaneously both > 2 and < 5? > Clearly the desired answer for $x is False, but > > my $x = any(1,2,5,6); say ?( 2 < $x < 5); # true > > Is there some combination of any/all that will achieve this? my @x = 1, 2, 5, 6; say ?(first { 2 < $_ < 5 }, @x); # false Problem solved. It doesn't involve the cool junctions technology, but it's not much longer, and perhaps slightly more understandable. // Carl
Re: S08 Draft questions (Captures and Signatures)
Jon Lang wrote: Invocants: * Is it illegal to specify an invocant in a sub, or is it merely nonsensical? That is, should the compiler complain, or should it silently treat the invocant as the first positional parameter? (The latter has the advantage that you don't have to worry about what the signature is being used for; it has the disadvantage of being, well, nonsensical: invocants are meaningless without the context of a method - and /maybe/ a role - to provide them meaning.) I'd think it was an error at compile time. We can easily detect it. * Likewise, if I interpolate a signature with an invocant into another signature (somewhere other than at the start), is this an error, or will the invocant be silently converted into an ordinary positional parameter? I think if the condition from above would check we are being used to define a signature for a method, that would make this case an error too. I can't immediately think of a use case for making an exception for a signature written elsewhere having one, but somebody else maybe can. * What types are you allowed to assign to an invocant? Any that you like, but you might find a lot of people yelling the word "Liskov" at you, or create a method that's impossible to call. ;-) * Does anyone object to roles having an invocant, and that invocant referring to the class that is doing the role? Yes; on further reflection, the ability to type that invocant raises all kinds of possible WTFs without a good enough use case. So I'd really rather we don't go down this road. Longnames: * Why are we using ";;" to denote the end of a multi function's longname? I'm thinking that doubling up on the normal delimiter may make more sense - which would normally mean ",,", but would mean ";;" if you're using a multidimensional argument list and the longname ends where a semicolon would normally go. Think it's probably a visual argument - ,, just doesn't stand out as "there's something different going on here" sufficiently. * Can any required parameter be part of the longname, or are only positional parameters allowed? (I'm expecting the latter; but I'd like confirmation.) Only positional parameters participate in multiple dispatch in Perl 6.0.0, so yes, the latter. * Are placeholder parameters ever considered to be part of a function's longname? (I'm expecting that they aren't: if you want a longname, you ought to specify it in a formal signature.) Placeholder parameters result in a signature being generated based upon them, as far as I can tell (and so far as we've implemented in Rakudo). So yes, they would all count in the long name - or at least, the positional ones. Also note that if you do have placeholder parameters it's illegal to write a signature on the block too. Starting and Ending delimiters: * Why are pointy blocks forbidden from enclosing their signatures in parentheses, or from using the ":( ... )" notation? Is this a holdover from the early days, when parentheses denoted a list? Or is there still a good reason not to allow such notation? Really not sure on this one. * Why do parameterized roles use "[ ... ]" for their signatures instead of ":( ... )" or "( ... )"? RoleName(...) is a type coercion, so we can't use that. I also think it's good that parametrized types have something visually distinctive about them, though, so I think the current syntax is probably just fine. Named parameters: * Must required named parameters be defined before optional named parameters are, or are we allowed to interleave the two? As far as I know, you can mix them for named (but not, obviously, for positional). Placeholder parameters: * does the use of placeholder parameters interfere with the use of the slurpy parameters normally provided by the default signature (i.e., *...@_ and *%_)? I'm guessing not. We only generate *...@_ and *%_ for subs when there is no signature; the presence of placeholder parameters generates a signature, so you'd not get them. Exception: methods, where by S12 we always add a *%_ unless the method defines its own slurpy named parameter. Hope this helps, Jonathan
[Fwd: Re: junctions and conditionals]
This email was mistakenly not sent to the p6l list. Jon writes: On Wed, Apr 1, 2009 at 12:54 AM, Richard Hainsworth wrote: Jon Lang wrote: In "Junction Algebra", Martin Kealey wrote: On Mon, 30 Mar 2009, Mark J. Reed wrote: ( $a <= any(-1,+1) <= $b ) == ( $a <= any(-1,+1) && any(-1,+1) <= $b )(*A) Clearly, the RHS is true for $a == $b == 0, but I'm not sure the LHS shouldn't also be. Isn't it just syntactic sugar for the RHS? I suspect not. Rather I think that $a <= any(-1,+1) <= $b corresponds to $tmp = any(-1,+1); $a <= $tmp <= $b and thence to $tmp = any(-1,+1); $a <= $tmp && $tmp <= $b (*B*) Quite how the lines I have labelled (A) and (*B*) are different, I do not understand. Unless wrapping a junction in a variable produces a different result. That was my initial reaction as well. A closer examination of Martin's message indicates that he tends to think that hitting a junction ought to thread the entire program throughout the rest of the lifespan of said junction, so that (e.g.) the thread that runs the comparison "$a <= -1" in (*B*) is the same thread that runs the comparison "-1 <= $b". OTOH, since (*A*) spells out two separate junctions, it would thread each one separately; resulting in four threads being used to resolve the expression. In theory, at least; in practice, he's looking for ways to simulate such threading without actually having to mess with all of the overhead that a literal implementation thereof would entail. In both cases, the problem arises when you apply a predicate to a junction, and then use the junction within code that only gets executed according to the truth of the predicate. "Using a junction" implies the extraction of the eigenstates. That is being frowned upon - I understand I've been doing my utmost to avoid making said implication. The possible solution to both of these: junctions collapse when they hit conditional statements - but only within the "conditioned scope". So: within the code block for the "if $x > 0" statement above, $x only equals +1, since -1 didn't pass the test. This is the sieving functionality. Since perl6 is being written explicitly to avoid sieving out eigenstates, this will not happen. What I'm hearing is that a decision has already been made on this matter, so we're stuck with it no matter how counterintuitive the results of that decision are. Thus, "say $x" is the same as "say 1". In the case of the range test, the code on the RHS of the && only executes if the code on the LHS evaluated to true; therefore, when evaluating the RHS, "$tmp" doesn't include any of the possibilities that would have failed on the LHS. That means that: 0 <= -1 | +1 <= 0 which is true, because using standard chaining semantics we have 0 <= -1|1 and -1|1 <= 0 Since the first condition is true (+1 >= 0) and the second condition is true (-1 <=0), the compound is true. Why you might want such a condition, I dont know. But that is the way junctions are designed to work. Right now, yes. I'm arguing that the way that they're designed to work doesn't DWIM. Try a slightly different example: 0 <= $x <= 1 # 0 is less than $x is less than 1. $x ~~ 0..1 # $x is in the range of 0 to 1. I submit that most people would expect these two statements to be conceptually equivalent to each other: they may go about tackling the issue from different angles, but they should always end up reaching the same conclusion. But as things stand now, if $x = -2 | 2, these result in two very different conclusions: the first evaluates as true, the second as false. This most certainly doesn't do what I mean until I have been indoctrinated into the intricacies of Perl and learned to think like it does - which runs directly counter to the principle of DWIM. Perhaps instead of 0 <= any(-1,1) <= 0, the programmer might want 0 <= all(-1,1) <= 0, which is false. You're assuming that the programmer gets to choose which junction he's sticking in the middle of the comparison chain. ...becomes: 0 <= -1 | +1 && +1 <= 0 ...which, obviously, is false. The question really is what is the desired meaning of this conditional. Yes. And my answer is that the desired meaning of "0 <= -1 | +1 <= 0" is closer to "(0 <= -1 <= 0) or (0 <= +1 <= 0)" than it is to "(0 <= -1 or 0 <= +1) and (-1 <= 0 or +1 <= 0)". The trick is to figure out how to get this result without needing a nightmarish amount of overhead to do it. -- Jonathan "Dataweaver" Lang
Re: S08 Draft questions (Captures and Signatures)
Jonathan Worthington wrote: > Jon Lang wrote: >> >> Invocants: >> >> * Does anyone object to roles having an invocant, and that invocant >> referring to the class that is doing the role? >> >> > > Yes; on further reflection, the ability to type that invocant raises all > kinds of possible WTFs without a good enough use case. So I'd really rather > we don't go down this road. How does this situation differ from the ability to type a method's invocant? I'm thinking that an argument might be made that you don't get to specify any invocant's type: a method's invocant would always be typed as the class to which it belongs (with the value set as the object calling it), while a role's invocant would always be typed as a type reference (i.e., the :: sigil), with the value being the class composing it. Would any significant functionality be lost in such a move? >> Longnames: >> >> * Are placeholder parameters ever considered to be part of a >> function's longname? (I'm expecting that they aren't: if you want a >> longname, you ought to specify it in a formal signature.) >> >> > > Placeholder parameters result in a signature being generated based upon > them, as far as I can tell (and so far as we've implemented in Rakudo). So > yes, they would all count in the long name - or at least, the positional > ones. Also note that if you do have placeholder parameters it's illegal to > write a signature on the block too. True: forbidding placeholder parameters from counting as part of the longname would effectively forbid functions that use placeholder parameters from _having_ a longname; and if you've explicitly asked for one (via the "multi" keyword), you should get one. >> Placeholder parameters: >> >> * does the use of placeholder parameters interfere with the use of the >> slurpy parameters normally provided by the default signature (i.e., >> *...@_ and *%_)? I'm guessing not. >> > > We only generate *...@_ and *%_ for subs when there is no signature; the > presence of placeholder parameters generates a signature, so you'd not get > them. Exception: methods, where by S12 we always add a *%_ unless the method > defines its own slurpy named parameter. Is this the desired behavior, or merely the current behavior? I can see a case for wanting the placeholder parameters to be pushed onto front of the default signature instead of replacing it. -- Jonathan "Dataweaver" Lang
Re: S08 Draft questions (Captures and Signatures)
Em Ter, 2009-03-31 às 22:54 -0700, Jon Lang escreveu: > Yes, I know that there is no S08. I'm working on writing one, and I'd > like some feedback to help me do so. ++ > My draft is going to be about Signatures and Captures. Thus, my questions: > Invocants: The concept of "invocant" only exists in terms of syntax now. In runtime the invocant is simply the first positional argument. This simplifies things a lot. > * Is it illegal to specify an invocant in a sub, or is it merely > nonsensical? There's nothing wrong about it. In fact, every time you do "my method" or "our method", you end up with a sub that has an invocant in its signature. > silently treat the invocant as the first positional parameter? Yes, that is basically the major side-effect on the latest capture change. As I said before, the invocant only exists in terms of syntax, it doesn't exist in terms of runtime. > * Likewise, if I interpolate a signature with an invocant into another > signature (somewhere other than at the start), is this an error, or > will the invocant be silently converted into an ordinary positional > parameter? What does "interpolate a signature" mean? But anyway, the invocant is the first positional argument, period. > * What types are you allowed to assign to an invocant? It's just a positional argument. But I suppose that on method declarations, the type of the invocant is ::?CLASS. (Although there is some debate if it's going to make some declarations too narrow unintentionally. > * Does anyone object to roles having an invocant, and that invocant > referring to the class that is doing the role? You mean methods declared in a role? Yes, they have an invocant, but the invocant type in the signature could be just the role, I guess... > * Why are we using ";;" to denote the end of a multi function's > longname? Because a capture may have more than one dimension, which would be delimited by ";". > * Can any required parameter be part of the longname, or are only > positional parameters allowed? (I'm expecting the latter; but I'd > like confirmation.) I suspect you meant "named parameter" in place of "required parameter". For Perl 6.0.0, it is accepted that named parameters don't take part in multi dispatch. > * Are placeholder parameters ever considered to be part of a > function's longname? (I'm expecting that they aren't: if you want a > longname, you ought to specify it in a formal signature.) placeholder variables are just a simplified way of writing a signature, after they are compiled, the routine has a regular signature, which means that it should work as if the signature was explicit. > * Must required named parameters be defined before optional named > parameters are, or are we allowed to interleave the two? named parameters order are, most of the time, irrelevant. But you can have the same named parameter twice, iirc. So, I don't think you need to put mandatory named parameters before the regular ones... > * does the use of placeholder parameters interfere with the use of the > slurpy parameters normally provided by the default signature (i.e., > *...@_ and *%_)? I'm guessing not. Yes, it does. The default signature is the *default*. Having placeholder parameters imply defining a signature, one could argue that *...@_ and *%_ are still part of that generated signature, but @_ certainly won't contain the values that were in the placeholder parameters. daniel
Re: simultaneous conditions in junctions
On Wed, Apr 1, 2009 at 12:58 AM, Richard Hainsworth wrote: > Thinking about Jon Lang's -1|+1 example in another way, I wondered about > simultaneous conditions. > > Consider > > $x = any (1,2,5,6) > > How do we compose a conditional that asks if any of this set of eigenstates > are simultaneously both > 2 and < 5? > Clearly the desired answer for $x is False, but > > my $x = any(1,2,5,6); say ?( 2 < $x < 5); # true > > Is there some combination of any/all that will achieve this? As Carl indicated, there are other ways to do this. For instance, s/ 2 < $x < 5 / $x ~~ 2 ^..^ 5 /. But as I indicated in a recent email, part of my concern is that those two expressions _ought to be_ equivalent: changing the junction, or making do without one as Carl proposes, doesn't fix this lack of equivalence. As for Carl's proposed alternative: no, it isn't _much_ longer (but it _is_ longer), and _perhaps_ it's _slightly_ more understandable - or perhaps not. Other than making the implementors' lives harder, what's wrong with trying to find a way to get Jonathan's example to work the way people expect it to? I don't understand this aversion to everything remotely hinting of eigenstates/eigenthreads/threshing/whatever. -- Jonathan "Dataweaver" Lang
Re: S08 Draft questions (Captures and Signatures)
On Wed, Apr 1, 2009 at 5:07 AM, Daniel Ruoso wrote: > Em Ter, 2009-03-31 às 22:54 -0700, Jon Lang escreveu: >> Yes, I know that there is no S08. I'm working on writing one, and I'd >> like some feedback to help me do so. > > ++ > >> My draft is going to be about Signatures and Captures. Thus, my questions: >> Invocants: > > The concept of "invocant" only exists in terms of syntax now. In runtime > the invocant is simply the first positional argument. This simplifies > things a lot. I think you're confusing signatures with captures here. Captures and the arguments that they, well, capture, don't care about the invocant; but signatures and the parameters that they define still do. >> * Likewise, if I interpolate a signature with an invocant into another >> signature (somewhere other than at the start), is this an error, or >> will the invocant be silently converted into an ordinary positional >> parameter? > > What does "interpolate a signature" mean? ...my bad. For some reason, I made the opposite mistake: I thought that it was possible to assemble a signature out of other signatures. >> * Why are we using ";;" to denote the end of a multi function's >> longname? > > Because a capture may have more than one dimension, which would be > delimited by ";". Note that I didn't propose ";" as the longname terminator. >> * Can any required parameter be part of the longname, or are only >> positional parameters allowed? (I'm expecting the latter; but I'd >> like confirmation.) > > I suspect you meant "named parameter" in place of "required parameter". I meant both, actually: can required named parameters be part of the longname? > For Perl 6.0.0, it is accepted that named parameters don't take part in > multi dispatch. OK. >> * does the use of placeholder parameters interfere with the use of the >> slurpy parameters normally provided by the default signature (i.e., >> *...@_ and *%_)? I'm guessing not. > > Yes, it does. The default signature is the *default*. Having placeholder > parameters imply defining a signature, one could argue that *...@_ and *%_ > are still part of that generated signature, but @_ certainly won't > contain the values that were in the placeholder parameters. ...nor would I expect it to. I'm just wondering if (@_, %_) _are_ still part of a placeholder-generated signature. In short, is there a way to access a slurpy array or hash in a block that uses placeholder parameters? -- Jonathan "Dataweaver" Lang
Re: S08 Draft questions (Captures and Signatures)
Em Qua, 2009-04-01 às 05:41 -0700, Jon Lang escreveu: > On Wed, Apr 1, 2009 at 5:07 AM, Daniel Ruoso wrote: > > The concept of "invocant" only exists in terms of syntax now. In runtime > > the invocant is simply the first positional argument. This simplifies > > things a lot. > I think you're confusing signatures with captures here. Captures and > the arguments that they, well, capture, don't care about the invocant; > but signatures and the parameters that they define still do. Not at all, if you declare a method with "my" or "our", it is seen as a sub (as with "is export"), but it will still have the same signature. So, the invocant only exists in the syntax even for signatures, in runtime, they are simply the first argument... Which, in terms of code, means: my method foo($b,$c) {...} $a.foo($b,c); foo($a,$b,$c); In both invocations, $a is seen by foo as "self", because that is how the signature is defined. > >> * Why are we using ";;" to denote the end of a multi function's > >> longname? > > Because a capture may have more than one dimension, which would be > > delimited by ";". > Note that I didn't propose ";" as the longname terminator. I see, but the idea of using ";;" is to be something invariably stronger than ";" . > ...nor would I expect it to. I'm just wondering if (@_, %_) _are_ > still part of a placeholder-generated signature. In short, is there a > way to access a slurpy array or hash in a block that uses placeholder > parameters? I'd guess not, but I think it's a plain design decision. In my head, the default slurpy only makes sense when no signature is provided at all, and only for some mindset compatibility with Perl 5. In fact... cases like: for 1,2,3,4,5,6 { say $^a, $^b } Imply that you can't have the slurpies there, otherwise the for loop would be run only once... daniel
Re: [Fwd: Re: junctions and conditionals]
On Wednesday, April 01 2009 07:38 am, Richard Hainsworth wrote: > Right now, yes. I'm arguing that the way that they're designed to > work doesn't DWIM. Try a slightly different example: > > 0 <= $x <= 1 # 0 is less than $x is less than 1. > $x ~~ 0..1 # $x is in the range of 0 to 1. > > I submit that most people would expect these two statements to be > conceptually equivalent to each other: they may go about tackling the > issue from different angles, but they should always end up reaching > the same conclusion. But as things stand now, if $x = -2 | 2, these > result in two very different conclusions: the first evaluates as true, > the second as false. This most certainly doesn't do what I mean until > I have been indoctrinated into the intricacies of Perl and learned to > think like it does - which runs directly counter to the principle of > DWIM. When you say DWIM, I take it you mean that there is an assumption that $x is a point in a field (http://en.wikipedia.org/wiki/Field_theory_(mathematics)). As you have illustrated, junctions do no form a field. You would run into the similar problems if $x was a point in a ring (http://en.wikipedia.org/wiki/Ring_(mathematics)). Consider the ring of "integers modulo 8": my Ring8 $x = 5 + 3;# evaulates to "0" say "OMG, its 0!" unless $x;# prints the message which does not DWIM if I am expecting $x to be part of a field. Maybe the problem is that junctions are too easy to create, which is causing people to confuse the "mathematical" structure of the space created by using a junction with that of the structure of the space of the underlying (non-junctioned) object. Regards, Henry
Re: simultaneous conditions in junctions
The idea is that junctions should usually be invisible to the code, and autothreading handles them behind the scenes. Once you start using the eigenstates as a collection, you're breaking the model and not gaining anything over just using a regular collection type. But the "behind the scenes" model fails when a junction passes through a condition into guarded code that assumes the condition is true, unless the eigenstates inside the guard are restricted to those for which the condition is true. Consider: my $x = 2|0; my $y = $x ?? 1/$x !! 0; The expected result is presumably $y == 0|.5, but if the $x in the denominator isn't restricted to the eigenstates that pass the conditional, you get a divide by zero in one of the autothreads. The code needs to behave as if each eigenstate is treated independently by a separate thread, and only combined back into a junction at the end of each autothreaded block, even if the implementation doesn't actually do it that way. We can't just test a junction using its junctive semantics and fall through with the junction intact. To go back to the Blackjack example: for junctions to apply, code written with the assumption that each hand's sum is a simple number should work when they're actually junctions. But that's not the case because the end goal is to pick a single winner, not a junction of possible winners depending on how you assign values to the Aces. There are specific rules for the selection of Ace values that don't necessarily follow junctive semantics, and just letting things thread through will not yield the right answer in all cases. (Yes, for those keeping score at home, I changed my mind about the applicability of junctions to that problem...) On 4/1/09, Jon Lang wrote: > On Wed, Apr 1, 2009 at 12:58 AM, Richard Hainsworth > wrote: >> Thinking about Jon Lang's -1|+1 example in another way, I wondered about >> simultaneous conditions. >> >> Consider >> >> $x = any (1,2,5,6) >> >> How do we compose a conditional that asks if any of this set of >> eigenstates >> are simultaneously both > 2 and < 5? >> Clearly the desired answer for $x is False, but >> >> my $x = any(1,2,5,6); say ?( 2 < $x < 5); # true >> >> Is there some combination of any/all that will achieve this? > > As Carl indicated, there are other ways to do this. For instance, s/ > 2 < $x < 5 / $x ~~ 2 ^..^ 5 /. But as I indicated in a recent email, > part of my concern is that those two expressions _ought to be_ > equivalent: changing the junction, or making do without one as Carl > proposes, doesn't fix this lack of equivalence. > > As for Carl's proposed alternative: no, it isn't _much_ longer (but it > _is_ longer), and _perhaps_ it's _slightly_ more understandable - or > perhaps not. Other than making the implementors' lives harder, what's > wrong with trying to find a way to get Jonathan's example to work the > way people expect it to? > > I don't understand this aversion to everything remotely hinting of > eigenstates/eigenthreads/threshing/whatever. > > -- > Jonathan "Dataweaver" Lang > -- Sent from my mobile device Mark J. Reed
r26042 - docs/Perl6/Spec
Author: moritz Date: 2009-04-01 16:03:18 +0200 (Wed, 01 Apr 2009) New Revision: 26042 Modified: docs/Perl6/Spec/S04-control.pod Log: [S04] fixed illegal construct, sbp++ Modified: docs/Perl6/Spec/S04-control.pod === --- docs/Perl6/Spec/S04-control.pod 2009-03-31 18:23:14 UTC (rev 26041) +++ docs/Perl6/Spec/S04-control.pod 2009-04-01 14:03:18 UTC (rev 26042) @@ -312,7 +312,7 @@ ... } -while something() -> { ... $^thing ... } +while something() { ... $^thing ... } Nothing is ever bound implicitly, however, and many conditionals would simply bind True or False in an uninteresting fashion. This mechanism
Re: simultaneous conditions in junctions
On Wed, Apr 01, 2009 at 09:44:43AM -0400, Mark J. Reed wrote: > The idea is that junctions should usually be invisible to the code, > and autothreading handles them behind the scenes. [ ... ] If I understand correctly, (which is by no means assured) a function call with a junction as an argument generally acts as if it were autothreaded. So: $x = any(1,2,3); $y = f($x); should work like: $y = any( f(1), f(2), f(3) ); Right? sub f($x) { return $x < 1.5 < $x ?? $x :: undef; } $y = f($x); $z = $x < 1.5 < $x ?? $x :: undef; Unless autothreading is also implied by conditionals, $y and $z would have significantly different results; $y === any(undef,undef,undef) while $z === any(1,2,3). But, if autothreading *is* implied by conditionals, where do the threads get joined? I have a feeling that the autothreading has to happen essentially at the point of the creation of the junction to avoid getting a result from a junction that none of the joined quantities is capable of justifying (such as the one described ealier of (-4|4) matching the criteria to be in the range 0..1). I suspect that juctions will be perl6's "action-at-a-distance" hazard. (With quantum entanglement, you get action-at-a-distance effects in the real world. When we import them into a computer language, the resulting action-at-a-distance should come as no surprise - except for its inherent surprise/hazard nature.) Now, if it is acceptable for -4|4 to return true for 0 <= $x <= 1 when tested directly in an expression, but to return false if it is tested in a subroutine, then perl6 junctions are not really modelling quantum superpositions and I, at least, will need to find a different metaphor for what they actually do do (and for what they can be used for and when).
Re: simultaneous conditions in junctions
Richard Hainsworth wrote: Thinking about Jon Lang's -1|+1 example in another way, I wondered about simultaneous conditions. Consider $x = any (1,2,5,6) How do we compose a conditional that asks if any of this set of eigenstates are simultaneously both > 2 and < 5? Clearly the desired answer for $x is False, but my $x = any(1,2,5,6); say ?( 2 < $x < 5); # true Is there some combination of any/all that will achieve this? Here it would seem that we would want to have some sieving, so that eigenstates that are true for one test can be given to another test. One answer is to use "grep": $x = any (1,2,5,6); say ?( (2^..^5).grep: { $_ == $x } ); # "False" This isn't, of course, quite what you asked for, because the semantics of relops are continuous. So you'd want something like: $x = any (1,2, 2.5, 5,6); say ?( (2^..^5 :real).grep: { $_ == $x } ); # "False" (or whatever the syntax for a continuous range is). That might take a while to complete, hence my desire for an analytic grep That said, the semantics of a chained relop really should work correctly for this. If you only reference a junction once in an expression, then it should behave as such: {a
Re: junctions and conditionals
HaloO, Jon Lang wrote: Another issue: what happens if conditional code mutates a junction that it filtered? For example: $x = any (-5 .. 5); if $x > 0 { $x++ }; At this point, which of the following does $x equal? any(-4 .. 6) # the original junction gets mutated any(-5 .. 0, 2 .. 6) # the filtered part of the original junction gets mutated; the rest is untouched any(2 .. 6) # the filtered part of the original junction gets mutated; the rest is lost This is an example why the controlled block should not be auto-threaded. That is the assembly point of the resulting junction any(0,0,0,0,0,1,1,1,1,1) is before the block. Thus I'm opting for any(-4..6). Regards, TSa. -- "The unavoidable price of reliability is simplicity" -- C.A.R. Hoare "Simplicity does not precede complexity, but follows it." -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: [Fwd: Re: junctions and conditionals]
HaloO, Richard Hainsworth wrote: ( $a <= any(-1,+1) && any(-1,+1) <= $b )(*A) [..] $tmp = any(-1,+1); $a <= $tmp && $tmp <= $b (*B*) Quite how the lines I have labelled (A) and (*B*) are different, I do not understand. Unless wrapping a junction in a variable produces a different result. That was my initial reaction as well. A closer examination of Martin's message indicates that he tends to think that hitting a junction ought to thread the entire program throughout the rest of the lifespan of said junction, so that (e.g.) the thread that runs the comparison "$a <= -1" in (*B*) is the same thread that runs the comparison "-1 <= $b". OTOH, since (*A*) spells out two separate junctions, it would thread each one separately; resulting in four threads being used to resolve the expression. In theory, at least; in practice, he's looking for ways to simulate such threading without actually having to mess with all of the overhead that a literal implementation thereof would entail. I like to throw in that junctions are value types. That is the two literal junctions in (*A*) are one and the same object and hence the global auto-threading should be the same as with an explicit variable. I like the idea of global auto-threading because it matches the behavior of the unitary state changes of quantum systems. That is it is the individual states that interact in a non-entangled fashion as part of a larger ensemble of execution paths ala Feynman. Just as in quantum mechanics there are collapse points of junctions in boolean context e.g. in an if statement. But if we define that && is not collapsing than it becomes part of a scope that a junction auto-threads through. Note that the collapse points are statically known from the structure of the source code! Literal junctions within this stretch of code need to be assembled as implicit parameters of the code block that implements the conditional of an if block. With the parameters upfront it is unimportant if the runtime systems starts multiple threads or iterates the junction sequentially. But a lightweight thread implementation boosts performance, of course. An important thing that has to go into the spec is how side-effective code is handled in conditionals. E.g. if $x.foo < $x.bar < $x.baz {...} first of all is specced to evaluate $x.bar only ones. But is it also specced that the three calls are evaluated left to right such that .foo can influence .bar? Also the $x.baz can be short circuited. The point I want to make is that in quantum computation a NOT gate *does* flip the individual value of the entangled states of a qubit. That is !any(0,1) becomes any(1,0) in such a way that it knows which 0 has become 1 and vice versa for as long as the scope of the junction runs. As of now this negation in Perl 6 is a no-op! And we should stop to compare the current junctions to quantum superposition! Other equivalences should hold as well. E.g. if one expands $x ^ $y to (!$x && $y) || ($x && !$y) it should result in the same program behavior irrespective of $x or $y being junctions. In both cases, the problem arises when you apply a predicate to a junction, and then use the junction within code that only gets executed according to the truth of the predicate. This implies that junctions also thread through the controlled block of an if. I hope that my assertion that structural analysis of the code suffices to define the points where the auto-threads are re-assembled into a junction still holds in this case. What I'm hearing is that a decision has already been made on this matter, so we're stuck with it no matter how counterintuitive the results of that decision are. You mean the decision that junction is now a native type with a private .eigenstates method? I think that is reasonable. The nativeness of the type is reflected in the fact that the junctive behavior becomes a structural property of the code. That is the junction as such has no magic. This magic is in the compiler! The junction as a native type is a simple list of values. The above to me implies BTW some finer control for signatures to specify what kind of junction they allow. E.g. :(Int $) auto-threads from the outside, :(Object $) passes a junction without auto-threading. But is :(junction of Int $) the right way to say that you want to deal with any(1,2,3) but not any('a','b','c')? That means that: 0 <= -1 | +1 <= 0 which is true, because using standard chaining semantics we have 0 <= -1|1 and -1|1 <= 0 No, there should be an outer scope that is in charge of auto-threading the junction through which was created by the compiler from the -1|+1 even though it sits in the middle of the conditional. I would call that junction propagation. Since the first condition is true (+1 >= 0) and the second condition is true (-1 <=0), the compound is true. Why you might want such a condition, I dont know. But th
Re: junctions and conditionals
Jon Lang wrote: [proposal that conditional statements should collapse junctions] $x = +1 | -1; if $x > 0 { say "$x is positive." } else { say "$x is negative." } I suspect that both codeblocks would be executed; but within the first block, $x == +1, and within the second codeblock, $x == -1. The problem I see with this (other than implementation issues) is that it would lead to unintuitive behavior in some cases: my $x = one(10,20); if $x > 15 { # here, $x collapsed to "20" if $x > 5 { say "$x > 5" } else { say "not $x > 5" } } if $x > 5 { say "$x > 5" } else { say "not $x > 5" } Some people might be surprised if the two tests of "$x > 5" result in two different results. I don't think that there is any single semantics that won't cause surprises (unintuitive behavior) in some cases. So I'd vote for going with simple semantics that are easy to explain -- that is, don't attempt implicit junctional collapse. Provide operators to collapse when needed, but don't attempt to be too clever.
Re: S08 Draft questions (Captures and Signatures)
On Wed, Apr 01, 2009 at 09:55:37AM -0300, Daniel Ruoso wrote: > Em Qua, 2009-04-01 às 05:41 -0700, Jon Lang escreveu: > > ...nor would I expect it to. I'm just wondering if (@_, %_) _are_ > > still part of a placeholder-generated signature. In short, is there a > > way to access a slurpy array or hash in a block that uses placeholder > > parameters? > > I'd guess not, but I think it's a plain design decision. @_ and %_ are part of a placeholder-generated signature if they're mentioned in the block. From S06:154: Note also that if the sub's block contains placeholder variables (such as C<$^foo> or C<$:bar>), those are considered to be formal parameters already, so in that case C<@_> or C<%_> fill the role of sopping up unmatched arguments. That is, if those containers are explicitly mentioned within the body, they are added as slurpy parameters. [...] Pm
Re: S08 Draft questions (Captures and Signatures)
HaloO, Moritz Lenz wrote: * What types are you allowed to assign to an invocant? Whatever the type constraint says. When you write class Foo { method bar ($x, $y) }, then bar's signature gets an invocant of type Foo implicitly. If you write ... method bar (A $s:, $x, $y), then the type constraint is A. I would say that the class is always implicitly the type constraint on the invocant. That is class Foo { method bar (A $s: $x, $y) } makes the type constraint the juxtaposition of Foo and A. And $s can only access the public interface of A. An interesting question is if methods are allowed outside of a class scope. That is, the type constraint of the invocant inserts it into the class. Perhaps in a non-privileged form, i.e. without access to private attributes and methods. Does that make sense? Regards, TSa. -- "The unavoidable price of reliability is simplicity" -- C.A.R. Hoare "Simplicity does not precede complexity, but follows it." -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: simultaneous conditions in junctions
HaloO, John Macdonald wrote: Unless autothreading is also implied by conditionals, $y and $z would have significantly different results; $y === any(undef,undef,undef) while $z === any(1,2,3). This is why I'm opting for statical analysis of auto-threaded conditionals. But, if autothreading *is* implied by conditionals, where do the threads get joined? Right after the conditional, of course. From there it could be necessary to branch into both blocks however if you have a result of any(0,1) and an else block. ?? !! essentially behaves like an if else. Question is how this applies to user defined control structures. I have a feeling that the autothreading has to happen essentially at the point of the creation of the junction to avoid getting a result from a junction that none of the joined quantities is capable of justifying (such as the one described ealier of (-4|4) matching the criteria to be in the range 0..1). I suspect that juctions will be perl6's "action-at-a-distance" hazard. (With quantum entanglement, you get action-at-a-distance effects in the real world. Quantum entanglement is no action at a distance because you can't transfer anything with the collapse. The local appearance is that of a normal quantum measurement. Only if you communicate information by traditional means you can compare *measurements*. The common misconception of Quantum Mechanics is that it is about small things whereas a two photons system can span galaxies. When we import them into a computer language, the resulting action-at-a-distance should come as no surprise - except for its inherent surprise/hazard nature.) Now, if it is acceptable for -4|4 to return true for 0 <= $x <= 1 when tested directly in an expression, but to return false if it is tested in a subroutine, then perl6 junctions are not really modelling quantum superpositions I agree. We should make sure that junctions model quantum computations. Regards, TSa. -- "The unavoidable price of reliability is simplicity" -- C.A.R. Hoare "Simplicity does not precede complexity, but follows it." -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: junctions and conditionals
On Wed, Apr 1, 2009 at 11:49 AM, Dave Whipp wrote: > The problem I see with this (other than implementation issues) is that it > would lead to unintuitive behavior in some cases: > > my $x = one(10,20); > if $x > 15 { > # here, $x collapsed to "20" > if $x > 5 { say "$x > 5" } else { say "not $x > 5" } > } > if $x > 5 { say "$x > 5" } else { say "not $x > 5" } > > Some people might be surprised if the two tests of "$x > 5" result in two > different results. That's surprising, yes, but I'd say the surprise comes from the fact that it's a one() junction, which has extra weirdness on top of the general junctional weirdnesses. So yes, if we collapse the junction, $x is both > 5 and not > 5 according to the output. If we *don't* collapse, $x will consistently fail the $x > 5 test - but then you have a value that is somehow both greater than 15 and not greater than 5, which I would still call surprising. I don't think that there is any single semantics that won't cause surprises > (unintuitive behavior) in some cases. Probably true. > So I'd vote for going with simple semantics that are easy to explain -- > that is, don't attempt implicit junctional collapse. Provide operators to > collapse when needed, but don't attempt to be too clever. While it's easier to find clever programmers than to write clever software, the gains from the latter are significant, as Larry's work pre- and post-Perl has repeatedly demonstrated. When a language implementation provides a feature like junctions that is arguably too clever by half to start with, I'd rather there be a commensurate amount of cleverness in the support of that feature. Basically, I want the specified behavior to make sense as much as possible, and for it to be easy to explain the places where it doesn't seem to make sense. Even if it means we don't get that behavior in 6.0.0. -- Mark J. Reed
Re: S08 Draft questions (Captures and Signatures)
On Tue, Mar 31, 2009 at 10:54:33PM -0700, Jon Lang wrote: : * Why are pointy blocks forbidden from enclosing their signatures in : parentheses, or from using the ":( ... )" notation? Is this a : holdover from the early days, when parentheses denoted a list? Or is : there still a good reason not to allow such notation? Because subsignatures within a signature match a single argument with that subsignature, on the assumption that the argument is something resembling a capture. Larry
Re: simultaneous conditions in junctions
On Wed, Apr 01, 2009 at 08:40:12AM -0700, Dave Whipp wrote: > That said, the semantics of a chained relop really should work correctly > for this. If you only reference a junction once in an expression, then > it should behave as such: {a
Re: junctions and conditionals
Mark J. Reed wrote: [I] wrote: So I'd vote for going with simple semantics that are easy to explain -- that is, don't attempt implicit junctional collapse. Provide operators to collapse when needed, but don't attempt to be too clever. While it's easier to find clever programmers than to write clever software, the gains from the latter are significant, as Larry's work pre- and post-Perl has repeatedly demonstrated. When a language implementation provides a feature like junctions that is arguably too clever by half to start with, I'd rather there be a commensurate amount of cleverness in the support of that feature. Basically, I want the specified behavior to make sense as much as possible, and for it to be easy to explain the places where it doesn't seem to make sense. Even if it means we don't get that behavior in 6.0.0. I'm thinking that the solution to this issue may be a little more radical than to-date: don't permit junctions to be stored in $ variables! Instead, require junctions to use a twiggle, to alert the reader that the surprises may be lurking. my $x = 1|2; #error my $|x = 1|2; # ok Then you just need to invent some syntax to say that collapse is (or perhaps isn't) desired: if [[ $|x > 1 ]] { say "$|x collapsed" } The most important thing that this does is that it leaves open the option to allow "$" variables to hold junctions in some future version of Perl, without that future version being constrained by legacy semantics.
Re: junctions and conditionals
On Tue, 31 Mar 2009, Jon Lang wrote: > Another issue: what happens if conditional code mutates a junction > that it filtered? For example: > > $x = any (-5 .. 5); > if $x > 0 { $x++ }; > > At this point, which of the following does $x equal? > > any(-4 .. 6) # the original junction gets mutated > any(-5 .. 0, 2 .. 6) # the filtered part of the original junction > gets mutated; the rest is untouched > any(2 .. 6) # the filtered part of the original junction gets > mutated; the rest is lost I choose #3. Reality can only take one path through a conditional; which one depends on the one/any/all/none binding of the junction. Once you've passed the conditional, you have: one -> single matching value (no longer a junction) any -> filtered list all -> original junction none -> empty (*1) The "threading" is an implementation detail; the important thing is a junction is collection of values and a smart way of rewriting expressions that contain them, with special treatment for comparison operators (or indeed anything that forces Boolean content): $x CMP all($y,$z) $x CMP $y && $x CMP $z $x CMP one($y,$z) $x CMP $y ^^ $x CMP $z (*2) $x CMP none($y,$z) all($x !CMP $y, $x !CMP $z) $x CMP any($y,$z) $x !CMP none($y, $x) $x OP all($y,$z)all( $x OP $y, $x OP $z) $x OP any($y,$z)any( $x OP $y, $x OP $z) $x OP one($y,$z)one( $x OP $y, $x OP $z) $x OP none($y,$z) none($x OP $y, $x OP $z) -Martin (*1: An argument could be made that "none" should leave the junction alone, the same as "all".) (*2: I would like to suggest that the semantics of "one" be changed to mean "pick one" (randomly) rather than "exactly one". In this respect it would be the same as "any" except it wouldn't have the overhead of filtering *every* match, just at least one.)
Re: [Fwd: Re: junctions and conditionals]
On Wed, 1 Apr 2009, Richard Hainsworth wrote: > A closer examination of Martin's message indicates that he tends to think > that hitting a junction ought to thread the entire program throughout the > rest of the lifespan of said junction Yes -- and well put, thank-you. The trick is that since conditionals generally force full or partial resolution on junctions, that lifetime won't tend to be very long. Re: Tsa's comment about junctions being "value types". In principle I agree, except that the value semantics are only within the eigenthreads; outside that, they are collections of indeterminate state. Indeterminate states aren't sufficiently "value-like" to justify "constant folding". -Martin
Re: simultaneous conditions in junctions
On Wed, 1 Apr 2009, John Macdonald wrote: > If I understand correctly, (which is by no means assured) a function > call with a junction as an argument generally acts as if it were > autothreaded. So: > > $x = any(1,2,3); > $y = f($x); > > should work like: > > $y = any( f(1), f(2), f(3) ); > > Right? In general yes. However if "f" involves some kind of "truth inversion" then logically f(any(@x)) == all(map.assuming(&f).(@x)) and f(all(@x)) == any(map.assuming(&f).(@x)) I have in mind something like these in the "standard preamble": prefix:«!»(Bool) does(junctive_inversion) prefix:«not»(Bool) does(junctive_inversion) infix:«ne»(String,String) does(junctive_inversion) infix:«!=»(Num,Num)does(junctive_inversion) infix:«!==»(Object,Object) does(junctive_inversion) (Excuse the rather lose syntax, but I hope you get the idea.) -Martin