Re: Junctions again (was Re: binding arguments)
On 1/4/06, Luke Palmer <[EMAIL PROTECTED]> wrote: > Of course, this was introduced for a reason: > > sub min($x,$y) { > $x <= $y ?? $x !! $y > } > sub min2($x, $y) { > if $x <= $y { return $x } > if $x > $y { return $y } > } > > In the presence of junctions, these two functions are not equivalent. > In fact, it is possible that both or neither of the conditionals > succeed in min2(), meaning you could change the order of the if > statements and it would change the behavior. This is wacky stuff, so > we said that you have to be aware that you're using a junction for > "safety". > > But now I'm convinced, but I've failed to convince anyone else, that > the behavior's being wacky doesn't mean that it should be declared, > but that the behavior is just plain wrong. I figure that if something > says it's totally ordered (which junctions do simply by being allowed > arguments to the <= function), both of these functions should always > be the same. The fact is that junctions are not totally ordered, and > they shouldn't pretend that they are. To me, this implies that junctions don't have a complete definition. Either they're ordered or they're not. Either I can put them in a <= expression and it makes sense or I can't. If it makes sense, then that implies that if $x <= $y is true, then $x > $y is false. Otherwise, the definitions of <= and > have been violated. And, if I can't put them in a <=, then Perl should complain very loudly, just as if I put something else that shouldn't be put into <=, like a Person object. If I call min() or min2() with a Person object and an array, I should expect loud complaints from the runtime. If a junction cannot behave itself in a numeric comparison, then similar complaints should be made. Rob
Re: Junctions again (was Re: binding arguments)
Rob Kinyon wrote: > To me, this implies that junctions don't have a complete definition. > Either they're ordered or they're not. Either I can put them in a <= > expression and it makes sense or I can't. If it makes sense, then that > implies that if $x <= $y is true, then $x > $y is false. Otherwise, > the definitions of <= and > have been violated. I'll beg to differ. If you insist on that kind of restriction on Junctions, they won't be able to serve their original (and primary) purpose of aggragating comparison tests together. Remember: if $x <= 1 & 5 {...} is intended to be 'shorthand' for if $x <= 1 && $x <= 5 {...} Therefore, $x = 3; if $x <= 1 & 5 {say 'smaller'} if $x > 1 & 5 {say 'larger'} should produce exactly the same output as $x = 3; if $x <= 1 && $x <= 5 {say 'smaller'} if $x > 1 && $x > 5 {say 'larger'} If it doesn't, then Junctions are useless and should be stricken from Perl 6. And the definition of '>' is "greater than", not "not (less than or equal to)". The latter is a fact derived from how numbers and letters behave, not anything inherent in the comparison operator. Just like '<=' is "less than or equal to", as opposed to "not greater than". You aren't violating the definitions of <= and > by failing to insist that they be logical negations of each other; you're only violating the common wisdom. -- Jonathan "Dataweaver" Lang
Re: binding arguments
Ingo Blechschmidt skribis 2005-12-25 17:37 (+0100): > I disagree about binding only being a language thing: I fail to see how your example code illustrates your disagreement. > return 42 > if (my $short := $long_parameter_name) == $specialcase; That's terribly horrible style! > push @foo, (my $head := pop @grtz); A bit better style, but I'd still recommend against it. > (Unless of course, you consider this to be obfuscation.) Not obfuscation, but horrible style. You're doing something in an expression that has no effect on what happens in the expression itself. ($bar = $foo) =~ s/// is useful because you need a copy, and the inline copying is a clear indication of $bar's function: to be $foo in its state after s///. The same thing with := instead of = would be horrible, because $bar and $foo would be the same thing, during and after the expression, and the aliasing itself had nothing to do with the substitution. Juerd -- http://convolution.nl/maak_juerd_blij.html http://convolution.nl/make_juerd_happy.html http://convolution.nl/gajigu_juerd_n.html
Re: binding arguments
Hi, Juerd wrote: > Ingo Blechschmidt skribis 2005-12-25 17:37 (+0100): >> I disagree about binding only being a language thing: > > I fail to see how your example code illustrates your disagreement. > >> return 42 >> if (my $short := $long_parameter_name) == $specialcase; I inferred that you think/thought that binding should/can't be used in expressions: Juerd wrote: > That works very well, because binding as an expression makes no sense > anyway, it being a language thing. Thus I wanted to demonstrate that "binding as an expression" does make sense (to me at least). Sorry if I misinterpreted your post. >> push @foo, (my $head := pop @grtz); > > A bit better style, but I'd still recommend against it. Consider: my @sites = < abc.org def.org ghi.org >; loop { push @sites, (my $site := shift @sites); check_for_updates($sites); sleep ...; } > You're doing something in an expression that has no effect on what > happens in the expression itself. Right; but I don't consider this as bad style or as "problematic". Consider a perhaps more usual example: # Perl 5 while(...) { process($tasks[$i++]); # The "++" does not have an effect on the expression itself, # writing "process($tasks[$i])" wouldn't make any difference. if(...) { $i-- } # redo the last task if(...) { $i = 0 } # redo all tasks if(...) { $i++ } # skip next task } --Ingo
Re: binding arguments
Ingo Blechschmidt skribis 2006-01-05 18:32 (+0100): > Juerd wrote: > > Ingo Blechschmidt skribis 2005-12-25 17:37 (+0100): > >> I disagree about binding only being a language thing: > > I fail to see how your example code illustrates your disagreement. > >> return 42 > >> if (my $short := $long_parameter_name) == $specialcase; > I inferred that you think/thought that binding should/can't be used in > expressions No, that's not what I meant. A "language thing" means it's mostly relevant for the way you write something as a result of the feature. In case of binding, the most used application is aliasing: getting a second way to address the same variable -- probably because the alias is less typing. > >> push @foo, (my $head := pop @grtz); > > A bit better style, but I'd still recommend against it. > Consider: > my @sites = < abc.org def.org ghi.org >; > loop { > push @sites, (my $site := shift @sites); > check_for_updates($sites); > sleep ...; > } my $site := shift @sites; push @sites, $site; check_for_updates($sites); Although in Perl 6 I'd be much tempted to do: given shift @sites { push @sites, $_; check_for_updates($_); } Because $_ is visually easy to recognise, making it immediately obvious that it's the same thing in both lines. (This is also my main argument against any style that ALWAYS provides an explicit loop variable: $_ is easy to spot, and thus is more than just easy to type.) > Consider a perhaps more usual example: > while(...) { > process($tasks[$i++]); > if(...) { $i-- } # redo the last task > if(...) { $i = 0 } # redo all tasks > if(...) { $i++ } # skip next task > } As ugly. In fact, using an index is the ugliest part of your example. Still, separately, $i++ in the process() instruction is bad style IMO. Incrementing $i is important for program flow, and should be its own statement, directly following indentation. Also, if you remove process() here, the entire program is broken, because there was an important but easy to overlook subexpression was in it. Juerd -- http://convolution.nl/maak_juerd_blij.html http://convolution.nl/make_juerd_happy.html http://convolution.nl/gajigu_juerd_n.html
Re: Junctions again (was Re: binding arguments)
On 1/4/06, Luke Palmer wrote: The other thing that is deeply disturbing to me, but apparently not to many other people, is that I could have a working, well-typed program with explicit annotations. I don't think it disturbs me... but that might just be because I don't really understand it. I could remove those annotations and the program would stop working! If it changes how the program works, then by definition doesn't that mean it wasn't really an "annotation" to begin with? As far as specifying "Junction" in signatures to control auto-threading, that always felt funny to me anyway, because it's not consistent with the normal meaning of specifying a parameter type. I would've expected "is threaded" or "is junctive" or "is junctothreaded" or something. I'm not sure if this is (part of) what you're getting at or not. In a strongly-typed language, can you always remove the typing from a working program without changing it? Or maybe just particular strongly-typed languages... in Perl, typing can be used to provide bonus information (say, as optimisation hints); but it can also be used for multiple-dispatch, so I certainly wouldn't expect a program to continue working properly if I changed *that* information. (Assuming "well-typed" refers to the former, but not the latter -- hope I've got that straight.) In that vein, I think of junctions as a sort of implicit polymorphism: I define "sub foo(Int $a)" and also get "sub foo(Junction of Ints $j)" for free. Which is why "<" acting wacky doesn't bother me -- numbers may be well-ordered, but junctions aren't, and there are two different <'s at work. Arguably, different functions should have different names to avoid confusion, but I think that calling the junctive less-than something other than "<" would be even more confusing. (Certainly it would be too unDWIMilly pedantic to be Perl.) Of course, I was also never bothered by using "+" to mean numeric addition and string concatenation. Come to think of it, perhaps that's because languages which do that are picky about distinguishing strings from numbers -- in Basic, 123 + "123" will get you a type-mismatch error, but to Perl, 123 and "123" are the same thing, so you need a numeric == and a stringic 'eq'. But Perl does know the difference between a number and a junction. That means the programmer has to follow along at home, but ok, sometimes you just gotta be aware of what your code is doing. I think I understand your Functor proposal, and it does have a certain appeal for me... but along with the advantage of making it clearer when junctions are being used, it carries the disadvantage of *requiring* you to know when junctions are being used. I can't just say "if $x<3 ..." and expect it to Do the Right Thing regardless of whether $x happens to be an ordinary number or a junction -- I have to split up the two cases and handle them separately. That's surely going to reduce the happy-go-lucky usefulness of junctions. Besides, don't we have a "no junctions" pragma that you can stick into any scope where you need exact mathematical purity? -David
Re: Junctions again (was Re: binding arguments)
HaloO, Jonathan Lang wrote: Rob Kinyon wrote: To me, this implies that junctions don't have a complete definition. Either they're ordered or they're not. So, is there a number between 0 and 1? Shades between black and white? When is a 360 degree turn not returning a system into its initial state? What has a 720 degree turn to do with sign reversal, negation and twisted arms? Anyone know the Eisenstein integers? Is 5 a prime complex number? What is its quadratic residue? (-1)**2 == -i**2 == +1 \ ?-->0 # if <=> / i**2 == -1 -- mirror symmetry axis j**2 == -1 \ !-->0 # unless <=> / (-1)**2 == -j**2 == +1 But note that *same* symmetrie is broken! Ever wondered why a mirror changes left and right, but not up and down? And what has all that to do with anagrams like 'OTTO' and 'TOOT' or with bits '.**.' and '*..*'? Or the range operators ^..^ .^^.? Conceptually the 0 has no sign unless you want it to be junctive ;) if you rotate the above vector diagrams by 120 degrees endlessly clockwise and counter clockwise you get upper: ...,0, 1,-1,0,... lower: ...,0,-1, 1,0,... which when superimposed additively lets the infinity of the lists nicely vanish. But not the same is not true if one is shifted, the other squared and then subtracted, or some such. The thing is you end up with the infinte list (...,!0,!0,...). The net effect is the same as reading the list's string representations in opposite directions. There is no dark side of the moon really! Here's the same in another ascii picture: i\+/+ -\+ +\-2**-<=>+**2+/+ -/- -/-\-i**2 center stage we find <=> which returns one(-1,0,+1) or rotations thereof: one(0,+1,-1) or one(+1,-1,0). Or the odd permutations one(0,-1,+1), one(-1,+1,0) and one(+1,0,-1). In other words three pairs of ones that cancel each other if zipped additively. The only thing we need is a neutral element to get a group. Let's take the empty one() junction. But an empty any() would do as well. These sort of represent no comparison at all and a comparison you don't care to constrain any further! In the latter case an undef return value is not unexpected, I hope. This is how that looks in an example: 'foo' cmp 'bor' --> »cmp« <-- --> (-1, +0, +1) | (+1, -0, -1) <-- The arrows indicate reading direction of the respective string. In a optimised implementation the outer f/b and and r/o give the invariant relative positions of one('foo','oof') and one('bor','rob') in the order of strings in viewing direction. At least that is the observable behaviour. Endianess of the machine, representation of junctions and what not may differ for concrete implementations of Perl6 :) Note that [?] (-1, +0, +1) »+« (+1, -0, -1) --> [?] (0,0,0) --> false With (-++) and (+--) beeing dual Minkowski metrics. Either I can put them in a <= expression and it makes sense or I can't. HiHi, this is a statement about the programmer's abilities... not about Perl 6 the language! If it makes sense, then that implies that if $x <= $y is true, then $x > $y is false. Otherwise, the definitions of <= and > have been violated. I'll beg to differ. If you insist on that kind of restriction on Junctions, they won't be able to serve their original (and primary) purpose of aggragating comparison tests together. Remember: if $x <= 1 & 5 {...} is intended to be 'shorthand' for if $x <= 1 && $x <= 5 {...} I beg to differ, two err too. I mean potentially from both depending on what they intented to say and how I understood them. My point is that the junctive case sort of means: if $x.all:{<=}(1,5) {...} where :{<=} receives similar meta treatment as [<=] reduce would. BTW, isn't bareword suffixing {<=} reserved for type theoretic manipulations? I still regard the junctions as Code subtypes and thus any{<=} and friends as parametric meta operation. Therefore, $x = 3; if $x <= 1 & 5 {say 'smaller'} if $x > 1 & 5 {say 'larger'} should produce exactly the same output as $x = 3; if $x <= 1 && $x <= 5 {say 'smaller'} This is slightly untrue. because if the junction contains two identical values or an undef ordered object the < part is essentially stripped away: if $x <= 5 && $x <= 5 {say 'smaller'} can be permuted into if $x <= 5 && 5 > $x {say 'smaller'} and optimized to if $x == 5 {say 'smaller'} if $x > 1 && $x > 5 {say 'larger'} If it doesn't, then Junctions are useless and should be stricken from Perl 6. And the definition of '>' is "greater than", not "not (less than or equal to)". The latter is a fact derived from how numbers and letters behave, not anything inherent in the comparison operator. The complete group of comparison operators imposes the
Re: Junctions again (was Re: binding arguments)
Me no follow. Please use smaller words? -- Jonathan "Dataweaver" Lang