Re: Unwanted failure and FAILGOAL
Hi Richard, Not a complete answer to your question; just an observation about your grammar: > rule TOP{ ^ + $ }; > > rule statement { '=' > | { { self.panic($/, "Declaration syntax incorrect") } } > }; > > rule endvalue { '(' ~ ')' > | { self.panic($/, "Invalid declaration.") } > } That's more or less the equivalent of: sub TOP { die if !at_start_of_input(); loop { last unless try statement() }; die if !at_end_of_input(); } sub statement { try { id(); match_literal('='); endvalue() } or die "Declaration syntax incorrect"; } sub endvalue { try { keyword(); match_literal('('); pairlist(); match_literal(')') } or die "Invalid declaration." } In which case, would you really have expected a call to TOP() NOT to throw an exception from statement(), the first time statement() couldn't match (as it inevitably won't if we're at the end of the input)??? If these were subroutines, I suspect you'd have written something more like: sub statement { try { id(); match_literal('='); endvalue() } or *!at_end_of_input()&& die "Declaration syntax incorrect"* } sub endvalue { try { keyword(); match_literal('('); pairlist(); match_literal(')' } or *!at_end_of_input()&& die "Invalid declaration.";* } which, in a regex, would be something like: rule TOP{ ^ + $ }; rule statement { '=' | * \S **# ...means we found something else, so...* * { self.panic($/, "Declaration syntax incorrect") }* }; rule endvalue { '(' ~ ')' | * \S **# ...means we found something else, so...* * { self.panic($/, "Invalid declaration.") }* } Though, personally, I'd have been inclined to write it like this: rule TOP{ ^ + *[ $ | ]* } rule statement { 'ID' '=' } rule endvalue { 'keyword' '(' ~ ')' 'pairlist' } *rule unexpected { $ = (\N+) { self.panic($/,"Expected statement but found '$'") }}* In other words: after the statements, we're either at the end of the input, or else we found something unexpected, so capture it and then report it. HTH, Damian
Perl 6 mentions on Wikipedia
Dear fellow revellers in the dawning Golden Age of Perl 6, I just had a colleague contact me, to express their surprise that Perl 6 does not rate a mention in: https://en.wikipedia.org/wiki/Functional_programming. The Perl 6 community (and Larry in particular) has already done an incredible job raising Perl 6's profile on rosettacode.org, but the language still seems under-represented on Wikipedia, especially on the various pages describing different language paradigms. As Perl 6 is now the pre-eminent example of the imperative, declarative, functional, parallel, concurrent, pipelined, vector, object-oriented, aspect-oriented, reactive, introspective, and metaprogramming paradigms, surely it should be mentioned on all those wiki pages? Yeah, I know: "Thanks for volunteering!". I can't at present, but I didn't want this important observation, or the opportunity it represents, to be lost, just because it was initially directed at someone who's currently drowning in other commitments. So I thought I'd mention it here, in the hope that someone else who is looking for a slightly unusual way to contribute to Perl 6 might find the suggestion worth considering. Damian
Re: [perl6/specs] 89cc32: Spec Bag.kxxv
> It's an awesome language, which is exactly the problem. "Inspiring > awe" is not far from inducing panic and terror, especially in people > who aren't feeling too confident in the first place. We want to be > accessible to the people who start looking nervous when the modulus > operator is added to the basic four mathematical signs as operators. This is an important point. And an area in which I believe Perl 6 can excel. I do think it will be possible to specify (and even enforce) suitable subsets of the language, to make it approachable by the easily over-awed. > Sorry if I'm being boringly repetitive, but I do see complexity as a > barrier to world domination. No, it's an important point. I get very excited about the power and sophistication of Perl 6. But I also get very excited about the straightforwardness and simplicity it can offer. It's important that we market both aspects...and to the right audiences. For example, at OSCON this year I'm concentrating on the simplicity of Perl 6: http://www.oscon.com/oscon2014/public/schedule/detail/33839 Damian
Re: [perl6/specs] 89cc32: Spec Bag.kxxv
Raiph Mellor wrote: > The .kxxv method name is a placeholder. Phew! Thanks for taking the time to respond and explain, Raiph. > The brief discussion that motivated introducing it is at: > http://irclog.perlgeek.de/perl6/2014-04-13#i_8582049 > > Larry has chimed in at: > http://irclog.perlgeek.de/perl6/2014-04-14#i_8582684 As I said before, I like the idea, just not the too-clever name. > Another discussion that's unfolding right now and could do with your > attention imo is: > https://github.com/perl6/specs/commit/9213b1382078fee890ab9d74223f3c7e95942837 Thanks for the pointer, though they seem to have resolved that question reasonably well now. ;-) > All of the above illustrates an issue that we ought to address, namely > where we best discuss this stuff to make the best use of your time: For the past few years I've been staying out of the discussion, quietly watching every doc commit, and commenting (either directly to Larry, or else on this list) whenever I was alarmed, confused, or worried by something. > 1. For the last few years almost all discussion is entirely on #perl6. Which seems to be working extremely well...just not for me. I can't manage to track these discussions (even via the logs). I find the interleaving of multiple threads utterly impossible to cope with. > The above arrangement works for us and $Larry. But I'm thinking we might > want to go back to @Larry with both you and him and figure out how we > make that work for you. You should first ask $Larry if he wants to go back to @Larry. ;-) Meanwhile, I'm reasonably happy being just a sanity check on spec commits. If there's greater need of me than that, perhaps I could also be a kind of evil djinn, to be conjured by emailed pointers (such as you so kindly provided) in cases of dire need. :-) > Did you see that lizmat has taken a stab at implementing 'is cached' -- > because she saw that that's the one unimplemented thing in some code > you recently published? She said she was going to raise the issue. I'm delighted to see her take it further than that. The lack of "is cached" was the sole point-of-failure in my "Perl 6 for CS" talk. > How confident are you that your all-in-one CS teaching platform concept > will be taken up by some educational institutions? What timeframe are > you thinking is involved here? Are you thinking P6 is already ready for it? I suspect that Rakudo-on-MoarVM is now (or very soon will be) fast enough and complete enough. It only needs to be sufficiently easy to install (e.g. a standard part of Rakudo*), which I understand is very close now. Of course, another 6-12 months of polishing...both of the specs and of the implementation...wouldn't go amiss either. In particular, the concurrency specs and implementation need to be a little more stable and tested. I have no confidence yet, however, that Perl 6 will be widely taken up as a CS teaching language. I think the presentation I made was compelling enough, but I've only given it at one institution, and my experience is that language decisions rarely get made on the basis of technical merit, or pedagogical merit... or even on the basis of mere pedagogical convenience. Rather, the decision on a teaching language usually reflects either the personal biases of the individual teacher, or those of the curriculum committee, or else mirrors the market demand of the local community. How else do we explain the awful languages that are so often taught in our universities. :-( > I don't think we're there yet but it seems like the perfect initial goal for > P6-as-a-product. I do think Perl 6 is an incredibly good fit for teaching both CS in general and programming paradigms in particular. And, if we could get it into schools, it would be a huge boost in its exposure and popularity. I'm going to continue to refine my presentation, and offer it at any educational institutions I can convince to host it in the various cities I will be visiting over the next twelve months. We'll see if I get any traction. Damian
Re: [perl6/specs] 89cc32: Spec Bag.kxxv
> Spec Bag.kxxv It's a clever name...but maybe too clever? I find it unfortunate that a method that only returns keys has a 'v' in its name. Up to now, we've had a more predictable pattern to naming these accessors. How about one of: .weighted-keys .distribution instead??? And what is the use-case for this? I can see that I might want: $bag.kxxv.pick; but: $bag.pick already does that. I guess you might want to separate out the steps for some reason: my $selection = median_value_from( $bag.kxxv ); but that would be far more readable/maintainable as: my $selection = median_value_from( $bag.distribution ); Damian
Re: [perl #121454] Can't inline complex constraints in multisub signatures
Moritz wrote: > To spin the tale further, we need to think about what happens if > somebody writes > > multi foo(1|2e0) { ... } > > so now we have Int|Num. We could explore the most-derived common > ancestor (Cool), or look into role space (Real, Numeric come to mind), > or simply error out. Or maybe we need to reconsider the whole idea that it's appropriate to infer type from a smartmatched constraint? Because, having pondered it at some length, I think we could very reasonably decide that, when providing a constraint, the coder is not making any reliable implication regarding the associated parameter type. Let's look at some examples... 1. Suppose we wanted a subroutine that classifies numbers according to a very simple scheme. We might write: multi classify($ where 0 ) { 'zero' } multi classify($ where 1..9) { 'digit'} multi classify($ ) { 'sequence' } It would be more convenient if we could just write: multi classify( 0) { 'zero' } multi classify( 1..9 ) { 'digit'} multi classify( $) { 'sequence' } But we can't, because the current inference rules would infer: multi classify(Int $ where 0 ) { 'zero' } multi classify(List[Int] $ where 1..9) { 'digit'} multi classify(Any $ where * ) { 'sequence' } which is not helpful. It goes wrong because, except in the first version of C, the type of the parameter constraint does not imply the type of parameter. 2. Or suppose we wanted a subroutine that only ever accepts a given argument once. We might write: sub unseen ($msg) { state %seen; %seen{$msg}++; } multi ping($ where &unseen ) { die 'One ping only!' } multi ping($msg) { say "PING! ($msg)" } It would be more convenient if we could write: multi ping({.&unseen}) { die 'One ping only!' } multi ping($msg ) { say "PING! ($msg)" } But we can't, because the current inference rules would make that: multi ping(Block $ where {.&unseen}) { die 'One ping only!' } which is not helpful. Because, again, the type of the constraint does not imply (nor is it even directly related to) the type of the parameter. 3. Or suppose we wanted to detect special boundary conditions (a case similar to Moritz's example above). We might write: multi check_value($ where 0|1e6) { fail 'edge case!' } multi check_value($) { return True } It would be more convenient if we could write: multi check_value(0|1e6) { fail 'edge case!' } multi check_value($) { return True } But we can't, because the current inference rules would make that: multi check_value(Junction $ where 0|1e6) { fail 'edge case!' } multi check_value( $) { return True } which is not helpful. Because, as before, the type of the constraint is not correlated with the type of the parameter. In each case (and in the majority of other cases, I suspect) the type and the constraint value are performing two entirely distinct tasks, and are often unrelated. Or, at least, unrelated in the sense that the constraint value is frequently not type-compatible with the type, because the constraint is verified by smartmatching, which is most often an operation between values of two unrelated types: integer matched against block, string matched against list, number matched against junction, etc. etc. In other words specifying a constraint value is a way of applying a smartmatched acceptance test to a parameter, but the type of the acceptance test is typically totally unrelated to the type of the parameter. Which is why it now seems very odd to me that we are currently inferring parameter types from constraint values. The type of the constraint value tells us nothing reliable about the type of the parameter it constrains. It only tells us that the value of that parameter must be matchable against the value of that constraint. And that appears to be true even for the very simplest example: sub foo($ where 1) { say 'There can be only one!' } foo(1); # Okay foo('1');# Okay foo(True); # Okay foo([42]); # Okay # et cetera... I ought to be able to write that as: sub foo(1) { say 'There can be only one!' } but I cannot, because the current rules don't even infer a coercive type. TL;DR: In general, the type of a parameter's C constraint value has little to do with the type of the parameter, because constraints are smartmatched, not type-matched. My proposal, therefore, is that any parameter specified only as a constraint value simply does not attempt to infer its parameter type at all, but just retains its default type of Any. That is, in all cases: sub foo( SOME_VALUE ) {...} is just a shorthand for: sub foo($ where SOME_VALUE ) {.
Re: [perl #113930] Lexical subs
> But by using the term ‘variable’, which is ambiguous, you are not > answering my question! :-) Sorry. I tend to think of *every* variable name as merely being an alias for some underlying storage mechanism. ;-) > Does > > my $x; > for 1..10 -> $x {} > > cause the existing name $x to refer temporarily to each of the numbers, > or is a new $x name created? A new one is created (each time through the loop). > What does this do? > > my $x; > my sub f { say $x } > for 1..10 -> $x { f(); } It prints 'Any()' ten times (i.e. the equivalent of printing ten Perl 5 undefs). The two $x's definitely exist at the same time during the loop. For example, this: my $x = 'outer x'; my sub f { say $x } for 1..10 -> $x { print $x, ": "; f(); } prints: 1: outer x 2: outer x 3: outer x 4: outer x 5: outer x 6: outer x 7: outer x 8: outer x 9: outer x 10: outer x Damian
Re: When do named subs bind to their variables? [perl #113930]
Father Chrysostomos pointed out: > I said when, not whether. :-) Isn't that just typical of me: confusing ontology with chronology. ;-) I'm afraid don't know the implementation details for Rakudo. It may be bound as the surrounding block is entered, or perhaps just-in-time when the Code object is first accessed in some way. > Does Perl 6 have an equivalent to this? > > my $x; > for $x(1..10) {} In Perl 6 that's: my $x; for 1..10 -> $x {} And, as in Perl 5, they're two separate variables. The iterator $x is a parameter of the loop block and acts as a readonly alias to each successive iterated value, unless you write: for 1..10 <-> $x {} in which case it's a read-write alias to each iterated value. Loop iterators are never package-scoped in Perl 6. > is just a syntactic convenience for: >> >> my &foo := sub { whatever() } > > Except that my sub foo happens upon block entry, right? Quite so. So the equivalence is more precisely: ENTER my &foo := sub { whatever() }; except that the named code object is visible throughout its surrounding block (even before its declaration point). So I guess that equivalence I keep referring to is a little shakey. ;-) > In Perl 5, $] in a piece of code is bound to *], not $], so it sees > changes made by local($]) (which actually puts a completely new scalar > in the *]{SCALAR} slot). But ‘my $x; sub { $x }’ is bound, not to the > $x slot in the outer block/sub/file, but to the actual scalar itself. > > It seems that Perl 6 closures close over the slot, not the > scalar/array/etc. Is that right? That's right. This: my $x = 1; my $x_prime = -1; sub foo { say $x } foo(); $x := $x_prime; foo(); prints: 1 -1 ...indicating that the $x in foo is bound to the slot, not to any var implementation currently in the slot. The way I would have described it is that binding is by name, not by reference. Damian
Re: When do named subs bind to their variables? (Re: Questionable scope of state variables ([perl #113930] Lexical subs))
Father Chrysostomos asked: > What I am really trying to find out is when the subroutine is actually > cloned, Yes. It is supposed to be (or at least must *appear* to be), and currently is (or appears to be) in Rakudo. > and whether there can be multiple clones within a single call of > the enclosing sub. Yes. For example, a lexical sub might be declared in a loop inside the enclosing sub, in which case it should produce multiple instances, one per iteration. For example, this: sub outer_sub () { for (1..3) { state $call_num = 1; my sub inner_sub { state $inner_state = (1..100).pick; # i.e. random number say "[call {$call_num++}] \$inner_state = $inner_state"; } say "\nsub id: ", &inner_sub.id; inner_sub(); inner_sub(); } } outer_sub(); produces: sub id: -4628941774842748435 [call 1] $inner_state = 89 [call 2] $inner_state = 89 sub id: -4628941774848253711 [call 3] $inner_state = 16 [call 4] $inner_state = 16 sub id: -4628941774839825925 [call 5] $inner_state = 26 [call 6] $inner_state = 26 under Rakudo BTW, Both the above "yes" answers are consistent with (and can be inferred from) the previous explanation that: my sub foo { whatever() } is just a syntactic convenience for: my &foo := sub { whatever() } HTH, Damian
Re: [perl6/specs] 6ef69b: pod vars are now lowercase as seen in 3e1a9a5a576b...
> Thank you damian, i will apply that patch, Much appreciated, Herbert! Damian
Re: [perl6/specs] 6ef69b: pod vars are now lowercase as seen in 3e1a9a5a576b...
Herbert Breunung asked: > what was you rational behind this decision. > I like it visually but my brain refuses to find any logic why only there > special vars should be different. This change stems from another change that we made after discussions at YAPC Riga last year. That change was to convert the =DATA and =END markers to =data and =finish. The rationale for that change was as follows... In the original redesign for Pod6, every built-in directive (=begin, =head1, =item, =table, etc.) was lower-case...except for =DATA and =END, which retained their vestigal upper-casing, in analogy to Perl 5's __DATA__ and __END__. And in the original Pod6 design, every upper-case directive (=SYNOPSIS, =AUTHOR, =COPYRIGHT, etc.) was a "semantic block"except for =DATA and =END, which were built-ins. In other words, =DATA and =END were violating both the syntax for built-ins (should be lower-case, but aren't) and the semantics of upper-case (should be semantic blocks, but aren't). So we changed them to what the syntax and semantics were telling us they should be: lower-case. But this change broke the one-to-one mapping between Pod sections and Pod-access variables. Previously it was: =pod<-> $=pod =UserDef<-> $=UserDef =SYNOPSIS <-> $=SYNOPSIS =DATA <-> $=DATA But, after the Riga discussions it became: =pod<-> $=pod =UserDef<-> $=UserDef =SYNOPSIS <-> $=SYNOPSIS =data <-> $=DATA (oops!) Now, this second change simply restores balance to the Force: =pod<-> $=pod =UserDef<-> $=UserDef =SYNOPSIS <-> $=SYNOPSIS =data <-> $=data Note too that, under the current notion that *any* Pod block (say: =foo or =BAR) is available under a variable of its own name (i.e. $=foo and $=BAR), then $=DATA is still a valid variable. It does not, however, access the built-in "data block" named =data. Instead, it accesses the (potential) semantic block named =DATA...which is an entirely different beastie. BTW, S02 still has remnant mentions of $=POD and $=DATA, as well as some other "antiquities" regarding Pod variables. I have attached a proposed docpatch. Damian S02.patch Description: Binary data
Re: Not-so-smart matching (was Re: How to make a new operator.)
yary suggested: > In a situation like this, I reach for a thesaurus The standout from that list for me is: 'consonance'. Second favorite is: 'gibe' or 'jibe'. But the underlying operation is .ACCEPTS(), so perhaps the operation should be referred to as "acceptance" or "acceptibility". Damian
Re: How to make a new operator.
> At least in #perl6 I've never seen anybody try to write an auto-deduced > sequence, and fail because of floating-point errors. Except for Martin's 1, sqrt(2), 2...8 But, yes, the widespread use of Rats rather than Nums means only the edgiest of edge-cases fails. And as you get an explicit Failure when it does happen, at least people will know when the numerical computations don't work as hoped. Damian
Re: How to make a new operator.
> Actually, that one works fine in both niecza and rakudo, since those are Rats. Oh, that's good to hear. It doesn't change my underlying argument however. Any operations performed on genuine floats are going to lose precision, and if we're using such operations to infer relationships (such as equality or sequence) then we ought to take the loss of precision we're causing into account when deciding outcomes. Which seems to mean either (a) making it a compiletime error to request sequence inferences on floats , or (b) comparing the differences and quotients within the sequence inference with a larger epsilon (or using interval arithmetic). Damian
Re: How to make a new operator.
> But unless we twist smartmatching semantics for that purpose, No! Please, no. ;-) > it means we cannot do the same fuzziness for the endpoint, Except that we will be encouraging people to use: * >= $END as their standard endpoint pattern, which will provide most of the necessary fuzz. > So I'm firmly against such magic. But that's the point: it's not magic. It's correct numerical computation under the limitations of floating-point arithmetic. As discussed in every numerical computing textbook for the last half a century. Note that this problem occurs for *arithmetic* deductions as well. If either number is floating point, some loss of precision in the difference between them is almost inevitable, especially if the two numbers are very close. For example: 1, 1.0001, 1.0002 ... * won't deduce a correct arithmetic sequence either (on most hardware). In fact that example would be slightly more likely to imply a geometric sequence, since a division operation loses fewer significant digits than a subtraction when the arguments are both so close to 1.0) > This discussion makes me think that maybe > deducing geometric sequences is too much magic as well. Geometric sequence inference is fine on Ints and Rats. But, if we can't perform inferences involving Nums in a sound numerical way (and it may well be that we can't, without taking a noticeable performance hit), then I think that we would be better off limiting the deduction of *both* arithmetic and geometric sequences to starting lists that contain only Ints and Rats. Damian
Re: How to make a new operator.
Patrick correctly observed: > On Rakudo on my system, sqrt(2) indeed produces a Num, > but since floating point arithmetic doesn't result in > sqrt(2) / 1 == 2 / sqrt(2), no geometric sequence is deduced > and the sequence fails with "unable to deduce sequence". Although, arguably, that might be considered a bug. Not that sqrt(2) / 1 should == 2 / sqrt(2) of course, but that, when deducing a sequence we know we're comparing quotients, so we ought to allow for the inevitable loss of significant digits within the two preliminary division ops, and therefore compare the results with an suitably larger epsilon. That would not only be computational more justifiable, I suspect it might also produce more "least surprise". ;-) Damian
Re: How to make a new operator.
> Ok, so infix:<...> isn't what I wish for either... Can you help me > understand Damian's example? Breaking down that example: $a, # Start at $a *+$c # Generate next number via: sub($prev_num} { $prev_num + $c } ... # Repeat until... * >=$b # ...this sub matches: sub($prev_num) { $prev_num >= $b } * used as an argument to an operator is a shorthand for constructing subroutines, where the * represents the subroutine's argument. Damian
Re: How to make a new operator.
> Interesting... but it doesn't seem to work in Rakudo Star (2012.02): > >> @(2,5..10) You need three dots, not two. Damian
Re: How to make a new operator.
> Is it possible to create a new range operator ':' such that: Do you need to? > a:b:c is a range from 'a' to 'b' by steps of 'c'. Perl 6 already has: $a,*+$c...* >=$b E.g. 2, 5 ...^ *>=15 > 2,5,8,11,14 > :b is the same as 0..b Perl 6 already has ^$b e,g, ^100 > 0..99 > a: is the same as a..Inf Perl 6 already has $a..* or $a...* e.g. 3..* > 3,4,5,6, > ::c is the same as 0:Inf:c Perl 6 already has: 0,$c...* e.g. 0,3...* > 0, 3, 6, 9, 12 > : is the same as 0..Inf Perl 6 already has: ^Inf > 0,1,2,3,4,5, Damian
Re: DBC-ish PRE and POST phasers, spec clarifications
Moritz observed: > And here the problem already starts. Signatures with where-blocks can't > by compared by a Turing machine. At least we know which signatures we > can compare and which we can't. So we need to think about that case too. Indeed. Although it's not as bad as it might be. A where-block on a parameter can be viewed as an implied 'requires', while an where-block on a return type is like an implied 'ensures'. So if you have a base-class method with a 'where' on its parameter and a derived-class method without a 'where' on the corresponding parameter, you're okay. And likewise, if a base-class method has no a 'where' on its return type and the return type of the corresponding derived-class method does have a 'where', your still okay. On the other hand the other four cases: * method Base::foo($x) {...} vs method Der::foo($x where {something}) {...} * method Base::foo(--> Type where {something}) {...} vs method Der::foo(--> Type) {...} * method Base::foo($x where {something}) {...} vs method Der::foo($x where {something_else}) {...} * method Base::foo(--> Type where {something}) {...} vs method Der::foo(--> Type where {something_else) {...} could all quite reasonably be presumed to be (at least potential) Liskov violations and loudly complained about: Possible Liskov violation on Der::foo() parameter $x at Der.pm line 42 (The 'where' makes it potentially more restrictive than in the base class method it overrides. Bad programmer! No DbC for you!!!) As long as we can support decidable cases and report undecidable cases, I think that's enough. > Though of course then we need a mechanism to silence that warning. no warnings :DbC; or perhaps: no warnings 'Liskov? Hah! I guffaw at your primitive Earth superstitions!!!' => 1; >> And, yes, this does indeed imply a syntax for optionally naming the >> return value in a signature (which syntax seems to fall out quite >> naturally in any case). > > Or we simply reuse the convention from POST and CATCH that the > interesting value (either exception or return value) is passed in as $_. But that's less explicit and obvious than named return values! :-( Not to mention much less "Nyah, nyah, Haskell...look what we've got!!!". ;-) Damian
Re: DBC-ish PRE and POST phasers, spec clarifications
Carl asked: >class A { >method foo($x) { >PRE { $x < 10 } ># ... >} >} > >class B is A { >method foo($a, $b, $c) { >PRE { [>] $a, $b, $c } ># ... >} >} > > When C is called, are both C blocks meant to be run? No. Contractual constraints are only inherited by methods of the same signature. BTW, that example isn't Liskov substitutable, so it really doesn't matter what it does under DbC. ;-) Also, it would be much better if such cases issued a warning in Perl 6, rather than just silently hiding the inherited method and thereby breaking the shared polymorphic interface of the hierarchy. > A modest proposal: we already have excellent IoC primitives with > C et al. Why not let DBC fall out of their use instead of > trying to impose it from the outside? This poses no problems at all: Except for the problem that it doesn't actually implement DbC semantics. ;-) For example: class A { method foo($x) { PRE { $x < 10 } my $result = 2 * $x; return $result; POST { $result > $x } } } class B is A { method foo($x) { PRE { $x < 100 } callwith($c % 10); return -$c; } } In a proper DbC system, calling B::foo would always fail, since A::foo's inherited POST requires the method's result be greater than its original argument. But under the proposed new semantics, this example succeeds in returning a result that violates the inherited contract. Even worse, this example: class A { method foo($x) { PRE { $x < 10 } my $result = 2 * $x; return $result; POST { $result > $x } } } class B is A { method foo($x) { PRE { $x < 100 } return -$c; } } ...fails to even test the inherited PRE and POST conditions, which is a complete violation of DbC. Note that I'm *not* saying that Carl's example isn't demonstrating useful behaviour...just that the behaviour it's demonstrating isn't DbC. For a start, PRE- and POST- inheritance should only occur when a derived method does indeed have the same signature as some base method, and then only from that identically signatured method. Secondly, PREs have to be inherited disjunctively (i.e. be allowed to weaken), rather than being conjunctively accumulated (i.e. being forced to to strengthened). > In fact, method-level C and C cease to be a concept, C > and C submethods can be handled delicately in a corner of the > MOP somewhere, the abomination that is C goes away, and > all that we're really left with are block-level C and C > phasers, which already seem like they could work. > > So, what do y'all think? I think this is probably the only reasonable way forward at the moment. What we've proposed as a DbC mechanism in the spec can't be implemented for all the reasons Carl enumerated so well. However, I'd also want the spec to remove all reference to DbC when talking about PRE and POST. Or, better still, to state explicitly that PRE and POST do *not* have DbC semantics when applied to methods (perhaps even using some of the examples above to illustrate why not). And if we are ever to properly supply DbC, then I think we'd also want to explicitly reserve--but not spec--the phaser names REQUIRE and ENSURE for possible later use (either in-core or via a future 'use contracts' pragma or module that some heroic soul may attempt write. ;-) On the other hand, because DbC "requires" and "ensures" are really much more like (inheritable) traits of a method's signature, rather than phasers tied to the method's block, it seems likely that any eventual DbC mechanism should not use phasers at all. So perhaps we ought to reserve the traits 'will require' and 'will ensure' so that the eventual DbC mechanism could be specified like so: class A { method foo(Num $x --> Num $result) will require { $x < 10 } will ensure { $result > $x } { return 2 * $x; } } class B is A { method foo(Num $x --> Num) will require { $x < 100 } { return $x+1; } } And, yes, this does indeed imply a syntax for optionally naming the return value in a signature (which syntax seems to fall out quite naturally in any case). Damian
Re: Setting private attributes during object build
yary wrote: >>The current approach is violating the DRY principle. When you write a >>.new method that wants to initialize private attributes, you have to >>repeat all their names again in the signature of your BUILD submethod: The other way of looking at this is that redefining the new() is about changing the constructor interface, whereas defining the BUILD() is about changing the initialization behaviour. So the current approach is violating DRY in order to preserve the more important principle of Separation of Concerns. After all, it doesn't seem unreasonable that, if you want to modify two behaviours, you have to rewrite two components to do it. On the other hand, rather than adding a blessall() alternative, perhaps we could say that, if the class explicitly redefines new(), then any call to bless() within that redefined new() will accept both public and private attributes for auto-initialization...under the theory that, by redefining new() the class implementor is taking direct responsibility for the construction...and is willing to live with the dire consequences if they mess it up. Incidentally, blessall() seems a dubious name to me, given that we already have BUILDALL() and CREATEALL(), where the '-ALL' suffix means something quite different from what the '-all' would mean at the end of blessall(). Better still, on the principle that abnormal behaviour should always be explicitly marked and lexically predeclared, perhaps a pragma would be appropriate: class A { has ($!x, $!y, $!z); method new($x, $y, $z) { no strict :autoinit; self.bless(*, :$x, :$y, :$z) } } >>The whole point of having BUILD() is to separate allocation >> concerns from initialization concerns. > > Here's where I am late to the conversation, I hadn't known that > distinction. S12 doesn't talk about the "why" of BUILD/BUILDALL, at > least not that detail. If "BUILD" is for allocation, and "new" is for > initialization, then hiding private attributes from "bless" is forcing > the programmer to use BUILD for initialization which wasn't the > intent. You have it the wrong way round: new() is for allocation; BUILD() is for initialization. From a design point-of-view, BUILD() probably should have been called INIT(), but that keyword was already taken. > "you must write your own BUILD (as above) in order to present private > attributes as part of your initialization API." > > And that's not so good, because it forces BUILD to be used for > initialization, ...which is precisely what it's supposed to be for. :-) Damian
Re: Setting private attributes during object build
My thanks to Kris and Moritz for reassuring me that the Perl 6 initialization semantics remain sane. :-) In response to yary's original observations, the extra work required to achieve non-standard semantics doesn't seem unreasonable to me. Especially as, should one need to do it regularly, one could just create a role (possibly parametric) to handle all the boilerplate and then mix just it into any class that requires it. Damian
Re: Setting private attributes during object build
Moritz clarified: > In BUILD, the object isn't yet fully constructed, and thus using $.attr > (which is really a virtual method call in disguise) is wrong. STD and > niecza already catch that at compile time, and I'm currently trying to > make rakudo catch it too (branch 'has-self' on github). Agreed. That example should certainly use $!attr instead. > More to the point, objects are constructed by .new calling .bless, which > in turn calls BUILDALL which finally calls BUILD. Since .bless only > takes named arguments (besides the candidate to be blessed), how could > BUILDALL know how to call BUILD with positional arguments? Agreed. That example should be: submethod BUILD( :$arg ) {...} > Finally Rakudo, Niecza and Pugs all agree that the default .new and thus > .BUILD only take named arguments, and while that's not authoritative, it > is a strong indicator that the example above contradicts the compiler > writer's understanding of object initialization system. Agreed. I dearly want BUILD to take only named args. My point was that I don't want the named arguments that BUILD can take to be restricted to only the names of public attributes...which was, I thought, yary's complaint when writing: >> If one wants to use any argument in the constructor other than a >> public attribute (positional OR named other than an attribute name), >> one must define a "method new( ... )". If the complaint is that yary wanted to pass positional args to a constructor, then I have no problem with having to write one's own non-standard new() method to achieve that. If anything, we should make it even harder than that. ;-) But if one can't pass arbitrary named values to the standard new() and have one (or more!) BUILD methods correctly use them, like so: class Date { has Num $!seconds_from_epoch; multi submethod BUILD (Str :$date) { $!seconds_from_epoch = _date_from_str($date); } multi submethod BUILD (Int :$year, Int :$month, Int :$day) { $!seconds_from_epoch = _date_from_YMD($year, $month, $day); } # etc. } and then be able to call: my $today= Date.new(date => 'Feb 2, 2012'); my $tomorrow = Date.new(year => 2012, month => 2, day => 3); then we've failed to make Perl 6 even as usable as C++, which is a tragedy. I sounds like I simply misunderstood yary's problem, but I'd be very glad to be reassured that's the case. :-) Damian
Re: Setting private attributes during object build
Yary wrote: > If one wants to use any argument in the constructor other than a > public attribute (positional OR named other than an attribute name), > one must define a "method new( ... )". Huh? I know I've been out of the loop lately, but this seems fundamentally wrong. Constructor args certainly shouldn't be restricted to just the names of public attributes. And one definitely shouldn't have to redeclare new() just to allow for more sophisticated initialization. The whole point of having BUILD() is to separate allocation concerns from initialization concerns. S12 has an example that explicitly contradicts this constraint that constructor args have to be public attribute names: submethod BUILD ($arg) { $.attr = $arg; } Either I'm missing the point here (which is entirely possible ;-) or something isn't right in the current semantics of object initialization. Damian
Re: [perl6/specs] a7cfe0: [S32] backtraces overhaul
> The current stance seems to be that low-level things are spelled with > underscores, while we reserve the minus character for user-space code. Try > grepping the specs for identifiers of built-ins that have a minus in it -- I > didn't find any in a quick search. I had a little more time to look and found... S12 describes Attribute objects as having a method named 'has-accessor', but also having a method named 'get_value'. S19 uses hyphens for all of perl6's long-form command-line flags. In S28, we find $*EXECUTABLE_NAME and %*META-ARGS listed within 10 lines of each other. S32-setting-library_IO.pod and S32-setting-library_Numeric.pod each have public multi-word method names with hyphens. And both also list other identifiers that use underscores. I'm not sure I'm seeing the pattern, though. Apart perhaps from "older parts of the spec use underscores, newer parts use hyphens". And I'd like there to be a more consistent approach than that (though I don't really care what it actually is). Damian
Re: [perl6/specs] a7cfe0: [S32] backtraces overhaul
It's a trivial point, but why hidden_from_backtrace instead of hidden-from-backtrace? Especially given that the associated method is is-hidden, not is_hidden? Are we consistently using underscores for multi_word traits and hyphens for multi-word methods? Wouldn't it be nice to have a consistent and teachable rule? And why is this entire message written in questions? Have I simply been watching too many "Whose Line Is It Anyway?" episodes? Damian?
Re: Encapsulating the contents of container types
Carl asked: > * What do we mean when we say 'has @.a is readonly'? > What do we want it to mean? Not sure about "we", but I want that to mean that nothing outside the class can alter any component of @.a, no matter how deeply nested that component may be. > * Are we fine with references from readonly attributes leaking out of the > class? > Should we be? No. No. > * What language components could be provided to put class implementors > on the right path so that their classes end up encapsulated by > default? Doing nothing should result in the safe behaviour (i.e. full encapsulation). You ought to have to explicitly request anything else. One of the *big* selling points of Perl 6 is the prospect of "OO done right". Leaky encapsulation ain't that. Damian
Re: Tweaking junctions
Moritz wrote: >> $value !~~ Junction && $value ~~ $junction > > In general this definition makes it impossible to return a list of > eigenstates from the junction. Just think of junctions containing Code > objects. Well, that's a deficiency in smartmatching: that Callable ~~ Code doesn't check for identity between the two objects. Likewise the Regex ~~ Regex doesn't check for identity. Likewise Range ~~ Range testing for identical endpoints. Etc. ;-) The definition of eigenvalues() is supposed to be abstractly descriptive, not specifically constructive. The idea is simply: any "leaf" state inside the junction to which the junction could collapse. Now the implementation I already provided does currently rely on smartmatching, but that will be fixed pronto, now that you've kindly pointed out that smartmatching is...well..."broken" on several interesting types of states. :-) > Right; but afaict it's the only thing that can actually be implemented. > And because it doesn't make all too much sense, it's specced to be private. Fine. But please change the name anyway. If we all agree it's not returning eigenstates, and some of us believe it *can't* every return eigenstates, then it certainly shouldn't be called C<.eigenstates>. Damian
Re: Tweaking junctions
Martin D Kealey suggested: > Well, I think returning or throwing an "Unordered" exception would be > the appropriate way to handle those, both for complex numbers and for > junctions. For complex numbers that might be true, because the order relationship between two complex numbers isn't expressible "in-band". But for junctions, the relationship of "sometimes <, somtimes >=" is entirely expressible. It's just: any(True, False). > And what about when that difference is wrapped up inside a function? In > other words, what's wrong when I expect the following two snippets to > work the same way? > >sub anything_is_broken($subject) { >grep { ! .test() } $subject.parts() >} > > >sub everything_is_working($subject) { >! grep { ! .test() } $subject.parts() >} > > Why should it make a difference whether $subject is a junction? Because, although the two subroutines seem like they're complementary, they actually only partition the universe when the universe is strictly one-dimensional. And sometimes not even then. For example, here's a *non-junctive* scalar subject for which the two don't provide consistent answers either: class Part { has $.value; method test { $.value != 0 } } class Subject { has Part @.parts; method parts { @.parts.pick(2) } } my Subject $subject .= new(0..9); say anything_is_broken($subject);# 0 (because .parts picked 3 and 7) say everything_is_working($subject); # 0 (because .parts picked 9 and 0) In other words, it isn't the junctive-ness that creates unexpected behaviour, it's the assumption that every scalar works the same way. > That's not true for user-defined functions, so I think the real problem > is that the parallelizing of the expression that contains a junction may > not be "obvious" at the point where it happens. But that's not a unique property of junctions; that "not obviousness" is equally true of any scalar that, for example, simply overloads .Num or .Str or .Bool. For instance: if $result { say $result } can easily print "0", which is not obvious, but is still both correct and useful (when, for example, $result the result of a call to C). > Hmmm maybe one way to improve that might be to say that you can't > put a junction into an untyped scalar, or indeed in any variable that > isn't explicitly marked as "this thing might contain a junction". That > would apply, as now, to function parameters and returns, but also to > variables and aggregate members; indeed, *everywhere*. But junctions are an intrinsic part of Perl 6. So it's unreasonable to *not* expect them. And if you want to not expect them, you can just mark your variables that way, with (ironically): my $subject where none(Junction); Besides, are you also going to extend this segregation of junctions to not allow C<0 but true> in untyped scalars either? Because how else will you avoid the non-obviousness of: if $result { say $result } ??? > I don't think strong typing is enough, because we explicitly mask the > application of type constraints by autothreading. Each thread sees a > thing with the type it expects, but the problem comes when the threads > are recombined; the result often won't be what's expected. Huh? If the variables are strongly typed as non-junctive, a junction will never be able "sneak past" into or out-of an autothreading. > Don't get me wrong, I think Junctions are a really clever way of > writing concise conditional expressions, but I think algebraic > consistency is more important than clever conciseness. Aha. I see that we mean different things when we use the term "algebraic consistency". You seem to want all algebras to be universally consistent; I want each algebra to be internally consistent. Or to put it another way, you appear to want: A given operator or function does one consistent thing (regardless of the specific types of its operands) whereas I want: A given operator or function does one thing (consistent with the specific types of its operands) In other words, you seem to be arguing for monomorphism, whereas I'm definitely arguing for polymorphism. Neither is inherently better, but one is inherently more powerful. While I deeply respect your position, I'm going to keep arguing for that more powerful alternative. Damian
Re: Tweaking junctions
Martin D Kealey asked: > Or do we not invert junctions, and run the risk of unexpected > action-at-a-distance instead? I think our current approach is correct. That is: we "invert" junctions on operators that are themselves intrinsically inverted (such as !=, !~~, !<), but do not invert on those that are not (such as ==, ~~, >=). Or rather, we *never* invert junctions at all, but merely honour the standard semantics of the prefix: metaoperator: hoisting the negation outside the entire operation and applying it once the underlying operation is complete. The apparent paradox you demonstrated with the two interpretations of C<$foo < ($bar | $zot)> is due to the assumption (employed in the second interpretation) that < is identical to !>=. Certainly that is true for simple scalar numbers, but not always for vector types such as tuples, sets, bags, complex numbers...or junctions. That doesn't make either < or !>= intrinsically invalid on vector types (though they obviously are inappropriate for *some* vector types); it just means you can't reasonably treat the two operators as universally interchangeable, just because they sometimes are. In summary, the "problem" here seems to be that, algebraically, junctions don't behave exactly like non-junctions. Which is true, but no more a problem than the fact that, algebraically, complex numbers don't behave exactly like non-complex numbers, or that sets don't behave exactly like non-sets, or that Rats don't behave exactly like Nums, which don't behave exactly like Ints, which don't behave exactly like ints either. And, of course, that's why Perl 6 has strong typing. So that, when these differences in behaviour do matter, we can specify what kind(s) of data we want to allow in particular variables, parameters or return slots...and thereby prevent unexpected kinds of data from sneaking in and violating (un)reasonable expectations or inducing (apparent) paradoxes. :-) With regard to your other point: > If it's about parallel data handling, then we have to be prepared to > (notionally) fork the entire rest of the runtime, even as far as > having a definition of what return value the parent process sees (from > "exit") when those threads are implicitly collapsed at termination. That's certainly true, although junctions are supposed to guarantee to coalesce all the threads they may generate back into a single superimposed result back in the originating thread. The problem only arises if an operation or subroutine that has been junctively threaded terminates without returning. But that's just "having a side-effect", which we already know is inappropriate for junctions (and hyperoperators, and autothreaded loops, and pretty much any other kind of parallel construct). Damian
Re: Tweaking junctions
Jon Lang wrote: > Personally, I don't think that it should be a public method: one thing > about junctions is that you can use them interchangeably with ordinary > scalars; giving them a public method breaks that. In particular, code > that makes use of a Junction public method would break if you were to > hand it a non-Junction. On the other hand, I would argue that, because non-junctive scalars are just an (uninteresting ;-) special degenerate case of junctions, they should have a public .eigenvalues() too! It would, of course, just return their uninteresting degenerate special-case scalar value. Alternatively, I would note that Perl 6 already provides a perfectly good way to handle this issue. If you're calling $someval.eigenvalues(), you're inherently assuming that you're calling it on a Junction. If there's any possibility that what you're calling it on *isn't* a junction, then you should either be unsurprised to get the exception that will be thrown, or else you should explicitly cater to the possibility with: my @values = $val.?eigenvalues; or perhaps: my @values = $val.?eigenvalues // $val; Although, if that second form is to become the standard "safe" approach, that argues to me that non-junctions ought to have a .eigenvalues() too, so that the first alternative above just DWIMs. BTW, given Larry's recent clarification about Sets producing a list of their keys in list context, I have absolutely no objection to .eigenvalues() returning a Set, rather than a List. Indeed, I think it would be even more valuable that way. Damian
Re: Tweaking junctions
Dave Whipp noted: > I think that the two proposals are equivalent, in the sense that either can > be trivially implemented using the other. Agreed. > However, I am a little concerned that the transjunction "magically" changes > an operator that returns a Boolean value into one that returns a list. Technically, it turns the operator into one that returns a transjunction. The "surprise" occurs because tranjunctions self-eigenvalue in a list context. That's a huge convenience in direct usages, but not an essential component of the proposal if indeed it proves too surprising in indirect usages. However, if we did lose that feature then usages like: say eigenvalues every(@number) < one(3,7); sacrifices more than a little of the construct's original appeal, I think. > If I wanted to write intentionally confusing code (which sometimes happens > due to carelessness) then I might take advantage of the fact that C > is, in English, a synonym for C, not C: > > if every(@values) < one(3..7) {...} Yes, Ted Z. pointed out to me that, as the name of this construct, "every" has ambiguity and synonym issues. Other possibilities are: select(@values) < one(3..7) those(@values) < one(3..7) whichever(@values) < one(3..7) itemize(@values) < one(3..7) extract(@values) < one(3..7) ...of which, only C really seems a good alternative. Any other suggestions most welcome! Damian
Re: Tweaking junctions
Ben Goldberg asked: > I'm probably missing something, but wouldn't it have been easier to > write that module by using eval STRING to create all of those infix > operators? Sure. But the module is already slow to start up. I was concerned that it would get even slower with an embedded eval. But, in the name of maintainability, I probably should benchmark it both ways. Thanks for pointing that out, Ben. Damian
Re: Tweaking junctions
> In general I like where this is going but need a little hand holding > here- I'm not an expert on junctions or anything perl6- > >> So I'm going to go on to propose that we create a fifth class of >> Junction: the "transjunction", with corresponding keyword C. > > It seems that by these definitions "every" isn't quite a junction- It's an unordered collection of values that can be used like a single value, is parallelizable, and has an intrinsic associated operation. That's pretty much a junction. The only difference is that the associated operation is (in a sense) C, rather than C<&&>, C<||>, C<^^>, or C > You'll need to specify "but not necessarily in the same order" if you > want junctive autothreading to work on "every" as it does with other > junctions. You're quite right. I should have been more specific about that. And, yes, I certainly do want to leave open the potential for parallel evaluation. > In which case it should probably be returning a junction > and not an ordered list. If you look at the implementation I appended, any comparison on a transjunction returns a transjunction. But it turns out to be much more useful if they also collapse to a list, which is why I implemented them as a role added to arrays/lists. > Which reminds me, .eigenvalues strictly speaking is a set and not a > list. Sure, but again, it's much more useful as a list. ;-) > And while I like the cleanliness of the "every" expressions I'm still > having trouble seeing why "every" should behave differently from > "any", "all". Maybe "every" isn't a junction? Maybe not, in the strictest sense. But it has many of the same characteristics and is extremely useful in many of the same kinds of ways as a duck^Wjunction. > Maybe junctions in general need to behave a little differently when > being compared against then they do now, so the need for "every" > goes away? Interestingly, that was how they were originally defined (back when they were called "Quantum::Superpositions"). Comparing a superposition produced a superposition of just those values for which the comparison was true. But I agree with Larry's decision to make junctions behave "normally" wrt comparisons. They're much easier to understand the way they are now. I am merely trying to reintroduce the useful extra concept of a collection of numbers that filters under comparisons. But if people aren't comfortable, I'm happy to leave it as a module (especially since it's already written). I would hate this (very worthwhile) discussion to distract from the key point of the original post: namely, that the private C is misnamed, and a public C<.eigenvalues> is missing. Damian
Re: Tweaking junctions
Brandon mused: > It occurs to me: If their purpose is that narrow, why are they wasting > conceptual space in the core language? Well, mainly because their purpose isn't narrow at all: it's parallelized data comparisons (all(@values) < $threshold), and multiway comparisons (all(@values) ~~ any(@ranges)), and distributed sub calls on a set of arguments (foo(any @alternatives), and subroutine call parallelism (&foo & &bar)($arg), and type unions (my Wax|Polish $shimmer), and type intersections (my $coefficient where Num & 0..1), and parallel lookup of arrays and hashes ($name ~~ %known_aliases{any $suspect}), and multiway existence checks (if any %f...@args} :exists), and convenient multiple file tests ($fh ~~ :r & :w & :!x), and overlapping or exhaustive matches (my $results = m:ex/foo/), and complex matching logic expressed declaratively (my $is_valid = Num & {$_>0} | Str & /zero|one/). And, of course, they're in the core because there's no point in having that much power and usefulness if it's not fast too. Damian
Re: Tweaking junctions
Dave Whipp wrote: > When this issue has been raised in the past, the response has been that > junctions are not really intended to be useful outside of the narrow purpose > for which they were introduced. Hmm. There are intentions, and then there are intentions. I know what I intended when I invented the original idea, and it wasn't just the narrow purpose for which they were added to Perl 6. :-) >> Problem 2 could be solved by defining a new (and public!) >> C<.eigenstates> method in the Junction class. [...] > > I think that you're proposed solution is a bit too specific: That's because I didn't explain Part B of my nefarious plan! namely that, if you'd only give me proper eigenstates, I'd give you an even nicer alternative. I actually think that the "meta" doesn't belong on the operator at all (though I have no problem with that idea in itself). Instead, I think the "meta" should be placed on the data (which, of course, is what any(), all(), one(), and none() already do). So I'm going to go on to propose that we create a fifth class of Junction: the "transjunction", with corresponding keyword C. Then we define: every(@list) every($junction) to mean repectively: grep * , @list; grep * , $junction.eigenstates; as well as the reverses: every(@list) every($junction) to mean respectively: grep*, @list; grep*, $junction.eigenstates; So then we get: >> sub factors (Num $n) { ( $n/any(1..$n) ).eigenstates.grep({ $^q.Int == >> $q }); } > > [which] could be: > > sub factors (num $n) { ^$n G[==] $n/any(1..$n) } could instead be: sub factors (Num $n) { every( $n/any(1..$n) ) ~~ { $^q.Int == $q }); # Every quotient of N divided by any lesser integer, where the quotient is also an integer } and: >>say UNACCEPTABLE.eigenstates¬».fmt("\t%s\n"); > > [which] could be > > say (::Str G[eq] UNACCEPTABLE)».fmt("\t%s\n") could also be: say (every(UNACCEPTABLE) ~~ ::Str)».fmt("\t%s\n") # Everything unacceptable that's a string, formatted as follows... > Operations other than equality could be used: > > say (^10 G[<] one(3,7)); >> 3 4 5 6 which could also be: say every(^10) < one(3,7); # Every value up to 10 that's greater than 3 or 7 but not both And so on: say every(factor_of($x) & factor_of($y)) > 10; # Every common factor of both X and Y that's greater than 10 say every(@coefficient) ~~ 0..1; # Every coefficient in the range 0 to 1 say every(@string) ~~ //; # Every string that matches the target pattern I just think those all read much better than the (otherwise excellent) meta-operator. In much the same way that the existing junctive types read better than their functional or operator-oriented alternatives. I'd like these in the core language (for performance and universal accessibility), but if not, I already have a nearly-complete implementation of a module implementing them, which runs successfully on the current release of Rakudo*. I append said model for your amusement (and suggestions!). Damian -cut--cut--cut--cut--cut--cut--cut--cut- module Transjunctions; # Add missing public method (and equivalent function) to junctions # Call them .eigenvalues(), so as not to clash with existing misnamed !eigenstates()... use MONKEY_TYPING; augment class Junction { method eigenvalues (Junction $j:) { my @values = $j.eigenstates; @values .= map({ $^val.?eigenstates // $^val }) while @values.grep(Junction); return uniq(@values).grep($j) does ::Transjunction; } sub eigenvalues (Junction $j) is export { $j.eigenvalues } } # Transjunctions are just lists that autofilter when matched... role Transjunction { method ACCEPTS (Mu $filter) { self.grep($filter) } } # Convenient functions to build transjunctions... multi sub every (*...@list is copy) returns Transjunction is export { return @list does Transjunction; } multi sub every (Junction $j) is export { return eigenvalues($j) does Transjunction; } # Comparing against a transjunction filters it with the comparison # Rakudo star seems to require we provide two versions, though # I had expected the Mu version ought to handle both Junctions and Anys... multi sub infix:«<» (Transjunction $list, Mu $n) is export { $list.grep( * < $n ) does Transjunction } multi sub infix:«<» (Transjunction $list,$n) is export { $list.grep( * < $n ) does Transjunction } multi sub infix:«>» (Transjunction $list, Mu $n) is export { $list.grep( * > $n ) does Transjunction } multi sub infix:«>» (Transjunction $list,$n) is export { $list.grep( * > $n ) does Transjunction } multi sub infix:«<=» (Transjunction $list, Mu $n) is export { $list.grep( * <= $n ) does Transjunction } multi sub infix:«<=» (Transjunction $list,$n) is export { $list.grep( * <= $n ) does Tr
Tweaking junctions
I've been thinking about junctions, and I believe we may need a small tweak to (at least) the jargon in one part of the specification. Specificially, in S32-setting-library_Containers.pod, we currently have: =item !eigenstates method !eigenstates (Junction $j: --> Parcel) Returns an unordered list of the values that constitute the junction (formerly called C<.values>). It flattens nested junctions of the same type, so C<(1|(2|3)).eigenstates> returns an arbitrary permutation of the list C<1, 2, 3>. The problem is the *name* of that method. By definition, the "eigenstates" of a junction are those non-superimposed values to which the junction's superimposed values could actually collapse. Or, to put it another way, those non-superimposed values that a junction would actually match. That is, a C<$value> is an eigenstate of a C<$junction> if-and-only-if: $value !~~ Junction && $value ~~ $junction But the C method (as currently defined) does not return a list of such eigenstates. Instead it merely returns a partially-flattened list of the raw "internal values" of the junction...which is not (usually) the same thing at all. That's because junctions often contain internal values to which *externally* they cannot actually collapse...and hence cannot actually match. Some examples, to illustrate the distinction: Internal states Actual eigenstates Junction(what !eigenstates returns) (what junction could match) = === === any(1,2,3) 1, 2, 3 1, 2, 3 all(1,2,3) 1, 2, 3 one(1,2,3) 1, 2, 3 1, 2, 3 none(1,2,3) 1, 2, 3 any(1&2, 2&3) all(1,2), all(2,3) all(1|2, 2|3) any(1,2), any(2,3)2 one(1|2, 2&3) any(1,2), all(2,3)1, 2 one(1|2, 2|3) any(1,2), any(2,3)1, 3 So the two problems are: 1. $j!eigenstates doesn't return $j's eigenstates (i.e. the method is misnamed) 2. $j!eigenstates doesn't return $j's eigenstates (i.e. there's no way to get a junction's actual eigenstates, which is a very useful thing to be able to do--see below) Problem 1 could be solved by renaming the method C to something like: C. And, of course, renaming the corresponding attribute in the Junction class from C<$!eigenstates> to something like C<$!internal-states>. Problem 2 could be solved by defining a new (and public!) C<.eigenstates> method in the Junction class. This method would be implemented as something like: method eigenstates(Junction $j: --> List) is cached { # No feasible way of representing the eigenstates of an injunction... fail if $j!type ~~ JUNCTION_TYPE_NONE; # Candidates for eigenstates are all the junction's internal values... my @possible-eigenstates = $j!internal-states; # Or, rather, candidates are all its *non-superimposed* internal values # so we need to iteratively flatten any superimposed values... @possible-eigenstates .= map({$^value ~~ Junction ?? $^value!internal-states !! $^value}) while @possible-eigenstates.grep(Junction); # Actual eigenvalues are those unique candidates # that successfully match the original junction... return uniq(@possible-eigenstates).grep($j); } There is no need for this new C<.eigenstates> method to be private, because it doesn't expose the internal data of its junction object, but rather calculates a useful external property of that object. Some examples of why that the actual eigenstates of a junction are useful (note that these all assume the above (re)definition of C<.eigenstates>): # Find the list of common elements in two lists... sub intersection (@list1, @list2) { (any(@list1) & any(@list2).eigenstates; } # Find the factors of a number... sub factors (Num $n) { ( $n/any(1..$n) ).eigenstates.grep({ $^q.Int == $q }); } # Check for an unacceptable password, and list all when warning... constant UNACCEPTABLE = any < Godel Escher Bart etc... >; if $passwd ~~ UNACCEPTABLE { say "Unacceptable password. Don't use any of these:"; say UNACCEPTABLE.eigenstates¬».fmt("\t%s\n"); } If nothing else, we really do need to rename the current C method. Damian PS: I also note that the most recent release of Rakudo* defines the C<.eigenstates> method as public, which is inconsistent with the current specification. That probably needs to be fixed as well.
Re: threads?
Leon Timmermans wrote: > For the love of $DEITY, let's please not repeat ithreads! $AMEN! Backwards compatibility is not the major design criterion for Perl 6, so there's no need to recapitulate our own phylogeny here. The problem is: while most people can agree on what have proved to be unsatisfactory threading models, not many people can seem to agree on what would constititute a satisfactory threading model (or, possibly, models). What we really need is some anecdotal evidence from folks who are actually using threading in real-world situations (in *any* languages). What has worked in practice? What has worked well? What was painful? What was error-prone? And for which kinds of tasks? And we also need to stand back a little further and ask: is "threading" the right approach at all? Do threads work in *any* language? Are there better metaphors? Perhaps we need to think more Perlishly and reframe the entire question. Not: "What threading model do we need?", but: "What kinds of non-sequential programming tasks do we want to make easy...and how would we like to be able to specify those tasks?" As someone who doesn't (need to) use threading to solve the kinds of problems I work on, I'm well aware that I'm not the right person to help in this design work. We need those poor souls who already suffer under threads to share their tales of constant misery (and their occasional moments of triumph) so we can identify successful patterns of use and steal^Wborg^Wborrow the very best available solutions. Damian
Re: [perl6/specs] 58fe2d: [S12] spec setting and getting values of attribute...
Jonathan wrote: > Sounds like the encapsulation breaking thingy probably wants to be looking > for some pragma to have been used in the lexical scope of the caller, maybe. > I'd rather that we called it something other than MONKEY_TYPING though. > Different evil, different pragma. :-) As long as it's easily searchable and vaguely pejorative (e.g. has the work MONKEY in it). Hm. You need to use MONKEY_TYPING when you're monkeying with typing, so maybe when you're monkeying with what can be seen (and abusing Perl 6 as if it were C) then you need to use MONKEY_SEE Damian
Re: [perl6/specs] 58fe2d: [S12] spec setting and getting values of attribute...
Moritz writes: >> Objects that you can't do that with don't make sense to be serialized and so >> .perl can reasonably refuse to work on them. > > method perl { >die "Can't serialize objects of type $?CLASS, because ..."; > } Sure. But now the cautious programmer has to add that to *every* class hierarchy. So we start to see endless variations on: role ProperlyEncapsulated { method perl {die} } class MyClass does ProperlyEncapsulated {...} class AnotherClass does ProperlyEncapsulated {...} class YetAnotherClass does ProperlyEncapsulated {...} which would be a sad indictment on Perl 6's otherwise brilliant OO model (and will encourage all the OO bully languages to publicly kick sand in our face). > My proposal: the default .perl method should only spit out value for > public attributes, ie those that have accessors. I'd be happy with that. > Maybe .new should also default to his behavior. I'd be happy with that too. >> Then Damian's position (which I support) is supported and so are monkeys. > > Ook ook! "Apes! I meant apes!!!" ;-) > Moritz > (who actually writes Perl 6 code on a nearly daily basis). Damian (who does too)
Re: [perl6/specs] 58fe2d: [S12] spec setting and getting values of attribute...
Moritz wrote: > To re-iterate, Perl 6 has no "real" privacy by default -- both the > default .new and .perl methods give you access to private attributes, > unless you explicitly override them. At least you *can* explicitly override them (and perhaps factor that out into a role that you could always use). But even then, I suppose, that's still all to easy to bypass, with a fully qualified call, if the core .perl stays broken. :-( > I would be fine with changing get_value and set_value method names to all > uppercase, as an additional warning sign, if that would comfort you in some > way. Thank-you, but no. Shouting doesn't really solve my problem. I'm looking for a consistent way to identify dangerous code. And we already have that, in the form of C. What would comfort me would be if objects and classes could actually be relied upon to be properly encapsulated and stable, unless someone explicitly declares they are monkeying. As it stands at the moment, it's not clear to me why we even bother with opaque objects, if it's going to be this trivial to break encapsulation. Damian
Re: [perl6/specs] 58fe2d: [S12] spec setting and getting values of attribute...
Carl wrote: > For what it's worth, we had exactly this discussion a couple of days > ago on IRC. I represented your views above, Damian. Thank-you for that. > As long as C<.perl> works the way it does, there can be no real > privacy. Sigh. That is indeed badly broken. Surely it ought to default to C, and require class architects to override .perl explicitly if they wish to break encapsulation. > And thus C<.get_value> and C<.set_value> are just convenient > access points for the same behaviour. Yes. People are going to shoot themselves in the foot anyway, so let's legalize semi-automatic weapons as well. > I'm still undecided on whether or not I think C is > the right way to enable this kind of privacy breakage. Maybe nothing > is needed, since the C<^> in C<$obj.^attributes> (or the C) > already says "warning! meta!". Except that, if the Attribute object is passed around, it may be saying "warning! meta!" in a completely different scope, in a completely different file. Damian
Re: [perl6/specs] 58fe2d: [S12] spec setting and getting values of attribute...
On 30 September 2010 06:09, Moritz wrote: > After lengthy IRC discussion, we concluded that it's a good idea to provide > some form of introspection that doesn't bother about perceived privacy > borders, provided that the implementation makes it feasible. Wow, that's the first time I've ever been sorry not to be on IRC! Talk about snatching (directly accessible) defeat from the jaws of (encapsulated) victory. :-( Could we at least specify that .get_value() and .set_value() can only be called if the calling scope declares a C so that violations of good OO practice are explicitly marked in a consistent and easily searched-for manner? Damian
Re: How are unrecognized options to built-in pod block types treated?
Darren suggested: > Use namespaces. The upper/lower/mixed approach *is* a namespace approach. > Explicit versioning is your friend. > > Can I get some support for this? Not from me. ;-) I think it's a dreadful prospect to allow people to write documentation that they will have to rewrite when the Pod spec gets updated. Or, alternatively, to require all Pod parsers to be infinitely backwards compatible across all versions. :-( Damian
Re: How are unrecognized options to built-in pod block types treated?
Aaron wrote: > I dislike "reserved" in this context, but understand why the namespace has > to be shared. For config options, I'd say anything should go, but people > inventing their own config options should be aware that across N release > cycles, new options may be introduced. ...which means that sensible people will avoid those namespaces anyway, so they might as well be reserved...which then enables us to warn any not-so-sensible people that their choice of an all-lower- or all-upper-case option name is brittle and likely to end in tears. BTW, I also like Darren's suggestion to restrict the reserved space for standard typenames and option names to the ASCII range. Dåmîäñ
Re: How are unrecognized options to built-in pod block types treated?
Carl proposed: > The other path that seems reasonable to me would be to use the same > naming scheme as for the block types, i.e. reserve all-upper and > all-lower forms (and die if an unrecognized one of this form is > encountered), and let the custom ones live in the namespace of > mixed-case identifiers. That sounds sane to me as well; the only > question is whether that much structure is needed for config options. I did not consider this issue when designing S26, but in considering it now, I think Carl's suggestion is entirely sensible and in line with what I intended. Specifically, I think it would be easiest to be consistent and say that all purely lowercase and all purely uppercase config option names are reserved, and that unrecognized reserved config options generate at least a warning when they are parsed. Mixed-case config options should be freely available to users and the parser should simply accept them without complaint and include them in the internal data structure it builds, whereupon they will be available to user-defined Pod extensions. Damian
Re: series operator issues
On 23 July 2010 01:41, Moritz Lenz wrote: > Use the right tool for the right job: > >> square numbers: 0, 1, 4, 9, 16, 25, 36, etc. > > (1..10).map(* ** 2) Or even just: (1..10) »**» 2 Note that you can also get most of the effects you want by using @_ in the series' generator block. For example, here are all the square numbers: 0, { @_**2 } ... * and all the factorials: 1, { (@_+1) * @_[*-1] } ... * or all the factorials more prettily but less inefficiently: 1, { [*] 1...@_ } ... * However, those *are* clunky and nigh unreadable, so I certainly wouldn't object to having the index of the next generated element readily available as an explicit variable in a series' generator block. That would make all manner of evil both easier and cleaner. >;-) Damian
Re: underscores vs hyphens (was Re: A new era for Temporal)
Well, if we're not going to try to implement linguistically based hyphenation/underscoriation rules (and I'd still argue that hyphenating adjectives to nouns and underscoring everything else isn't exactly rocket science), then I'd suggest we reconsider a radically different proposal that was made on this list five years ago: http://www.mail-archive.com/perl6-language@perl.org/msg22675.html The relevant suggestion regarding hyphens vs underscores is: "...to allow both characters, but have them mean the same thing." That is, any isolated internal underscore can be replaced with an isolated internal hyphen (and vice versa), without changing the meaning of the identifier. This would be the death of fine distinctions such as between: activate_main-sequence_detonator(); and: activate_main_sequence-detonator(); which would now resolve to the same subroutine...and do so even if that subroutine had been declared as sub activate-main-sequence-detonator {...} But perhaps such distinctions are indeed too fine and subtle, and we would be better off eliminating the possibility of them entirely. Hyphen/underscore equivalence would allow those (apparently elite few) who can correctly use a hyphen to correctly use the hyphen, whilst the shambling masses can just randomly type underscores or hyphens between each word, as their atavistic whims dictate. ;-) Damian
Re: underscores vs hyphens (was Re: A new era for Temporal)
John Siracusa commented: > That's certainly an example of how hyphens might gain meaning in Perl > 6 names, but I don't think I can endorse it as a convention. People > can't even use hyphens correctly in written English. I have very > little faith that programmers will do any better in code But then the only alternative is to suffer under Slartibartfast's Conundrum: Slartibartfast: I'd much rather be happy than right, any day. Arthur Dent: And are you? Slartibartfast: Ah, well...that's where it all falls down, of course. ;-) And is it really so hard to teach: "use underscore by default and reserve hyphens for between a noun and its adjective"? Perhaps it *is*, but then that's a very sad reflection on our profession. I'm certainly not saying we mightn't collectively find a better (more useful) rule, but that one doesn't strike me as particularly hard. Damian
Re: underscores vs hyphens (was Re: A new era for Temporal)
Personally, I'd prefer to see the English conventions carried over to the use of general use of hyphen and underscore in identifiers in the core (and everywhere else). By that, I mean that, in English, the hyphen is notionally a "higher precedence" word-separator than the space (or than its intra-identifier stand-in: the underscore). For example: there's an important difference between: initiate_main-sequence_detonator_phase() and: initiate_main_sequence-detonator_phase() The former initiates the detonator phase for the main sequence; the latter initiates the main phase of the sequence detonator. More simply, there's a difference between: $obj1.set_difference($obj2); and: $obj1.set-difference($obj2); The first is setting a difference; the second is computing a difference-of-sets. The rule I intend to use and recommend when employing this new identifier character in multiword names is that you should place an underscore between "ordinary unrelated" words, and a hyphen only between a word and some modifier that applies specifically to that word. Which, if applied to Temporal, would lead to: my $now = DateTime.from_epoch(time); The C method also has the synonym C. (These are also available through the methods C and C, respectively.) There's a C method, The C method returns a number 1..5 The C method returns the day of the quarter. The C method returns the day of the year, The method C returns the second truncated to an integer. The C method returns the C object (i.e. only C<.from_epoch()> actually uses underscore). Oh, and the optional C<:timezone> argument to C<.new()> should probably become C<:time-zone> for consistency with the C<.time-zone()> method (or, preferably, we should jut bite the bullet and go with C throughout). Damian
Re: A common and useful thing that doesn't appear to be easy in Perl 6
> We could make enum declarators even more like constant declarators > by using a pseudo assignment. Then we could use = instead of parens: > > enum Perms = Z=> 1,2,4...*; Hmm. That doesn't seem very like constant declarators. In a constant declarator, the constant appears on the lhs and its value on the rhs. In this proposal, the constants all appear on the rhs, along with the values. Besides, enums are type declarators, not (just) object declarators, and no other type declarator uses a pseudo-assignment, does it? If we wanted enums to use something more like the constant declarator syntax, I'd have thought: enum Perms = 1,2,4...*; was a much closer analog (and syntactically cleaner too). Damian
Re: A common and useful thing that doesn't appear to be easy in Perl 6
Jonathan Lang wrote: > Wouldn't that be C< = 0...* >? Indeed. Thanks for the correction. > That said, don't we already have a means of assigning specific values > to individual members of an enum? I forget the exact syntax, The exact syntax is: enum Perms [Read => 1, Write => 2, Exec => 4, Fold => 8, Spindle => 16, Mutilate => 32] or enum Perms << :Read(1), :Write(2), :Exec(4), :Fold(8), :Spindle(16), :Mutilate(32) >> or any other variation that uses a list of pairs. > Clumsy, sure; The clumsiness isn't the main problem, in my view; the explicitness of having to provide the values is. Even the hyperoperated version (which isn't currently legal, BTW) requires an explicit series to generate the values. Yet the whole point of enums is to avoid explicitly enumerating the values (as far as possible). The secondary point here is that an enum type doesn't solve the original problem, since it won't allow combinations of enumerated values: enum Perms [Read => 1, Write => 2, Exec => 4, Fold => 8, Spindle => 16, Mutilate => 32]; my Perms $perms = Read +| Write; # Error I'm now strongly convinced that a module is the right answer here. We have the need for a datatype that is essential is a couple of domains, but much better handled via Sets in most other contexts. So it's inherently a special-purpose datatype, and hence not appropriate in the core language. And Perl 6 already provides the macro mechanism needed to allow such a datatype to be seamlessly added with a convenient and "natural" syntax. Which is what I shall eventually do, I suspect. In that sense this discussion *vindicates* the current design, demonstrating that it provides the necessary flexibility and tools to allow someone to implement a new datatype and declarator syntax and integrate them seamlessly into the language, without having to redefine the language itself...or modify the compiler. Damian
Re: A common and useful thing that doesn't appear to be easy in Perl 6
Daniel Ruoso pointed out: > Using bitsets in Perl 6 is just as easy as using in Perl 5 -- which > happens to be the same as using in C, but it's not C... > > constant PERM_WRITE = 0b0001; > constant PERM_READ = 0b0010; > constant PERM_EXEC = 0b0100; > constant PERM_NAMES = { PERM_WRITE => 'Write', >PERM_READ => 'Read', >PERM_EXEC => 'Exec' }; > subset Perm of Int where * < 8; Sure. This certainly works, but the technique requires the developer to hard-code each name twice and to hard-code the constant 8 as well. This seems unfortunately brittle from a maintainability point of view. I know hardware engineers aren't supposed to care about maintainability, but I'd like us to make it easier for them to do the right thing than not. ;-) > The thing that bugs me is that sets have way more uses then bitsets, and > we might be overspecializing sets to support that semantics. Yes. I have the same concern. > If there's a strong case for bitsets, maybe it's worth having a > specialized declarator. Or maybe it doesn't need to be core syntax at all and I just need to create a module that implements my original dream syntax/semantics; namely a macro implementing a C type declarator that allows: use Type::Bitset; bitset Perms ; # Declares enumerated constants with successive powers-of-two values # Also declares: subset Perms of Int where 0 .. [+|] @constant_values; # Hence allows: my Perms $perms = Read +| Write +| Mutilate; # Okay my Perms $bad_perms = Read +| Write +| 42; # Error Aw heck, now that I've specified it, the implementation is just a SMOP. Forget I asked. I'll just write it myself! ;-) Damian
Re: A common and useful thing that doesn't appear to be easy in Perl 6
Larry mused: > Alternatively, maybe there should be some way to express infinite sets. > Not sure I like the idea of an infinite junction, but something resembling: > > subset PowersOf2 of Int where any(1,2,4...*) > enum Perms of PowersOf2 ; > say Exec; # 4 > > Presumably the series in the junction would have to be sufficiently > monotonic so we can know when we've looked far enough. Or we just > allow something like one of: > > subset PowersOf2 is Set(1,2,4...*); > constant PowersOf2 = Set(1,2,4...*); > > In any case, the idea is that an enum of something like PowersOf2 would > be smart enough not to use values that aren't in the 'of' type. I do like the idea of being able to specify the sequence of values of an enumeration by using a series of some kind. And I must say the one that feels most natural is the one that plays on the equivalence of underlying equivalence of enums and constants, namely: enum Perms = 1,2,4...*; This would also mean you could think of a "normal" enum: enum Days ; as simply defaulting to C< = 1...* >. > We've got these silly series operators; it seems a shame not to use > them for powers of two when appropriate. I certainly agree there. Damian
Re: A common and useful thing that doesn't appear to be easy in Perl 6
Larry concluded: > I do freely admit that most Perlfolk are not used to thinking of > permissions in terms of set theory. But as I said, we're looking at > kind of a strange use case here, and perhaps not typical of the kinds > of sets of small numbers that people will be using in the future. The reason I raised the issue is because I believe it *is* a very typical use-case...in certain hardware-oriented domains. > I kinda hope we can get a bit further away from the machine code > level of reality one of these decades. Perl 6 should not be > optimized for C semantics. Agreed. But it should at least support those who need to work at the machine code level, but would prefer not to have to do so in C. That said, I'd be perfectly happy to encourage the use of proper set abstractions for this purpose, so long as the long-suffering hardware engineers can still easily convert the final set to an appropriate bit-pattern when it's time to pump the results out to the hardware. Damian
A common and useful thing that doesn't appear to be easy in Perl 6
An issue came up in a class I was teaching today... There doesn't seem to be an easy way to create a type that allows a set of enumerated bit-flags *and* all the combinations of those flags...and nothing else. For example: enum Permissions ( Read => 0b0001, Write => 0b0010, Exec => 0b0100 ); my Permissions $rwx = Read +| Write;# Error I know I could use junctions: subset BitFlag where Read|Write|Exec; my BitFlag $rwx = Read | Write; but it's not easy to recover the actual bitpattern from that, except with: $bitpattern = [+|] $rwx.eigenstates; which is suboptimal in readability (not to mention that it requires MONKEY_TYPING to allow access to the .eigenstates method). Ideally, what I'd like to be able to do is something like: enum Permissions is bitset < Read Write Exec >; # The 'is bitset' starts numbering at 0b0001 (instead of the usual zero) # and doubles each subsequent enumeration value (instead of the usual ++). # It also implicitly fills in the various other bitwise-or permutations # as valid-but-nameless enumerated values my Permissions $rwx = Read +| Write;# Now fine The closest I can think of at the moment is something like: enum NamedPermissions ( Read => 0b0001, Write => 0b0010, Exec => 0b0100 ); subset Permissions of Int where 0 .. [+|]NamedPermissions.enums.values; my Permissions $rwx = Read +| Write;# Fine which is still a little too constructive, too explicit (you have to get the bit values right), as well as being too obscure for such a common task. Of course, I could always create a macro to encapsulate the explicit constructive obscurity: macro bitset ($typename, @value_names) is parsed(/:s () '<' ( )+ '>' /) { # [build code to implement the above trick here] } # and later... bitset Permissions < Read Write Exec >; but this is such a common requirement in engineering applications that it would be great if this wheel didn't constantly have to be reinvented. If anyone can think of a cleaner way to do it within the current semantics, I'd be very happy to hear of it. I'm jetlagged and bleary from a full day of teaching and I may well be missing an obvious answer. Thanks, Damian
Re: continuation markers for long literals (was Re: r29931 - docs/Perl6/Spec)
Surely this is not a common-enough requirement to warrant a special syntax. At 80-columns, you can represent integers up to ninety-nine quinvigintillion, nine hundred ninety-nine quattuorvigintillion, nine hundred ninety-nine trevigintillion, nine hundred ninety-nine duovigintillion, nine hundred ninety-nine unvigintillion, nine hundred ninety-nine vigintillion, nine hundred ninety-nine novemdecillion, nine hundred ninety-nine octodecillion, nine hundred ninety-nine septendecillion, nine hundred ninety-nine sexdecillion, nine hundred ninety- nine quindecillion, nine hundred ninety-nine quattuordecillion, nine hundred ninety-nine tredecillion, nine hundred ninety-nine duodecillion, nine hundred ninety-nine undecillion, nine hundred ninety-nine decillion, nine hundred ninety-nine nonillion, nine hundred ninety-nine octillion, nine hundred ninety-nine septillion, nine hundred ninety-nine sextillion, nine hundred ninety-nine quintillion, nine hundred ninety- nine quadrillion, nine hundred ninety-nine trillion, nine hundred ninety- nine billion, nine hundred ninety-nine million, nine hundred ninety-nine thousand, and nine hundred ninety-nine. Surely that's enough for the vast majority of users, isn't it? And if you *do* need anything bigger (perhaps to represent the burgeoning U.S. national debt) then there's always some variation on: my $debt = +( 123456789012345678901234567890123456789012345678901234 ~ 567890123456789012345678901234567890123456789012345678 ~ 901234567890123456789012345678901 ); or even: my $debt = +( 123_456_789_012_345_678_901_234_567_890_123_456_789_012_345_678_901_234 ~ 567_890_123_456_789_012_345_678_901_234_567_890_123_456_789_012_345_678 ~ 901_234_567_890_123_456_789_012_345_678_901 ); if you like to group your thousands for better readability. With adequate constant folding, both of those are still compile-time constants. Damian
Re: r29768 - docs/Perl6/Spec
>>> + rhyme((1,2),3,:mice) # rhyme has 2 arguments >> >> Should that say 3 arguments? I believe so. >> (If not, please can somebody clarify what >> the 2 arguments are.) > > (1,2) and 3. Named arguments ("mice" in this case) are handled separately. That interpretation is not consistent with the other examples immediately above and below it. Damian
Re: Gripes about Pod6 (S26)
Carl observed: > Partly that is because documentation isn't at the forefront of things > that need to be implemented for Perl 6 to be useful, so it's kind of > lagging behind the rest. > > Partly it's because Damian is the "owner" of that synopsis, and he > practices a kind of "drive-by-updating" to it. As a case in point of > this latter effect, the extensive changes made by Damian in August > *still* haven't hit the Pugs repo. The latter is entirely true but, fortunately, also very easily remedied. I hereby disclaim all present and future "ownership" of S26. :-) By all means put the latest update on the repo (or maybe remove S26 entirely), and start redesigning it collaboratively. Please note that I am not in any way upset, angry, petulant, or otherwise disaffected. I only want the very best for every aspect of Perl 6. If the experience of respected and active developers suggests that Pod 6 isn't a step in the right direction, I can only feel disappointed in myself, apologize for my failure, and gratefully turn the task over to those with better ideas and more time and energy to devote to the problem. As regards Pod vs Pandoc (which is pretty clearly the leading contender of the structured text notations), I do think Pod has some decided advantages. For example, I feel it's better to have four basic metasyntaxes (X<>, =IDENT, :OPTION, #=) and most with identifier-based labels, than to have over two dozen (plus embedded HTML and TeX) all with symbolic labels. I guess I feel that Pandoc/Markdown/ReST/etc. are optimized for writing documentation "source", whereas Pod is optimized for reading documentation "source". I'm not sorry I aimed for the latter, whatever the deficiencies in the result. Carl also suggested: > I think that the future of S26 is very much dependent on whether it'll > be able to respond to the needs of Perl 6 developers. Right now it > doesn't respond to much of anything. Outwardly this is self-evidently true. One need only look at the (lack of) commit log for S26. :-( Inwardly, something else entirely is happening. A design(er) can only respond effectively when subjected to a clear net force pushing or pulling in some well-defined direction. The redesign of Pod has been subject to an enormous number of such forces. Unfortunately they push and pull it in every possible mutually contradictory direction, thereby producing very little overall impetus. So I would encourage those of you who are going to collectively take over the shepherding of this synopsis to go back through the p6l archives and review the many many posts commenting on and requesting features for Perl 6 documentation. In particular, please look carefully at the very different needs of those who document OO code, procedural code, frameworks, modules, applications, design documents, presentations, and Perl itself. You will find that many of these contributors ignore, discount, or actively disparage the needs of their fellow users. For example, in this very thead: > I'm not writing a book, I'm writing code. And if I was writing a book, > I wouldn't be dumb enough to write it in POD. Yet what is the Perl documentation itself but a series of book chapters? And surely that documentation is the largest single use of Pod anywhere? Should we not write Perl's own documentation in Perl's own documentation notation? Should we really discourage the use of standard headings to consistently mark the common components of these (and most other) Perl-related documents? I sincerely hope that the future community of designers of Perl 6 's documentation format will find a way to honour and support the very different needs of *all* the creators and users of Perl, not just the needs of the most prominent, or the needs of the most experienced, or the needs of the most loquacious. I have always thought that was the *real* challenge of post-modern language design. Damian
Re: S26 - The Next Generation
Jon Lang asked: > Not actually S26; but closely related: should $=POD and .WHY be > read-only? I had assumed so. > Also, should there be other Pod variables besides $=POD? > If so, which ones? The original idea was that every Pod block with any kind of TYPENAME would be available as $=TYPENAME. For example: $=USAGE, $=OPTIONS, $=SYNOPSIS, etc. In particular, $=DATA is likely to be heavily used. > Back on the subject of S26: should declarator blocks and aliases be > able to introspect the object with which they're associated? That is, > should you be able to say things like A<.WHAT> or A<.^methods>? (If > so, be sure never to say A<.WHY>.) We pretty much have to provide a way for a Pod object to know what Perl object it's associated with. The whole point is to create an open-ended mechanism to allow people to twiddle how Pod is rendered. To do that, they need to be able to walk the documentation tree (a.k.a. $=POD) and extract useful information from any class, code, or variable declarations associated with a particular comment-style node in the doctree. Damian
Re: S26 - The Next Generation
yary asked: > Can some concept/implementation of $=POD lazyness only incur the > memory and performance hit on access? IANAImplementor, but I suspect that virtually all of the performance hit could be incurred at run-time, if it happened to be implemented that way. The memory hit too, if necessary, but that would then make the performance hit hit very hard indeed. I suspect that it would be better to preserve the Poddish parts of the AST structure and just have them transmogrify into the appropriate Pod objects on demand. Damian
Re: S26 - The Next Generation
Aaron Sherman asked: > Should there be an explicit way to step this down to just parsing the bits > that are called out as pod? The original conception allowed for Pod to be independent of the interleaved language. That has now been supplanted by a model that views Pod as an integral part of Perl. There's definitely a trade-off there, but one we've decided to make. So, no, there are no longer any plans to extend Pod to documenting *everything*, except so far as Perl 6 will be ale to subsume everything (in line with Larry's musings of "braided languages"). > There is no explicit mention in the document as to what happens at the Perl > level when the closing bracket is reached at a point that is not the end of > a line (i.e. it is not followed by whitespace that contains a newline > character). Here's an example: > > my $a #-[stop the presses!] = 4; Except for the #~ instead of #=, that's valid (and documented) Perl 6. That is, Pod comments work exactly like non-Pod comments. As Synopsis 26 now states: That is, declarator Pod blocks are syntactically like ordinary Perl 6 single-line comments and embedded comments. >> * This new declarator block form is special. During source code parsing, >> normal Pod blocks are simply appended into an array attribute of >> surrounding Comment object in the AST (which is just $=POD, at the >> top level). However declarator blocks are *also* appended to the >> .WHY attribute of the declarator at the start of the most recent >> (or immediately following) line. > > I'd very much like to establish that at default optimization levels for > execution, this information is not guaranteed to be maintained past the > creation of the AST. Unfortunately, it is. Perl 6 defines that Perl 6 programs can always access their own Pod at runtime (via $=POD). You probably can't even optimize the information away in the absence of any compile-time reference to $=POD, since there are plenty of symbolic ways to refer to $=POD at run-time. Damian
Re: Looking for help updating Perl 6 and Parrot part of Perl Myths talk
Darren Duncan wrote: > So another proposal I have is to add to the slideshow mentions of the > Enlightened and Modern Perl movements and where one can go to read more, > this being supplemental to PBP. With that suggestion I'd whole-heartedly concur. > My own opinion is that the modern best way to use inside-out objects is in > combination with Moose, as the physical representation used for objects > behind the scenes, rather than each user class having direct package > lexicals like %foo_attr and %bar_attr. No doubt that's a best-of-both-worlds solution...for those who can handle it. I guess my point is simply that not everyone can handle it. Just as not everyone could handle raw inside-out techniques, which is why Class::Std was written in the first place. But, as you say, this is now far off-topic, so let's leave it at that. Damian
Re: Looking for help updating Perl 6 and Parrot part of Perl Myths talk
Darren Duncan wrote: > pg 36 - About the "Perl Best Practices" book, you should be clear to > mention that what is considered best practices has evolved significantly > since that book came out, so teams can't simply agree on "We'll just follow > PBP guidelines" and call it a day, but should study more modern resources > also; While it's certainly true that best practices have evolved (and modernized ;-) since PBP came out, teams *can* still simply agree to follow PBP. They won't we as well off as if they'd thought about the issues themselves (i.e. read and followed the advice in Chapter 1) and explored the various modern/evolved resources now available, but they'd still be much better off than they are at present. Not everyone has the time, inclination, or capacity to evaluate the myriad possibilities and make informed personal judgements in every case. Ideally, if you mention PBP, describe it as a starting point (which is how it describes itself in Chapter 1, btw), and the various Enlightened and Modern Perl movements as evolutionary resources for going much further in certain very specific directions. > in particular the recommendation to use Class::STD/etc is outdated, > and people should use Moose instead. There is no doubt that Moose is an excellent and very advanced framework, but both the above assertions are highly debatable, especially if you s/moribund Class::Std/actively developed Object::InsideOut/. Damian
Re: S26 - The Next Generation
Jon Lang elaborated: > I don't think that there will be a problem. First, #=> is easy enough > to distinguish from #=; I don't foresee any confusion. I'm not so sure. #=> is a lot more like #= that =alias is. And the one character of difference is on the non-significant (right-hand) side. Need to think about it and role-play it a little. > With the ability to attach multiple declarator blocks to a single > declarator, it should be trivial to replace any one of them with a > declarator alias: > > #=> > class Foo { > #= Class Foo > #= a sample class used to illustrate. > #= This particular class has nothing in it. > } See that's precisely my problem. I don't think the #=> stands out at all there as being an alias. > #= Class A > class Foo { > #= a sample class used to illustrate. > #= This particular class has nothing in it. > #=> X And this illustrates my other qualm, that the two forms are just too similar. And, yes, having the aliasing mechanism be something postfix(able) creates issues of when the aliases come into existence. > I tend to agree. I only proposed numbering as a way of being able to > access different declarators without having to explicitly label them. > I can definitely understand if this option gets dropped as being too > error-prone with regard to maintenance. That's my plan. >> =alias >> class Database::Handle { >> =alias >> has IO $!handle; >> >> =alias open >> my Bool method open ($filename) {...} >> >> =alias close >> my Bool method close() {...} >> >> =for para >> Note that the A method of class A >> stores the resulting low-level database handle >> in its private A attribute, while the A >> method closes that handle. >> } > > The problem with this example is that '=alias name' isn't a declarator > alias; it's a block alias. I'm proposing to change that and allow explicit names on declarator aliases as well. Or, rather, to unify the two into a "block-or-declarator" alias. > my Bool method open ($filename) {...} #=>[m1] #= Here's a > block for A. > my Bool method close () {...} #=>m2 > > And given that brief names are going to be preferred, this could > result in very compact, yet still readable, combinations of declarator > aliases and blocks. Yes, this is a definite advantage of the proposal. No question. But I'm still concerned that the two syntaxes are just so similar. I'll continue pondering the trade-off. Damian
Re: S26 - The Next Generation
Jon Lang huh'd: > Huh. Would you be able to do something like: > > =begin pod > Welcome to $?FILE. > > ...and have it interpolate the file's name? Or would you need some > special markup for this, such as: > > =begin pod > Welcome to A<$?FILE>. The latter. Variables are just too common in documentation to have (some of) them interpolate automagically. > Or would you have to alias the variable and then refer to it? No. I envisage that A<> would recognize an alias starting with a sigil, and "auto-alias" it for you. Damian
Re: S26 - The Next Generation
Jon Lang kept his promise: > I promised some further thoughts; here they are: Much appreciated. > As written, declarator aliasing attaches the alias to a piece of code, > and draws both the name and the alias from that. What about using a > special case of the declarator block for this? That is: > > class Database::Handle { #=alias > has IO $!handle; #=alias > my Bool method open ($filename) {...} #=alias > > =for para > Note that the A method of class A > stores the resulting low-level database handle > in its private A attribute. > > } > or: > class Database::Handle { #=> > has IO $!handle; #=> > my Bool method open ($filename) {...} #=> > > =for para > Note that the A method of class A > stores the resulting low-level database handle > in its private A attribute. > > } Definitely interesting ideas, especially the second one. My concern would be that they compete with the #= blocks which might also be needed on such declarations. > Regardless of what syntax you use for declarator aliasing, I'd also > recommend some sort of numbering scheme if you alias more than one > declarator of the same type in the same lexical scope: It's definitely an issue I hadn't considered properly. However, I think the correct solution is not numbering (which is always fraught with problems when subsequent maintenance adds an extra declarator in the middle), but rather naming. Like so: =alias class Database::Handle { =alias has IO $!handle; =alias open my Bool method open ($filename) {...} =alias close my Bool method close() {...} =for para Note that the A method of class A stores the resulting low-level database handle in its private A attribute, while the A method closes that handle. } I know this looks redundant. But the whole point of logical names is you don't have to change them when the physical name changes: =alias class Database::Handle { =alias has IO $!handle; =alias open my Bool method open_file ($filename) {...} =alias close my Bool method close_and_sync() {...} =for para Note that the A method of class A stores the resulting low-level database handle in its private A attribute, while the A method closes that handle. } > If you adopt the declarator block basis for declarator aliasing, you > could even let the documenter choose his own names: > > class Database::Handle { #=> > has IO $!handle; #=> > > my Bool method open ($filename) {...} #=>m1 > my Bool method close () {...} #=>m2 > An unrelated possibility would be to allow empty A<> tags in a > declarator block, with 'A<>' being replaced with the name of the > declarator to which the block is attached: These are both very useful ideas. I'll ponder them carefully in preparation for the next revision. Thanks, Jon! Damian
Re: S26 - The Next Generation
Raiph elucidated: > Hmm. I was thinking Pod would be parsed by a P6/PGE grammar, one that > could be relatively easily edited/extended to suit another context, because, > I thought, it could then be made available as a stock --doc subsystem that > all PCT based languages get more or less for free. Sure, that might be possible. The problem is one of syntax. Pod, as currently specified, defines two syntaxes for magic comments that define documentation. The difficulty is that both those syntaxes might already be in use in other languages (the /^ \h* \= / syntax most certainly will be), so you end up having to change the Pod parsing syntax on a per-language basis. I can't really see that being very attractive to the implementors of other languages, nor the inconsistency being very attractive to users of those languages. >> We need a way of referring to ambient code within Pod, without the >> Podder having to write more code to get it. > > I was thinking it would be possible to reference (compiler) variables > representing eg. the name and sig of a block being parsed, or a block > or declaration which has just been parsed, or which is just about to be > parsed, and that simply referencing these variables would be ok and > would save the need to create explicit named anchors. Well, that certainly *is* possible in Pod, which will definitely have access to any compile-time Perl variables, including the following usually bits of information: $?FILE Which file am I in? $?LINE Which line am I at? &?ROUTINE Which routine am I in? &?BLOCK Which block am I in? $?SCOPE Which lexical scope am I in? $?PACKAGE Which package am I in? $?MODULEWhich module am I in? $?CLASS Which class am I in? (as variable) $?ROLE Which role am I in? (as variable) $?GRAMMAR Which grammar am I in? But that's not necessarily enough. I can imagine many other pieces of code that you might want both in the source and in the documentation, but which it would not be easy to extract from the introspective variables. For example: PRE =alias precondition { $_ > 0 } or: if ($?TESTING) =alias example1 { my $tree = TreeClass.new(); $tree.size() == 0 :ok; $tree.insert("node value"); $tree.size() == 1 :ok; } Not to mention all of the clever uses I can't think of yet. ;-) Damian
Re: S26 - The Next Generation
Smylers pointed out: >> * Hence it must always parsed using full Perl 6 grammar: perl6 -doc > > Having a multi-character option preceded by a single hyphen doesn't play > well with bundling of single-character options... You make many good points. Changed to: perl --doc Thanks, Damian
Re: S26 - The Next Generation
Jonathan "Dataweaver" Lang proposed: > OK. Let me propose an alternative (which I expect will be immediately > shot down): BANG! ;-) > Allow '=begin alias', '=end alias', and '=for alias' as special cases: > the Perl parser makes an exception for them and doesn't treat them as > the start or end of POD Blocks, merely as single-line directives; but > the Pod parser treats them as normal Pod Blocks, with the contents > being attached to the alias. Well, clearly I'm not going to be in favour of introducing exceptions to the general syntax. However, I had originally thought that we should have =alias and =dealias directives to delimit code extractions. In the end I liked the use of the code's own delimiters better, but I guess if people preferred to have two directives as delimiters, we could consider that instead. Let's see what others think. Damian
Re: S26 - The Next Generation
Kyle suggested: > Pod itself is a DSL. Sure. But to allow arbitrary processing and rendering of Pod, a DSL isn't enough. > If we're committed to giving guns to books, can we default to having > the safety on? Can it be so that 'perl6doc foo.pl' does not execute > any code without an option to allow it? There is no perl6doc. There is only: perl6 -doc That is, running the Perl interpreter in a special mode to get documentation. > Perl 5 programmers are sometimes surprised to find that 'perl -c > strange.pl' can execute code. Imagine their surprise to find that > 'perl6doc' does too. But the reason will be exactly the same. Namely, because in Perl you can't tell what's documentation and what's code until you parse the mixture. And you can't parse Perl (5 or 6) without executing stuff. Look, I'm sure we *will* have a safety mode of parsing Pod (maybe: perl -undoc) But it can't be on by default, otherwise no-one can write anything but vanilla Pod and expect it to work. It's like saying that 'use' is potentially dangerous (which it *is*) so can we have it off by default. In Perl, the answer has to be "no". Damian
Re: S26 - The Next Generation
> Could we also get "=numbered" and "=term" directives that are > equivalent to "=item :numbered" and "=item :term", respectively, for > use with abbreviated blocks? E.g.: > > =numbered First Item > =numbered Second Item > =numbered Third Item That's just: =item # First Item =item # Second Item =item # Third Item or even just: =item# First Item =item# Second Item =item# Third Item > =term First Name > Definition > =term Second Name > Definition This doesn't work, because it doesn't conform to the general syntax of abbreviated blocks (which is that the content starts immediately after the typename). The term of a term/definition is basically a very complicated bullet point, and hence needs to be configured with an option. Of course, we could make a special exemption to the general syntax, or say that in this one case the first line of content is special, but I'm *really* loathe to inject special cases when a general mechanism already exists. > Within tables, you should probably replace "whitespace" with "multiple > whitespace" as a column delimiter; otherwise, the space between two > words in an identifier would trigger a new column: Indeed. That was both the intention and the implementation in Perl6::Perldoc, but it definitely needs to be mentioned explicitly. Thank-you. > When using the code block alias, are the outermost curly braces > considered to be part of the ambient code? Yes. All ambient code is actual code. > Why is =END a block, and not a directive? Damn good question. I can't think of any reason off the top of my head. I'll need to ponder that. Damian
Re: S26 - The Next Generation
Jonathan "Dataweaver" Lang enquired: > Will ther be any ambiguity between Pod and wraparound operators that > begin with =? No. Lines that start with an '=' that is *immediately* followed by an identifier are always Pod. If there's a space after the '=' it's always an assignment. You could *create* an ambiguity, by defining an operator such as &infix:<=x> but then you get precisely what you deserve. ;-) > if really_long_expression > == value { ... } # Pod, or equality operator? Always equality. Pod is always =IDENT. Only. > Note the recent revisions to how Perl comments work - in particular, > an embedded comment is now spelled "#`[ ... ]". Should "embedded > attached Pod" be spelled as "#=`[ ... ]"? Larry and I discussed this and concluded that #=[ is better. I can see the logic of #`[= but I just can't see the aesthetics of it. I'd much rather have to only look at the second character to determine it's Pod, not a vanilla comment. Besides, I think people will simply learn that #[ is an embedded comment, where specifies what kind of comment it is (I can certainly envisage other kinds besides just vanilla and Pod-flavoured) Damian
Re: S26 - The Next Generation
Raiph commented: > Couldn't the pod processing be encapsulated, perhaps in PGE/NQP, so > that it could be reused in a different Parrot language, provided that > said language supports declarators and comments, or even just comments > (if one downgrades the impact of encountering an "attached" comment > that has no declarator to a warning). The latter would fully restore > the generic applicability of the POD 5 parser, right? While I'm all in favour of other languages using Pod as a documentation format, I think that's unlikely. Pod says that anything of the form: =identfiier *anywhere* as the first non-whitespace of a line, is considered a Pod directive. I can't see many other language designers being willing to limit their assignment statements that way. > While I like the design, and I think it's near enough complete, and I > think a reader who knows perl and pod well could understand your > current description of that design, I think it could do with a major > rewrite to make it less confusing to work out what you really mean as > against what's currently written. ;) However, I think it's too early > to attempt such a rewrite, or even to comment on specific problems; I > plan to wait another couple weeks for some list back-and-forth before > commenting further about clarity and/or proposing edits and/or > providing patches. I agree that a rewrite would certainly help it. And will be happy to kibitz anyone who volunteers to do so! ;-) Or, of course, to accept patches. > You don't say whether attached pod allows for configuration info or > formatting codes. It does. I don't say it doesn't, and I do show attached comments with it (e.g. the $chainsaw example). I'll make it explicit however. > (Incidentally, .WHY seems a bit too cute; what about .DOC or .POD? > Same with .WHEREFORE; my boring suggestion is .CODE.) I think you're going to have to take that up with Larry. Presumably the WHO, HOW, WHERE, WHENCE, etc. should go too? Personally (and I say this as the guy who pioneered "you think that's cute now..." ;-) I think the interrogatives work very well, especially because they stay so well out of the way of anything a sane person (pace Larry) would use to name an ordinary method. > Declarator aliases, as specced, seem to me the weakest part of the > design. Declarator aliases seem to only allow one my, one has, etc. in > a given context. We could certainly consider allowing a fourth form of alias like so: =alias IDENTIFIER DECLARATOR which would use the specified identifier as the alias's name, rather than the declarator. Lets see what other people think. > Having to use non-attached pod syntax to do an > attached thing seems very weird. I think they have to be different, because they do opposite things...or at least things in opposite directions. A declarator block says "this Pod belongs to this code"; an alias says "this code can be referred to in subsequent Pod". I'd be happy to be proved wrong if someone can come up with a better mechanism than aliases that still allows us to pull code into Pod. > Having to use aliases at all to refer > to things that the Perl 6 compiler already has a name for seems like > an ugly/heavyweight/suboptimal approach. I think aliases are essential. We need a way of referring to ambient code within Pod, without the Podder having to write more code to get it. Damian
Re: S26 - The Next Generation
Moritz wrote: > However it seems we have to pay a price: each act of rendering a Pod > file actually means executing the program that's being documented (at > least the BEGIN blocks and other stuff that happens at compile time), > with all the security risks implied. So we'll need a *very* good > sandbox. Is that worth it? I believe so. The sheer range of approaches that people said they wanted Pod to support made it impossible for Pod to support anyone, unless everyone can configure Pod directly. The choice then becomes: do we provide Pod with a DSL for configuration, or do we just use Perl 6 as its metalanguage? The answer seemed pretty obvious then. I'm certainly not smart enough to design a config language that's powerful enough to do everything everyone wants documentation-wise. But Larry is. And already did. ;-) Sure, there are downsides: Pod becomes much more tightly tied to Perl 6. And the black hats can indeed do bad things with it. But, you know, the bad guys have been able to do that with CPAN modules for a long time now, and the incidence of that happening is vanishingly small. I'm prepared to bet that most people who download something from CPAN don't scour the source checking for system('rm -rf /')'s, nor do they run that code in a sandbox. And the people who *do* take such precautions will simply start to do the same thing for any documented code (or coded documentation :-). Or maybe the sandbox will just be an option to disable any DOC blocks except the default one. Or else maybe perl -doc will just run under an augmented taint mode that suspects not just anything that emerges from an input op, but also anything created in a DOC'd command. > Two minor comments: > > A valid identifier is a sequence of alphanumerics and/or > underscores, beginning with an alphabetic or underscore > > > > Is there a good reason to deviate from Perl 6's definition of an > identifier? For the sake of consistentcy I'd just say that the Perl 6 rules > apply. Great idea. Should definitely be that way. Patch applied. > sub fu ( #= This text stored in C<&fu.WHY> > > This seems to be ignorant of multi subs. Not ignorant of. Just not an example of. ;-) > If I write > > multi sub fu () { #= some Pod > > Then &fu is a multi, not a particular candidate. Does it actually > attach to the .WHY of the candidate? Or of the multi? Of the particular candidate. I'll make that clearer. (If you want to document the entire multi, attach the documentation to the proto.) Damian
Re: S26 - The Next Generation
Darren Duncan asked: > But one thing I'm not sure whether or not it was addressed is regards to > whether free-form documentation is still supported or can be effectively > combined with embedding documentation into the places that it is > documenting. Yes and yes. Normal Pod blocks weren't mentioned in the executive summary because they haven't changed. Except that they got much better, because now you can indent them to match the layout of the code they're interleaving. Or, indeed, indent them simply to indicate the Pod's own lexical structure. The Necrotelecomnicon example was originally written like so (before I removed the Pod blocks...to keep the example properly focussed): =head2 IPC magic =para The base class for doing deep and dangerous things with IPC is #= Base class for comms necromancy hierarchy class Magic::Necrotelecomnicon { has $.elemental; #= Source of all power has $!true_name; # Source of all self-protection (not documented) method cast(Spell $s) #= Initiate a specified spell normally { do_raw_magic($s); } #= Initiate a specified spell abnormally method kast(Spell $s) { do_raw_magic($s, :alternative); } } which, by default (and in the absence of any semi-literate or OO-bsessive modules one might explicitly C), will simply produce something like: IPC Magic The base class for doing deep and dangerous things with IPC is Name: Magic::Necrotelecomnicon: Desc: Base class for comms necromancy hierarchy Attrs: .elemental : Source of all power Methods: .cast(Spell $s) : Initiate a specified spell normally .kast(Spell $s) : Initiate a specified spell abnormally Damian
Re: comments as preserved meta-data (was Re: Embedded comments ...)
Raiph Mellor hyperpunned: > With this whiny man exchange ultimately having bourne supreme fruit, > the apocalypse watch for the post damian weekend begins... ARRRG! Damian ;-)
Re: comments as preserved meta-data (was Re: Embedded comments ...)
Raiph Mellor wrote: > Anyhoo, I'd love to see a session of brainstorming, with nitty gritty > detail, about possible ways to get what you guys and Mark and I and > perhaps others think we would like to see in the way of super tightly > woven together comments and code, where said brainstorming initially > works within the creative constraint of leveraging the P6 spec as is, > plus reasonable extrapolation of unspecced bits. Think grammar > morphing, aspects of macros, the existing unfinished POD6 spec, and > any other relevant existing bits I'm forgetting. Excellent idea. But may I suggest you perhaps might like to hold off that discussion until next week? @Larry had some very fruitful discussions about the long-overdue Pod spec during YAPC::EU last week and, as a result, I plan to (finally!!!) release a new version of S26 this week-end. I very much hope that this new revision will satisfy The Overmeer Desiderata [1] too. Damian [1] Sounds like a Robert Ludlum novel, eh?
Re: confusing list assignment tests
Mark J. Reed wrote: > My understanding is that the P6 way to do that is to return a Capture > containing the desired return values (which can lazily do things only > when accessed) in the appropriate slots. Return a Capture or a more heavily overloaded object, depending on how fine a degree of context discrimination you need. Further to that idea, I'm actually planning to attempt to port Contextual::Return to Perl 6 in the next few weeks. Damian
Re: XOR does not work that way.
Perl 6's approach to xor is consistent with the linguistic sense of 'xor' ("You may have a soup (x)or a salad (x)or a cocktail"), and also with the IEEE 91 standard for logic gates. See: http://ozark.hendrix.edu/~burch/logisim/docs/2.1.0/libs/gates/xor.html for a concise explanation of both these senses of xor. Damian
Re: Multi-d array transforms (was Re: Array rotate)
Larry mused: > �...@a.mung > > the .mung could return > > A) a modified @a (treat @a as mutable) > B) a new array (treat @a as immutable) > C) a remapped array whose elements refer back to @a's elements > > Currently .rotate is defined as A, but I could easily switch it to B, I, for one, would vastly prefer to see the majority of (or even all) container methods being non-mutating (with sugary shortcuts for the most common mutators, if necessary). A major advantage of having both .= and . in the language is that they make it easy to see when something is (and isn't!) being altered in-place. The fewer special-case "it-uses-plain-dot-but-it's-actually-a-mutator" exceptions we have, the better. In fact, I would even be happy with requiring @a.=push and @a.=shift, if it meant that there were *no* special cases. One extra character is a small price to pay for perfect SWIM (and not just "Say What I Mean", the real benefit is the other SWIM: "See What I Meant"). Of course, this assumes that @a.=shift, @a.=push, etc. aren't actually implemented with a copy-modifier-and-replace, but are optimized to in-place mutators, under the hood. Damian
Re: Amazing Perl 6
Daniel Ruoso asked: >> &prefix:<[+]> > > Is that really? I mean... [ ] is a meta-operator, Sure. But once you "[]-meta" an infix operator, you get a prefix operator. See http://perlcabal.org/syn/S03.html#Reduction_operators, which states: "Any infix operator (except for non-associating operators) can be surrounded by square brackets in term position to create a list operator" and has an example of actually implementing the &prefix:<[+]> operator. Damian
Re: Amazing Perl 6
Mark J. Reed asked: > So how is this: > >> Any infix operator (except for non-associating operators) can be surrounded >> by square brackets in term position to create a list operator >> that reduces using that operation: > > reconciled with this: > >> Any ordinary infix operator may be enclosed in square brackets with the same >> meaning The first refers to (meta)operators encountered where a term is expected; the second refers to operators encountered where an infix is expected (i.e. after a term). > ? And if &[+] means &infix:<+>, how do I refer to the Code of the > list operator [+]? &prefix:<[+]> Damian
Re: Amazing Perl 6
Jon Lang suggested: > Start with the addition operator, '1 + 1'. Apply the reducing > metaoperator to it so that it works syntactically like a function: > '[+] 1, 1'. Instead of calling it, pass a code reference to it: > '&[+]'. No. &[+] isn't the Code object for [+]; it's the Code object for &infix:<+>. See http://perlcabal.org/syn/S03.html#Nesting_of_metaoperators > What I'm wondering is how the list knows to feed two items into '[+]'. > While 'infix:<+>' must accept exactly two arguments, '[+]' can accept > an arbitrarily long (or short) list of arguments. And since &[+] is &infix:<+>, that's how it knows. :-) Damian
Re: Amazing Perl 6
Daniel Carrera wrote: > This is a really good list. Mind if I copy it / modify it and post it > somewhere like my blog? That's fine. > One question: > >> * Compactness of expression + semi-infinite data structures: >> >> �...@fib = 1,1...&[+] # The entire Fibonacci sequence > > Very impressive. That's even shorter than Haskell. What's &[+] ? How does > this work? The ... operator takes a list on the left and a generator sub (or block) on the right. It creates a lazy list consisting initially of the left operand. When the left operand runs out, the right operand is invoked to generate extra values. The generator grabs as many existing values from the end of the list as it needs arguments, then appends its result to the end of the lazy list. Lather, rinse, repeat, as often as necessary. In the Fibonacci example, the generator sub is &[+], which is a shorthand for &infix:<+>. So, after 1,1 the generator grabs the last two values (i.e. 1,1), adds them with &infix:<+>, and puts 2 on the end of the list. Next time a value is needed, &infix:<+> grabs the final two list elements (now: 1,2), adds them, and appends 3 to the list. Et cetera, et cetera. For the use of ... to generate lists see: "infix:<...>, the series operator" under http://perlcabal.org/syn/S03.html#List_infix_precedence. For the &[+] syntax, see http://perlcabal.org/syn/S03.html#Nesting_of_metaoperators >> PS: A really mean, but very effective, way of emphasizing the ease, >> expressiveness, compactness, and readability of Perl 6 code is to >> take each of the examples and show the same thing written in Java. >;-) > > It might be appropriate to compare some examples with Ruby or Python. Only if the comparisons are suitably invidious. ;-) Damian
Re: Amazing Perl 6
Here are a few of my favourite Perl 6 selling points: * Compactness of expression: say 'Hello, World!'; * Compactness of expression + semi-infinite data structures: @fib = 1,1...&[+]# The entire Fibonacci sequence * Junctions make comparisons much more natural: if $dice_sum == 7 | 11 { say 'Natural!' } elsif $dice_sum == 2 | 3 | 12 { say 'Craps!' } * Given/when takes that even further: given $dice_sum { when 7 | 11 { say 'Natural!' } when 2 | 3 | 12 { say 'Craps!' } } * Junctions + n-ary comparison help too: if 0 < all(@coefficients) <= 1 { say 'Coefficients are already normalized.'; } * Junctive comparisons + the max operator: if any(@new_values) > all(@existing_values) { $upper_limit = [max] @new_values; } * .invert and .push makes hashes (especially hoa's) vastly more useful (and .perl makes debugging vastly easier): my %comments = perl6 => , perl5 => , perl4 => , perl1 => ; my %epithets; %epithets.push(%comments.invert); say %comments.perl; say %epithets.perl; * Unicode source and data overthrows US cultural hegemony! (oh, and Hinrik has the coolest name in the entire Perl community :-) my @recepción; my $Gruß = 'olá' my $óvoµa = 'Hinrik Örn Sigurðsson'; push @recepción, "$Gruß, $óvoµa!"; * Unary method call + topicalization simplifies multiple operations on objects: for @parcels { .address; .weigh; .ship; while .shipping { .fold; .spindle; .mutilate; } .deliver; } * Subtypes make typing far more precise (and hence more useful): my $filename of Str where /\w**8 '.' \w**3/; my $octet of Int where { 0 <= $^value <= 255 } * Command-line parsing using standard language features: sub MAIN ($text, Bool :f($foo), Str :B($bar), *...@files) { ... } # Can then be invoked as: > my_prog.p6 -f -Bbaz 'two words' file1 file2 etc * Grammars built into the language: grammar Expr::Arithetic { rule Expression { ** $=< + - > } rule Mult { ** $=< * / % > } rule Pow{ ** $=< ^ > } token Term { | '('')' } token Literal { <[+\-]>? \d+ [ \. \d+ ]? } } * Grammar inheritance: grammar Expr::Algebraic is Expr::Arithetic { token Literal { + | } } * "Only perl can parse Perl 5" but "Even Perl 6 can parse Perl 6": given $source_code { $parsetree = m:keepall//; } And that's without even mentioning all the new OO features, multiple dispatch, roles, delegation, macros, etc., etc. The problem with demo- ing the awesomeness of Perl 6 is always running out of demo time before running out of demo-able awesomeness. Damian PS: A really mean, but very effective, way of emphasizing the ease, expressiveness, compactness, and readability of Perl 6 code is to take each of the examples and show the same thing written in Java. >;-)
Re: Docstrings in Perl 6
Hinrik Örn Sigurðsson wrote: > I've been thinking lately about how Perl 6 might offer functionality > similar to Python's docstrings. That is, documentation which is tied > directly to a particular routine, class or module[1]. This is > something which would is very useful in a REPL, and for documentation > readers[2]. For the latest S26 proposal that I'm (very quietly) working on, I'm considering two possible mechanisms to support tying docs to specific components of a program. The first is an C trait: method reverse ( Bool $recursive is docs too> ) is doc with the order of elements reversed.> { my @result; for @.list { @result.unshift($_); } return @result; } The second is a generalized Pod comment form: method reverse #={ Returns copy of L with order of elems reversed. } ( Bool $recursive #={ reverse nested Ls too } ) { my @result; for @.list { @result.unshift($_); } return @result; } Each approach has advantages and disadvantages. Feedback via this forum would be most welcome. > Something similar could be done for MODULE, CLASS, GRAMMAR, ROLE, > TOKEN, and REGEX. Indeed. And with both of the above alternatives that's also true. > One advantage to using Pod blocks in place of actual strings a la > Python, is that the documentation is still independent of the source > code, and need not be in the same file. That's certainly true of your proposal. However, many might argue that one *disadvantage* of using Pod blocks plus :name<> that way is that the documentation is independent of the source code, and need not be in the same file. ;-) Damian
Re: Getting rid of want()
Moritz Lenz wrote: > Instead we should provide a very DWIMmy way to (lazily) create objects > that behave differently in different contexts. That's precisely what the Contextual::Return module does for Perl 5. It's less than perfect in Perl 5, because it has to be implemented via runtime trickery, and hence is too slow. But that problem will disappear in Perl 6 (and perhaps eventually in Perl 5 too) as I'll be able to use macros to remove the runtime overheads. > Patrick pointed out that it can currently be done with > > return $value but role { method Bool { > $code_for_boolean_context_here } }; This is essentially what Contextual::Return does, only with a dwimmier syntax. > And if you propose to keep want(), how would you think it could work? The only thing C::R doesn't handle that want() does is determining the arity of a list context (i.e. how many elements are expected back). That information can be very handy for optimization. And, yes, C::R would already handle it if I could think of a clean interface that was implementable in Perl 5 without source filters. Damian
Re: Junction Algebra
Richard Hainsworth conjectured: > 1) Is the following true for an any junction? > any( ... , any('foo','bar')) === any(...,'foo','bar') > > If yes, then > if an 'any' junction is contained in an outer 'any', the inner 'any' can be > factored out? Yes. More precisely, an 'any' that is directly nested inside another 'any' can be flattened. By "directly", I mean with no intervening levels of non-'any' junctions. That is, not like: any(...,all(...,any('foo', 'bar'))) > 2) Also, is the following true for nested 'all' junctions? viz. > all(... , all('foo', 'bar')) === all(...,'foo','bar') Yes, with a similiar "directly" caveat, as above. > 3) Conjecture: The following is true of all junction types, eg., > junc(..., junc(...)) === junc(..., ...) No. As Patrick so ably pointed out, this is not true for 'one' nor for 'none' Damian
Re: On Junctions
> I stand corrected. That said: with the eigenstates method now private, > it is now quite difficult to get a list of the eigenstates of the > above expression. Yes, that's a concern. Most of the interesting junction-based algorithms I've developed in the past rely on two facilities: the ability to extract eigenstates, and the ability to "thresh" a junction: to determine which eigenstates caused a boolean expression involving the junction to be true. However, I suspect that if these two capabilities prove to be all("not easy", "very useful") in Perl 6, there will soon be a module that facilitates them. ;-) Damian
Re: On Junctions
Jon Lang wrote: > For that matter, I'm not seeing a difference between: > >any( 1&2 ) # any of all of (1, 2) > > ...and: > >any( 1, 2 ) # any of (1, 2) Those two are very different. any(1,2) == 2 is true any(1&2) == 2 is false Nested heterogeneous junctions are extremely useful. For example, the common factors of two numbers ($x and $y) are the eigenstates of: all( any( factors($x) ), any( factors($y) ) ) > If I'm not mistaken on these matters, that means that: > >any( 1|2, 1&2, 5|15, 5&15 ) eqv any(1, 2, 5, 15) No. They have equivalent eigenstates, but they are not themselves equivalent. For example, any( 1|2, 1&2, 5|15, 5&15 ) compares == to 1&2; whereas any(1, 2, 5, 15) doesn't. > And I expect that similar rules hold for other compound junctions. In > short, I won't be surprised if all compound junctions can flatten into > equivalent simple junctions. In general, they can't; not without changing their meaning. Damian
Re: Logo considerations
Earlier I wrote: > Maybe just something like one of the attached graphics > (only redone by someone with actual graphical design skills ;-)? It occurs to me that this comment might be misread as an implied criticism of Conrad's original artwork as well. Just wanted to make it very clear that was definitely not the case. Damian
Re: RFD: Built-in testing
Larry observed: > My feeling on this is that the compiler should simply hardwire this > particular adverb so that all the tests can be autogenerated, and the > multi system never needs to see those versions. I strongly agree. > We are merely hijacking the adverb syntax so that is clear which > operator is being modified. There is no need for the late binding of > multi. It's just a "reserved adverb" if you will. Which probably means > it should be something unlikely to collide with user-defined adverbs. > Maybe something in all caps. For what it's worth, :OK<> can be typed > with one hand while the other holds down the shift key. :) Typical right-hander fascism! We do indeed want to encourage testing by making it easy to write tests, but naming it :TEST<> makes it far easier to *read* tests, which seems to me a better long-term optimization. We would probably also want a mechanism for switching tests on or off in a given compilation unit, or globally, so they can be placed in (and left in!) production code. Perhaps we could use the same mechanism for PRE{...} and POST{...} blocks as well? Which also suggests that a general TEST {...} block (which only runs if testing is enabled) might be valuable? Damian
Re: Should $.foo attributes without "is rw" be writable from within the class
Larry wrote: You have to have a way of talking about your own attributes *as if* they were not your own attributes, and $.foo is that way. When thinking about this, it's also important to remember that, in Perl 6, not everything with a sigil is automatically writeable. For example: constant $answer = 42; $answer = 99; # Kaboom! sub foo( $bar ) { $bar = 42 # Biff!! } $baz := 86; $baz++;# Zowie!!! Likewise a $.foo attribute defaults to read-only, whereas a $!foo attribute defaults to read-write. Damian
Re: adverbial form of Pairs notation question
On Sat, Sep 06, 2008 at 07:06:30PM +1100, Илья wrote: : Hello there, : what :foo<> should exactly produce? : At first I was expecting: : foo => "" : but in Rakudo: : foo => [] : and it looks like the right thing on the other hand. At YAPC::EU I pointed out to Larry that we have an adverbial form that defaults to true: :foo and one that defaults to false: :!foo but none that defaults to undef. After rejecting my very reasonable suggestion of: :¡foo (;-) Larry then proposed that: :foo() should be identical to: :foo(undef) I mention this merely to point out that Larry's response in this thread seems to revise that proposition somewhat, and I would like to suggest that, if :foo() is now to mean something more sophisticated that :foo(undef), then we should still find a "cheap" way of building adverbs with undef values. Damian
Re: List.uniq
Moritz Lenz wrote: There are some tests for List.uniq in the test suite, and pugs implements it, but it's not in S29. Damian seems to have though we should have it. So should we have it? I still think we should. If only because I've seen it re-(mis)-implemented so many times. I'd also suggest that it have the same interface as .sort. Namely that you can pass a block to specify either a unary key-extractor or a binary comparator function. Damian
Re: Perl 6 fundraising and related topics.
Richard Hainsworth wrote: Consider the position you put me, or another sponsor, in. I want to endorse everything Richard then went on to say. I have already contacted Uri and expressed my dismay at his entirely inappropriate interjection of an advertisement for our Perl College event into this discussion about funding for critical Perl projects and personnel. And I am especially upset that anyone might ever feel pressured to be involved in any project or sponsorship just because my name and reputation were invoked on its behalf. It's critical that we find ways to support those in the Perl community who are either building our future or (just as importantly) maintaining our present. But injecting UCE into such discussions does not further that goal, and I am sincerely sorry that it was done in my name. Damian
Re: Documenting Perl6 part 2
Just a brief note to reassure Mark--and everyone else who's interested-- that I'm not ignoring his post...I'm just fully occupied at the moment with other (paying) work. In the meantime I'm thinking very carefully about what Mark suggested. I'll reply properly as soon as I am able. Damian
Re: [svn:perl6-synopsis] r14421 - doc/trunk/design/syn
Mark Overmeer wrote: >> Would the following syntax suffice? >> >>method isValidPostalCode(str $postalcode) returns bool {...} >>=PURPOSE Check weather the postal code confirms to the standards >>=ARG $postalcode >>a string with blanks trimmed. >>=RETURN >>the string is not cleaned-up. >> >> Because you can already do precisely that in the current design of Pod 6. > > This is syntactically what can be done with the current design, > but is semantically very different. I don't think so. It's all just mark-up, no matter what the specific syntax looks like. The semantics are provided by the behaviour of the tools that parse and interpret that mark-up. If the tools treat: =ARG $postalcode a string with blanks trimmed. the same as they treat: `$postalcode: a string with blanks trimmed. then semantically the two are exactly the same. > Besides the point that I do not really like the YELLING all the time, So you create a Pod module that defines "quieter" user-defined block names, and write: =use OOdoc:ver<6.0.0> method isValidPostalCode(str $postalcode) returns bool {...} =Purpose Check weather the postal code confirms to the standards =Arg $postalcode a string with blanks trimmed. =Return the string is not cleaned-up. > You gave the hint that comments are also in the parse tree. They can be. Better still, the (raw) Pod can also be kept in the parse tree...since, like comments, the Perl parser still has to recognize it, even when it's focusing on extracting Perl. > So, that is sufficient for me: And for others too, I hope. Defining Perl 6 and Pod 6 independently opens up so many options for building documentation tools: * As you've observed, you can build them on top of the Perl 6 parser, using any mark-up syntax that will fit in a comment; * And, as I've indicated, you can build them on top of the Pod parser, using the standard Pod syntax; * Or you can build them on top of the Perl 6 parser, but using the standard Pod syntax...by parsing Pod from within the appropriate nodes of the Perl AST using the Pod parser; * Or you can build them on top of the Pod parser, using the standard Pod syntax, by parsing any code-bearing "ambient" nodes within the Pod DOM using the Perl 6 parser; * Or you can even build them by using *both* parsers at once and then walking the two resulting hierarchical representations (AST and DOM) in parallel, since Perl 6 has very good support for such concurrent tree traversals. I don't believe any one of those alternatives will prove to be *the* universal best approach for implementing all documentation tools, but I do believe that having all those alternatives will make it as easy as possible for us to collectively create the best tools for the each of the many approaches to documentation that the Perl community is ultimately going to want to support. And that's what keeping Perl 6 and Pod 6 separate buys you: choice, options, alternatives, the possibility of creating very different styles of documentation for very different styles of programming. And for different kinds of programmer: for the Busy Documentor, tools that extract documentation automatically from code; for the Exacting Documentor, a structural mark-up that allows precise manual control over what's documented...and how; for the Pragmatic Documentor, tools that allow structural mark-up and automatic extraction to be sensibly mixed. And therefore I see the very fact that you don't like my design of Pod 6 as a strong argument in *favour* of that design, since that design aims to provide the necessary syntactic extensibility and the essential building blocks (parser, DOM, module support) required for the proponents of each individual documentation philosophy to create a mark-up system and supporting tools best suited to their specific needs and objectives. Damian