Re: S02 mistake re Blob?
On Feb 21, 2015, at 2:45 AM, Moritz Lenz mor...@faui2k3.org wrote: Hi Darren, On 21.02.2015 08:51, Darren Duncan wrote: I notice from looking at http://design.perl6.org/S02.html that Blob is listed both as being a role and as a type. See http://design.perl6.org/S02.html#Roles for an example of the former, and http://design.perl6.org/S02.html#Immutable_types for an example of the latter. -- Darren Duncan so, you think roles aren't types? (Also, roles auto-pun into classes upon usage). Cheers, Moritz You gotta love a language that “auto-puns” things. :)
Re: Unexpected expansion of string with xx
On Dec 21, 2013, at 12:00 AM, Moritz Lenz mor...@faui2k3.org wrote: On 12/20/2013 04:52 AM, Richard Hainsworth wrote: OK x not xx. The doubling of operators is confusing. OTOH having a single operator which two different meanings is also confusing (and very un-perlish). Sometimes, yeah. On a related note, I sometimes wish that qw«= » and the like were general-purpose comparison operators rather than explicitly numeric comparators. I understand why Perl uses them in the way that it does (mainly, it’s a legacy thing from Perl 5, when there weren’t any data types and the distinction between “number” and “string” had to be built into the operator); but it takes a lot of getting used to, and there are times that I wish that the language would use some argument-based magic to let me sort arbitrary objects using “” instead of “before”. If it wasn’t for the need for backward compatibility, I’d want something like the following: $a $b :as(Num) #[coerce $a and $b to Num. Same as “$a $b” now.] $a $b :as(Str) #[coerce $a and $b to Str. Same as “$a lt $b” now.] $a $b :as(*) #[don’t coerce anything. Same as “$a before $b” now.] $a $b #[coerce $b to whatever type $a is for the comparison. No simple equivalent now.] That strikes me as better “principle of least surprise” than the current approach. Alas, I suspect that the ship has long since sailed on this idea.
Re: [perl6/specs] 9c428a: /.sleep/.alarm/
On Nov 4, 2013, at 12:19 AM, GitHub nore...@github.com wrote: Branch: refs/heads/master Home: https://github.com/perl6/specs Commit: 9c428a98d060811fa086d3168321cfe437be695a https://github.com/perl6/specs/commit/9c428a98d060811fa086d3168321cfe437be695a Author: Elizabeth Mattijsen l...@dijkmat.nl Date: 2013-11-04 (Mon, 04 Nov 2013) Changed paths: M S17-concurrency.pod Log Message: --- /.sleep/.alarm/ I think .sleep is confusing, as its functionality does not match sleep(). And from this, we could spec an alarm() function, which would just create a subscribable with an .alarm and code to be executed when the alarm arrives. This sounds a lot like WHEN (i.e., the hook that exists for the eventual implementation of an event-driven programming paradigm) should be involved somehow.
Re: Commensurability as Key
On Aug 23, 2013, at 2:41 AM, Steve Pitchford steve.pitchf...@gmail.com wrote: How would you implement, in a robust way, the following things: 1 kg + 1 kg = 2 kg 2 m * 3 m = 6 m^2 5 kg * (3 m/s)^2 = 45 J The answer is that you wouldn't - the problem domain is so vague as to be meaningless. 1kg or 1m of what? Understood; but it misses the point I was trying to make. Bringing a measuring system into play needs to be more robust than merely addition and subtraction of common units; it also needs to be able to transform those units into related ones. Let's do a little rocket science: DeltaV = Ve * ln ( m0 / m1 ) Where DeltaV is the total amount your velocity can change, Ve is the velocity of your rocket propellant, m0 is your initial mass, and m1 is your final mass. Simple enough: as long as m0 and m1 are both measured using the same units, they cancel out with each other, letting us take the natural log of a unitless number — which is fortunate, because I don't have a clue how you'd take the logarithm of a number that has units of measure. You then multiply that unitless number by a velocity (measured in units of distance over units of time) to get another velocity (measured in the same units). In this problem, the question of what? is largely irrelevant; the rocket formula will work equally well whether you're shooting a jet of hydrogen out the back of your spacecraft or if you're throwing rocks. Likewise, the number of things that you use as propellant is largely irrelevant. It doesn't hurt to keep track of that information, as long as doing so doesn't interfere with your calculations; but you don't really need it. A related formula is the thrust formula: F = Isp * m' * g0 Where F is the thrust generated, Isp, is the specific impulse of the fuel (a measure of how efficient the fuel is), m' is the mass flow: the rate (measured in mass per unit of time) that the fuel is being expelled, and g0 is the gravitational acceleration at Earth's surface. The reason why g0 is in there is because of a conflation between two very different kinds of units in the early days of rocket science, before metric became the standard in rocketry; namely, pounds (of force) and pounds (of mass). Originally, the formula was simply C F = Isp * m' , with F measured in pounds and m' measured in pounds per second; as such, Isp was assigned units of seconds to make these measurements balance out. When the formula was converted over to metric, it became blatantly obvious that things had been improperly conflated, since force is measured in Newtons and mass flow is measured in kilograms per second. When that's done, it becomes obvious that the Specific Impulse ought to be measured in units of speed (meters per second, in this case) rather than in units of time. But by then, the convention of measuring Specific Impulse in seconds was firmly rooted in the rocket engineering community; so the surface gravity of Earth was brought in as a fudge factor, since that is the ratio of one pound of force to one pound of mass. Going back to apples - The value of 1kg of apples in terms of representation depends on context. For example, it would be a chore to try to arrange a group of apples to make an exact kilogram. On an individual basis you may have 6 apples. In some cases you may represent that as 6 instances. In another context, you may represent a collection of apples in their tray form - which may have a notional weight with a tolerance. Now, if one were writing a checkout system, it may be sufficient for one to have a fruit class, of which apples and oranges are instances, and both are charged in weight - and their may be additional algorithms to predict stocking levels and re-ordering thresholds, but from personal experience, these algorithms often require the backup of business process such as stock takes to ensure that waste, theft, and approximation errors are taken for granted, and we don't end up with a backlog of rotten apples or empty shelves. Some relevant tools: There's a repetition operator infix:xx that's currently set up to take a string and construct a longer one made up of multiple consecutive copies of the original string. e.g., C 5 xx ab eq ababababab . That might be leveraged into a general-purpose assign a count to an object operator: e.g., C 5 xx apple means that you have five apples; C 5 xx kg of apple (would that parse correctly? I'm not sure off the top of my head; but I hope so) means that you have 5 kilograms of apples; and so on. Turning that around, the infix:xx operator could be used to assign a measure (defined by whatever is on the right-hand side) to an otherwise-unitless value (defined by whatever numeric value is on the left-hand side) to get a quantity. You could then do things like multiplying a quantity measured in kg of apple by a quantity measured in dollars / kg of apple to get a quantity
Re: How to make a new operator.
My understanding is if you want to count by threes, starting at 2 and ending at 14, you should be able to write: 2, 5 ... 14 That is, the list-building operator looks at the previous two or three terms preceding it to determine where to start and what step function to use, and then looks at the first term following it to determine where to stop. The use of lambda functions in the immediately preceding and following terms provides a means to explicitly define the step function and the test condition, respectively; but Perl 6 is supposed to be smart enough to intuit linear step functions from two strictly numeric prior terms, geometric step functions from three such terms, and a test condition that stops the series at ' $n' from a numeric right term. So: 1, 3 ... 13 # same as 1,3,5,7,9,11,13 1 ... 10 # same as 1,2,3,4,5,6,7,8,9,10 1, 2, 4 ... 100 # same as 1,2,4,8,16,32,64 and 2, 5 ... 14 # same as 2,5,8,11,14 Meanwhile, using Whatever for the test condition means keep the series going indefinitely: 1, 3 ... * # every positive odd number. 1 ... * # all counting numbers. 1, 2, 4 ... * # all powers of 2. And using '...^' instead of '...' changes the default final test condition from ' $n' to '= $n': 1, 3 ...^ 13 # same as 1,3,5,7,9,11 1 ...^ 10 # same as 1,2,3,4,5,6,7,8,9 1, 2, 4 ...^ 100 # same as 1,2,4,8,16,32,64 In short, what Damian is talking about is the more powerful and reliable use of the syntax; but the above approach (assuming it has been properly implemented) is a more intuitive use that covers the most common cases. Make common things easy, and make uncommon things possible. Likewise, using Whatever in conjunction with operators is there to provide an intuitive way to calculate the next term from the previous one(s): 1, *+2 ... 13 # start at 1, step by 2s, stop at 13. 1, 1, *+* ... * # each new term is the sum of the previous two. 1, 1, infix:+ ... * # same as last one.
Re: How to make a new operator.
What I want to know is whether there's a way to define a step function that's based in part or in whole on the current term's index. For example, how would I use infix:... to generate the perfect squares between 0 and 100? Namely, '0,1,4,9,16,25,36,49,64,81,100'. For example, is Perl 6 set up to try to pass the current element's index into the step function by means of a named parameter? I would hope for something like: - :index { $index * $index } ... 100 or 1, *+:index ... * # 1,3,6,10,15,21,28,36,45,... (Note: I _don't_ expect the above to work as is; they're merely intended to convey a rough idea of what I _do_ want.) If not, how _would_ I generate these lists?
Re: Setting private attributes during object build
Why must we use 'submethod BUILD' instead of 'method BUILD'? Is it some sort of chicken-and-egg dilemma?
Re: Musings on operator overloading (was: File-Fu overloading)
Aristotle Pagaltzis wrote: And this contradiction – that being able to declare sugar is good, but the way that languages have permitted that so far leads to insanity – is what sent me thinking along the lines that there has to be some way to make overloading sane. And we all know that all is fair if you predeclare. And that led me to the flash of inspiration: why not make overloading a property of the source (lexical, early-bound) rather than of the values (temporal, late- bound)? And what we need to do that is a way to say this scope is special in that the operators herein follow rules that differ from the normal semantics. There you have it. So if I'm understanding you correctly, the following would be an example of what you're talking about: { use text; if $a 49 { say $a } } ...with the result being the same as Perl5's 'if $a gt 49 { say $a }' (so if $a equals '5', it says '5'). Am I following you? If so, I'm not seeing what's so exciting about the concept; all it is is a package that redefines a set of operators for whatever scopes use it. If I'm not following you, I'm totally lost. -- Jonathan Dataweaver Lang
Re: [svn:perl6-synopsis] r14510 - doc/trunk/design/syn
+Despite the appearance as a subscripting form, these names are resolved +not at run time but at compile time. The pseudo-subscripts need not +be simple scalars. These are extended with the same two-element list: + +infix:?? !! +infix:['??','!!'] Huh. I thought that multiple elements were only permitted in circumfix and postcircumfix, and that even there you had to use precisely two. Not that I'm complaining; but if this is a change of policy, we should consider the ramifications: An infix operator with multiple delimiters must be list-associative; it must use the delimiters in order; and it must have one fewer delimiter than the number of positional parameters in the signature. Exception: if the signature includes a slurpy array, one more delimiter can be added to separate the slurped arguments. An infix operator with one delimiter is under none of these restrictions. A circumfix or postcircumfix operator can have three or more delimiters. In this case, the first and last delimiters get treated as the bracketing characters, and the bracketed contents get parsed using the remaining delimiter(s) as per the rules for infix operators (trimming off the leading parameter, in the case of postcircumfix operators). The only catch with this is that Conditional Operator Precedence is left-associative, not list associative. List-associativity would probably work as well or better for infix:?? !!; but this precedence level also includes ff and fff. -- Jonathan Dataweaver Lang
Re: [svn:perl6-synopsis] r14501 - doc/trunk/design/syn
+++ doc/trunk/design/syn/S03.podTue Feb 5 09:55:29 2008 @@ -2791,7 +2791,7 @@ are insufficient for defining the pecking order of code. Note that you can bind to either a bare block or a pointy block. Binding to a bare block conveniently leaves the topic in C$_, so the final form -above is equivalent to a Cdefault. (Placeholders parameters may +above is equivalent to a Cdefault. (Placeholder parameters may also be used in the bare block form, though of course their types cannot be specified that way.) Is it forbidden to use placeholder parameters in conjunction with my? Or would it simply not do anything useful? I ask because Do what I mean would seem to imply that 'my Dog $^foo' would specify $^foo's type as 'Dog'. Though if you start doing too much of that, you're almost certainly better off explicitly defining a signature. Also, how much trouble would we get in if we spelled the ubiquitous alias for a method's invocant as C $^_ instead of C $self ? -- Jonathan Dataweaver Lang
Re: [svn:perl6-synopsis] r14501 - doc/trunk/design/syn
Larry Wall wrote: : Is it forbidden to use placeholder parameters in conjunction with : my? Or would it simply not do anything useful? I ask because Do : what I mean would seem to imply that 'my Dog $^foo' would specify : $^foo's type as 'Dog'. Though if you start doing too much of that, : you're almost certainly better off explicitly defining a signature. Indeed. So we're agreed that it could be abused if permitted. Still, is it permitted? : Also, how much trouble would we get in if we spelled the ubiquitous : alias for a method's invocant as C $^_ instead of C $self ? Then we're back to confusing people over the difference between the object and the topic, and the topic-as-self breaks as soon as you topicalize some other way. And you can always throw in a $_ := self or a given self if you really want it. Plus $.foo is still only one character longer than .foo so it doesn't really get you much most of the time. Huh. My intention was not to topicalize the invocant. Rather, I thought that $_ and $^_ would be treated as two separate variables: $_ would be the topic, while $^_ would be the invocant. I'm trying to think of why this distinction might not be. Unless I'm missing something, it would be very much like what we have now, except that '$self' would be spelled '$^_' (shorter and not tied to English, but instead evocative of I'm using a parameter that I may not have declared in the signature, sort of like what placeholder parameters do and I'm using the parameter that defines what this routine is talking about, sort of like what the topic variable does). -- Jonathan Dataweaver Lang
Re: pluralization idea that keeps bugging me
Larry Wall wrote: Any other cute ideas? If you have '\s', you'll also want '\S': $n cat\s fight\S # 1 cat fights; 2 cats fight I'm not fond of the 'ox\soxen' idea; but I could get behind something like '\sox oxen' or 'ox\sen'. '\sa b' would mean 'a is singular; b is plural' '\sa' would be short for '\s a' '\s' would be short for '\s s' \Sa b' would reverse this. Sometimes, you won't want the pluralization variable in the string itself, or you won't know which one to use. You could use an adverb for this: :s$nthe cat\s \sis are fighting. and/or find a way to tag a variable in the string: $owner's \s=$count cat\s '\s=$count' means set plurality based on $count, and display $count normally. -- Jonathan Dataweaver Lang
Re: pluralization idea that keeps bugging me
Gianni Ceccarelli wrote: Please don't put this in the language. The problem is harder than it seems (there are European languages that pluralize differently on $X % 10, IIRC; 0 is singular or plural depending on the language, etc etc). -snip- I know Perl is not minimal, but sometimes I feel that it will end up being maximal... and the more you put in the core, the less flexibility you get in the long term. This _does_ appear to be something more suitable for a Locale:: module. I just wonder if there are enough hooks in the core to allow for an appropriately brief syntax to be introduced in a module: can one roll one's own string interpolations as things stand? E.g., is there a way to add meaning to backslashed characters in a string that would normally lack meaning? Do we have the tools to build $m tool\s? -- Jonathan Dataweaver Lang
Re: pluralization idea that keeps bugging me
Yuval Kogman wrote: You can subclass the grammar and change everything. Theoretically that's a yes =) Right. One last question: is this (i.e., extending a string's grammar) a keep simple things simple thing, or a keep difficult things doable thing? -- Jonathan Dataweaver Lang
Re: Definition of Order in S29
Thom Boyer wrote: The enumerations and the numerical values are both in correct order. Since abc is less than xyz, abc cmp xyz is being invoked with its arguments in increasing order, So it returns Order::Increase. That numifies to -1 because that's how less-than is usually encoded. Others have pointed out Joe's actual intent in asking the question; so I won't belabor the point. Instead, I'll say that the idea that Order::Increase numifies to -1 is going to take some getting used to. While I understand the reasoning behind it, my intuition would have been to numify it to +1 for an increase and -1 for a decrease. If Cabc cmp xyz must numify to -1, could we please choose something like 'Order::Before' and 'Order::After' instead of 'Order::Increase' and 'Order::Decrease'? Not only does this make more intuitive sense, but it also pairs the Order values more closely with the type-neutral comparison operators ('before' and 'after'). (Which brings up another point, which I'll freely admit I'm too lazy to look up at the moment: do we already have a type-neutral operator that corresponds to 'Order::Same'? I suspect that '===' is it; but my grasp of the plethora of equivalence operators is somewhat shaky. If not - and possibly even if so, depending on which paradigm is the most important one to reinforce - I might recommend using 'same' to complete the 'before'/'after' set of operators.) -- Jonathan Dataweaver Lang
Re: Instance and Class disambiguation?
Ovid wrote: If I call this: if $class.^can('wibble') { ... } Does Perl 6 return false if that's only an instance method? Will the WALK iterator returned by .^can return references to instance methods? As I understand it, Perl 6 generally doesn't bother with the class-vs-instance distinction. Instead, it uses an objects and prototypes paradigm, much like the distinction between proper nouns and common nouns. -- Jonathan Dataweaver Lang
Re: S02 interpolation of entire hashes
Dave Whipp wrote: The tests in S02 LS02/Literal/In order to interpolate an entire hash appear to assume that an interpolated hash renders its keys in a sorted order. But this property doesn't seem to be stated in the text. Is it true that the keys are always sorted for interpolation? (is it possible, in P6, for hash keys to not be comparable?) I don't know if it's stated anywhere; but ISTR something about %h.keys returning a Set instead of a List, and %h.vals returning a Bag. In fact, I believe that this sort of thing was part of the motivation behind adding Sets and Bags to the core language: hash keys are not inherently sorted; and if you're using something other than strings as your hash keys, the keys may not be sortable. -- Jonathan Dataweaver Lang
Re: Sequential bias in S04 (and Perl6 in general)
Joe Gottman wrote: On the other hand, this being Perl, I do believe it should be easy to specify the concurrent case. I think that a forall keyword (and a givenall keyword corresponding to given) would be a good idea. These would not be quite parallel to for and given because there would be some subtle differences arising from the concurrent processing. For instance, forall probably should not be used with last, because last should stop subsequent iterations and the subsequent iterations could already have occurred when it is called. Similarly, givenall should not be used with continue, because the next case might already have been checked when continue is called. I don't think that there's need for a 'forall' keyword. Note that Perl 6 has both Lists and Bags, the difference being that a List is ordered while a Bag isn't. So what happens when you feed a Bag into a for statement? Conceptually, you'd expect to get evaluation across its members with no promises concerning the order of evaluation. Likewise, I wonder if there might be a more general way to handle the 'givenall' concept. Say, by marking a block as being concurrent (i.e., parallel) in nature rather than sequential (i.e., series). That is, you normally evaluate a block's statements in order from the first to the last; marking the block as concurrent would tell the parser that the order of evaluation within this block isn't important. If a block of when statements is parallelized in this manner, you get the effect of the proposed 'givenall' keyword without the inherent restrictions that requiring the keyword would impose. -- Jonathan Dataweaver Lang
Re: Sequential bias in S04 (and Perl6 in general)
Dave Whipp wrote: No, you're not the only person thinking Occam ... though I should point out that none of my suggestions are par blocks -- a par block made every statement within the block execute in parallel with the other statements in that block (much like a Verilog fork/join pair). No; that was me. Although, as Luke pointed out, I wasn't thinking parallel execution so much as arbitrarily ordered execution (which, as Dave points out, is a prerequisite for true parallel execution). Paul Seamons wrote: I disagree with the idea that humans don't think concurrently (though more often they think in terms of data dependencies). I think this is more analogous to event based programming rather than parallel programming. Event based and parallel based have some similarities but the are fundamentally different. Humans typically interact with events and only occasionally are able to walk and chew gum at the same time. As a human (as opposed to that weird creature known as a professional programmer), I tend to do one thing at a time, though I'm more than capable of prioritizing a set of tasks that are handed to me, even if new tasks are added to my workload while I'm still working on others. And if I'm working as part of a team, I know how to delegate tasks to others. As Dave points out, it isn't parallelism that's hard so much as it is coordination with the rest of the team in order to prevent conflicts involving shared resources. -- Jonathan Dataweaver Lang
Re: Sequential bias in S04 (and Perl6 in general)
Larry Wall wrote: I (impersonally) believe that hyper context is the right solution to this because context can propagate to where it needs to dynamically. As for the fact that it's not the default list context for for, that could easily be changed with a pragma. Maybe that could even be the default someday, but we have to educate people to think about hyper first. As I just indicated, I'm a mere mortal; so some of the terminology you're using here is throwing me. When I hear hyper context, my gut instinct is to think he's advocating some sort of application of the hyperoperator. Is that what you mean, or would the substitution of a bag for a list in a for statement qualify as hyper context? Or maybe you mean something like the use of a junction in a given statement as the parallelized equivalent of a for statement? for @x { ... } # executes the block for each element of @x in series given all(@x) { ... } # executes the block for each element of @x in parallel As for the other part of the proposal, a parallel smartmatch would need new comb syntax for the compound pattern--I wouldn't overload given/when for that. Or maybe just make a way to attach a mapreduce action to any leg of a junction or hyperoperator. Again, I'm not up on the terminology being used here. But if I'm getting the gist of it right, the following is in the spirit of what you're suggesting: Introduce a function that does given/when-type smart-matching, but geared around pattern/code Pairs: e.g., match $x: 1..3 = { dothis() }, 4..6 = { dothat() } # equivalent to: given $x { when 1..3 { dothis() } when 4..6 { dothat() } } Then you could use a junction of Pairs in place of a single Pair to smart-match the patterns in parallel: match $x: 1..3 = { dothis() } 2..4 = { dothat() } # smart-matches 1..3 and 2..4 in parallel In any case, we need to make sure it's easy to place such a parallel comb of matchers at the pointy end of a feed, and if the source of the feed is also executing in parallel, make sure the feed can be optimized to a full crossbar based on packet destination. In the above example, you might say: @x».match 1..3 = { dothis() } 2..4 = { dothat() } or match any(@x): 1..3 = { dothis() } 2..4 = { dothat() } in order to get a full crossbar. It's also possible that we should discourage syntactic parallel matching in favor of parallel polymorphic dispatch, given that signatures can also express patterns. Might need to tweak the current multiple dispatch rules a bit though if we want dispatch ambiguity to express nondeterminism. In any case, real mapreduce situations are often generated dynamically, and cannot easily be expressed in a syntactically fixed set of options. No idea what you're talking about here. -- Jonathan Dataweaver Lang
Re: Multiline comments in Perl6
Paul Hodges wrote: http://perl6.org/doc/design/syn/S02.html still says: Intra-line comments will not be supported in standard Perl This is wrong, since S02 also defines intra-line comments, under Whitespace and Comments. It calls them 'embedded comments'. You don't need a 'use' statement. Is there any restriction of the whitespace *inside* the comment? Not from my reading of it, no. And is / a valid bracketer? No. The valid bracketers are defined under Lexical Conventions - in layman's terms, bracketing characters are matching pairs of characters: so '(' and ')' are bracketing characters, but '/' is not. Likewise, the matches are based on individual characters, so if you use -- at the start of a bracketed segment, only the counts as a bracketing character. or should I stick to things like $x = #-- comment -- 1; $x = #{ comment #} 1; $x = #( comment +) 1; $x = #[ comment =o] 1; Or will any of these not work? All four of those work as written. In addition, S06 demonstrates how you can use macros to create custom embedded comments: macro circumfix:«!-- --» ($text) is parsed / .*? / { } !-- this is now a comment -- -- Jonathan Dataweaver Lang
Re: Multiline comments in Perl6
I've been putting a fair amount of thought into this. Here's what I've come up with: Perl 6 has several instances where whitespace is required or forbidden in order to better facilitate Do What I Mean programming: for instance, by having the presence or absence of whitespace before curly braces affect their meaning, you're allowed to omit the parentheses around the parameters of the various control structures: e.g., 'if $x { ... }' is now valid, whereas in Perl 5 you would have had to say 'if ($x) { ... }'. Likewise, the same technique lets you provide an unambiguous distinction between an infix operator and a postfix operator (IIRC). So it isn't much of a stretch to require the use of whitespace in order to distinguish between a standard line comment and an embedded comment. Except that that isn't what Perl 6 is doing. All that it does is to say there's this one case where there's some ambiguity between line comments and embedded comments; it's up to the programmer to remove the ambiguity, through whatever means he sees fit. In many ways, this is the opposite of the above cases, and is more akin to how role composition must be explicitly disambiguated by the programmer, instead of having the compiler take a best guess. I must admit: as nice as it is to be able to create an embedded comment by wrapping the actual comment in brackets, the existence of that one point of ambiguity is troubling. -- What I like about the current embedded comments: 1. They're short. You need a single leading character (the '#'), followed by content wrapped in as little as a pair of bracketing characters. That's three characters in addition to the content itself. 2. They're flexible. By going with user-specified bracketing characters, the programmer can choose an intuitive closing sequence that won't conflict with content that he's commenting out. Of the two features, the second one is the more important one. Likewise, the central most important feature concerning line comments is that you can initiate them using a single character, allowing you to reliably comment out a set of lines through a straightforward - and short - sequence of keystrokes. The problem arises from the fact that embedded comments start with the same character that line comments start with. This means that the second character is the one that gets used to distinguish between line comments and embedded comments, which at best interferes with the main benefit of line comments described above, and at worst leads to an extra round of debugging as the programmer is forced to go through and add whitespace (or other characters) to disambiguate the two. -- The solution, then, would be to change embedded comments so that they're initiated by something that doesn't begin with a '#'. Ideally, you'd still use a single character (plus the brackets) to define an embedded comment. Unfortunately, I'm pretty sure that we've got a severe shortage of such characters available for use. Assume, then, that a two-character initializer is going to be needed, and that the first character cannot be a '#'. -- I'm leery about making the first character be a '=', as there's the potential for conflict with POD sections. IIRC, there's a (currently unspoken?) design goal involving POD sections that says that any line beginning with a '=' ought to be able to be stripped out of the program without affecting the code. Those with more familiarity with POD design philosophy can please speak up? OTOH, it might be possible that '=#[ ... ]' could be used to add versatility to the POD syntax. Consider the possibility of saying that '=#[blah blah blah]' at the start of a line is equivalent to '=blah blah blah', except that the POD header ends at the ']' instead of the first '\n'. This could be used to wrap a POD header over several lines, and/or to put the first line of POD content on the same line as a short POD header. So: =#[for comment params] text foo; would be equivalent to: =for comment params text foo; ...or not; this could lead to the same sort of trouble that we currently have with line comments vs. embedded comments. If we were to go this route, I'd be inclined to say that '=#[ ... ]' isn't just an embedded comment; it's an embedded POD header. This removes all ambiguity regarding what it is, at the expense of forcing the POD Parser to look at more than just the first character of each line to determine whether or not it's meaningful. The expense may be too great. At the very least, it opens up a whole new can of worms. -- OK; so let's assume a two-character sequence prior to the opening bracket of an embedded comment, with the first character being something other than '#' or '='. It's perfectly acceptable (and, IMHO, desirable) for the second character to be a '#'. How about '~#', meaning something along the lines of string-like comment? The idea is that the syntax that follows this would conform closely to that of string
Re: Multiline comments in Perl6
Jonathan Lang wrote: How about '~#', meaning something along the lines of string-like comment? The idea is that the syntax that follows this would conform closely to that of string literals (i.e., quotes). We might even consider loosening the restrictions on delimiter characters, allowing the full versatility of quoting delimiters, since there'd no longer be any danger of confusing this with a line comment. So: For the record: if this gets implemented as I'm describing above, I will personally restrict myself to using bracketing characters as the delimiters. Non-bracketing delimiters have issues that, as a programmer, I don't want to have to deal with: e.g., if I were to use '~#/ ... /' to comment out a block of code, I'd have to be very sure that said code doesn't do any division. This is still a problem with brackets, but less so - especially with the ability to double up (or more) on the brackets. E.g., '~#[[ ... ]]' pretty much guarantees that I'll comment out exactly what I want to comment out on the first try. Oh, and I just realized: '~#( ... )' looks a bit like an ascii-graphics thought bubble, as used in old text-based MUXs. If '~#' gets nixed, perhaps 'oO' would be a viable alternative? $x = oO(here's a comment) 5; -- Jonathan Dataweaver Lang
Re: Multiline comments in Perl6
Amir E. Aharoni wrote: On 30/12/2007, Jonathan Lang [EMAIL PROTECTED] wrote: The only wart is that '#( ... )' cannot begin at the very start of a line; but it's easy enough to get around that restriction - say, with some leading whitespace. Thanks for the reply - can you please what is the problem with having it in the beginning of the line? Short answer: the compiler has no way of knowing whether the programmer wants an embedded comment or a line comment; so instead of guessing, it requires the programmer to disambiguate. Long answer: a standard method of commenting out code is to manually prefix each line with a '#'. If embedded comments were allowed at the beginning of a line, then people using this technique would occasionally get some nasty surprises. For example: if ($test) { .say; } else { .doit; } Let's say that the programmer in question wants to comment out all but the third line; so he prefixes everything else with '#': #if ($test) #{ .say; #} else { # .doit; #} What the writer _wants_ this to do is the equivalent of: .say; What he'd get with embedded comments would be the equivalent of: else { -- Initially, the rule was that any line beginning with a '#' would be considered a line comment, regardless of what the second character is. The result was that the above code worked as expected. However, it lead to the possibility of someone putting a '#{' at the start of a line, expecting an embedded comment, and getting a line comment instead: #{ start here } if ($test) { .say; } else { .doit; } There's no way for the compiler to reliably guess which semantics the programmer intended, so it complains. The easiest way to keep it from complaining is to add some whitespace: # if ($test) # { .say; # } else { # .doit; # } or #{ start here } if ($test) { .say; } else { .doit; } -- Jonathan Dataweaver Lang
Re: Multiline comments in Perl6
Offer Kaye wrote: #( commenting out a large code section, yey for Perl6 multi-line comments... if ($foo) { print ...or not :(\n } ) # this should have been the end of the embedded comment ...and since it wasn't, you probably should have chosen other brackets such as: #[[ commenting out a large code section, yey for Perl6 multi-line comments... if ($foo) { print ...or not :(\n } ]] or just used POD sections: =begin comment if ($foo) { print ...or not :(\n } =end comment Comments are a some of the most commonly used constructs in code. Every code has them, even the simplest script. If you have to get around a limitation whenever using them (your words - but it's easy enough to get around that restriction) you're doing something wrong with their design. My words; not the designer's. Where is the sense in making the closing of the embedded comment a single bracket only? It seems so natural to me that I find myself wondering how it can be thought of as nonsense. I think the Perl 5 method of having just # for single-line and =pod for multi-line was better. IMHO, the _only_ problem with the current commenting system is that there's potential ambiguity when you start a line with '#('. Many of us find that the benefits of having embedded comments outweigh this one flaw. Yes simple Perl users I know didn't use =pod but it was there if they needed it. It still is. Embedded comments do not replace POD sections any more than they replace traditional line comments. -- Jonathan Dataweaver Lang
Factoring Arguments
I'm thinking aloud here, so please bear with me. A number of languages have a with ... construct that's intended to cut down on repetitive typing, by factoring the invocant out of every method call. Perl 6 also has this, in the form of given ...: given $foo.bar.baz { .dothis(); .dothat(); .doanother(); } (same as) $foo.bar.baz.dothis(); $foo.bar.baz.dothat(); $foo.bar.baz.doanother(); I'm wondering if something similar could be done for optional arguments - something along the lines of within the following block, assign value V to argument X of routine R by default. This would allow for a similar factoring out of repetitive flags. So instead of: say qq:!c ... { ... } ...; say qq:!c ... { ... } ...; say qq:!c ... { ... } ...; and so on, you might do something like: with qq :(c = false) { say ... { ... } ...; say ... { ... } ...; say ... { ... } ...; } Or maybe it could be a pragma (which, by definition, lasts only until the end of the current scope): { use defaults { qq = :!c } say ... { ... } ...; say ... { ... } ...; say ... { ... } ...; } The core concept here is to allow the programmer to easily change the default behavior of a routine within a given scope so that he doesn't have to repeatedly override the default behavior every time it comes up. -- Is this reasonable, or is this too much of a corner case to be worth the effort? -- Jonathan Dataweaver Lang
Re: Concerns about {...code...}
Dave Whipp wrote: If the construct is used only rarely then it should have a longer name, Actually, Huffman coding implies that if the construct is used regularly then it should have a short name. It does not mandate a long name for rare constructs; it merely says that if a given short name is suitable for both a common construct and a rare construct, the common construct should get it. If there's no such conflict, there's no reason not to give the short name to a rarely used construct. -- Jonathan Dataweaver Lang
Re: Factoring Arguments
Ryan Richter wrote: Jonathan Lang wrote: and so on, you might do something like: with qq :(c = false) { I think this can be done with normal currying, something like temp circumfix: := quote:qq.assuming(:!c); That handles the specific example that I had in mind, but does so in a rather brittle way. First, the programmer is forced to use double-quotes to make use of the currying; he cannot switch to another quoting character if one of the strings that he's dealing with has a number of double-quote characters in it. This being a quoting-specific issue, it should be no surprise that it comes with a quoting-specific solution, e.g., use 'qs' instead of 'qq:!c') - but that still leaves you with having to prefix every string in the target scope: cqs ... instead of c ... . Still, that isn't my main concern here. There's no way that I know of to override the currying: every .assuming that you use removes one parameter from the signature (if I understand currying correctly). This means that you don't get to set assumed values for three different parameters at the start of the block and then override just one of them for a single use of the function in the middle of the block. This concern could probably be addressed if currying doesn't remove arguments from a signature, but instead forces them to be optional and assigns default values to them; but this can lead to its own problems, such as what happens when you curry the second of three required positional parameters. What I was thinking of would be somewhat more modest: it would be a variation on the currying mechanic, but would only apply to optional parameters. It wouldn't remove them from the signature at all; it would merely change the default values assigned to them. -- Jonathan Dataweaver Lang
Re: perl 6 grammar
Another thing to note about given ... when: you don't have to use them together. All that given does is to set $_ to the variable provided; this can be used in a manner similar to with statements in other languages. And when doesn't have to be inside a given block, either: it can be used in any block that sets $_. For example: for @list { when *..^0 { say $_ is negative } when 0 {say $_ is zero } when 0^..* { say $_ is positive } default { say $_ is something else } } or (I think): method test ($value) { setup(); when $value { doit() } #[smart-match the calling object $_ against $value.] } (Question: assuming that the above is valid, would breaking out of the when block be the same as returning from the method? Or would it qualify as an abnormal termination of the method?) -- Jonathan Dataweaver Lang
Re: , , and backtracking.
Jonathan Scott Duff wrote: How do C and C differ with respect to backtracking? For instance, foobar ~~ / [a..z]+ [ ... ] /; Both sides of the C happen in parallel, so I would guess that they both match foo then stop. Please correct me if that's wrong. As written, this match would fail, since '[a..z]+' would match foobar while '[ ... ]' would match foo. '' requires that both sides match the same start and end points. I suppose that it might be worth considering requiring only the start points to match, and having the conjoined match use the earliest end point; so that the above match would then match foo instead of failing. But it's entirely possible that there's something faulty with this approach. The difference between '' and '' is that '' evaluates the two sides in an arbitrary order, possibly even in parallel; '' always evaluates the left side first, and only bothers with the right side if the left side matched. -- Jonathan Dataweaver Lang
Re: [svn:perl6-synopsis] r14447 - doc/trunk/design/syn
So 'orelse' is exactly like '//', except that the result of the left side gets passed to the right side as an error message. Is there a reason to make this exception, as opposed to altering '//' to behave exactly like 'orelse' does? -- Jonathan Dataweaver Lang
Re: [svn:perl6-synopsis] r14447 - doc/trunk/design/syn
Larry Wall wrote: Jonathan Lang wrote: : So 'orelse' is exactly like '//', except that the result of the left : side gets passed to the right side as an error message. Is there a : reason to make this exception, as opposed to altering '//' to behave : exactly like 'orelse' does? How 'bout, it's convenient to have the simpler defaulting semantics when you don't care what kind of undefined value is on the left. If you don't care what kind of undefined value is on the left, you probably won't notice if it's passed to the right; and the optimizer may very well end up implementing the simpler semantics in this case, even if you use 'orelse'. And if you explicitly want to use the simpler semantics, you can come very close by blocking the right side in a block that takes no arguments. Conversely: if you do care about the undefined value, the subtle distinction between '//' and 'orelse' (beyond the implied difference in precedence) will be yet another language quirk that you'll have to remember. Very inconvenient. -- Jonathan Dataweaver Lang
Re: A problem about IPC::Open2
Admittedly, that wasn't particularly germane to the perl6 mailing list; but it did bring up an issue that's been bothering me for a while. I would like to see Perl6 handle the equivalent of IPC::Open2 using the same sort of syntax and semantics that it uses for sockets, by default. That is, I'd like to be able to say something like: $fh = filename.open :rw; # same as open2 filename, $in, $out; $line = =$fh; # same as $line = =$in; $fh.say rewrite!; # same as $out.say rewrite!; -- Jonathan Dataweaver Lang
Re: Referring to source code within Perldoc
David Green wrote: (Unless I'm missing something, which is always possible; you can put a piece of POD geographically next to a Perl declaration, but I'm not sure that's unambiguous enough. Hm, why not? POD doesn't know what's going on around it, but Perl does, and could say, I've just declared $size, and the next line starts a chunk of POD, so I'll simply copy it into $size's 'documented' trait... would that work??) It is doable: say that any Pod section that appears within or after a class definition is considered by perldoc to refer to that class. The problem with this is that you're forcing the Pod author to organize his documentation in a manner that precisely mirrors the organization used by the Perl programmer, and to scatter it throughout the module. This isn't necessarily a deal-breaker because the Pod author is usually(?) going to _be_ the Perl programmer (thus letting him reorganize the classes to match the preferred documentation sequence or vice versa), and because the Pod author may _prefer_ to place the documentation in close proximity to the source code being documented. But it would be nice to have more freedom of placement of documentation for those with other preferences. There's the new 'A' tag, which specifically refers to a word or phrase in the source code. But that's a single inline tag; so it's questionable as to how useful it would be for the purpose of associating an entire Pod section to a piece of source code. In addition, the 'A' tag, as written, makes explicit use of exactly the geographic positioning that we're trying to get around. -- Then there's the suggestion that I made about providing a Pod rule (or Pod rules) for the purpose of identifying points in or sections of the source code for more robust referencing. In my proposal, I suggested being able to say something like '=code Foo' to identify the start of a section of source code that abstractly relates to the label 'Foo', coupled with the ability to tell a Pod section elsewhere that it is associated with the source code identified by 'Foo' (using something like '=begin pod :AFoo' to do so). At the time, I was thinking in terms of allowing more freedom of placement of 'A' tags; but it also works for giving entire pod sections freedom of placement while still maintaining ties to specific source code: for example, perldoc could look for the '=code' rule that precedes or encompasses a given class definition and then associate any Pod sections that attach themselves to that rule with that class. So while the '=code' rule would have to maintain a close geographic relationship to the source code in question, the documentation itself would not. Ideally, this wouldn't replace the proximity-based bindings, but would supplement it, with the idea that Pod sections with :A... traits would be bound to whatever follows the associated '=code' rule, while those without :A... traits would be bound to whatever they follow. Best of all, none of these bindings would be Pod's responsibility. As far as Pod is concerned, the only use that '=code' rules would have would be in service to 'A' tags, and could maintain ignorance about what the source code speaks of. Perldoc would have the final responsibility of binding documentation to definitions. -- The other way to go about it would be to have the source code refer to Pod sections: class Foo is documented(Bar) { has $.x is documented(Baz); } ... =begin Bar ... =begin Baz ... This places the responsibility of bindings on the language (in this case, Perl) - each of which would have to come up with its own syntax for referencing documentation. This is fine as far as Perldoc is concerned, but does raise issues if you decide that you want to do something similar with, say, C++ or HTML. -- Jonathan Dataweaver Lang
Re: [svn:perl6-synopsis] r14421 - doc/trunk/design/syn
Mark Overmeer wrote: * Damian Conway ([EMAIL PROTECTED]) [070622 09:02]: Mark Overmeer wrote: Then, when you want to add some docs to the method, to help the correct use, add it, for instance like: method isValidPostalCode(str $postalcode) returns bool {...} ` Check wether the postal code confirms to the standards `$postalcode: a string with blanks trimmed. `return: the string is not cleaned-up. or maybe (exact syntax open to discussion) method isValidPostalCode(str $postalcode) returns bool {...} #= Check wether the postal code confirms to the standards #=$postalcode #= a string with blanks trimmed. #=return #= the string is not cleaned-up. 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. For the record, I find Damian's example to be considerably more readable. The needs for my kind of documentation generators are very simple: the Perl6 parser needs to collect all lines of docs which follow a certain line with code into the AST node of that line or item. The Perl6 parser itself doesn't need to do anything more than that. Tools doing introspection on the AST do the rest. Please forgive my ignorance: what does AST stand for? -- Jonathan Dataweaver Lang
Re: Referring to source code within Perldoc: the new A code
OK. After much thinking on the subject, here are my recommendations: First: give Pod the ability to delimit blocks of ambient text, e.g.: =text class Foo { has $bar; } =stop '=text' and '=stop' would be considered to be separate but related single-line Pod Sections, so Pod-stripping utilities would remove them while leaving the lines between them intact. (I'm not sold on the specific names for these tags; just the principles behind them.) By default, 'A' searches backward from its current position within the scope of the current ambient text block. This helps you catch gotchas such as removing a piece of code and failing to remove the documentation that was referencing it. Consider, for example, documenting the first attribute of a class that follows another class. The coder removes the attribute, but fails to remove the documentation that references it. Suddenly, that documentation is referencing the last attribute of the previous class. If each class were encapsulated in a separate ambient text section, Pod would then know to complain that there is no attribute to reference anymore. -- Allow ambient text blocks to be named, and allow 'A' to choose a named ambient text block to search. When you do this, the position of the A tag relative to the ambient text block becomes irrelevant. Example: =begin pod AFoo.has =end pod =text Foo class Foo { has $bar; } =stop Foo You might also consider changing the rules when searching ambient text blocks in this way, so that it searches for the first instance of the prefix in the block instead of searching for the last one. -- Let a pod section specify a default ambient code block, causing all ambient references within its scope to automatically reference that block: =begin pod :AFoo Ahas =end pod =text Foo class Foo { has $bar; } =stop Foo -- Allow ambient text blocks to be nested: =begin pod :AFoo =ATTRIBUTE Ahas =METHOD Amethod :Abaz =NAME Aname =RETURNS Areturn =end pod =text Foo class Foo { has $bar; =text baz method baz () returns Number { ... } =stop baz } =stop Foo -- Allow an optional array index for the prefix so that you can skip over a given number of matches, rather than being limited to the first one you find: =begin pod :AFoo Ahas[0] Ahas[1] =end pod =text Foo class Foo { has $bar; has $baz; } =stop Foo -- Finally, there are cases where prefix handles won't be readily available. Consider what happens when you try to document a C++ function: extern void swap(int*, int*); =NAME Avoid =RETURN Aextern How do you reference the 'extern' in that function definition? Now let's say that the C++ programmer decides that he wants this function to return a success flag: extern int swap(int*, int*); =NAME Aint =RETURN Aextern Note that he had to change 'void' to 'int' in two places: once in the code, and once in the documentation. This, combined with the distinctly unintuitive prefixes being used in the ambient references, can lead to a real mess. In cases such as these, it might be best to have Pod punt to an 'assistant parser' that returns the equivalent of a list of '=alias' tags. I see this as being a case of All's fair if you predeclare, and I was inspired by XML's Processor Instructions (conceptually) and namespaces (syntactically). Using this, the above might be handled as: =parser C++ uri ... =text swap :parsedC++ extern void swap(int*, int*); =stop text =for pod :Aswap =NAME Aname =RETURN Areturn The '=parser' line tells Pod that some later ambient text sections will be parsed using a C++ helper utility. It's assumed that Pod will search for said helper utility, and will complain if it can't find it. I'm assuming that the helper utility would return the equivalent of: =alias name swap =alias return void when given the ambient text section in question. I'm also figuring that these parser-generated aliases would take precedence over prefix-based referencing, but that explicit '=alias' tags would take precedence over them. -- One ramification of Larry's earlier suggestion that Perl not handle Pod sections exactly the same way that Pod does is that it's possible for certain sections of Perl code to not register as ambient text in a Pod Parser: say qq:to(END) =begin pod oops =end pod END =for pod A=begin To a Perl Parser, the code is as follows: say qq:to(END) =begin pod oops =end pod END To the Pod Parser, the ambient text is this: say qq:to(END) END This wasn't a big deal when Pod was completely ignoring the ambient text. But once it starts referencing ambient text, you're best off keeping Perl code and Pod ambient text in sync with each other. -- Jonathan Dataweaver Lang
Quirky comments
In [svn:perl6-synopsis] r14421 - doc/trunk/design/syn, Damian Conway wrote: brian wrote: So, if this is the case, how will a new Perl 6 user debug a program failure when part of their program mysteriously disappears because they just happened to have =begin at the beginning of a line? The same way they debug it when part of their program mysteriously disappears because they just happened to have # at the beginning of a line: by learning to distinguish between code and commentary. Except, of course, the Pod mysteriously vanishing will be considerably easier to debug, because ALL lines starting with =begin vanish, whereas only some lines beginning with # do. By this reasoning, a case could be made for declaring that all lines that begin with '#' are comments (either block or line, depending on the second character), no matter what. That way, you'll have more consistency between block comments and Pod Sections (which, from Perl's perspective, should be equivalent). The price to be paid (in both cases) is that you have to finagle any code that would normally start a line with a '#' or '=' respectively, such as the aforementioned block quote. Admittedly, this isn't hard to do: starting the line with whitespace or an unspace will do the trick. (But ending the previous line with an unspace won't, as comments are apparently found and turned into whitespace by the lexer.) There is an additional price to be paid in the case of '#': you'd have to distinguish between end-of-line comments (which cease to be comments if placed in quotes) and line comments (which are always comments, no matter what). In effect, you would have four kinds of comments, not counting Pod sections: bracketed? starts line? yes: no: no: line end-of-line yes:block embedded The semantic similarities would be as follows: * line-oriented comments (line and block) don't care about quotes; character-oriented comments (end-of-line and embedded) do. * block and embedded comments continue until explicitly terminated; line and end-of-line comments are terminated by newline. -- Another quirk concerning comments: if I'm reading S02 correctly, C\# is an unspaced comment whenever it would normally be a comment, and is only an escaped pound sign when it would normally be a quoted pound sign. This is one (possibly the only) case where backslashing a special character does _not_ shut off its special behavior. As a result, you have to quote a pound sign if you want to use it in a pattern. If this behavior is kept (I don't care either way), it should probably be noted in Learning Perl 6 or the like, as a gotcha. -- I also can't seem to find any means of starting a comment from within a quote, aside from Pod Sections (and, if my first suggestion is adopted, line and block comments). Perhaps C\# should count as the start of a comment when appearing in a quote? This has the advantage that almost every appearance of that pair of characters will act to comment out what follows; the only exception would be when it appears as part of the C\\# sequence, which is easily tested for. It does, however, mean that you can't start a line that's within a quote with C\# in order to start that line with a literal pound sign. C\ # would work, though, as would indenting the quote in the case of a heredoc. -- Also from S02: Although we say that the unspace hides the whitespace from the parser, it does not hide whitespace from the lexer. As a result, unspace is not allowed within a token. Technically true; but what does this mean? If I were to say foo\ bar would the lexer generate a pair of tokens ('foo' and 'bar') that don't have any intervening whitespace (which might be important in some cases that involve whitespace-based disambiguation), or would it complain about finding an unspace where it doesn't belong? I hope that the former is true; although Larry seems to have been very conscientious about making sure that whitespace is never forbidden between tokens unless a dot can be placed there instead. Still, letting unspace split tokens provides a more general solution. -- Finally, from S02: Since there is a newline before the first =, the POD form of comment counts as whitespace equivalent to a newline. This rationale doesn't hold, for two reasons. First, there is not going to be a newline before the first = in a Pod Section if said Pod Section starts the file. Second, the stated behavior doesn't follow from the premise. Given the logic that Pod Sections are effectively stripped out of the file before anything else happens, one would expect: say qq:to'END'; =begin comment END =end comment END to be equivalent to: say qq:to'END'; END instead of: say qq:to'END'; END However, the latter is what occurs under the current rule. I submit that Pod Sections shouldn't be equivalent to whitespace; they should be equivalent to empty strings. Likewise with line and block comments: all
Re: [svn:perl6-synopsis] r14421 - doc/trunk/design/syn
brian d foy wrote: Whereas the rule you have to teach under the Integration model is: We don't teach any rule under this model, and it's been fine for over a decade :) When we do teach the current Pod, the simple rule is that Pod starts: * when Perl is expecting a new statement * there is a =something at the beginning of the line Which is considerably simpler than the long rule list you used to say the same thing (which seems a bit of FUD, honestly). Agreed about the parenthetical. From my perspective, the proponents of the Separation Model are overstating the difficulties inherent to the Integration model. That said: By the rule you give above, Pod Sections cannot be embedded in the middle of statements. For example, given: if a = 5 { say ouch! } you couldn't insert a Pod Section between the first and second lines, or between the second and third lines. From a guy-in-the-trenches perspective, this isn't a problem; interrupting an instruction mid-stream in order to talk about it is very bad form. Still, it's a restriction that Damian's Separation model lacks. So, if this is the case, how will a new Perl 6 user debug a program failure when part of their program mysteriously disappears because they just happened to have =begin at the beginning of a line? The same way they debug it when part of their program mysteriously disappears because they just happened to have # at the beginning of a line: Except, of course, the Pod mysteriously vanishing will be considerably easier to debug, because ALL lines starting with =begin vanish, whereas only some lines beginning with # do. That's not really the case. The # only affects one line, and a pound in a literal string doesn't start a comment. People grok single line comments very well. With the advent of block comments, this isn't as true as it used to be. In fact, I expect that some people will have to take a moment to wrap their heads around the notion that you ignore everything that follows the closing bracket on the last line of the block quote. That said, I don't expect there to be much of a learning curve here. Still, it may be worth it to state that a line that starts with '#' followed by a closing bracket is _not_ commented out (although said character sequence should be stripped out of the line). Less cognitive dissonance that way. The start of a Pod comment now affects its line and the ones following it. ...also not much in the way of a learning curve; in fact, I expect that people will grok Pod Sections more readily than they will grok block comments as currently written. Well, easy to use Pod with other languages until they try to use the assignment operator at the beginning of the line, or a = in a literal string at the beginning of a line. ...or you're dealing with a language that assigns special meaning to lines that begin with '='. You are not going to be able to make Pod completely orthogonal to the code that it's embedded in. You can come close (and IMHO you come _very_ close with the Separation model that you're discussing), but there will always be some sort of constraint placed on the code into which you're embedding Pod. There are other things to consider, and to me it looks like this design decision isn't based on what's easier for the Perl 6 programmer but what's easier for the implementors. It's not that I don't understand both sides, I just disagree about where the complexity should be. Thank you, Brian. That's exactly the sense that I've been getting from the explanations being given. Which is not to say that there isn't a time and place when ease of implementation should trump ease of programming; taking an extreme example, being able to write a program that consists of the single line: attend my every wish is the ultimate in terms of ease of programming; it's also impossible to implement, barring the invention of mind-reading hardware and sapient artificial intelligence software. If a small increase in the programmer's learning curve is the price that must be paid to achieve a massive reduction in the implementor's workload, it may very well be worthwhile to foist some of the complexity onto the programmer. The question is whether or not this is one of those cases. -- Jonathan Dataweaver Lang
Re: [svn:perl6-synopsis] r14421 - doc/trunk/design/syn
Jonathan Lang wrote: Which is not to say that there isn't a time and place when ease of implementation should trump ease of programming; taking an extreme example, being able to write a program that consists of the single line: attend my every wish is the ultimate in terms of ease of programming; it's also impossible to implement, barring the invention of mind-reading hardware and sapient artificial intelligence software. If a small increase in the programmer's learning curve is the price that must be paid to achieve a massive reduction in the implementor's workload, it may very well be worthwhile to foist some of the complexity onto the programmer. The question is whether or not this is one of those cases. Addendum: let me note that Perl has a reputation for bending over backward to accommodate the programmer; as such, the difference in implementation workloads for the two models that Damian referenced is going to have to be _very_ severe for ease of implementation to win out over ease of programming - IMHO. Unfortunately for me, MHO doesn't count as much as DHO. Help, help! I'm being oppressed! -- Jonathan Dataweaver Lang
Re: Quirky comments
Larry Wall wrote: I have a problem with both extremes, and I want to solve it with a dose of postmodern apathy. It may seem a bit insane, but I think that in print qq:to/END/ =for whatever END I would prefer that the =for is considered Pod by any standard Pod parser, but is *not* considered Pod by the Perl 6 parser. And I think that's just fine. If the programmer really wants to put Pod in a string, they can just be responsible for stripping it out themselves. And a standard Pod parser shouldn't be expected to parse full-up Perl. Summary: Perl treats quoted Pod as quoted text, and all other Pod as comments; Pod treats all Pod as Pod. Effects: 1. You trade the brutally surprising behavior of whole lines of string literal content vanishing for the much more subtle surprising behavior of whole lines of string literal content being available via $=pod variables (some might consider the latter to be a feature). 2. Pod Sections behave just like block comments (aside from the pod variables thing), which is very nice. 3. There will be a few rare cases where the Perl programmer will need to cheat to keep something that looks like Pod from registering as Pod; this will be easy enough to do when it's needed. Opinion: That's a significant trade up, and addresses my biggest concerns. -- The only other thing that I'll continue to lobby for is that the line starting with a block comment's termination tag should _not_ be considered part of the comment, save for the termination tag itself. Programmers are likely to be surprised when text that follows a closing bracket is treated as being included within it. -- Jonathan Dataweaver Lang
Re: [svn:perl6-synopsis] r14421 - doc/trunk/design/syn
I'm going to stay away from the POD referencing Perl debate for the time being. Instead, a couple of thoughts: 1. It has always been my understanding that comments intimately relate to documentation, despite being part of Perl's syntax. As such, they are a technical violation of this separation of Church and State, being State-sponsored religion as it were. (Who'd have thought that we'd be talking politics and religion on a programming language mailing list? Egad!) Not that I'm advocating the removal of comments; their sheer practical value makes up for their heathen ways. 2. Getting block comments to hide POD blocks wouldn't require the POD parser to have a full implementation of a Perl parser. It would require the POD parser to have a _limited_ implementation of a Perl parser, one that's capable of identifying block comments. And IIRC, you already have to do something like this with respect to block quotes: say :to(END); =begin POD blah blah blah =end POD END If I understand matters correctly, the POD code in the above example isn't POD code at all, but rather the content of a multi-line quote. So extending the POD parser's awareness of Perl syntax to handle block comments as well isn't much of a stretch. -- Jonathan Dataweaver Lang
Re: [svn:perl6-synopsis] r14421 - doc/trunk/design/syn
Larry Wall wrote: So I think a named reference is a good compromise, where the name in the documentation (in some easily recognized syntactic form) refers to the next declaration (or set of declarations) of that same name. Hopefully the pod either knows implicitly or has been told explicitly how to parse out such declarations for insertion into the document. (And a positional notation could just be a degenerate case of not specifying the name (or using a name of * maybe), so it finds the next declaration of any name. Maybe even some kind of wildcarding works for hybrid situations.) The syntax for such named forward references is open for bikeshedding. (I've intentionally not given any examples in this message to avoid prejudicing the matter.) My first instinct for such a thing would be to surround the perl code to be referenced with POD-like tags: =code name class foo ... =/code ...the idea being that a Perl parser treats the =code and =/code lines as line comments, while a Pod parser would take the block of lines that exists between the two and attaches it to 'name', to be rendered as is whenever 'name' is referenced. In short, =code and =/code would define a target which could then be referenced as few or as many times as you want within your regular perl code using something like =ref name ...where POD would substitute class foo ... every time that it sees =ref name -- Expanding on this idea: * if you don't specify a name on a '=ref' line, you automatically reference the next '=code' section to be found. If you don't bother naming a '=code' section, this is the only way that it can be referenced. If you give '^' as the name, then you automatically reference the last code section that was found. So: =begin pod =ref =end pod =code foo =/code =begin pod =ref ^ =end pod would render the same as =begin pod foo =end pod =begin pod foo =end pod * Put a number instead of a name, and it counts up (if negative) or down (if non-negative) through the code blocks, with -1 being the previous code block and 0 being the next one. A blank name is equivalent to 0, and a '^' is equivalent to -1. This should be used sparingly. * Add or subtract a number to/from a name, and you count up or down from that name, with '+1' giving the first code block following the named codeblock and '-1' giving the last code block prior to it. * In the same way that '=code'...'=/code' is designed to mimic the '=begin'...'=end' syntax of POD blocks, you could introduce a variation of '=code' that mimics the '=for' syntax by grabbing the next line or block of code (say, '=codeline' and '=codeblock'), where a block of code is terminated by a blank line. * the final violation of the separation of Church and State would be to have the Church ask the State to do something for it. Let a '=code' line specify a parser (such as perl): Pod passes the block of code to the specified parser; that parser then (presumably) goes through its paces with the goal of extracting language-specific documentation (such as the previously suggested 'is doc' traits), formatting the result as a text block, and handing that block back to the POD parser. If Pod can't talk to the language parser or vice versa, Pod simply uses the code block as is. -- Jonathan Dataweaver Lang
Re: [svn:perl6-synopsis] r14421 - doc/trunk/design/syn
[EMAIL PROTECTED] wrote: +Block comments may be nested within other block comments (with the +same or differing brackets). POD comments may also be nested within +block comments. (These are still visible to the POD parser; if you +wish to comment out a block of mixed POD and Perl 6 code, either use a +POD comment around it all, or prefix every line with C#.) The parser must report mismatched openers or closers to prevent, for example, unwitting use of bare C} as a closer for an opening C#{. ...or put it all in a block comment, and prefix POD's block tags with C#. What's the rationale for keeping POD comments that are nested in block comments visible to the POD parser? It seems to me that the least surprising behavior would be for the POD comment to be swallowed up by the block comment, on the basis that a block comment ought to be equivalent to prefixing every line from its start to end with a C# . Conversely, I'd expect a block comment that's nested inside a POD comment to be passed to the POD parser as ordinary POD text. In short, whichever kind of comment comes first should dominate. -- Jonathan Dataweaver Lang
Re: Generalizing ?? !!
Charles Bailey wrote: I'm concerned that the relevant precedent isn't just Perl5. The ?: spelling of the ternary is pretty deeply embedded in programming languages -- I'm hard pressed to think of a widely used language in the past 10-15 years that spells it differently (though that may say more about my experience than the universe of widely used languages). Put more practically, I don't think the issue is just moving people forward from Perl5; we need to think about whether it'll help or hinder users moving back and forth among several languages, or bringing familiarity with other languages to the process of learning Perl6. In short, is C:: ?? going to be Perl 6's C - ? Again, this presupposes that C: ? is a feasible option (i.e., doesn't conflict with anything important) now that we have whitespace disambiguation. If it isn't, then this whole line of reasoning is moot. So: Is it feasible? -- Jonathan Dataweaver Lang
Re: Generalizing ?? !!
Audrey Tang wrote: Jonathan Lang wrote: A variation of chaining associativity gets used, with the chaining rule being '$v1 op1 $v2 // $v1 op2 $v3' instead of '$v1 op1 $v2 $v2 op2 $v3', as is the case for comparison chaining. But wouldn't that make: True ?? undef !! Moose; evaluate to Moose, instead of undef as we wanted? Nope; because of the short-circuiting behavior: True ?? undef !! Moose - True ?? undef // True !! Moose The condition evaluates to True, causing the ?? to evaluate its RHS and then short-circuit the rest of the expression. The fact that the RHS evaluates to undef is irrelevant. In a sense, ?? and !! would invert the usual short-circuiting behavior: with normal short-circuiting operators ( and ||), the RHS is evaluated if and only if the operator does not short-circuit; with ?? and !!, the RHS would be evaluated if and only if the operator _does_ short-circuit. NeonGraal wrote: Surely if you defined !! to return undef but true and both operators to be left associative then it all works. 1==0 ?? True !! False - (undef) !! False which seems right to me. 1==1 !! False ?? True - (undef but true) ?? True also good. ...except that '1==1 !! False' would return 'undef but true' on a failure. I'm sure that a rationale could be provided for doing this; but it's a potentially surprising result which could get you in trouble. Best to keep to a simple 'undef' result on a failure. Hakim: I'm not familiar with Haskell, so I can't follow your code as well as I need to to provide an informed response. Juerd Waalboer wrote: Zev Benjamin wrote: ?? and !! could always return some kind of result object that boolizes to true or false. Can we *please* keep simple things simple? Agreed. I'm in favor of this proposal to the extent that it breaks a simple trinary operator down into equally simple binary operators (with the trinary form continuing to exist as an emergent property of the interaction of the binaries); if those binary operators become more complex than the trinary form, or if you lose the ability to recover the trinary form from them, there's no point in pursuing this proposal. -- Jonathan Dataweaver Lang
Re: Generalizing ?? !!
[EMAIL PROTECTED] wrote: Besides ?? !! with out an else part is just . No, it isn't. While behaves properly when the condition turns out to be true, the result of the condition turning out to be false is whatever the condition turned out to be. Still, Damian has a good point - which renders the bulk of this discussion moot. The one thing left to consider (IMHO) is whether or not it's worthwhile (or even possible) to go back to '$c ? $t : $f' or to '$c ? $t ! $f'. As I said, the primary concern originally expressed about the Perl 5 syntax involved matters of ambiguity which seem to have been resolved since then. A case could be made that if the Perl 5 syntax for this doesn't clash with the rest of Perl 6, it should be used: anything else would be change for change's sake. -- Jonathan Dataweaver Lang
Generalizing ?? !!
Rereading A03, I ran across the original reasoning behind why Perl 5's '?:' trinary operator became '?? ::' first, and then '?? !!'. Three reasons were given: * the '?' and ':' tokens are far too broadly useful to be gobbled up by the trinary operator. * the doubled symbols bring to mind the short-circuiting operators (e.g., '' and '||'), suggesting a similar short-circuiting behavior here. * the '!!' brings to mind evaluate this when the condition fails. IMHO, the first point was always more about the ':' than it was about the '?'; if you were to replace ':' with '!', I suspect that this concern would largely go away. That is, I don't see any infix:? or infix:! operators in the current draft. A case could be made that a trinary '... ? ... ! ...' operator could work within the current state of things without conflict. Also, the whitespace disambiguation rules that were later implemented go a long way to resolving the original problem of ':' trying to do too much. That said, the latter two points are still valid. '... ? ... : ...' might be perfectly workable; but so is '... ?? ... !! ...'. However, there still may be room for improvement. Consider the following possibility: Instead of being a single, inflexible trinary operator, break this into a pair of binary operators: infix:?? and infix:!!. Each can be used on its own, returning the right side if the condition evaluates as expected (i.e., true for ?? and false for !!), and otherwise returns 'undef'. A variation of chaining associativity gets used, with the chaining rule being '$v1 op1 $v2 // $v1 op2 $v3' instead of '$v1 op1 $v2 $v2 op2 $v3', as is the case for comparison chaining. So all of the following would be valid syntax: $test ?? $a !! $b # true: $a; false: $b $test !! $a ?? $b # true: $b; false: $a $test ?? $a # true: $a; false: undef $test !! $b # true: undef; false: $a I suggest this mainly because it's potentially more extensible than the current model. I could see someone devising a fuzzy logic module which could allow for such things as: $test ?? $a !! $b maybe $c likely $d unlikely $e -- Jonathan Dataweaver Lang
Re: [svn:perl6-synopsis] r14415 - doc/trunk/design/syn
Larry Wall wrote: : * In item context, a list of captures becomes a single Array object, : and the question about whether or not it gets flattened gets deferred : until its contents get looked at in list, slice, or hash context. That's the intent. $() used to assume @@ inside till this latest change, but that seemed insufficiently lazy to me... But it kinda means there's yet another list context that doesn't decide yet, used explicitly by the insides of \(...) and implicitly by the $() context. Not sure if it needs a name yet, or whether it's a design smell. IMHO, no name is needed; just note that \(...) generates a variation of the list context that is agnostic to flattening, but is otherwise equivalent to list. Arguably list should be non-committal and we give @() a different name like flat, but that grates in my brain for some reason, if only because most list contexts would in the end be flat anyway. And list in English already implies something flatter than, say, an outline. ...which tends to be more akin to slice. In fact, consider renaming slice as outline. Sure, it's two characters longer; but it's _much_ more descriptive of what's going on. Slice strikes me as something of a holdover from its origins in array indices. Conversely, our agnostic list _is_ flatter than a slice or outline, just like a hardcore list is flatter than an agnostic list. I'd tend to agree about keeping list tied to the flattened stuff. IMHO, you're not going to find anything in English to represent the agnostic list of captures. In essence, we have: list, list-of-captures, and slice (or outline?); also, hash and item. : Meanwhile, 'zip' produces a list of captures - which, because list : context is the default plural context, immediately gets flattened : most of the time. As I see it, then, the serial equivalent to : 'zip(@a;@b)' would be '(@a;@b)', and 'list(@a;@b)' would be the serial : equivalent to 'list(zip(@a;@b))'. That doesn't make sense to me. You seem to be thinking that semicolon has zip semantics, when it doesn't. All ; does is make a list of captures. My focus in this comparison is on what is being produced, rather than on what is being passed in. My understanding is that 'zip' produces a list of captures. It's just that the default context that zip is likely to work in is list context, which flattens that list of captures. Or am I wrong about this? The other alternative is that zip knows whether it's being called in list or slice/outline context, and produces its output accordingly. I was assuming that zip wouldn't need to know; but I could be wrong about this. If zip _does_ tailor its return value according to the variety of list context that it finds itself in, then 'list()' is _still_ not the serial analog to 'zip()', any more than 'slice()' is, since both impose a specific context on the product. You'd need a new function that takes a list of captures as its parameters, and produces a flat list in list context or a slice or outline in slice/outline context. : Or does '(@a;@b)' default to slice context? Parentheses don't supply context. They only group. (@a;@b) returns a list of captures. It requires a binding (or other sigil) coercion to supply context. The parentheses weren't concerning me here; the semicolon within brackets was. I've been working under the assumption that a bracketed @a;@b produces an agnostic list of captures, which then gets flattened or structured when it hits list or slice context, respectively; I was asking about the possibility that I was wrong about this, and that bracket-within-semicolons produces a slice/outline outright. -- This does bring up another question, though: when are you in list context, and when are you in list-of-captures context? That is, when do you force a list of captures to flatten, and when do you leave it alone? -- Jonathan Dataweaver Lang
Re: [svn:perl6-synopsis] r14415 - doc/trunk/design/syn
Jonathan Lang wrote: Arguably list should be non-committal and we give @() a different name like flat, but that grates in my brain for some reason, if only because most list contexts would in the end be flat anyway. And list in English already implies something flatter than, say, an outline. ...which tends to be more akin to slice. In fact, consider renaming slice as outline. Sure, it's two characters longer; but it's _much_ more descriptive of what's going on. Slice strikes me as something of a holdover from its origins in array indices. An even better choice might be tree: it's the same length as list and item, and conveys the hierarchal structure inherent to that context quite nicely. Then again, [[['a', 'b'], ['c', 'd']], 'e', ['f', 'g']] isn't really a tree _or_ an outline, since only the leaf nodes actually have content. -- Jonathan Dataweaver Lang
Re: 'x' vs. 'xx'
Chas Owens wrote: Jonathan Lang wrote: Chas Owens wrote: Jonathan Lang wrote: Is there any reason why we can't simply define '$a x $n' as being shorthand for 'cat($a xx $n)'? In what way does the former differ from the latter, other than the use of a Whatever in place of $n? $a x $n is equivalent to join '', $a xx $n, but that isn't an apt description of its behavior. cat($a xx *) is an attempt to provide an infinite string since 'a' x Inf would result in memory overflow (but the cat trick works since lists are evaluated lazily). Then it looks to me like 'cat($a xx $n)' is more flexible than join '', $a xx $n, and would work better as the baseline definition for '$a x $n'. Is there any reason to prefer a join-based definition to a cat-based one? AFAICT, the only thing that 'join' can do that 'cat' can't is to provide a delimiter when stitching the component strings together; in the case of 'x', this feature is (rightfully) not being used. Okay, maybe my understanding of the cat function is flawed, but I thought it walked through each array handed to it in a serial fashion (as opposed to zip which walks the arrays in a parallel fashion). Hmm... true enough. That was an aspect of the 'cat' function that I hadn't been aware of. Rather, what came to mind when I saw the 'cat' function was the following (from S29): ...a CCat in item context emulates the CStr interface lazily. In short, 'cat(a x 5)' effectively _is_ a scalar string value of five characters - in item context. And because it emulates the string interface _lazily_, there's no danger from an infinitely long string. Again, I was not aware that there _was_ a distinct list context result for 'cat'; and I'm pretty sure that it was referenced as an alternative to '$a x *' due to its behavior in scalar context, rather than its behavior in list context. So the question is this: is there a problem with 'a' x 5 producing 'a', 'a', 'a', 'a', 'a' in list context, and 'a' in item context? Or should it produce the latter in anything but void context? -- Jonathan Dataweaver Lang
Re: 'x' vs. 'xx'
Chas Owens wrote: I am almost certain that the following code is in list context. pugs my @a = '-' x 5, 'foo', '-' x 5; pugs @a (-, foo, -) pugs my @b = cat('-' xx 5), 'foo', cat('-' xx 5) (-, -, -, -, -, foo, -, -, -, -, -) However, it does seem that Pug's version of cat does not handle the Str emulation, so that may fix it, but I don't see how it could since (at least in my mind) the code above is in list context. You're right; it is. From what you're saying, I get the impression that you think that '-' x 5 ought to produce a single string of five dashes regardless of whether the context is item or list. Correct? (Note: I'm not asking about what the spec says, since what it says is potentially up for revision, given sufficient cause; I'm asking about what you think the spec _should_ say.) If so, cat($n xx *) is not an adequate replacement for $n x *, since it produces a list of one-character strings if used in list context. OTOH, ~cat($n xx *) might work. Personally, I would tend to favor the notion that infix:x always produces a single string. With this in mind, I'm now leaning toward ~cat($a xx $n) as the more verbose equivalent of $a x $n. You always produce a single string, and you do so lazily (according to the way that 'cat' works in item context). -- Jonathan Dataweaver Lang
Re: 'x' vs. 'xx'
Mark J. Reed wrote: Is item context what we're calling scalar these days, or something else? According to S03, it does indeed appear that item context is the current terminology for what perl 5 called scalar context: The item contextualizer item foo() The new name for Perl 5's scalar contextualizer. Equivalent to $(). We still call the values scalars, and talk about scalar operators, but scalar operators are those that put their arguments into item context. -- Jonathan Dataweaver Lang
Re: 'x' vs. 'xx'
Chas Owens wrote: The current Perl 5 behavior is [EMAIL PROTECTED]:~$ perl -le 'my @a = (- x 5, foo, - x 5); print @a' - foo - [EMAIL PROTECTED]:~$ perl -le 'my @a = ((-) x 5, foo, (-) x 5); print @a' - - - - - foo - - - - - I am against anything other than that for x or xx without a really compelling reason. ...with x always corresponding to the first and xx always corresponding to the second, right? In essence, x always produces a string, while xx always produces a list. Jonathan Lang wrote: Personally, I would tend to favor the notion that infix:x always produces a single string. With this in mind, I'm now leaning toward ~cat($a xx $n) as the more verbose equivalent of $a x $n. You always produce a single string, and you do so lazily (according to the way that 'cat' works in item context). I assume it is a bug in Pugs implementation of cat, but pugs ~cat('a' xx 5) a a a a a Yes, that would be a bug - probably closely tied to the fact that pugs doesn't implement cat properly in item context. IIRC, the original inspiration for the 'cat' function was 'concatenate' - thus, in item context at least, one would expect 'cat' to resemble '[~]'. I also am having a hard time figuring out why I would want an infinite string. My first thought was something like my $ten_zeros = substr(cat(0 xx *), 0, 10); but that is more clearly written as my $ten_zeros = 0 x 10; I'll punt the practical usage to someone else, other than to suggest that the goal of using an asterisk for the number of repetitions isn't so much to produce an infinite string as a string of arbitrary length. Remember, '*' ne 'Inf'; '*' eq 'Whatever'. A practical use for '~cat($string xx *)' would most likely be one that relies on the arbitrariness of the number of repetitions. Hmm... how about something like: if $a gt ~cat('-' xx *) { ... } or, if 'x' is defined along the lines that I'm considering: if $a gt '-' x * { ... } Bear in mind that you're not limited to single-character repetitions: if $a lt '142857' x * { ... } In short, the string will get replicated exactly as many times as is needed to resolve the comparison. -- Jonathan Dataweaver Lang
Re: [svn:perl6-synopsis] r14415 - doc/trunk/design/syn
[EMAIL PROTECTED] wrote: Author: larry Date: Sun Jun 3 17:23:15 2007 New Revision: 14415 Modified: doc/trunk/design/syn/S03.pod doc/trunk/design/syn/S04.pod doc/trunk/design/syn/S06.pod Log: typo from Aaron Crane++ s/cat/list/ for flattening captures in order cat() now only produces pseudo-strings even in list context Modified: doc/trunk/design/syn/S03.pod == --- doc/trunk/design/syn/S03.pod(original) +++ doc/trunk/design/syn/S03.podSun Jun 3 17:23:15 2007 @@ -610,7 +610,7 @@ $string x $count Evaluates the left argument in string context, replicates the resulting -string value the number of time specified by the right argument and +string value the number of times specified by the right argument and returns the result as a single concatenated string regardless of context. If the count is less than 1, returns the null string. @@ -625,7 +625,7 @@ @list xx $count Evaluates the left argument in list context, replicates the resulting -CCapture value the number of time specified by the right argument and +CCapture value the number of times specified by the right argument and returns the result in a context dependent fashion. If the operator is being evaluated in ordinary list context, the operator returns a flattened list. In slice (C@@) context, the operator converts each CCapture @@ -3554,15 +3554,12 @@ ... } -To read arrays serially rather than in parallel, use Ccat(@x;@y). -This wins a useless use of cat award in this case since you could +To read arrays serially rather than in parallel, use Clist(@x;@y). +This wins a useless use of list award in this case since you could always just write C(@x,@y) to mean the same thing. But sometimes it's nice to be explicit about that: -@foo := [[1,2,3],[4,5,6]]; say cat([;] @foo); # 1,2,3,4,5,6 - -(The Ccat function is not entirely useless; it also provides stringy -semantics in string context.) +@foo := [[1,2,3],[4,5,6]]; say list([;] @foo); # 1,2,3,4,5,6 Let me see if I understand this correctly: * In list context, a list of captures gets flattened. * In slice context (a variant of list context), a list of captures doesn't get flattened. * In hash context (another variant of list context), a list of captures gets flattened, and then grouped into Pairs. * In item context, a list of captures becomes a single Array object, and the question about whether or not it gets flattened gets deferred until its contents get looked at in list, slice, or hash context. Meanwhile, 'zip' produces a list of captures - which, because list context is the default plural context, immediately gets flattened most of the time. As I see it, then, the serial equivalent to 'zip(@a;@b)' would be '(@a;@b)', and 'list(@a;@b)' would be the serial equivalent to 'list(zip(@a;@b))'. Or does '(@a;@b)' default to slice context? -- Jonathan Dataweaver Lang
'x' vs. 'xx'
Is there any reason why we can't simply define '$a x $n' as being shorthand for 'cat($a xx $n)'? In what way does the former differ from the latter, other than the use of a Whatever in place of $n? -- Jonathan Dataweaver Lang
Re: 'x' vs. 'xx'
Chas Owens wrote: Jonathan Lang wrote: Is there any reason why we can't simply define '$a x $n' as being shorthand for 'cat($a xx $n)'? In what way does the former differ from the latter, other than the use of a Whatever in place of $n? $a x $n is equivalent to join '', $a xx $n, but that isn't an apt description of its behavior. cat($a xx *) is an attempt to provide an infinite string since 'a' x Inf would result in memory overflow (but the cat trick works since lists are evaluated lazily). Then it looks to me like 'cat($a xx $n)' is more flexible than join '', $a xx $n, and would work better as the baseline definition for '$a x $n'. Is there any reason to prefer a join-based definition to a cat-based one? AFAICT, the only thing that 'join' can do that 'cat' can't is to provide a delimiter when stitching the component strings together; in the case of 'x', this feature is (rightfully) not being used. -- Jonathan Dataweaver Lang
Purging [-1]
I just went through all of the synopses searching for instances where [-1] is still being referenced in its perl5 sense; the following patches update them to correct perl6 syntax. I also took the liberty of fixing up a markup glitch in S03.pod. =begin S02 @@ -1379,7 +1379,7 @@ =item * -The C$#foo notation is dead. Use C@foo.end or C@foo[-1] instead. +The C$#foo notation is dead. Use C@foo.end or C@foo[*-1] instead. (Or C@foo.shape[$dimension] for multidimensional arrays.) =back =end S02 =begin S03 --- S03.pod 2007-05-25 17:32:16.0 -0700 +++ S03a.pod2007-05-25 17:38:14.0 -0700 @@ -1606,7 +1606,7 @@ =item * -Cqw{ ... } gets a synonym: C ... , and an interpolating +Cqw{ ... } gets a synonym: C ... , and an interpolating variant, C«...». For those still living without the blessings of Unicode, that can also be written: C ... . @@ -1614,7 +1614,7 @@ =item * In item context comma C, now constructs a CList object from its -operands. You have to use a C[-1] subscript to get the last one. +operands. You have to use a C[*-1] subscript to get the last one. =item * @@ -2146,7 +2146,7 @@ is short for something like: -@[EMAIL PROTECTED], @array[-1] xx * +@[EMAIL PROTECTED], @array[*-1] xx * An empty Range cannot be iterated; it returns a CFailure instead. An empty range still has a defined min and max, but the min is greater than the max. @@ -3050,8 +3050,8 @@ are equivalent to -$x = @y[0] = @y[1] = @y[2] ... @y[-1] = $z = 0 -$x += @y[0] += @y[1] += @y[2] ... @y[-1] += $z += 1 +$x = @y[0] = @y[1] = @y[2] ... @y[*-1] = $z = 0 +$x += @y[0] += @y[1] += @y[2] ... @y[*-1] += $z += 1 rather than =end S03 -- Jonathan Dataweaver Lang
Re: [svn:perl6-synopsis] r14401 - doc/trunk/design/syn
Darren Duncan wrote: Jonathan Lang wrote: I see no mention of C@@x in this section. I would assume that C@@x may be bound to any object that does the CMultidimensional role, with a note to the effect that the CMultidimensional role does the CPositional role (and thus anything that C@x may be bound to, C@@x may also be bound to). I would argue that multi-dimensional is too generic a name for what you describe. In particular, I wouldn't say that something with that name does positional, at least in a conventional sense. ...another reason to consider my more recent suggestion of replacing 'Positional', 'Associative', etc. with 'sigil:@', 'sigil:%', and so on. '@@x' would then bind to any object that does 'sigil:@@'. If we have a multidim role, don't make it do positional. Those can only be combined on a case by case basis. If you do make multidim positional, then you might as well say that every type does ordered, because that makes as much sense. I suggested this because anything that can be bound to '@@' can also be bound to '@'; this implies to me that 'sigil:@@' does 'sigil:@'. That said, you have a point, in that '@@' vs. '@' is a strange dog; an object that is bound to '@@' behaves differently than one that's bound to '@', which would not be the case if we relied solely on something to the effect of 'sigil:@@ does sigil:@' to handle matters. -- Jonathan Dataweaver Lang
Re: [svn:perl6-synopsis] r14401 - doc/trunk/design/syn
Perhaps it's better to think of '@' and '@@' as working with different contexts. S02 says that there are three main contexts (void, scalar, and list); that scalar context has a number of sub-contexts (boolean, integer, number, and string), and that list context has a number of sub-contexts based on the container type. The difference between '@' and '@@' seems to be 'list context' vs. 'lisp context', as it were - i.e., whether or not nested lists should be flattened. How this maps to required roles, I'm still not sure. -- Jonathan Dataweaver Lang
Re: [S02] Sigils
Larry Wall wrote: Well, it's already too easy, but the problem I have with it is not that. My problem is that sigil:@ is the name of a very specific syntactic notion, while Positional is the name of a very generic semantic notion. I don't think those levels should be confused. Fair enough. -- Jonathan Dataweaver Lang
Re: [svn:perl6-synopsis] r14401 - doc/trunk/design/syn
[EMAIL PROTECTED] wrote: Sigils indicate overall interface, not the exact type of the bound +object. Different sigils imply different minimal abilities. I see no mention of C@@x in this section. I would assume that C@@x may be bound to any object that does the CMultidimensional role, with a note to the effect that the CMultidimensional role does the CPositional role (and thus anything that C@x may be bound to, C@@x may also be bound to). -- Jonathan Dataweaver Lang
[S02] Sigils
From S02: -- Perl 6 includes a system of Bsigils to mark the fundamental structural type of a variable: $ scalar (object) @ ordered array % unordered hash (associative array) code/rule/token/regex :: package/module/class/role/subset/enum/type/grammar @@ multislice view of @ C$x may be bound to any object, including any object that can be bound to any other sigil. C@x may be ... bound to any object that does the CPositional role C%x may be bound to any object that does the CAssociative role Cx may be bound to any object that does the CCallable role C::x may be bound to any object that does the CAbstract role -- IIRC, could the above section about C$x be considered equivalent to saying that C$x may be bound to any object that does the CObject role? Also, a possible change in terminology: s/CPositional/C sigil:@ / s/CAssociative/C sigil:% / s/CCallable/C sigil: / s/CAbstract/C sigil::: / s/CObject/C sigil:$ / if every object does the Object role This would free up more role names for programmer use. It would also imply that one could create a new sigil by defining a role named 'sigil:...', with the behavior of the sigil being established by the definition of the role. Or does this make it too easy to create new sigils? -- Jonathan Dataweaver Lang
Re: [svn:perl6-synopsis] r14399 - doc/trunk/design/syn
Some additional suggestions for S02: -- @@ -740,9 +740,9 @@ Range A pair of Ordered endpoints; gens immutables when iterated Set Unordered group of values that allows no duplicates Bag Unordered group of values that allows duplicates -JunctionSets with additional behaviors +JunctionSet with additional behaviors PairTwo elements that serve as key/value in a one-element Mapping -Mapping Pair set with no duplicate keys +Mapping Set of Pairs with no duplicate keys Signature Function parameters (left-hand side of a binding) Capture Function call arguments (right-hand side of a binding) BlobAn undifferentiated mass of bits -- Also, the definitions of Pair and Mapping almost seem to be circular: what is a Pair? A one-element Mapping. What is a Mapping? A Set of Pairs. Perhaps replace Pair with: PairTwo elements that represent a key and its value -- Jonathan Dataweaver Lang
Re: explicit line termination with ;: why?
Larry Wall wrote: Dave Whipp wrote: : A slightly tangental thought: is the behavior of Cgiven with no block : defined? I.e. is It would be illegal syntax currently. As I understand it, the proposal is to say that if the parser finds a ';' where it was expecting to find a control block, it treats the rest of the current block as the expected control block - or something to that effect. Eh... messy, and with no substantial gain. : given $foo { when 1 {...} }; : : equivalent to : : given $foo; : when 1 {...}; Both of these suggestions would seem to duplicate the existing construct: $_ = $foo; :-) Agreed. But I think that postfix:? is rather clean: $foo? when 1 {...} Two catches: 1. I could easily define postfix:? myself, save for one thing: what would I put as the parameter for the 'is equiv' trait, so that it has terminator precedence? 2. 'when' implicitly leaves its current block after successfully being executed (as per 'last'), since it's designed primarily for use as one of a set of mutually-exclusive options. I'm not sure how wise of a decision that is, since it's easier to add a last to a block that implicitly lacks one than it is to remove a last from a block that implicitly includes one. Part of me would strongly prefer that when $x { ... } be exactly equivalent to if $_ ~~ $x { ... }, except for the inability to append an else block to the former. Of course, now someone will argue that unary:= should assign to $_ by default, in which case we'd have to find a new iteration operator... Horrors, no! '=$filehandle' works just fine for reading an iterator, thank you... I _might_ flirt with the idea of postfix:= being equivalent to a filehandle's '.say' method (i.e., writing to an iterator) - or not. Given the mandatory whitespace that a postfix operator imposes on an equivalent infix operator, I'd strongly suggest that good practice for Perl 6 would be to avoid defining both forms if at all reasonable; and infix:= definitely has the edge here. (Rule of thumb: if you can avoid doing something that will mandate or forbid whitespace, avoid it.) -- Jonathan Dataweaver Lang
Re: explicit line termination with ;: why?
gabriele renzi wrote: Hi everyone, I don't want to argue about the design of perl6, I just wonder: why the semicolon is still needed in the end of lines in perl6? It isn't - sometimes. S03 identifies a number of ways that an expression can be terminated: the semicolon (';'), a block-final ('}'), a control block (' { ... }'), a statement modifier ('if'|'unless'|'while'|'until'|'for'|'given'|'when')^, or a feed operator ('==', '==', '==', '=='). ^ FWIW, S03 needs updating, since it doesn't list 'given' or 'when' among the statement modifiers in the block termination section. A couple of thoughts: 1. There's a subtlety here: termination of an expression is not always the same as termination of a statement. In particular, ';' is pretty much equivalent to the '==' feed operator when used in a bracketing construct [1]^, and feed operators in general don't appear to force statement termination the way that control blocks, statement modifiers, and block-finals do. Of course, this distinction may be me misunderstanding how expression termination works. 2. This brings up the possibility of custom-designed termination operators. Question: which kinds of operators can have this precedence? That is, prefix, postfix, infix, circumfix, or postcircumfix? It appears to me that our current list of termination operators includes analogs of most of these: postfix:;, infix:{'=='}, circumfix:{ }, and postcircumfix:«\s{ }» [2]^. Meanwhile, how much clarity does the parser have between postfix and infix? That is, if I defined both postfix:foo and infix:foo, would the parser be able to reliably distinguish between them? This matters to the current topic because ';' could be thought of as 'postfix-like' when used to terminate a statement, and 'infix-like' when being used to construct feeds; if clarity between postfix and infix exists, you might be able to do away with the bracketed context clause - though it might not be wise to do so, even if you could.) I'm thinking about this in terms of the possibility of adding more punctuation to the syntax: consider something akin to a postfix:? operator that behaves exactly like postfix:;, except that it automatically topicalizes the expression's value. Or a postfix:. that always behaves the way that postfix:; does at statement level [3]^. Borrowing from Spanish, circumfix:¿ ? might be to circumfix:{ } as postfix:? would be to postfix:;. And so on. As long as we maintain clarity between the grammatical categories, such punctuation operators shouldn't present any difficulty; e.g., postfix:? will not clobber prefix:? or vice versa, even if the former has terminator precedence and the latter has symbolic unary precedence. Or is this the sort of thing that you'd rather consign to explicit hacks of the parser? ^[1]: see S09. ^[2]: Admittedly, this last one cheats a bit by putting whitespace into the delimiter. But the principle is the same. ^[3]: If this were included in the core, you might even reverse things so that ';' is defined in terms of postfix:. or infix:{'=='}, depending on the context; in this case, postfix:? would be defined in terms of postfix:., rather than postfix:;. In fact, the only thing keeping postfix:. from completely replacing postfix:; as a statement terminator and insisting that the latter always be used as a shortcut for feeds is the long tradition that the latter has in programming languages - much like perl 6's infix:. replaces perl 5's '-' because that's what everyone else uses. -- Jonathan Dataweaver Lang
Re: Sigils by example (was: Re: Is Perl 6 too late?)
Good examples. Now could you provide some to explain to me why it's important to distinguish between '$', '@', '%', and ''? I ask because I've seen a lot of object-based code that has said stuff like '$container{$key}'; it seems that there's an assumption that $foo can be used as a list, a hash, or even a routine if the object that it's tied to has list-, hash-, or routine-like behavior: i.e., it no longer seems to be a scalar variable, but rather a variable. Whereas '@', '%', and '' still seem to promise list, hash, and routine functionality, respectively. In short, there no longer appears to be a sigil that says I give my solemn promise that the contents herein will be scalar. -- Jonathan Dataweaver Lang
Re: explicit line termination with ;: why?
Jonathan Lang wrote: ^[3]: If this were included in the core, you might even reverse things so that ';' is defined in terms of postfix:. or infix:{'=='}, depending on the context; in this case, postfix:? would be defined in terms of postfix:., rather than postfix:;. In fact, the only thing keeping postfix:. from completely replacing postfix:; as a statement terminator and insisting that the latter always be used as a shortcut for feeds is the long tradition that the latter has in programming languages - much like perl 6's infix:. replaces perl 5's '-' because that's what everyone else uses. Umm, never mind. I just realized that introducing a postfix:. operator would complicate matters in unexpected ways by forcing infix:. to require disambiguating whitespace, as per S02. This would be Very Bad in several ways, e.g., an infixed dot is given as the appropriate way to separate a postfix operator from the term in front of it when whitespace is forbidden. Or the fact that 'foo.bar' would no longer parse as expected. :sigh: -- Jonathan Dataweaver Lang
Re: Sigils by example (was: Re: Is Perl 6 too late?)
Mark J. Reed wrote: Jonathan Lang wrote: Good examples. Now could you provide some to explain to me why it's important to distinguish between '$', '@', '%', and ''? I ask because I've seen a lot of object-based code that has said stuff like '$container{$key}'; Well, $container{$key} is how you access elements of %container in Perl5; in Perl6 that's %container{$key}. But in object-based P5 code, you'd be much more likely to see $container-{$key}, where $container contains a reference to a hash. True; but not at all what I was referring to. I believe in P6 you could write that either as $container.{$key}, $container{$key} (where the . is implied since $container{$key} can't refer to %container anymore), or %$container{$key}. _This_ is closer to what I'm referring to. As I understand it, Hash is a role that provides (among other things) postcircumfix:{ }. So any object that does Hash should be able to call the above method. And unless I've missed something, there's nothing in perl 6 that insists that an object that does Hash must be assigned to a variable that uses the '%' sigil; the '$' sigil seems to work equally well. i.e., I've seen code to the effect of: class Foo does Hash { ... } my $obj is Foo; $objkey = 5; say $objkey; In short, it appears that there's nothing keeping you from assigning hash-like or list-like objects to scalar variables. And this is without bringing references into the picture. You aren't the only person who feels this way; there was a proposal back in the RFC process to remove sigils in favor of everything is a scalar, dereference as needed. I was in that camp myself. But Larry rejected that proposal, defending the utility of sigils, and I have been swayed by the arguments, which I'm not going to repeat because I can't say it as well, but I do advise you to go read - it was either Apoc1 or Apoc2, I think. I have never been in that camp. In fact, I tend to see the points I raise above as a bug, not a feature. Perhaps the relationship between sigils and roles will be addressed in the as-yet unwritten S14 (or whichever spec is supposed to address tied variables)? -- Jonathan Dataweaver Lang
Re: explicit line termination with ;: why?
On 5/14/07, Daniel Hulme [EMAIL PROTECTED] wrote: On Mon, May 14, 2007 at 02:29:11PM -0700, Jonathan Lang wrote: 2. This brings up the possibility of custom-designed termination operators. cf. Semi::Semicolons. Close. I'm thinking added functionality for semicolon alternatives rather than the replace the semicolon stunt that Semi::Semicolons pulls. In particular, as long as there's no ambiguity between prefix:? and postfix:?, I think that it would be quite useful for postfix:? to act as a semicolon that additionally sets $_ equal to the expression's value, allowing for a pseudo-Prolog style of syntax (i.e., the code could include questions as well as declarations and instructions). -- Jonathan Dataweaver Lang
Re: Default filehandles, or topicalizing filehandles, or something
On 5/1/07, brian d foy [EMAIL PROTECTED] wrote: I was thinking about default filehandles yesterday. select() doesn't seem to be around except as an Unfiled function in S16. Then, as I was looking at .say( Hello World ); At various times, I have seen something to the effect of each of the following being bandied about: $*OUT.say( Hello World ); Hello World.say; That is, both filehandles and strings have 'say' methods that do essentially the same thing, but using subtly different syntax. How would I use (Hello World.say) to write to filehandle $FH? My gut reaction would be to use an adverb for the purpose: Hello World.say :to($FH); This would also work for the sub version: say :to($FH) Hello World; With this in mind, you probably could create a localized alias for 'say', if you wanted to: { my say := OUTER::say.assuming(:to($FH)); say Hello World; # same as 'say Hello World :to($FH);' } The catch with this is that you'd have to do this for each output routine separately. How about this: Do the output routines default to the global filehandles directly, or do they default to lexical bindings of them? That is, does 'say' output to $*OUT in the absence of an explicit filehandle, or does it output to $OUT (with the latter normally being bound to $*OUT)? If the latter, you should be able to redirect all of your output in the rest of the current scope by saying: $OUT := $*ERR; I can understand not being able to rebind the global filehandles. After all: once they're rebound, how would you ever find what they were originally bound to? -- Jonathan Dataweaver Lang
Re: S12: can(), signatures and casting
Larry Wall wrote: The fundamental problem here is that we're forcing a method name to be represented as a string. We're basically missing the foo equivalent for methods. Maybe we need to allow the indirection on method names too: if $obj.fribble:(Str -- BadPoet) { Takes a little getting used to (it isn't immediately obvious that you're testing for the existence of a method - at least, not until you've spent some time thinking about it); but otherwise, I like. -- Jonathan Dataweaver Lang
Re: S12: can(), signatures and casting
Larry Wall wrote: Maybe we need to allow the indirection on method names too: if $obj.fribble:(Str -- BadPoet) { -snip- Note that we already define foo:(Int, Str) to return a list of candidates if there's more than one, so extending this from the multi dispatcher to the single dispatcher just seem like a SMOS (small matter of syntax). One corollary of this is that querying an object for its available methods should probably give you a list of coderefs instead of method names. What threw me initially was that I wasn't used to thinking of a coderef as a test for existence - in particular, I couldn't see how the method's name could be specified using such a syntax. Another question: what about $obj.?fribble:(Str -- BadPoet) $obj.*fribble:(Str -- BadPoet) $obj.+fribble:(Str -- BadPoet) As I understand it, placing a ? or * between an object and a method results in the method only being called if it exists (although I'm not clear on what happens if it doesn't); placing a * or + between the object and method calls every version of the method that applies. Couldn't you just cap one of the former two with a '' to prevent the resulting methods from actually running? $obj.?fribble:(Str -- BadPoet) $obj.*fribble:(Str -- BadPoet) $obj.+fribble:(Str -- BadPoet) Or would you have to hyperize the '' in the latter cases? $obj.fribble:(Str -- BadPoet) # dies if fribble doesn't work as advertised; $obj.?fribble:(Str -- BadPoet) # returns undef instead. «$obj.*fribble:(Str -- BadPoet) # returns a list of all fribbles; «$obj.+fribble:(Str -- BadPoet) # as above, but fails on an empty list. Regardless, I agree: can '.can()'. -- Jonathan Dataweaver Lang
Re: S12: can(), signatures and casting
Ovid wrote: My apologies if these have been answered. I've been chatting with Jonathan Worthington about some of this and any misconceptions are mine, not his. In reading through S12, I see that .can() returns an iterator for the methods matched. What I'm curious about is this: if $obj.can('fribble') { my BadPoet $jibbet = $obj.fribble('repeatedly'); } Just because $obj.can('fribble') does not mean that the available fribble(s) will accept a string argument or return BadPoet instances. In chatting with Jonathan about this, he speculated that I would have to manually walk the method objects in the iterator to find out if I really have a suitable method. This seems like what we really have is $object.might($method). Is there a simpler way of determining if there's an appropriate method for what I need? It seems like what we really want is a method object where I can declare a signature and then do this: if $obj.can($object_with_signature){ ... } I suppose. Still, an easier solution might be to allow an optional second parameter for .can that takes a signature object: if $obj.can('fribble', :(string - BadPoet)) { my BadPoet $jibbet = $obj.fribble('repeatedly'); } Or you could allow signatures to be attached to strings: # pseudo-code: if $obj.can('fribble':(string - BadPoet)) { my BadPoet $jibbet = $obj.fribble('repeatedly'); } In effect, the signature gets attached as a property of the string, and 'can()' checks for the signature property. The only problem that I have with this idea is that I can't think of any uses for a signatory string outside of '.can()'. This raises my second question. What if I have this? class MadHatter is BadPoet { ... } If I get back a MadHatter instead of a BadPoet, but I really want the superclass and not a subclass, how can I enforce that? Do I have to do something like this? (pseudo-code) What are you looking for that .is() doesn't provide? The only thing I can think of is that you're trying to insist that $obj's implementation be BadPoet - not BadPoet or a class derived from it, but BadPoet. This strikes me as getting into the same territory as finalized classes. subset ReallyABadPoet where { $^N.type eq BadPoet } my ReallyABadPoet = $obj.fribble('repeatedly'); I'll assume that you meant to include a variable name on the second line: subset ReallyABadPoet where { $^N.type eq BadPoet } my ReallyABadPoet $obj2 = $obj.fribble('repeatedly'); If so, I fail to see what you gain from this, as opposed to: my BadPoet $obj2 = $obj.fribble('repeatedly'); In this case, $obj2 won't accept the product of $obj.fribble('repeatedly') unless that product .does('BadPoet'). That seems to fail because the you'd have to invoke every method to guarantee that you're really getting back the exact type you want. As I understand it, Perl 6's typing system does not do duck typing - that is, it uses .does() as its primary means of type-checking, not .can(). As such, you can check an object's type directly without having to examine its set of methods - just scan the set of roles that the object composes until you find the role that you're looking for. Or am I misunderstanding you? As such, it seems like we'd need return values to guarantee that the returned type is exactly what we claimed. method foo(Int $bar, Int $baz) returns Int { return $foo/$baz; } Since the return value might be a Float, does it get cast to an Int, thereby discarding information? As I understand it, yes; a Float would be cast into an Int in this case. Though my understanding is that this says more about Ints and Nums than it does about objects in general. -- Jonathan Dataweaver Lang
Re: File test operators as Pairs
Luke Palmer wrote: These things are methods, and I'm not sure why we've crammed them into smart match. Things like :M have nothing to do with matching. What would it mean if smart match returned false? This file has not been modified ever? :e has a bit more merit for a smart match, but the operation has little to do with the concept of a string or the pair e = 1. Also, I found the following line from S03 to be jolting: Any Pair test object .STATUS(X) (Str,IO do filetest) It struck me as a rather specific application for such a generic data type. I'm inclined to say that the best solution for filetests is to throw out our dwimmery altogether. Back in Perl 4 days, using stat explicitly was awkward, because you had to use it as a list and memorize the positions of all the returns. -s $file beats the heck out of (stat $file)[7], for sure. It also had the benefit that shell people would instantly recognize what's going on. However, now we have stat($file).size. With that, every programmer will recognize what's going on, not just people with shell background. And I don't think even people with a shell background will know what ($file ~~ :s) means (their guess could be right, but they'd have to look it up to confirm, and they would never think to *write* such a thing). I can never remember whether mtime is -m or -M anyway... Let's get rid of all the filetest magic, in favor of using stat explicitly. I tend to agree that the magic should go away. However, I already miss the filetest operators. Given the way that prefix operators work, wasn't it already possible to say something like the following? given $handle { when .'-r' .'-w' .'-x' { ... } when !.'-w' | !.'-x' { ... } when * { ... } } sort { $^a.'-M' = $^b.'-M' }, @files sort { .'-M' }, @files What does pair notation buy us that quoted-postfix notation doesn't already cover? -- Jonathan Dataweaver Lang
Re: Should a dirhandle be a filehandle-like iterator?
brian d foy wrote: As I was playing around with dirhandles, I thought What if... (which is actualy sorta fun to do in Pugs, where Perl 5 has everything documented somewhere even if nobody has read it). My goal is modest: explain fewer things in the Llama. If dirhandles were like filehandles, there's a couple of pages of explanation I don't need to go through. Witness: I can iterate through the elements of a named array with [EMAIL PROTECTED]: my @a = 1 2 3 4 5 ; for [EMAIL PROTECTED] { .say } # but not = 1 2 3 4 5 :( and I can read lines from a file: for =$fh { .say } Should I be able to go through a directory handle that way too? A yes answer would be very pleasing :) my $dh = doc.opendir; for =$dh { .say }# doesn't work in pugs And, since we're using objects now, .closedir can really just be .close, right? Please. I've always found the opendir ... readdir ... closedir set to be clunky. Also: why distinguish between open and opendir? If the string is the name of a file, 'open' means open the file; if it is the name of a directory, 'open' means open the directory. If it's the name of a pipe, it opens the pipe. And so on. Note that the above could be further shorthanded, as long as you don't need the directory handle after the loop: for =doc.open { .say } -- Jonathan Dataweaver Lang
Re: Should a dirhandle be a filehandle-like iterator?
Geoffrey Broadwell wrote: Jonathan Lang wrote: Also: why distinguish between open and opendir? If the string is the name of a file, 'open' means open the file; if it is the name of a directory, 'open' means open the directory. If it's the name of a pipe, it opens the pipe. And so on. As long as you still have some way to reach the low-level opens -- though it's an odd thing to do (except perhaps in a disk integrity checker), there's no fundamental reason why you shouldn't be able to actually look at the bytes that happen to represent a directory structure on disk. It wouldn't be hard to allow .openfile, .opendir, and .openpipe as well as .open. -- Jonathan Dataweaver Lang
Re: Should a dirhandle be a filehandle-like iterator?
Uri Guttman wrote: JL == Jonathan Lang [EMAIL PROTECTED] writes: JL Please. I've always found the opendir ... readdir ... closedir set JL to be clunky. JL Also: why distinguish between open and opendir? If the string is JL the name of a file, 'open' means open the file; if it is the name of JL a directory, 'open' means open the directory. If it's the name of a JL pipe, it opens the pipe. And so on. maybe this won't help you but if you did open on a dir in perl5 you can read the raw directory data which is pretty useless in most cases. so with open working as opendir on directories, what is the op/method to get the next directory entry? that isn't the same as reading a line. there won't be any trailing newlines to chomp. marking a location is not the same with tell and telldir (one is a byte offset, the other a directory entry index). and since dirs can reorder their entries (especially hash based dirs) the ordering and seek points may move. not gonna happen on text files. there are many differences and the only one you seem to see is a linear scan of them (which is just the most common access style). Well, I did suggest that openfile and opendir exist alongside open, with openfile being more akin to Perl 5's open or sysopen, and open being a bit more dwimmy. But in general, most of the differences that you mention are things that ought to be addressed in the resulting iterators, not in the creating statement. No, a directory handle will not behave exactly like a file handle. But then, a file handle doesn't behave exactly like standard in or standard out, either (last I checked, Perl 5 won't do anything useful if you say seek STDIN, 0, SEEK_END). -- Jonathan Dataweaver Lang
[S03] Negation metaoperator
Generalize the negated relational operators to apply to any infix operator that returns a boolean. In terms of the standard operators, this will add || ^^ // and or xor err to the family that is implicitly equipped with logical negations. For consistency's sake, you may also want to define junctive operators ! !| !^. '!|' corresponds with the list-op 'none', although I can think of no intuitive list-ops for the other two; we might have to settle for '!all' and '!one'. If so, consider '!any' as a synonym for 'none', much like '!eq' and 'ne' are synonyms for each other. Or just reduce the operators: [!] and [!^]. Personally, I find '!all' and '!one' to be more legible; but YMMV. -- Jonathan Dataweaver Lang
[S03] Range Semantics
Inspired by the new array indexing syntax from S09. Modify S03 (under Range Semantics) so that if a Range is operating in a bounded space, a 'whatever' star as the starting or ending point maps to the lower or upper bound: my enum Months «:Jan(1) Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec» Mar..*# same as Mar..Dec *..Mar# same as Jan..Mar This makes Ranges in an array index a natural outgrowth of the standard Range semantics, rather than being an exceptional case. -- Jonathan Dataweaver Lang
Re: [svn:perl6-synopsis] r14359 - doc/trunk/design/syn
[EMAIL PROTECTED] wrote: +Arrays may also be defined with a mixture of fixed and autoextending +dimensions: + +my @calendar[12;*;24]; # Month dimension unlimited + + Move this out of the section on fixed-length arrays and into the section on multidimensional arrays; it fits most naturally as the second paragraph of the latter section. -- Jonathan Dataweaver Lang
Enhanced enumerations
Some (many?) enumerations represent cycles, where incrementing from the last element takes you back to the first: the seasons, the months, the days of the week, the hues, etc. How hard would it be to write a module that lets you say something like: enum weekdays is cycle Sun Mon Tue Wed Thu Fri Sat So that Sat++ eqv Sun (and a resumable control exception is thrown so that you can do something fancy whenever you return to the start of the cycle)? Likewise, how would one be able to legally say: enum seasons spring summer autumn|fall winter That is, to use a junction in the definition in order to provide synonyms for one of the enumerated values? -- Jonathan Dataweaver Lang
Re: [S09] Whatever indices and shaped arrays
OK: before I submit a patch, let me make sure that I've got the concepts straight: @x[0] always means the first element of the array; @x[-1] always means the last element of the array; @x[*+0] always means the first element after the end of the array; @x[*-1] always means the first element before the beginning of the array. That is, the indices go: ..., *-3, *-2, *-1, 0, 1, 2, ..., -3, -2, -1, *+0, *+1, *+2, ... ^ ^ | | first last As well, a Whatever in square braces is treated as an array of the valid positions; so @x[*] is equivalent to @x[0..-1]. If you want to use sparse indices and/or indices that begin somewhere other than zero, access them using curly braces. Consider an array with valid indices ranging from -2 to +2: @x{-2} means element -2, which would be equivalent to @x[0]; @x{+2} means element 2, which would be equivalent to @x[-1]. Likewise, @x{0} is the same as @x[2], @x{-3} is the same as @x[*-1], @x{+3} is the same as @x[*+0], and so on. If @y has a series of five indices that start at 1 and double with each step, then @y{1} will be the same as @y[0]; @y{4} will be the same as @y[2], and so on. A Whatever in curly braces is treated as an array of the valid index names; so @x{*} means @x{-2..+2}, and @y{*} means @y{1, 2, 4, 8, 16}. Because it is treated as an array, individual index names can be accessed by position: @x{*[0]} is a rather verbose way of saying @x[0]. This lets you embed ordinal indices into slices involving named indices. Conversely, using *{...} inside square braces lets you embed named indices into slices involving ordinal indices: @x[*{-2}] is the same as @x{-2}. Multidimensional arrays follow the above conventions for each of their dimensions; so a single-splat provide a list of every index in a given dimension, a 0 refers to the first index in that dimension, and so on. A double-splat extends the concept to a multidimensional list that handles an arbitrary number of dimensions at once. -- Commentary: I find the sequence of ordinals outlined above to be a bit messy, especially when you start using ranges of indices: you need to make sure that @x[0..-1] dwims, that @x[-1..(*+0)] dwims, that @x[(*-2)..(*+3)] dwims, and so on. This is a potentially very ugly process. As well, the fact that @x[-1] doesn't refer to the element immediately before @x[0] is awkward, as is the fact that @x[*-1] doesn't refer to the element immediately before @x[*+0]. IMHO, it would be cleaner to have @x[n] count forward and backward from the front of the array, while @x[*+n] counts forward and backward from just past the end of the array: ..., -3, -2, -1, 0, 1, 2, ..., *-3, *-2, *-1, *+0, *+1, *+2, ... ^^ || first last So perl 5's $x[-1] would always translate to @x[*-1] in perl 6. Always. Likewise, @x[+*] would be the same as @x[*+0]. (In fact, the semantics for @x[*+n] follows directly from the fact that an array returns the count of its elements in scalar context.) And @x[*] would be the same as @x[0..^*] or @x[0..(*-1)]. You would lose one thing: the ability to select an open-ended Range of elements. For a five-element list, @x[1..^*] means @x[1, 2, 3, 4], not @x[1, 2, 3, 4, 5, 6, 7, 8, ...]. Technically, one could say @x{+*} to reference the index that coincides with the number of indices; but it would only be useful in specific cases, such as referencing the last element of a one-based contiguous array. -- Jonathan Dataweaver Lang
Re: [S09] Whatever indices and shaped arrays
Larry Wall wrote: I like it. I'm a bit strapped for time at the moment, but if you send me a patch for S09 I can probably dig up a program to apply it with. :) Could someone advise me on how to create patches? -- Jonathan Dataweaver Lang
Re: for ... else
Larry Wall wrote: On Mon, Mar 05, 2007 at 04:13:16PM +1030, Tom Lanyon wrote: : Sounds like the following will work, but it doesn't seem 'nice'. : : for @invoice : { : .process; : 1; : } or fail 'No invoices to process'; Still think if there's no invoices it logically should be tested first. If you don't want to repeat mentioning the array, how 'bout: @invoice or fail 'No invoices to process' == for @() { .process } or equivalently @invoice or fail 'No invoices to process' == map { .process } all assuming you don't like my original for @invoice || fail 'No invoices to process' { .process } These should work, as long as you don't replace fail 'no invoices to process' with something that returns a non-empty list. That said, you could: { for = || fail 'no input' { .process } CATCH { do_something_else if 'no input' } } ...where the 'no input' string is there only so that failures generated by .process will propagate correctly. -- This solution isn't generalizable beyond for, though: you wouldn't be able to use it for while, until, or loop, all of which could potentially follow the logic of do something special if the loop fails to run even once. Hmm... while test - $result { do_something; FIRST { do_something_else unless $result } } ...except that I don't think that FIRST would run unless $result is true. I suppose that you _could_ write: if test { repeat { do_something } while test } else { do_something_else } You'd be having to spell out the test twice, though. -- Jonathan Dataweaver Lang
Re: for ... else
herbert breunung wrote: Von: Thomas Wittek [EMAIL PROTECTED] That's, well, elegant! Yes. Because and but it's tricky. Nothing where I'd say wow, thats an easy solution to my problem!. It's a bit complicated, because you have to understand and combine several concepts. That's elegant. But not easy, I think. I think it's not simple enough for this simple kind of problem. exactly, my full support to thomas with this, perl was always about keep simple things simple too. Seconded. I would favor allowing an else block to be attached following any loop block, with the semantics being that the else block only gets triggered if the loop block doesn't run at least once. I'd do this instead of a block trait (such as FIRST or LAST) because of the either-or relationship between the loop block and the else block. -- Jonathan Dataweaver Lang
Re: for ... else
Jonathan Lang wrote: Seconded. I would favor allowing an else block to be attached following any loop block, with the semantics being that the else block only gets triggered if the loop block doesn't run at least once. I'd do this instead of a block trait (such as FIRST or LAST) because of the either-or relationship between the loop block and the else block. The one exception would be the repeat statement, because attaching an else block to it would be as confusing semantically as attaching an else block to an unless statement. -- Jonathan Dataweaver Lang
Re: for ... else
Daniel Brockman wrote: What about this? given @foo { for $_ - $x { ... } when .empty { ... } } You can reverse the order if you want: given @foo { when .empty { ... } for $_ - $x { ... } } Actually, you'd be better off using the second order; the when statement would drop you out of the given block if triggered, and you'd never get to the loop. In the first order, you'd be triggering both the loop and the when every time the given block executes. -- Jonathan Dataweaver Lang
Re: for ... else
Rick Delaney wrote: Smylers wrote: for @invoice { .process; } or fail 'No invoices to process'; If that actually works then I'm happy. It's dependent on .process not returning a false on the final iteration. -- Jonathan Dataweaver Lang
statement modifiers
The text of S02, S03, and S04 still contain references to the now-defunct statement_modifier grammatical category. Also, what's the reasoning behind specifically disallowing _all_ statement modifiers to do blocks (as opposed to forbidding just looping statement modifiers)? Is this legacy from when the distinction wasn't being made, or is there still a valid reason for forbidding conditional modifiers? Finally: when used as a statement modifier, is given considered to be conditional or looping? (Gut instinct: conditional.)
Compound grammar
AFAICT, there's nothing in the documentation to explain how one would define a statement or operator with syntax along the lines of if ... else ... or ... ?? ... :: ... Admittedly, the only cases I know of where this is still an issue are the two listed above: for statements, all other perl 5 parallels have been replaced by the use of closure traits; and the operator listed above is the only more-than-binary operator that I've ever heard of which uses different delimiters. That said, for the sake of future customization, it would be nice to have a way to do these things. (Or is this what macros are for?) In the latter case, I find myself thinking about expanding on infix: to allow for a list of tokens, much like circumfix: does: infix:?? :: ($condition, $true, $false) # $condition ?? $true :: $false ...and I'm wondering if something like this could be done in the former case as well: statement_control:if else ($condition, true, false?) # if $condition { ... } else { ... } Although this wouldn't cleanly handle an if ... elsif ... elsif ... else ... statement. -- Jonathan Dataweaver Lang
Re: statement modifiers
Larry Wall wrote: Jonathan Lang wrote: : Larry Wall wrote: : : Finally: when used as a statement modifier, is given considered to : : be conditional or looping? (Gut instinct: conditional.) : : Why does it have to be one or the other? It's just a topicalizer. : : One implication of replacing statement_modifier with : statement_mod_cond and statement_mod_loop is that every statement : modifier has to be defined as one or the other. Ah, in that sense 'given' is currently considered a loop, and 'when' is considered a conditional, so it's legal to say say halt when 42 given $answer; That follows from the recent decision to allow a condition inside a loop to make it easy to write list comprehensions. (The same decision that turned 'for' into a map clone, by the way, and made 'if' return () when false, at least in the absence of an 'else'.) Nice. Thank you. -- Jonathan Dataweaver Lang
Re: [S09] Whatever indices and shaped arrays
David Green wrote: On 2/24/07, Jonathan Lang wrote: In effect, using * as an array of indices gives us the ordinals notation that has been requested on occasion: '*[0]' means 'first element', '*[1]' means 'second element', '*[-1]' means 'last element', '*[0..2]' means 'first three elements', and so on - and this works regardless of what the actual indices are. Using * that way works, but it still is awkward, which makes me think there's something not quite dropping into place yet. We have the notion of keyed indexing via [] and counting/ordinal indexing via [*[]], which is rather a mouthful. So I end up back at one of Larry's older ideas, which basically is: [] for counting, {} for keys. What if you want to mix the two? I want the third element of row 5. In my proposal, that would be @array[5, *[2]]; in your proposal, there does not appear to be a way to do it. Unless the two approaches aren't mutually exclusive: @array{5, *[2]}. That is, allow subscripted Whatevers within curly braces for to enable the mixing of ordinals and keys. Since this is an unlikely situation, the fact that nesting square braces inside curly braces is a bit uncomfortable isn't a problem: this is a case of making hard things possible, not making easy things easy. What about shaped arrays? A shape means the indices *signify* something (if they didn't, you wouldn't care, you'd just start at 0!). So they really are *keys*, and thus should use a hash (which may not use any hash tables at all, but it's still an associative array because it associates meaningful keys with elements). I'm not put off by calling it a hash -- I trust P6 to recognise when I declare a hash that is restricted to consecutive int keys, is ordered, etc. and to optimise accordingly. The one gotcha that I see here is with the possibility of multi-dimensional arrays. In particular, should multi-dimensional indices be allowed inside square braces? My gut instinct is yes; conceptually, the third row of the fourth column is perfectly reasonable terminology to use. The thing that would distinguish [] from {} would be a promise to always use zero-based, consecutive integers as your indices, however many dimensions you specify. With that promise, you can always guarantee that the wrap-around semantics will work inside [], while nobody will expect them to work inside {}. In short, the distinction being made here isn't unshaped vs. shaped; it's ordinal indices vs. named indices, or ordinals vs. keys. That said, note that - in the current conception, at least - one of the defining features of a shaped array is that trying to access anything outside of the shape will cause an exception. How would shapes work with the ordinals-and-keys paradigm? First: Ordinals have some severe restrictions on how they can be shaped, as specified above. The only degrees of freedom you have are how many dimensions are allowed and, for each dimension, how many ordinals are permitted. Well, also the value type (although the key type is fixed as Int where 0..*. So you could say something like: my @array[2, 3, *] ...which would mean that the array must be three-dimensional; that the first dimension is allowed two ordinals, the second is allowed three, and the third is allowed any number of them - i.e., 'my @array[^2; ^3; 0..*]' in the current syntax. Or you could say: my @array[2, **, 2] ...meaning that you can have any number of dimensions, but the first and the last would be constrained to two ordinals each: 'my @array[^2; **; ^2]'. Note the use of commas above. Since each dimension can only take a single value (a non-negative integer), there's no reason to use a multidimensional list to define the shape. Personally, I like this approach: it strikes me as being refreshingly uncluttered. Furthermore, you could do away with the notion of shaped vs. unshaped: just give everything a default shape. The default shape for arrays would be '[*]' - that is, one dimension with an indeterminate number of ordinals. Meanwhile, shapes for {} would continue to use the current syntax. '[$x, $y, $z]' would be nearly equivalent to '{0..^$x; 0..^$y; 0..^$z}'. If there are no meaningful lookup keys, if all I can do to get through my list is count the items, then an array is called for, and it can work in the usual way: start at 0, end at -1. It is useful to be able to count past the ends of an array, and * can do this by going beyond the end: *+1, *+2, etc., or before the beginning: *-1, *-2, etc. (This neatly preserves the notion of * as all the elements -- *-1 is the position before everything, and *+1 is the position after everything else.) Regardless, I would prefer this notion to the offset from the endpoint notion currently in use. Note, however, that [*-1] wouldn't work in the ordinals paradigm; there simply is nothing before the first element. About the only use I could see for it would be to provide an assignment equivalent of unshift: '@array[*-1] = $x' could
Re: What criteria mark the closure of perl6 specification
Smylers wrote: Richard Hainsworth writes: When does the specification of perl6 come to an end? At a guess: when it's implemented. Many of the recent changes have been made by Larry in response to his trying to write the grammar, and encountering problems. With all due respect: Once the grammar is written, what's left to do in terms of finalizing the Perl 6.0 specification? Surely we don't need to wait for the Perl 6 implementors to finish their work before declaring 6.0 to be fully specified (and getting on with the business of working on 6.1 features)? Admittedly, the best way to know if something is implementable is to implement it; but I doubt that it's the only way. There are still some 'hey wouldn't it be great if ...' threads on this list, proposing brand new features, but nowhere near as many as there used to be. And at least some of us are trying to discourage such things, hoping to deflect them away from taking Larry's time away from getting finished synthesizing what we already have -- especially in the case of things which could easily be provided by a module. I submit that you'll have even more luck discouraging such things if you can give a reasonable and believable timeline as to when the 6.0 spec will be ready and perl 6.1 features can start being considered. -- Jonathan Dataweaver Lang
Re: [S09] Whatever indices and shaped arrays
Jonathan Lang wrote: Larry Wall wrote: : If you want the last index, say '*[-1]' instead of '* - 1'. : If you want the first index, say '*[0]' instead of '* + 0'. So the generic version of leaving off both ends would be *[1]..*[-2] (ignoring that we'd probably write *[0]^..^*[-1] for that instead). Correct - although that assumes that the indices are consecutive (as opposed to, say, 1, 2, 4, 8, 16...); this version of * makes no such assumption. Another thought: '*[1..-2]' or '*[0^..^-1]' would do the trick here - except for the fact that the Range 1..-2 doesn't normally make sense. Suggestion: when dealing with Ranges in unshaped arrays, negative endpoints are treated like negative indices (i.e., '$_ += [EMAIL PROTECTED]'). In effect, using * as an array of indices gives us the ordinals notation that has been requested on occasion: '*[0]' means 'first element', '*[1]' means 'second element', '*[-1]' means 'last element', '*[0..2]' means 'first three elements', and so on - and this works regardless of what the actual indices are. Like I said, I tend to miss intricacies. For instance, I never considered what would be involved in applying a subscriptor to a multidimensional Whatever (e.g., what can you do with '**[...]'?). Part of that is that I'm not yet comfortable with multidimensional slices (or arrays, for that matter); when reading about them, I keep on getting the feeling that there's something going on here that the big boys know about that I don't - implicit assumptions, et al. I think I've got a better grip on it now. Here's how I understand it to work: A multidimensional array is defined by providing a list of lists, each giving all of the valid indices along one axis (i.e., in one dimension). The overall shape of the array will be rectangular, or a higher-dimensional analog of rectangular. There may be gaps in the indices (in which case the array is a sparse array as well as a multidimensional array); but if there are, the gaps also conform to the rectangular structure: it's as if you carved a solid rectangle into two or more rectangular pieces and pulled them apart a bit. That is, @array[-1, +1; -1 +1] is effectively a 2x2 square array with valid x-indices of -1 and +1 and valid y-indices of -1 and +1. To access an element in a multidimensional array, use a semicolon-delimited list of indices in the square braces: '@cube[1;1;1]' will access the center element of a [^3;^3;^3] shaped array, while '@array[*;*;1]' will access a 3x3 horizontal slice of it. When putting together a list literal, things work a bit differently. Create a one-dimensional literal by means of a comma-delimited list of values; create a two-dimensional literal by means of a semicolon-delimited list of comma-delimited lists of values: 1, 2, 3 # one-dimensional list literal with a length of 3 (1, 2, 3; 4, 5, 6) # two-dimensional list literal with a length of 2 and a width of 3. (1; 2; 3) # two-dimensional list literal with a length of 3 and a width of 1. I would guess that you would build higher-dimensional literals by nesting parentheses-enclosed semicolon-delimited lists: (( 0, 1; 2, 3; 4, 5; 6, 7; 8, 9); (10, 11; 12, 13; 14, 15; 16, 17; 18, 19); (20, 21; 22, 23; 24, 25; 26, 27; 28, 29)) # three-dimensional list literal with a length of 3, a width of 5, and a height of 2. The outermost set of semicolons delimits the first dimension, and the commas delimit the last dimension. That is, semicolon-delimited lists nest, and comma-delimited lists flatten. Furthermore, the list literal gets assigned to the array by means of ordinal coordinates: my @cube[-1..+1; -1..+1; -1..+1] = ((1, 2, 3; 4, 5, 6; 7, 8, 9); (10, 11, 12; 13, 14, 15; 16, 17, 18); (19, 20, 21; 22, 23, 24; 25, 26, 27)); would be equivalent to my @cube[1..3; 1..3; 1..3]; @cube[**[0; **]] = (1, 2, 3; 4, 5, 6; 7, 8, 9); @cube[**[0; **]] = (10, 11, 12; 13, 14, 15; 16, 17, 18); @cube[**[0; **]] = (19, 20, 21; 22, 23, 24; 25, 26, 27); or my @cube[1..3; 1..3; 1..3]; @cube[**[0; 0; *]] = 1, 2, 3; @cube[**[0; 1; *]] = 4, 5, 6; @cube[**[0; 2; *]] = 7, 8, 9; @cube[**[1; 0; *]] = 10, 11, 12; @cube[**[1; 1; *]] = 13, 14, 15; @cube[**[1; 2; *]] = 16, 17, 18; @cube[**[2; 0; *]] = 19, 20, 21; @cube[**[2; 1; *]] = 22, 23, 24; @cube[**[2; 2; *]] = 25, 26, 27; or my @cube[1..3; 1..3; 1..3]; @cube[**[0; 0; 0]] = 1; @cube[**[0; 0; 1]] = 2; @cube[**[0; 0; 2]] = 3; @cube[**[0; 1; 0]] = 4; @cube[**[0; 1; 1]] = 5; @cube[**[0; 1; 2]] = 6; ... where say @cube[**[1; 1; 1]]; would be equivalent to say @cube[0; 0; 0]; Do I have the general idea? -- Jonathan Dataweaver Lang
[S09] Whatever indices and shaped arrays
From S09: When you use * with + and -, it creates a value of Whatever but Num, which the array subscript interpreter will interpret as the subscript one off the end of that dimension of the array. Alternately, *+0 is the first element, and the subscript dwims from the front or back depending on the sign. That would be more symmetrical, but makes the idea of * in a subscript a little more distant from the notion of 'all the keys', which would be a loss, and potentially makes +* not mean the number of keys. If '*+0' isn't the first element, then '*+$x' is only meaningful if $x 0. That said, I think I can do one better: Ditch all of the above. Instead, '*' always acts like a list of all valid indices when used in the context of postcircumfix:[ ]. If you want the last index, say '*[-1]' instead of '* - 1'. If you want the first index, say '*[0]' instead of '* + 0'. So the four corners of a two-dimensional array would be: @array[ *[0]; *[0] ]; @array[ *[-1]; *[0] ]; @array[ *[0]; *[-1] ]; @array[ *[-1]; *[-1] ]; The only thing lost here is that '@array[+*]' is unlikely to point just past the end of a shaped array. But then, one of the points of shaped arrays is that if you point at an invalid index, you get a complaint; so I don't see why one would want to knowingly point to one. -- Also, has the syntax for accessing an array's shape been determined yet? If not, I'd like to propose the following: @array.shape returns a list of lists, with the top-level list's indices corresponding to the dimensions of the shape and each nested list containing every valid index in that dimension. In boolean context, the shape method returns true if the array is shaped and false if not - though an unshaped array will otherwise pretend to be a one-dimensional, zero-based, non-sparse, shaped array. So: @array.shape[0][2] # the third valid index of the first dimension of the shape @array.shape[-1][0] # the first valid index of the last dimension of the shape @array.shape[1] # every valid index of the second dimension of the shape @array.shape[1][*] # same as @array.shape[1] [EMAIL PROTECTED] # is this a shaped array? exists @array.shape[2] # does the array have a third dimension? exists @array.shape[3][4] # does the fourth dimension have a fifth element? [EMAIL PROTECTED] # how many dimensions does the shape have? [EMAIL PROTECTED] # how many indices does the first dimension have? If we use this notation, then @array[ *; * ] is shorthand for @array[ @array.shape[0]; @array.shape[1] ] -- Jonathan Dataweaver Lang
Re: [S09] Whatever indices and shaped arrays
Larry Wall wrote: On Fri, Feb 23, 2007 at 10:49:34AM -0800, Jonathan Lang wrote: : That said, I think I can do one better: : : Ditch all of the above. Instead, '*' always acts like a list of all : valid indices when used in the context of postcircumfix:[ ]. Ooh, shiny! Or at least, shiny on the shiny side... Thank you... : If you want the last index, say '*[-1]' instead of '* - 1'. : If you want the first index, say '*[0]' instead of '* + 0'. So the generic version of leaving off both ends would be *[1]..*[-2] (ignoring that we'd probably write *[0]^..^*[-1] for that instead). Correct - although that assumes that the indices are consecutive (as opposed to, say, 1, 2, 4, 8, 16...); this version of * makes no such assumption. I do find myself wondering what *[-1] would be for an infinite array, such as @nums[0..*:by(2)]. One possible answer: Inf. Another possible answer: the shape sets limits on the indices; it does not set requirements. For instance: my @nums[0..*:by(2)]; @nums[2 * $_] = $_ for 0..5]; say @nums[ *[-1] ]; # same as 'say @nums[10];' @nums[42] = 21; say @nums[ *[-1] ]; # same as 'say @nums[42];' say @nums[ *[-2] ]; # same as 'say @nums[40];' - whatever that means. : Also, has the syntax for accessing an array's shape been determined : yet? If not, I'd like to propose the following: : : @array.shape returns a list of lists, with the top-level list's : indices corresponding to the dimensions of the shape and each nested : list containing every valid index in that dimension. In boolean : context, the shape method returns true if the array is shaped and : false if not - though an unshaped array will otherwise pretend to be a : one-dimensional, zero-based, non-sparse, shaped array. That's more or less how I was thinking of it, though I hadn't got as far as boolean context. I'm still debating the boolean context myself. I _think_ it will work; but I have a tendency to miss intricacies. You might instead want to require someone to explicitly check for definedness or existence instead of merely truth; or you might not. : If we use this notation, then : : @array[ *; * ] : : is shorthand for : : @array[ @array.shape[0]; @array.shape[1] ] Note also that multidimensional whatever gives us @array[ ** ] to mean @array[ @@( @array.shape[*] ) ] or some such. Like I said, I tend to miss intricacies. For instance, I never considered what would be involved in applying a subscriptor to a multidimensional Whatever (e.g., what can you do with '**[...]'?). Part of that is that I'm not yet comfortable with multidimensional slices (or arrays, for that matter); when reading about them, I keep on getting the feeling that there's something going on here that the big boys know about that I don't - implicit assumptions, et al. Though ** might want to be even smarter than that if we want @array[ 0; **; 42] to dwim. That'd have to turn into something like: @array[ 0; @@( @array.shape[*[1]..*[-2]] ); 42 ] Also +** might return a shape vector, or maybe +«**. If by shape vector you mean something that says the array has a length of 5, a width of 3, and a height of 2, +«** would seem to be the more appropriate syntax. Why you'd want that inside an array's subscriptor is beyond me, for a similar reason to +*. But that's what the logic of the syntax gives. But I _could_ see using '[EMAIL PROTECTED]' to get an array's measurements. Hmm... my @@square = (1, 2; 3, 4); say +@@square; # say what? '2', as in 2 dimensions? Or '4', as in 4 items? Answer that, and you'll know what +** would give you. -- BTW: could the parser handle the following? @array[ *[0] * 2; 2 ** **[ [;] 0 x *] ] -- Jonathan Dataweaver Lang
Y not
Luke Palmer wrote: % as the mod operator is a good example of what you describe. There's no need for mod to be a symbolic operator: when you read 5 % 3 you say 5 mod 3. Why would we not write 5 mod 3: it is just as obvious what and how we are doing this operation. And % is uncommon enough that no huffman coding principals may apply. The only thing we have here is cultural baggage. I can think of one case where % would be preferable to 'mod': when you want to ask for a 'remainder' in the form of a non-integer. That is, '4.5 % 3' returns 1.5 (and parallels '/'), while '4.5 mod 3' returns 1 (and parallels 'div'). That said, if it's decided that the latter definition is inappropriate or unnecessary, then I'd be all in favor of completely dropping '%' in favor of 'mod' for the former definition. But I do think that Perl 6 is gathering some operator bloat, in that we are defining symbols for things that are not adding to the obviousness of the code. They may not be taking away, but all else being equal, we should choose the option of lower abstraction Hear, hear. Huffman coding is all well and good; but not when taken to the point that it starts interfering with legibility. That said, six-character words are the longest that I'd want to see, and I'd much prefer three- or four-character words if reasonable. Mind you, there are some cases where I'd like to see the symbol-based operators supplemented by name-based ones instead of being replaced by them. For instance, I could live with a few more word-based contextualizers: 'scalar' (same as '$:'), 'hash' (same as '%:'), and 'nested' (same as '@@:'); but I wouldn't want to remove '$:', '%:', or '@@:'. The only reason I don't also suggest 'sub' to supplement ':' is the confusion that could arise between contextualization and declaration. -- Jonathan Dataweaver Lang
Re: Y not
Thomas Wittek wrote: Larry Wall schrieb: I think the ¥ and Y operators are going to have to change to something else. Very probably I missed something as I'm only a distant observer of the Perl6 development: Why not just call it zip?! There is a function called zip, wouldn't it be possible to create an operator with the same name? zip(@a; @b) - function @a zip @b - operator Or would that lead to grammar ambiguities, that are impossible to resolve? more generally, could we say that any function that has no parameters other than a list - i.e., :(*@) - automatically gets a list-infix operator form as well? e.g.: my sub zip([EMAIL PROTECTED]) { ... } could be called with zip (@a; @b; @c) or @a zip @b zip @c -- Jonathan Dataweaver Lang
Re: Y not
Damian Conway wrote: I'd be more inclined to go the other way and say that you can transform any list infix form to the corresponding function form: @a ZZ @b ZZ @c - zip operator ZZ(@a; @b; @c) - zip function @a XX @b XX @c - cross operator XX(@a; @b; @c) - cross function @a X*X @b X*X @c - cross product operator X*X(@a; @b; @c) - cross product function @a MM @b MM @c - minmax operator MM(@a; @b; @c) - minmax function Can't you already do this, with square braces? @a XX @b XX @c [XX] (@a; @b; @c) etc? Or am I missing something about the reduction metaoperator? I'm not strongly opposed to this, unless they're the *only* forms of the functions. If the very much more readable 'zip' and 'minmax' are to be replaced with 'ZZ' and 'MM', then I think that's a serious step backwards in usability. Hear, hear. I very much prefer 'zip' and 'minmax' to 'ZZ' and 'MM'. -- Jonathan Dataweaver Lang
Re: Negative fraction subscripts
Larry Wall wrote: TSa wrote: : Luke Palmer wrote: : When do we do integer/rational math and when do we do floating point math? : : Since we have now flooring semantics on modulus and division I wonder : how the coercion of nums to ints takes place. Does it also use floor? : E.g. is @array[-0.3] accessing the last element or is it truncating : to zero and indexing from the front? Perl 5 truncates, I believe. One could argue that floor is better behaved, but the 0/-1 transition in subscripts is totally cork-brained anyway, so I don't think it really matters if our numbers behave when wrapping around the end of an array. Perhaps. Then again, it isn't the remainder that would define which element you're looking at in this case; it would be the integer portion. And if I understand flooring semantics properly, -0.3 div 1 == -1. Also, -0.3 mod 1 == 0.7; right? Or is that the difference between mod and %: the former returns the remainder as an integer (e.g., '0'), while % return the remainder as a Num (e.g., '0.7')? With truncating semantics, -0.3 div 1 == 0, and -0.3 % 1 == -0.3. I think that TSa has a point here: converting from Num to Int should always be equivalent to saying 'Num div 1'. Which means that if you ever override div to provide different semantics by default (e.g., Euclidean), you would also change the semantics of the Num-to-Int coercion. Interestingly, negative fractions, if truncated, would give us a way to talk about the element off the end of the array, presuming that the endness of the subscript is determined from the sign before it is truncated: push @array, 42; @array[-0.1] = 42; # same thing @array[-0.0] = 42; # same thing? Eh. A neat little bell-and-whistle, but more confusing than it is useful. But it probably doesn't matter. If one really wants infinite modular arrays, then you probably just say @array[$x % @array] or some such, which gives you the floor semantics. True enough. I'd suggest doing this implicitly (with 'mod' instead of '%'), ensuring that virtually every index maps to an existing element; but then you'd lose the ability to append to an array by assigning to '@[EMAIL PROTECTED]' (not that I'd do this; but I can see why some might prefer this idiom to being pushy). It's the sort of thing that I could see using a trait for: 'my @array but oroborus' would invoke an implicit modulus on the index, while standard arrays would not. Likewise, those who don't want the backward-indexing semantics could remove them by saying something like 'my @array but ray', causing negative indices to throw errors instead. Ideally, applying both would cause negative indices to choke, but would wrap too-large positive indices back to the beginning of the array. -- Jonathan Dataweaver Lang