Re: CALL-ME vs. Callable
So what is the assuming method, and why is it in a callable role? What was the logic behind that decision? On Nov 14, 2016 1:38 PM, "Brandon Allbery" <allber...@gmail.com> wrote: > This should probably have been cc-d to the list. > > Callable claims to be the thing we want. What it actually is, is a mix-in > that adds the assuming method. I am not sure these can be conflated. > > Note that the current docs actually do claim it is what I want. This is > because I first brought this up in IRC while the documentation for > Callable was being written, and it got modified to match my then current > musings because nobody who actually works on the spec was around. I had in > fact specified that this was a "would be nice" but that I wasn't sure if it > would actually work; I have since concluded that it likely won't, and needs > to be a distinct role. Which is part of why I brought this up: the current > doc does not match what currently happens, and may not actually be > implementable without breaking the spec (that is, 6.d would have a > fundamental conflict with 6.c over the meaning of Callable). > > On Mon, Nov 14, 2016 at 4:30 PM, Jon Lang <datawea...@gmail.com> wrote: > >> Okay, let's go with that. What does Callable do, and why is it called >> that? >> >> On Nov 14, 2016 1:09 PM, "Brandon Allbery" <allber...@gmail.com> wrote: >> >>> >>> On Mon, Nov 14, 2016 at 3:42 PM, Aaron Sherman <a...@ajs.com> wrote: >>> >>>> I do think, though that if the concern is really with "the 4 cases >>>> when nqp hauls a CALL-ME out of its bowels" then that's what should be >>>> addressed... >>>> >>> >>> The main addressing of that is some kind of role to abstract it >>> properly. I just think the current situation is bad and even if we come up >>> with a name for the new role, it's still going to be confusing ("ok, why do >>> we have both Callable and Invokable? ...uh wait, Callable means *what* >>> exactly?"). >>> >>> >>> -- >>> brandon s allbery kf8nh sine nomine >>> associates >>> allber...@gmail.com >>> ballb...@sinenomine.net >>> unix, openafs, kerberos, infrastructure, xmonad >>> http://sinenomine.net >>> >> > > > -- > brandon s allbery kf8nh sine nomine > associates > allber...@gmail.com > ballb...@sinenomine.net > unix, openafs, kerberos, infrastructure, xmonad > http://sinenomine.net >
Re: Anonymous multi-subs
On Wednesday, June 24, 2015, yary not@gmail.com wrote: Now that I've thought about it for 90 seconds (not fully-formed idea), if one were to have an anonymous multi-sub, it ought to be constructed from a list of *signature*, *body *pairs. And/or, any non-finalized sub could have a method to add another *signature, body* to its dispatch list. apologies if this discussion is already captured in a design doc, I am posting this without having read much of the past. Or, in the body, be able to examine the actual signature passed in and decide what to do based on that, That [i]could[/i] be done using a given/when structure, which would be equivalent to a list of signature/body pairs. -- Jonathan Dataweaver Lang
Re: How to make a new operator.
On Thu, Mar 22, 2012 at 9:07 AM, Bruce Gray bruce.g...@acm.org wrote: On Mar 21, 2012, at 11:49 PM, Jonathan Lang wrote: 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? In real life, you would just use this: my @squares = map { $_ * $_ }, 0..10; or, for an infinite list, use a binding instead of an assignment: my @squares := map { $_ * $_ }, 0..*; True enough. But you were asking about ... specifically :^) Yes, I was. On freenode/#perl6, I was pointed to part of the spec that I had overlooked. The sequence operator is defined in S03: http://perlcabal.org/syn/S03.**html#List_infix_precedencehttp://perlcabal.org/syn/S03.html#List_infix_precedence Buried in its definition is this gem: http://perlcabal.org/syn/S03.**html#line_1884http://perlcabal.org/syn/S03.html#line_1884 The function may also be slurpy (n-ary), in which case all the preceding values are passed in (which means they must all be cached by the operator, so performance may suffer, and you may find yourself with a space leak). Interesting; it never occurred to me to try to retrieve the current index by slurping in all of the previous elements and counting them. After writing all the above, it occurred to me that the use of @_ should implicitly define a closure as slurpy/n-ary. That would remove the need for the arrow, and make the code much less ugly. Also, the first value (0) might be unnecessary. The spec says that it should not be required when the closure is 0-ary, but I think that should also be true for slurpy/n-ary closures. Agreed: starting values should only be mandatory when dealing with a step function that definitely requires them. These work in Niecza: my @squares := { @_ ** 2 } ... *; And this is rather elegant, syntactically (though not so much in the performance department). -- Jonathan Dataweaver Lang
dimensionality in Perl 6
Here's my proposal for how to handle dimensionality in Perl 6: Create a units trait that is designed to attach to any Numeric object. Dimensional information gets stored as a baggy object - that is, something that works just like a Bag, except that the count can go negative. (I don't know if the count should be a signed integer or a Num; what happens in dimensional analysis when you try to take the square root of two inches?) Overload the Numeric operators to properly track the units as well as performing their normal activities. Add one or two methods that allow you to easily extract the raw number and/or the units. For now, unit conversions are always handled manually, and the units themselves are completely arbitrary At some later date we might consider adding a robust database of units and conversion rates; but that's a complication that we needn't deal with up front. Indeed, it might work best as a module to be included by those who want the added tools. Regardless, such a module should not interfere in the ability to use made-up units on the fly; instead, it should provide additional details for units that have been properly registered (such as what kind of value is being measured, which measurement system it's a part of, what the conversion rates are, and what synonyms exist for it). The goal should be to enhance, not restrict. If this is implemented, Duration should be an alias for something to the effect of Num but unitssecond. Otherwise, Instant and Duration remain unchanged. Thoughts? -- Jonathan Dataweaver Lang
Re: dimensionality in Perl 6
On Thu, Nov 18, 2010 at 8:25 PM, Carl Mäsak cma...@gmail.com wrote: Jon (): Here's my proposal for how to handle dimensionality in Perl 6: [...] Thoughts? The idea has come up before, everyone thinks that Perl 6 and unit handling are a good fit for each other, and we're basically waiting for someone to write such a module. Incidentally, your phrase a complication that we needn't deal with up front is exactly why there's no pressing need to put this in Perl 6 core (fsvo core). I'm suggesting this because the recent thread about Duration indicates to me that there _is_ a need to put at least a minimally-featured unit handling system into the core, if for no other reason than to ensure that Durations will be part of said system. The trick is to come up with something that's simple enough that including it in the core won't unduly delay release of Perl 6, but robust enough that we can build on it after release. See also the Physical::Unit example in a blog post of mine, for an example of how postfix ops can be used to mark the units: http://strangelyconsistent.org/blog/6-builtins-in-perl-6-that-you-never-knew-you-needed Nice. 5 sec definitely beats 5 but unitssec for legibility, and would be a very nice way of generating Durations on the fly. -- Jonathan Dataweaver Lang
Re: dimensionality in Perl 6
Buddha Buck wrote: Jon Lang wrote: Here's my proposal for how to handle dimensionality in Perl 6: Create a units trait that is designed to attach to any Numeric object. Dimensional information gets stored as a baggy object - that is, something that works just like a Bag, except that the count can go negative. (I don't know if the count should be a signed integer or a Num; what happens in dimensional analysis when you try to take the square root of two inches?) Overload the Numeric operators to properly track the units as well as performing their normal activities. Add one or two methods that allow you to easily extract the raw number and/or the units. An added complication is dimensionality. ergs, joules, btu and eV are all units of energy, and it isn't unreasonable to want to add or subtract energies of different units (my house used (100 therm + 8000kWh) of energy last month, for example). However, it is incorrect to add ergs and Newtons, since they are of different dimensionality. Right. And in the basic package, it would be the programmer's responsibility to convert therms to kWh, or vice versa, before the addition takes place. And just like Perl 6 implements Instant without reference to a specific calendar system, leaving that to be implemented by appropriate modules, dimensionality would leave the implementation of specific systems of measurement to appropriate modules. With that in mind, your further suggestions would work well for the purpose of defining such a module: The more robust units/dimensional analysis packages I've seen might not allow one to add therms and kWh, but they do know that therms and kWh are both [ML^2/T^2], I believe at the time I was looking at JScience's work on JSR-275. In this setup, when units are registered, they are given a dimensionality (essentially, a baggy of dimensions), and values are given a baggy of units (and thus an implicit baggy of dimensions, the union of the dimensions of the units). I was using Baggy to describe an as-yet-hypothetical role that is to Bags and Sets as Numeric is to Num, Rat, Int, Complex, and so on. The actual type for units would probably best be called an SBag, where the S stands for Signed (meaning that its count can be negative as well as positive). That said, it might need to be a RatBag, or possibly even a NumBag, if we want to leave open the possibility of fractal dimensions. Still, I'm thinking that an SBag would be good enough to start with. Your idea of having a registered unit be associated with an SBag of dimensions (e.g., ML^2T^-2) would be good for allowing more intelligent exceptions, and would cover what I was talking about in terms of defining what kind of value a unit measures. I don't think a Num is necessary, but I could see a Rat. As is, is Duration implemented by means of a Num, or a Rat? Whichever it is, that's the type that the difference of two Instances would return (properly tagged with seconds, of course). -- Jonathan Dataweaver Lang
Re: exponentiation of Duration's
If I'm following this correctly, shouldn't we just say that Duration does Num? That way, a Duration can be used exactly like a Num is (with units measured in seconds); but it could also have special capabilities above and beyond what a Num can do, if such capabilities are needed. More generally, I wonder if maybe we _should_ provide a tool to help with dimensional analysis: a role that does Num, but also tracks the units for you. The simplest version would leave it up to the programmer to handle unit conversions (e.g., divide a Dimensional that uses the seconds unit by a Dimensional that contains 86400 for its value and seconds/day for its units to get a Dimensional that uses the days unit, rather than providing built-in unit conversion routines). Indeed, th simplest form of Dimensional ought to be able to work with arbitrary units. The idea here isn't to place limitations on anything, but rather to make it easier to track additional data that's relevant to the calculations being performed. With this in place, Duration would be synonymous with Dimensional, measured in 'seconds'. That said, it's possible that this would open up a can of worms. Would it? If so, it can be postponed; Perl 6 has this nice little versioning ability that lets us retroactively alter roles; so one could easily put together a Dimensionality module at a later date that redefines what a Duration is. -- Jonathan Dataweaver Lang
Re: exponentiation of Duration's
Moritz Lenz wrote: Am 17.11.2010 17:50, schrieb Jon Lang: More generally, I wonder if maybe we _should_ provide a tool to help I think this question can only be answered in a meaningful way if somebody actually implements such a thing as a module (which should be entirely possible in Rakudo right now). Then we'll see if people take it up and use it. That said, it's possible that this would open up a can of worms. Would it? Another reason to prototype it as a module. Agreed. I'll look into writing something up. That said, I'm short on time, so don't hold your breath waiting for me to do it. I've been thinking about this some more: perhaps the dimensionality feature, if included at all, should be done as a trait; e.g., 5 seconds would be C 5 but units(sec) , or something to that effect. That way, you could easily add units to Num, Rat, Int, Complex, or anything else that could reasonably be dimensional, and they would continue to be usable in their original context. With respect to Instant and Duration, my gut instinct would be to change things so that in the default Perl setting, Duration goes away and is replaced by Num; but the Dimensionality module would modify Instant to be aware of units, and to act accordingly (e.g., Instant - Instant returns Num but units(sec); Instant + Num looks for units on the Num and throws an exception if it finds the wrong ones, or none). If you don't want to bother with dimensionality, use the standard perl setting; if you want perl tracking these things for you, use Dimensionality. In short, take Duration out of the default setting, but make its added functionality available by means of a module. -- Jonathan Dataweaver Lang
Re: Packed arrays and assignment vs binding
On Sun, Nov 14, 2010 at 2:54 AM, Moritz Lenz mor...@faui2k3.org wrote: On IRC, Jonathan said that 1 is basically an Int, which is something like a boxed int. So whatever operation works removes the box, and puts the result in the variable. However I wonder how well that's going to work, since Int can store arbitrarily large integers, while int can't. What happens on overflow? An exception gets thrown, I'm guessing. -- Jonathan Dataweaver Lang
Re: Packed arrays and assignment vs binding
Jonathan Worthington wrote: In the latter case, it's fairly clear how these differ: @x[0] = 1; @x[0] := 1; In the first, we look up the container in slot 0 or the array and assign a 1 into it. In the second, we bind a 1 directly into the slot. There's no container any more (so any future assignment attempts will fail, for example). I'll have to beg to differ. My understanding of it is as follows: the first case works as you describe. The second case differs, though, because there is no way to bind a variable directly to a value; variables can only be bound to containers. So the interpreter creates a new item container, assigns 1 to it, and binds the zero slot to it. Mind you: when the optimizer gets its hands on this, it'll probably just simplify it to the first case, as the two are functionally equivalent. The distinction only really matters when you're binding to an already-existing container (e.g., @x[0] = $foo vs. @x[0] := $foo). With packed arrays, however, I'm less clear what they mean. Since the point of a packed array is compact storage, there's no chance to actually have containers. Thus does assignment to a slot in a compact array ever make sense? There's not a container to look up and store things in. Assignment makes perfect sense: the compact storage is the container (which is bound to @x), and you assign a value to a slot in that container. What doesn't make sense is binding a slot of a packed array to some other container: @x[0] := $foo; # this should die. The only way I can see this working is if perl first converts the packed array into a normal array, and then binds slot 0 to $foo. -- Jonathan Dataweaver Lang
Re: Bag / Set ideas - making them substitutable for Arrays makes them more useful
Brandon S Allbery KF8NH wrote: -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 11/7/10 23:19 , Jon Lang wrote: 1 -- 2 -- 3 Would be a Bag containing three elements: 1, 2, and 3. Personally, I wouldn't put a high priority on this; for my purposes, Bag(1, 2, 3) works just fine. Hm. Bag as [! 1, 2, 3 !] and Set as {! 1, 2, 3 !}, with the outer bracket by analogy with arrays or hashes respectively and the ! having the mnemonic of looking like handles? (I have to imagine there are plenty of Unicode brackets to match.) That saves a singlr character over Bag( ... ) and Set( ... ), respectively (or three characters, if you find decent unicode bracket choices). It still wouldn't be a big enough deal to me to bother with it. As well, my first impression upon seeing [! ... !] was to think you're negating everything inside? That said, I could get behind doubled brackets: [[1, 2, 3]] # same as Bag(1, 2, 3) {{1, 2, 3}} # same as Set(1, 2, 3) AFAIK, this would cause no conflicts with existing code. Or maybe these should be reversed: [[1, 1, 2, 3]] # a Set containing 1, 2, and 3 {{1, 1, 2, 3}} # a Bag containing two 1s, a 2, and a 3 {{1 = 2, 2 = 1, 3 = 1}} # another way of defining the same Bag, with explicit counts. OTOH, perhaps the outermost character should always be a square brace, to indicate that it operates primarily like a list; while the innermost character should be either a square brace or a curly brace, to hint at thye kind of syntax that you might find inside: [[1, 1, 2, 3]] # a Set containing 1, 2, and 3 [{1, 1, 2, 3}] # a Bag containing two 1s, a 2, and a 3 [{1 = 2, 2 = 1, 3 = 1}] # another way of defining the same Bag, with explicit counts. Yeah; I could see that. The only catch is that it might cause problems with existing code that nests square or curly braces inside of square braces: [[1, 2, 3], [4, 5, 6], [7, 8, 9]] # fail; would try to create Set from 1, 2, 3], [4, 5, 6], [7, 8, 9 [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ] # creates 3-by-3 array ...so maybe not. It should never be more than two characters on either side; and there's some benefit to using square or curly braces as one of them, to hint at proper syntax within. Hmm... how about: |[1, 2, 3]| # Set literal |[1=true, 2=true, 3=true]| # technically possible; but why do it? |{1, 1, 2, 3}| # Bag literal |{1=2, 2=1, 3=1}| # counted Bag literal -- Jonathan Dataweaver Lang
Re: Bag / Set ideas - making them substitutable for Arrays makes them more useful
Carl Mäsak wrote: Jonathan Lang (): That saves a singlr character over Bag( ... ) and Set( ... ), respectively (or three characters, if you find decent unicode bracket choices). It still wouldn't be a big enough deal to me to bother with it. +1. Let's leave it at that. That said, I do think that Bag( ... ) should be able to take pairs, so that one can easily create a Bag that holds, say, twenty of a given item, without having to spell out the item twenty times. Beyond that, the only other syntax being proposed is a set of braces to be used to create Bags and Sets, as part of the initiative to make them nearly as easy to use as lists. In essence, you'd be introducing two operators: circumfix:|[ ]| and circumfix:|{ }|, as aliases for the respective Set and Bag constructors. As I said, it's not a big deal - either way. Really, my main issue remains the choice of sigil for a variable that's supposed to hold baggy containers. -- Jonathan Dataweaver Lang
Re: Bag / Set ideas - making them substitutable for Arrays makes them more useful
Darren Duncan wrote: Jon Lang wrote: That saves a singlr character over Bag( ... ) and Set( ... ), respectively (or three characters, if you find decent unicode bracket choices). It still wouldn't be a big enough deal to me to bother with it. As well, my first impression upon seeing [! ... !] was to think you're negating everything inside? That said, I could get behind doubled brackets: [[1, 2, 3]] # same as Bag(1, 2, 3) {{1, 2, 3}} # same as Set(1, 2, 3) snip I prefer to have the mnemonic that {} means unordered and that [] means ordered, so please stick to [] meaning arrays or ordered collections, an {} meaning unordered collections, so set and bag syntax should be based around {} if either. This said, I specifically think that a simple pair of curly braces is the best way to mark a Set. So: {1,2,3} # a Set of those 3 elements ... and this is also how it is done in maths I believe (and in Muldis D). In fact, I strongly support this assuming that all disambiguation eg with hashes can be specified. That would be great. {a=1,b=2} # a Hash of 2 pairs {:a1, :a2} # we'll have to pick a meaning My preference would be for this to be a Set that contains two items in it, both of which are pairs. IIRC, there's already behavior along these lines when it comes to pairs. {} # we'll have to pick a meaning (Muldis D makes it a Set; %:{} is its Hash) Is there any difference between an empty Set and an empty Hash? If so, is one more general than the other? Just as importantly, what does {} do right now? {;} # an anonymous sub or something {a=1} # Hash {1} # Set {1;} # anonymous sub or something Sets built from multi-dimensional arrays migt be a problem: {1, 2, 3: 4, 5, 6} But keep that simple an let nesting work normally, so: {{1}} # a Set of 1 element that is a Set of 1 element {{a=1}} # a Set with 1 Hash element {[1]} # a Set with 1 Array element [{1}] # an Array with 1 Set element In certain cases, we can always still fall back to this: Set() # empty Set Hash() # empty Hash Set(:a1) # if that's what we wanted As for bags, well I think that is where we could get fancier. But *no* doubling up, as we don't want to interfere with nesting. Instead, it is common in maths to associate a + with set syntax to refer to bags instead. So, does Perl already ascribe a meaning to putting a + with various bracketing characters, such as this: +{1,2,2,5} # a Bag of 4 elements with 2 duplicates +{} # an empty Bag, unless that already means something So would the above try to cast the collection as a number, or take the count of its elements, or can we use something like that? I'd expect +{...} to count the elements. -- Jonathan Dataweaver Lang
Re: Bag / Set ideas - making them substitutable for Arrays makes them more useful
Solomon Foster wrote: Well, hyperoperators work fine on Hashes, they operate on the values, paired up by key if needed. (That is, %hash++ doesn't care about the keys, %hash1 + %hash2 sums based on keys.) I would assume that Bag should work in the exact same way. Dunno how Set should work in this context, though. I would hope that Bags would not work the same way. If they do, then you get things like: Bag(1, 3, 2, 1) + Bag(2, 3, 1, 2) # same as Bag(1, 1, 1, 2, 2, 2, 3, 3) I'm not sure how (or even if) Bags _should_ work in this context; but the above is definitely not what I'd expect. IMHO, a key point about Bags and Sets (no pun intended) is that the values of the elements _are_ the keys; the existence of separate values (unsigned integers in the case of Bags; booleans in the case of Sets) are - or should be - mostly a bookkeeping tool that rarely shows itself. Incidently, we might want to set up a role to define the shared behavior or Bags, Sets, et al. My gut instinct would be to call it Baggy; Setty would make the stargazers happy, but otherwise wouldn't mean much. With this, you could do things like creating a FuzzySet that stores a number between zero and one for each key, but which otherwise behaves like a Set. -- Jonathan Dataweaver Lang
Re: Bag / Set ideas - making them substitutable for Arrays makes them more useful
This is going to be a rambling answer, as I have a number of questions but no firm conclusions. Please bear with me. Mason Kramer wrote: Having Bags flatten in list context is pretty crucial to their being as easy and terse to use as arrays, because flattening is fundamental to how Arrays are used, and Bags will be used like Arrays. Luckily, however, %, which implies the Associative contract, also flattens in list context. If Bags and Sets are sigiled with %, they should flatten, and all that remains is to make sure they flatten into a list of keys, and not a list of enums. The only qualm that I have with using % as a prefix for baggy things is that % carries the connotation that you're dealing with key/value pairs. While baggy things _can_ be thought of as pairs, they're value/membership pairs rather than key/value pairs; and the membership side of the pair should be hidden from view unless explicitly requested. In short, a casual programmer ought to be encouraged to think of a baggy thing as being a collection of values; the % sigil implicitly encourages him to think of it as a collection of pairs. That said, the problem with % is that baggies implement its features in an unusual way; the problem with @ is that baggies don't implement all of its features. Conceptually, @ (a collection of values) is a better fit than % (a collection of pairs); but technically, the reverse is true: % (does Associative) is a better fit than @ (does Positional). Query: should %x.k, %x.v, %x.kv, and %x.pair produce lists, bags, or sets? As I understand it, right now all four produce lists. I could see a case for having %x.k and %x.pair produce sets, while %x.kv definitely should produce a list (since even though the overall order doesn't matter, which even element follows which odd element _does_ matter); and %x.v might reasonably produce a bag. OTOH, if this is done then there will be no way to talk about, e.g., %x.k[0]. I'm wondering if bags and sets _should_ do Positional, but with the caveat that the order is arbitrary. After all, that's what currently happens with %x.k: you get a list of the keys, but with the understanding that the order in which you get them is ultimately meaningless. Or is it that the difference between Iterable and Positional is that Positional provides random access to its membership, whereas Iterable only guarantees that you can walk through the members? Another way to phrase my concern is this: one reason why Perl 6 has gone with nominal typing rather than structural typing is that does x can and does promise more than just implements the same features that x implements; it also promises something about the way in which said features will be implemented. In this regard, I would argue that baggies should not do Associative; because even though they implement all of the same features that Associative promises to implement, they don't do so in a way that's compatible with Associative's underlying philosophy of keys and values. And if they don't do Associative, it doesn't make sense for them to use the % sigil. I hesitate to suggest this; but might we want a special sigil for Iterable, to be used when neither Positional nor Associative is quite right? Such a sigil might be useful for more than just baggies; for instance, a stream is Iterable but neither Positional nor Associative. -- Jonathan Dataweaver Lang
Re: Bag / Set ideas - making them substitutable for Arrays makes them more useful
Mason Kramer wrote: I'd like to anticipate one objection to this - the existence of the 'hyper' operator/keyword. The hyper operator says, I am taking responsibility for this particular code block and promising that it can execute out of order and concurrently. Creating a Bag instead of an Array says, there is no meaning to the ordering of this group of things, ever. Basically, if I know at declaration time that my collection has no sense of ordering, then I shouldn't have to annotate every iteration of that collection as having no sense of ordering, which is nearly what hyper does (though, I readily admit, not quite, because there are unordered ways to create race conditions). My understanding of the hyperoperator is that its primary use is to say operate on the individual elments of this collection, instead of on the collection itself. In that regard, it's just as applicable to Bags and Sets as it is to lists. Except... Except that the hyperoperator assumes that the collections are ordered. It matches the first element on the left with the first element on the right; the second element on the left with the second on the right; and so on. Bags and Sets don't have a useful notion of first, second, etc. So what should happen if I try to apply a hyperoperator with a Bag or Set on one side? The cross operators should also be looked at in this regard, though I anticipate fewer problems there. This, however, probably requires a change to S03, which says that the @ sigil is a means of coercing the object to the Positional (or Iterable?) role. It seems to me, based on the guiding principle that perl6 should support functional idioms and side-effect free computing, the more fundamental and important aspect of things with @ in front is that you can go through them one by one, and not that they're ordered (since ordering is irrelevant in functional computing, but iterating is not). My feeling is that we should reserve the special syntax for the more fundamental of the two operations, so as not to bias the programmer towards rigid sequentiality through syntax. I tend to agree here - though to be clear, my @x should still normally result in a list, sans further embellishments (e.g., my Bag @x). Second, I would be even more likely to replace my ordered lists with Bags if there were a convenient operator for constructing Bags. I can't think of any good non-letter symbols that aren't taken right now (suggestions welcome), but, at least, b and s as aliases to bag and set would be convenient. Such a character ought to be some sort of punctuation, preferably of a type that's similar to the comma and semicolon. For a Bag, you might consider an emdash (—), with the ascii equivalent being infix:--. So: 1 -- 2 -- 3 Would be a Bag containing three elements: 1, 2, and 3. Personally, I wouldn't put a high priority on this; for my purposes, Bag(1, 2, 3) works just fine. -- Jonathan Dataweaver Lang
Re: Lists vs sets
yary wrote: +1 on this On Mon, Oct 25, 2010 at 4:56 PM, Jon Lang datawea...@gmail.com wrote: As for the bit about sets vs. lists: personally, I'd prefer that there not be quite as much difference between them as there currently is. That is, I'd rather sets be usable wherever lists are called for, with the caveat that there's no guarantee about the order in which you'll get the set's members; only that you'll get each member exactly once. The current approach is of much more limited value in programming. I think of a list conceptually as a subclass of a set- a list is a set, with indexing and ordering added. Implementation-wise I presume they are quite different, since a set falls nicely into the keys of a hash in terms of what you'd typically want to do with it. By implementation-wise, are you referring to under the hood details? If so, I agree: it's OK to implement a set internally as a hash. But as far as the user is concerned, it ought to look like a list. Well, technically, a list should look like a set that has additional features. But as Damian pointed out earlier, one reason why he chose to use lists in his transjunction module instead of sets is that as they are now, you can iterate over a list; but you can't iterate over a set. From a practical standpoint, sets would be considerably more attractive if you could iterate over them as well without having to first turn them into lists via the .k method. Thus my suggestion to treat a set as a list of unique values without a guaranteed order, at least as far as the user is concerned. -- Jonathan Dataweaver Lang
Re: Lists vs sets
Mason Kramer wrote: But I don't think that thinking about who is subclassing whom is is how to think about this in Perl 6. All of these types are capable of doing the Iterable role, and that is what methods that could operate on a List, Array, Bag, or Set, should be calling for. This. Really, as long as Set does Iterable, it's not as important if it's treated as hash-like or list-like - though I'd still prefer to deal with @sets rather than %sets. Conceptually, it feels like a better fit. -- Jonathan Dataweaver Lang
Re: Lists vs sets
Darren Duncan wrote: If a list is a set, does that mean that a list only contains/returns each element once when iterated? If a list can have duplicates, then a list isn't a set, I would think. -- Darren Duncan Thus Mason's point about Bags. Really, I think that Mason's right in that we should be looking as which roles each of these does rather than which classes each of them is. -- Jonathan Dataweaver Lang
Re: threads?
When Larry decided that Perl 6 would incorporate concepts from prototype-based objects, he did so at least in part because it's more intuitive for people to work with, e.g., a cow than it is to try to work with the concept of a cow as a thing unto itself. In a similar way, I think that Perl's dominant concurrency system ought to be of a type that people who aren't computer scientists can grok, at least well enough to do something useful without first having to delve into the arcane depths of computing theory. As such, I'm wondering if an Actor-based concurrency model[1] might be a better way to go than the current threads-based mindset. Certainly, it's often easier to think of actors who talk to each other to get things done than it is to think of processes (or threads) as things unto themselves. [1] http://en.wikipedia.org/wiki/Actor_model -- Jonathan Dataweaver Lang
Re: r31972 -[S05] specify what .keys, .values and .kv do on Match objects
How does a Match compare to a Parcel? -- Jonathan Dataweaver Lang
Re: pattern alternation (was Re: How are ...)
Aaron Sherman wrote: You know, this problem would go away, almost entirely, if we had a :f[ull] adverb for regex matching that imposed ^[...]$ around the entire match. Then your code becomes: m:f/[A..Z]+|[a..z]+/ for grins, :f[ull]l[ine] could use ^^ and $$. I suspect :full would almost always be associated with TOP, in fact. Boy am I tired of typing ^ and $ in TOP ;-) The regex counterpart of C say $x vs. C print $x\n . Yes, this would indeed solve a lot of problems. It also reflects a tendency in some regular expression engines out there to automatically impose full string matching (i.e., an implicit ^ at the start and $ at the end). That said: for mnemonic purposes, I'd be inclined to have :f do /^[$pattern]$/, while :ff does /^^[$pattern]$$/. -- Jonathan Dataweaver Lang
Re: S26 broken link
Moritz Lenz wrote: Offer Kaye wrote: The link to the S26 Synopsis on http://perlcabal.org/syn/ points to http://perlcabal.org/syn/S26.html which is a broken link - would it be possible to fix this? I't not that easy, because we currently don't have tool to turn p6doc into HTML. I can remove the link for now, if it's a concern to you. And a major reason why we don't have a p6doc-to-HTML converter is because there are still some outstanding issues with the p6doc spec: it's not ready for prime time, as it were. IIRC, the biggest unresolved issues involved the code-sensitive documentation features: getting a pod6 parser to read perl code and extract appropriate values on the one hand, vs. safety concerns about its ability to _run_ perl code on the other. -- Jonathan Dataweaver Lang
Re: Suggested magic for a .. b
Aaron Sherman wrote: In the end, I'm now questioning the difference between a junction and a Range... which is not where I thought this would go. Conceptually, they're closely related. In particular, a range behaves a lot like an any() junction. Some differences: 1. An any() junction always has a discrete set of options in it; but a Range could (and generally does) have a continuous set of options. 2. An any() junction can have an arbitrary set of options; a Range's set of options is defined entirely by its endpoints. -- Jonathan Dataweaver Lang
Re: Suggested magic for a .. b
On Wed, Jul 28, 2010 at 10:35 PM, Brandon S Allbery KF8NH allb...@ece.cmu.edu wrote: On 7/28/10 8:07 PM, Michael Zedeler wrote: On 2010-07-29 01:39, Jon Lang wrote: Aaron Sherman wrote: In smart-match context, a..b includes aardvark. No one has yet explained to me why that makes sense. The continued use of ASCII examples, of course, doesn't help. Does a .. b include æther? This is where Germans and Swedes, for example, don't agree, but they're all using the same Latin code blocks. This is definitely something for the Unicode crowd to look into. But whatever solution you come up with, please make it compatible with the notion that aardvark..apple can be used to match any word in the dictionary that comes between those two words. The key issue here is whethere there is a well defined and meaningful ordering of the characters in question. We keep discussing the nice examples, but how about apple .. ส้ม? I thought that was already disallowed by spec. As a range, it ought to work; it's only when you try to generate a list from it that you run into trouble, as the spec currently assumes that z.succ eqv aa. Anyway: whatever default algorithm we go with for resolving cmp, I strongly recommend that we define the default .succ so that $x lt $x.succ is always true. -- Jonathan Dataweaver Lang
Re: Suggested magic for a .. b
Dave Whipp wrote: To squint at this slightly, in the context that we already have 0...1e10 as a sequence generator, perhaps the semantics of iterating a range should be unordered -- that is, for 0..10 - $x { ... } is treated as for (0...10).pick(*) - $x { ... } Then the whole question of reversibility is moot. No thanks; I'd prefer it if $a..$b have analogous meanings in item and list contexts. As things stand, 10..1 means, in item context, numbers that are greater or equal to ten and less than or equal to one, which is equivalent to nothing; in list context, it means an empty list. This makes sense to me; having it provide a list containing the numbers 1 through 10 creates a conflict between the two contexts regardless of how they're arranged. As I see it, C $a..$b in list context is a useful shorthand for C $a, *.succ ... $b . You only get into trouble when you start trying to have infix:.. do more than that in list context. If anything needs to be done with respect to infix:.., it lies in changing the community perception of the operator. The only reason why we're having this debate at all is that in Perl 5, the .. operator was used to generate lists; so programmers coming from Perl 5 start with the expectation that that's what it's for in Perl 6, too. That expectation needs to be corrected as quickly as can be managed, not catered to. But that's not a matter of language design; it's a matter to be addressed by whoever's going to be writing the Perl 6 tutorials. -- Jonathan Dataweaver Lang
Re: Suggested magic for a .. b
TSa wrote: Swapping the endpoints could mean swapping inside test to outside test. The only thing that is needed is to swap from to ||: $a .. $b # means $a = $_ $_ = $b if $a $b $b .. $a # means $b = $_ || $_ = $a if $a $b This is the same sort of discontinuity of meaning that was causing problems with Perl 5's use of negative indices to count backward from the end of a list; there's a reason why Perl 6 now uses the [*-$a] notation for that sort of thing. Consider a code snippet where the programmer is given two values: one is a minimum value which must be reached; the other is a maximum value which must not be exceeded. In this example, the programmer does not know what the values are; for all he knows, the minimum threshold exceeds the maximum. As things stand, it's trivial to test whether or not your sample value is viable: if $x ~~ $min .. $max, then you're golden: it doesn't matter what $min cmp $max is. With your change, I'd have to replace the above with something along the lines of: if $min = $max $x ~~ $min .. $max { ... } - because if $min $max, the algorithm will accept values that are well below the minimum as well as values that are well above the maximum. Keep it simple, folks! There are enough corner cases in Perl 6 as things stand; we don't need to be introducing more of them if we can help it. -- Jonathan Dataweaver Lang
Re: Suggested magic for a .. b
Darren Duncan wrote: Does ... also come with the 4 variations of endpoint inclusion/exclusion? If not, then it should, as I'm sure many times one would want to do this, say: for 0...^$n - {...} You can toggle the inclusion/exclusion of the ending condition by choosing between ... and ...^; but the starting point is the starting point no matter what: there is neither ^... nor ^...^. In any event, I still think that the mnemonics of ... (yadda-yadda-yadda) are more appropriate to a generator, where it says produce this and so on. A .. does not have that mnemonic and looks better for an interval. Well put. This++. -- Jonathan Dataweaver Lang
Re: Suggested magic for a .. b
Aaron Sherman wrote: In smart-match context, a..b includes aardvark. No one has yet explained to me why that makes sense. The continued use of ASCII examples, of course, doesn't help. Does a .. b include æther? This is where Germans and Swedes, for example, don't agree, but they're all using the same Latin code blocks. This is definitely something for the Unicode crowd to look into. But whatever solution you come up with, please make it compatible with the notion that aardvark..apple can be used to match any word in the dictionary that comes between those two words. I've never accepted that the range between two strings of identical length should include strings of another length. That seems maximally non-intuitive (well, I suppose you could always return the last 100 words of Hamlet as an iterable IO object if you really wanted to confuse people), and makes string and integer ranges far too divergent. This is why I dislike the notion of the range operator being used to produce lists: the question of what values you'd get by iterating from one string value to another is _very_ different from the question of what string values qualify as being between the two. The more you use infix:.. to produce lists, the more likely you are to conflate lists with ranges. -- Jonathan Dataweaver Lang
Re: Suggested magic for a .. b
Michael Zedeler wrote: Jon Lang wrote: This is definitely something for the Unicode crowd to look into. But whatever solution you come up with, please make it compatible with the notion that aardvark..apple can be used to match any word in the dictionary that comes between those two words. The key issue here is whether there is a well defined and meaningful ordering of the characters in question. We keep discussing the nice examples, but how about apple .. ส้ม? All I'm saying is: don't throw out the baby with the bathwater. Come up with an interim solution that handles the nice examples intuitively and the ugly examples poorly (or better, if you can manage that right out of the gate); then revise the model to improve the handling of the ugly examples as much as you can; but while you do so, make an effort to keep the nice examples working. I don't know enough about Unicode to suggest how to solve this. All I can say is that my example above should never return a valid Range object unless there is a way I can specify my own ordering and I use it. That actually says something: it says that we may want to reconsider the notion that all string values can be sorted. You're suggesting the possibility that a cmp ส้ is, by default, undefined. There are some significant problems that arise if you do this. -- Jonathan Dataweaver Lang
Re: Suggested magic for a .. b
Aaron Sherman wrote: As a special case, perhaps you can treat ranges as special and not as simple iterators. To be honest, I wasn't thinking about the possibility of such special cases, but about iterators in general. You can't generically reverse lazy constructs without running afoul of the halting problem, which I invite you to solve at your leisure ;-) A really obvious example occurs when the RHS is a Whatever: (1..*).reverse; .reverse magic isn't going to be generically applicable to all lazy lists; but it can be applicable to all lazy lists that have predefined start points, end points, and bidirectional iterators, and on all lazy lists that have random-access iterators and some way of locating the tail. Sometimes you can guess what the endpoint and backward-iterator should be from the start point and the forward-iterator, just as the infix:... operator is able to guess what the forward-iterator should be from the first one, two, or three items in the list. This is especially a problem with regard to lists generated using the series operator, as it's possible to define a custom forward-iterator for it (but not, AFAICT, a custom reverse-iterator). In comparison, the simplicity of the range operator's list generation algorithm almost guarantees that as long as you know for certain what or where the last item is, you can lazily generate the list from its tail. But only almost: (1..3.5); # list context: 1, 2, 3 (1..3.5).reverse; # list context: 3.5, 2.5, 1.5 - assuming list is generated from tail. (1..3.5).reverse; # list context: 3, 2, 1 - but only if you generate it from the head first, and then reverse it. Again, the proper tool for list generation is the series operator, because it can do everything that the range operator can do in terms of list generation, and more. 1 ... 3.5 # same as 1, 2, 3 3.5 ... 1 # same as 3.5, 2.5, 1.5 - and obviously so. With this in mind, I see no reason to allow any magic on .reverse when dealing with the range operator (or the series operator, for that matter): as far as it's concerned, it's dealing with a list that lacks a reverse-iterator, and so it will _always_ generate the list from its head to its tail before attempting to reverse it. Maybe at some later point, after we get Perl 6.0 out the door, we can look into revising the series operator to permit more powerful iterators so as to allow .reverse and the like to bring more dwimmy magic to bear. -- Jonathan Dataweaver Lang
Re: series operator issues
On Thu, Jul 22, 2010 at 9:25 AM, Aaron Sherman a...@ajs.com wrote: On Thu, Jul 22, 2010 at 11:41 AM, Moritz Lenz mor...@faui2k3.org wrote: The difficulty you're running into is that you're trying to use the wrong tool for the job. Just don't use the series operator when it's not easy to use. Perl 6 has other mechanism too, which are better suited for these particular problems. In general, I'd agree. However, there is something to be said for the underlying question: is there a way to get at the iteration index from the lambda in a series? It seems like that's something that it's not unreasonable to want. I also think it's doable without a special tool: 0, { state $i = 1; $^a + $i++ } ... * That should work, no? Granted, state doesn't seem to work in Rakudo, unless I'm mis-understanding how to use it, but that's the idea. Kludgey; but possibly doable. Another possibility that might work would be to use the default list parameter to count the previous elements: +...@_. That would be notationally more compact, but would also potentially wreak havoc on the computational efficiency of the model; and while you could get the index number from it, it wouldn't always be quite as simple as counting its elements. But what I'd really like to see would be for the index to be passed into the step function via a named parameter. Yes, it would be a special tool; but it would be much more in keeping with the keep simple things easy philosophy that Perl 6 tends to promote: 0, { $^a + $:i } ... * # series of triangle numbers 0, { $^a + (2 * $:i - 1) } ... * # series of square numbers { $:i ** 2 } ... * # series of square numbers 1, { $^a * $:i } ... * # series of factorials -- Jonathan Dataweaver Lang
Re: series operator issues
On Thu, Jul 22, 2010 at 11:35 AM, Aaron Sherman a...@ajs.com wrote: On Thu, Jul 22, 2010 at 1:13 PM, Jon Lang datawea...@gmail.com wrote: Yes, it would be a special tool; but it would be much more in keeping with the keep simple things easy philosophy that Perl 6 tends to promote: 0, { $^a + $:i } ... * # series of triangle numbers 0, { $^a + (2 * $:i - 1) } ... * # series of square numbers { $:i ** 2 } ... * # series of square numbers 1, { $^a * $:i } ... * # series of factorials I do have to admit that that's awfully clean-looking, but the implementation would force a closure in a series to behave differently from a closure anywhere else. How so? Without changing closure definitions and without extending the syntax any, you could make the series operator do a little bit more introspection work and if a parameter is named index, track an index value and pass it by name, passing any remaining parameters positionally from the previous n values as normal. ...which differs from my example in several ways, all of which are detrimental: it puts the index in among the positional parameters, meaning that odd things would have to happen if you ever decide to use, say, $^i and $^j as your prior items parameters; and it locks you into a specific name for the index instead of letting you choose one of your own liking. That makes your examples: 0, { $^a + $^index } ... * 0, { $^a + (2 * $^index - 1) } ... * { $^index ** 2 } ... * 1, { $^a * $^index } ... * Not changing the syntax of closures seems like a reasonable goal at this late stage. Who said anything about changing the syntax? $:i is perfectly valid syntax that is already spelled out in S06, under Placeholder Variables. Granted, it's rarely used; but it exists. And unless I'm missing something, this would be a perfectly valid use for it. Essentially, my suggestion is this: if the step function's signature (or implied signature, in the case of a function with placeholder variables) includes any named parameters, then the index is used as the argument corresponding to the first one. (the only catch would be if you decide to use the slurpy named placeholder, since the compiler can't be expected to know which keys are being used inside the block; in this case, it would be fair to assume that index is to be used, or maybe 0.) As such, the above examples could also be done as: 0, - $a, :$i { $a + $i } ... * # series of triangle numbers 0, sub ($_, :$x) { $_ + (2 * $x - 1) } ... * # series of square numbers { %_{0} ** 2 } ... * # series of square numbers 1, { @_[0] * %_0 } ... * # series of factorials My own preference would be to angle for the more compact form that I originally illustrated, unless and until its limitations force me to do otherwise. But then, TIMTOWTDI. -- Jonathan Dataweaver Lang
Re: Suggested magic for a .. b
Smylers wrote: Jon Lang writes: Approaching this with the notion firmly in mind that infix:.. is supposed to be used for matching ranges while infix:... should be used to generate series: With series, we want C $LHS ... $RHS to generate a list of items starting with $LHS and ending with $RHS. If $RHS $LHS, we want it to increment one step at a time; if $RHS $LHS, we want it to decrement one step at a time. Do we? Yes, we do. I'm used to generating lists and iterating over them (in Perl 5) with things like like: for (1 .. $max) where the intention is that if $max is zero, the loop doesn't execute at all. Having the equivalent Perl 6 list generation operator, C..., start counting backwards could be confusing. Especially if Perl 6 also has a range operator, C.., which would Do The Right Thing for me in this situation, and where the Perl 6 operator that Does The Right Thing is spelt the same as the Perl 5 operator that I'm used to; that muddles the distinction you make above about matching ranges versus generating lists. It does muddy the difference, which is why my own gut instinct would have been to do away with infix:..'s ability to generate lists. Fortunately, I'm not in charge here, and wiser heads than mine have decreed that infix:.., when used in list context, will indeed generate a list in a manner that closely resembles Perl 5's range operator: start with the LHS, then increment until you equal or exceed the RHS - and if you start out exceeding the RHS, you've got yourself an empty list. You can do the same thing with the infix:... operator, too; but doing so will be bulkier (albeit much more intuitive). For example, the preferred Perl 6 approach to what you described would be: for 1, 2 ... $x The two-element list on the left of the series operator invokes a bit of magic that tells it that the algorithm for generating the next step in the series is to invoke the increment operator. This is all described in S03 in considerable detail; I suggest rereading the section there concerning the series operator before passing judgment on it. . -- Jonathan Dataweaver Lang
Re: multi-character ranges
Aaron Sherman wrote: Darren Duncan wrote: 3) It seems that there are two competing multi-character approaches and both seem somewhat valid. Should we use a pragma to toggle behavior between A and B: A: aa .. bb contains az B: aa .. bb contains ONLY aa, ab, ba and bb I would find A to be the only reasonable answer. [Before I respond, let's agree that, below, I'm going to say things like generates when talking about ... What I'm describing is the idea that a value exists in the range given, not that a range is actually a list.] I would find B to be the only reasonable answer, but enough people seem to think the other way that I understand there's a valid need to be able to get both behaviors. FWIW, the reasoning behind A is that it's very much like looking up a word in a dictionary. Is az greater than, less than, or equal to aa? Greater than. Is az greater than, equal to, or less than bb? Less than. Since it is greater than aa and less than bb, it is between aa and bb. This is what infix:.. tests for. If you want B's semantics then use ... instead; .. should not be overloaded for that. I wasn't really distinguishing between .. and ... as I'm pretty sure they should have the same behavior, here. The case where I'm not sure they should have the same behavior is apple .. orange. Frankly, I think that there's no right solution there. There's the one I proposed in my original message (treat each character index as a distinct sequence and then increment in a base defined by all of the sequences), but even I don't like that. To generate all possible strings of length 5+ that sort between those two is another suggestion, but then what do you expect father-in-law .. orange to do? Punctuation throws a whole new dimension in there, and I'm immediately lost. When you go to my Japanese example from many messages ago, which I got from a fairly typical Web site and contained 2 Scripts with 4 different General Categories, I begin to need pharmaceuticals. What you're asking about now isn't the range or series operators; its the comparison operators: before, after, gt, lt, ge, le, leg, and so on. When comparing two strings, establishing an order between them is generally straightforward as long as both are composed of letters from the same alphabet and with the same case; but once you start mixing cases, introducing non-alphabetical characters such as spaces or punctuation, and/or introducing characters from other alphabets, the common-sense meaning of order becomes messy. Traditionally, this has been addressed by falling back on a comparison of the characters' ordinals: 0x0041 comes before 0x0042, and so on. It includes counterintuitive situations where d E, because all capital letters come earlier in the Unicode sequencing than any lower-case letters do. OTOH, it's robust: if all that you want is a way to ensure that strings can always be sorted, this will do the job. It won't always be an _intuitive_ ordering; but there will always be an ordering. I don't see any value in having different rules for what .. and ... generate in these cases, however. (frankly, I'm still on the fence about ... for single endpoints, which I think should just devolve to .. (... with a list for LHS is another animal, of course)) The only area where infix:.. and infix:... overlap is when you're talking about list generation; when using them for matching purposes, C $x ~~ 1..3 is equivalent to C $x = 1 $x = 3 (that is, it's a single value that falls somewhere between the two endpoints), while C $x ~~ 1...3 is equivalent to C $x ~~ (1, 2, 3) (that is, $x is a three-element list that contains the values 1, 2, and 3 in that order) - two very different things. There simply is not enough similarity between the two operators for one to degenerate to the other in anything more than a few edge-cases. -- Jonathan Dataweaver Lang
Re: Suggested magic for a .. b
Solomon Foster wrote: Ranges haven't been intended to be the right way to construct basic loops for some time now. That's what the ... series operator is for. for 1e10 ... 1 - $i { # whatever } is lazy by the spec, and in fact is lazy and fully functional in Rakudo. (Errr... okay, actually it just seg faulted after hitting 968746 in the countdown. But that's a Rakudo bug unrelated to this, I'm pretty sure.) You took the words out of my mouth. All the magic that one wants for handling loop indices -- going backwards, skipping numbers, geometric series, and more -- is present in the series operator. Range is not supposed to do any of that stuff other than the most basic forward sequence. Here, though, I'm not so sure: I'd like to see how many of Aaron's issues remain unresolved once he reframes them in terms of the series operator. -- Jonathan Dataweaver Lang
Re: Suggested magic for a .. b
Approaching this with the notion firmly in mind that infix:.. is supposed to be used for matching ranges while infix:... should be used to generate series: Aaron Sherman wrote: Walk with me a bit, and let's explore the concept of intuitive character ranges? This was my suggestion, which seems pretty basic to me: x .. y, for all strings x and y, which are composed of a single, valid codepoint which is neither combining nor modifying, yields the range of all valid, non-combining/modifying codepoints between x and y, inclusive which share the Unicode script, general category major property and general category minor property of either x or y (lack of a minor property is a valid value). This is indeed true for both range-matching and series-generation as the spec is currently written. In general we have four problems with current specification and implementation on the Perl 6 and Perl 5 sides: 1) Perl 5 and Rakudo have a fundamental difference of opinion about what some ranges produce (A .. z, X .. T, etc) and yet we've never really articulated why we want that. 2) We deny that a range whose LHS is larger than its RHS makes sense, but we also don't provide an easy way to construct such ranges lazily otherwise. This would be annoying only, but then we have declared that ranges are the right way to construct basic loops (e.g. for (1..1e10).reverse - $i {...} which is not lazy (blows up your machine) and feels awfully clunky next to for 1e10..1 - $i {...} which would not blow up your machine, or even make it break a sweat, if it worked) With ranges, we want C when $LHS .. $RHS to always mean C if $LHS = $_ = $RHS . If $RHS $LHS, then the range being specified is not valid. In this context, it makes perfect sense to me why it doesn't generate anything. With series, we want C $LHS ... $RHS to generate a list of items starting with $LHS and ending with $RHS. If $RHS $LHS, we want it to increment one step at a time; if $RHS $LHS, we want it to decrement one step at a time. So: 1) we want different behavior from the Range operator in Perl 6 vs. Perl 5 because we have completely re-envisioned the range operator. What we have replaced it with is fundamentally more flexible, though not necessarily perfect. 3) We've never had a clear-cut goal in allowing string ranges (as opposed to character ranges, which Perl 5 and 6 both muddy a bit), so intuitive becomes sketchy at best past the first grapheme, and ever muddier when only considering codepoints (thus that wing of my proposal and current behavior are on much shakier ground, except in so far as it asserts that we might want to think about it more). I think that one notion that we're dealing with here is the idea that C $X $X.succ for all strings. This seems to be a rather intuitive assumption to make; but it is apparently not an assumption that Stringy.succ makes. As I understand it, Z.succ eqv AA. What benefit do we gain from this behavior? Is it the idea that eventually this will iterate over every possible combination of capital letters? If so, why is that a desirable goal? My own gut instinct would be to define the string iterator such that it increments the final letter in the string until it gets to Z; then it resets that character to A and increments the next character by one: ABE, ABF, ABG ... ABZ, ACA, ACB ... ZZZ This pattern ensures that for any two strings in the series, the first one will be less than its successor. It does not ensure that every possible string between ABE and ZZZ will be represented; far from it. But then, 1...9 doesn't produce every number between 1 and 9; it only produces integers. Taken to an extreme: pi falls between 1 and 9; but no one in his right mind expects us to come up with a general sequencing of numbers that increments from 1 to 9 with a guarantee that it will hit pi before reaching 9. Mind you, I know that the above is full of holes. In particular, it works well when you limit yourself to strings composed of capital letters; do anything fancier than that, and it falls on its face. 4) Many ranges involving single characters on LHS and RHS result in null or infinite output, which is deeply non-intuitive to me, and I expect many others. Again, the distinction between range-matching and series-generation comes to the rescue. Solve those (and I tried in my suggestion) and I think you will be able to apply intuition to character ranges, but only in so far as a human being is likely to be able to intuit anything related to Unicode. Of the points that you raise, #1, 2, and 4 are neatly solved already. I'm unsure as to #3; so I'd recommend focusing some scrutiny on it. The current behaviour of the range operator is (if I recall correctly): 1) if both sides are single characters, make a range by incrementing codepoints Sadly, you can't do that reasonably. Here are some examples of why, using only Latin and Greek as examples (not the most convoluted Unicode
Re: Suggested magic for a .. b
Aaron Sherman wrote: So, what's the intention of the range operator, then? Is it just there to offer backward compatibility with Perl 5? Is it a vestige that should be removed so that we can Huffman ... down to ..? I'm not trying to be difficult, here, I just never knew that ... could operate on a single item as LHS, and if it can, then .. seems to be obsolete and holding some prime operator real estate. On the contrary: it is not a vestige, it is not obsolete, and it's making good use of the prime operator real estate that it's holding. It's just not doing what it did in Perl 5. I strongly recommend that you reread S03 to find out exactly what each of these operators does these days. The questions definitely look different that way: for example, ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz is easily and clearly expressed as 'A' ... 'Z', 'a' ... 'z' # don't think this works in Rakudo yet :( I still contend that this is so frequently desirable that it should have a simpler form, but it's still going to have problems. One example: for expressing Katakana letters (I use letters in the Unicode sense, here) it's still dicey. There are things interspersed in the Unicode sequence for Katakana that aren't the same thing at all. Unicode calls them lowercase, but that's not quite right. They're smaller versions of Katakana characters which are used more as punctuation or accents than as syllabic glyphs the way the rest of Katakana is. I guess you could write: ア, イ, ウ, エ, オ, カ ... ヂ,ツ ...モ,ヤ, ユ, ヨ ... ロ, ワ ... ヴ (add quotes to taste) But that seems quite a bit more painful than: ア .. ヴ (or ... if you prefer) Similar problems exist for many scripts (including some of Latin, we're just used to the parts that are odd), though I think it's possible that Katakana may be the worst because of the mis-use of Ll to indicate a letter when the truth of the matter is far more complicated. Some of this might be addressed by filtering the list as you go - though I don't remember the method for doing so. Something like .grep, I think, with a regex in it that only accepts letters: (ア ... ヴ).«grep(/:alpha:/) ...or something to that effect. Still, it's possible that we might need something that's more flexible than that. -- Jonathan Dataweaver Lang
Re: Suggested magic for a .. b
Mark J. Reed wrote: Perhaps the syllabic kana could be the integer analogs, and what you get when you iterate over the range using ..., while the modifier kana would not be generated by the series ア ... ヴ but would be considered in the range ア .. ヴ? I wouldn't object to such script-specific behavior, though perhaps it doesn't belong in core. As I understand it, it wouldn't need to be script-specific behavior; just behavior that's aware of Unicode properties. That particular issue doesn't come up with the English alphabet because there aren't any modifier codepoints embedded in the middle of the standard alphabet. And if there were, I'd hope that they'd be filtered out from the series generation by default. And I'd hope that there would be a way to turn the default filtering off when I don't want it. -- Jonathan Dataweaver Lang
Re: Suggested magic for a .. b
Aaron Sherman wrote: Oh bother, I wrote this up last night, but forgot to send it. Here y'all go: I've been testing .. recently, and it seems, in Rakudo, to behave like Perl 5. That is, the magic auto-increment for a .. z works very wonkily, given any range that isn't within some very strict definitions (identical Unicode general category, increasing, etc.) So the following: A .. z produces very odd results. Bear in mind that .. is no longer supposed to be used to generate lists; for that, you should use That said, that doesn't address the issues you're raising; it merely spreads them out over two operators (.. when doing pattern matching, and ... when doing list generation). Your restrictions and algorithms are a good start, IMHO; and at some point when I have the time, energy, and know-how, I'll read through them in detail and comment on them. In the meantime, though, let me point out a fairly obvious point: sometimes, I want my pattern matching and list generation to be case-sensitive; other times, I don't. More generally, whatever algorithm you decide on should be subject to tweaking by the user to more accurately reflect his desires. So perhaps .. and ... should have an adverb that lets you switch case sensitivity on (if the default is off) or off (if the default is on). And if you do this, there should be function forms of .. and ... for those of us who have trouble working with the rules for applying adverbs to operators. Likewise with other situations where there might be more than one way to approach things. -- Jonathan Dataweaver Lang
Re: Perl 6 in non-English languages
Another thing to consider is that Perl 6 is symbol-heavy: that is, keywords are often symbols (such as , =, or $_) rather than words. AFAIK, those symbols are not English, and I would not expect them to change under a natural language transformation of the setting. And to elaborate on Aaron's point, I'd expect such things as function call syntax, operator syntax, method call syntax, and the like to remain the same, as these things aren't English either. As for seeing a natural language variant of Perl, my own thought is that the first such variant might be most useful if it mines a decidedly artificial natural language for its keywords, such as Esperanto or Interlingua. Given that Perl is not English, and merely uses English loan words whenever it needs alphanumeric keywords, I suspect that an Interlingua-based variant might be close enough to, say, a Spanish- or French-based variant that the latter two might possibly end up not being worth the trouble of writing. Not being a linguist, I could be wrong about any or all of the above. As for Aaron's concerns about the use of alternate natural languages complicating the use of modules: note that this really isn't any different from any case where you change the underlying grammar. Perl has a robust module system that assumes that each module is written in the Perl dialect that the module specifies rather than in the dialect that the script is written in, and vice versa; so aside from the optional hassle of translating English-based modules into the preferred natural language setting when you import them (or vice versa, in the case of modules that are written in other natural language variants), there is unlikely to be much of a problem from Perl's perspective. In terms of the Perl community, I suspect that we're best off assuming that most Perl modules and scripts should be written using the default English-based setting for the foreseeable future; the use of natural language variants should be considered to be a niche market. When and if English gets supplanted by some other language as the technical language of choice, this notion can be revisited. Assuming that Perl is still in reasonably wide use when that happens, it will have the flexibility to make the transition. -- Jonathan Dataweaver Lang
Re: r31050 -[S03] refine hyper dwimminess to be more like APL, with modular semantics
Smylers wrote: pugs-comm...@feather.perl6.nl writes: Author: lwall Log: [S03] refine hyper dwimminess to be more like APL, with modular semantics + (1,2,3) »+» 1 # 2,4,4,6 rhs dwims to (1 xx *).batch(3) I'd've expected the output to be 2,3,4; is the 2,4,4,6 copy pasta or am I missing something? Likewise with: +(1,2,3) »+» (1,2) # 2,4,4,6 rhs dwims to ((1,2) xx *).batch(3) Wouldn't that be equivalent to: (1,2,3) »+« (1,2,1) # 2,4,4 ? In fact, could you show what each of the successful examples dwim to in the form of (1,2,3) »+« (A,B,C)? It would make it a bit easier to follow. -- Jonathan Dataweaver Lang
Re: r31054 -[S03] suggestions from dataweaver++
pugs-comm...@feather.perl6.nl wrote: +Regardless of whether the dwim is forced or emergent from the shapes +of the arrays, once the side to dwim on has been chosen, the dwim +semantics on the dwimmy side are always: + + (@dwimmyside xx *).batch(@otherside.elems) + +This produces a list the same length as the corresponding dimension +on the other side. The original operator is then recursively applied +to each corresponding pair of elements, in case there are more dimensions +to handle. Very useful; thank you. One more request: could you provide a few multidimensional examples? For instance: (1, 2, 3; 4, 5, 6) «+» (1, 2; 3, 4; 5, 6) My gut instinct is that this would be equivalent to: (1, 2, 3; 4, 5, 6; 1, 2, 3) «+» (1, 2; 3, 4; 5, 6) # lhs dwimmery in the first dimension ...which in turn would be equivalent to: (1, 2, 3; 4, 5, 6; 1, 2, 3) «+» (1, 2, 1; 3, 4, 3; 5, 6, 5) # rhs dwimmery in the second dimension Or: (2, 4, 4; 7, 9, 9; 6, 8, 8) But I'm not sure. If I'm right, I'd like it confirmed; if I'm wrong, I want to see what the right way to do it is. -- Jonathan Dataweaver Lang
Re: r31051 -[S02] refine Blobs to simply be immutable Bufs, with similar generic characteristics
Darren Duncan wrote: With the above addition, you have both Buf and Blob roles as well as Buf and Blob types. I think you need to make each of those just a role or a type, and then add another named entity which is the counterpart role or type. For example, as you have Stringy as a role with the Str type, maybe you can have Blobby with the Blob. And maybe Buffy with the Buf? The Perl community already seems to like such puns, so why not? I second the notion of a separate role, like Str vs. Stringy. However, the idea here is that a Blob is an immutable Buf. AFAICT, the roles are agnostic concerning mutability: you have Positional, which applies to both Arrays and Lists (IIRC). So you'd have one of Blobby or Buffy, but not both. Or perhaps you'd have another name for it that captures the essentials that Blobs abd Bufs share, without privileging one over the other. Or not. -- Jonathan Dataweaver Lang
Re: Proposal for a new Temporal time-measurement paradigm
Darren Duncan wrote: I think that the most thorough solution is to just take it for granted that there are multiple reference timelines/calendars and that in general it is impossible to reconcile them with each other. Taking this to its logical extreme, there might be a few (admittedly fringe) cases where someone might want a calendar that, even in principle, cannot be reconciled with anything else: consider someone who's writing an application that tracks events in a fantasy setting, such as the Lord of the Rings or the Wheel of Time. (Something like this actually occurred with a friend of mine, who's hobby is pen-and-paper roleplaying games; he wanted to build a database to track the events in his campaign, but ran into the problem that nothing allowed for the creation of a custom calendar such as the one in his fictional setting.) And so, what we can do in general is simply have an Instant role and a Duration role, and pairs of types where each member composes one of those, and then all that needs to exist for temporal routines is an independent collection for each pair that is closed within that pair. This is what I was trying to say. And where you _can_ convert between calendars, you can always write a type-casting routine that takes, say, a Julian Instant as an input and produces a Gregorian Instant as the output. Incidently, it might be possible for two calendar systems to share the same Duration implementation; IIRC, the Julian and Gregorian calendars both use the same concept of seconds, minutes, hours, etc. Likewise, a calendar system might end up with more than one type of Duration: it's always possible to convert between seconds, minutes, hours, days, and weeks; and its also always possible to convert between months, years, decades, centuries, and millenia; but it isn't always so easy to convert between days and years. I could see the Gregorian implementation having two kinds of Durations: short Durations that deal with everything from seconds to weeks, and long Durations that deal with everything from months to millennia. Similarly, there would be a calendar for I don't know what calendar, or varying degrees of such, which is often the case for dated historical records. With this, I'm not quite following you. Could you give an example of what you mean? What calendars/timelines are supported can be implementation-defined and/or provided by modules. Each Perl 6 implementation can be minimalist as far as composing classes go; just provide some programmatically readable way to discover what calendar the system uses so then modules can use that to decide how to make a particular calendar work on any system as possible. We _should_ define a default calendar, which is the one that Perl uses when returning values from now(), etc. That is, Perl 6.0.0 should define the Instant and Duration roles as you outlined above, plus a set of classes that implement those roles according to the Gregorian calendar system. If you want to replace that with another calendar system in your implementation of Perl, the language already has the means of allowing you to do so (e.g., replacing now with a variant that returns a different type of Instant). -- Jonathan Dataweaver Lang
Re: Proposal for a new Temporal time-measurement paradigm
Why do I find myself thinking of roles and classes here? IMHO, we should have a role that represents abstractly a moment in time. This role should, in and of itself, not be tied to any particular calendar; its purpose is so that one can write functions that make reference to instances in time without locking oneself into a particular labeling scheme. We should also have a series of classes that compose that role, each class representing a different calendar scheme. For perl 6.0.0, only one such class need be defined: the one representing the Gregorian calendar. Later on, modules can be written to provide additional classes representing other calendar schemes. Fine in theory; in practice, the big question is: how much can we get the role to do, within the no calendar preference constraint? And a corollary to this: can we get it to do enough to be worthwhile? -- Jonathan Dataweaver Lang
Re: r30357 - docs/Perl6/Spec/S32-setting-library
Log: [Numeric] Move sqrt to Numeric. Remove incorrect return value type of roots. Move cis and unpolar to Real. Add to-radians and from-radians to Numeric. The return value for roots should have been corrected (to List of Numeric), not removed. -- Jonathan Dataweaver Lang
Re: A common and useful thing that doesn't appear to be easy in Perl 6
Damian Conway wrote: I do like the idea of being able to specify the sequence of values of an enumeration by using a series of some kind. And I must say the one that feels most natural is the one that plays on the equivalence of underlying equivalence of enums and constants, namely: enum Perms Read Write Exec Fold Spindle Mutilate = 1,2,4...*; This would also mean you could think of a normal enum: enum Days Sun Mon Tue Wed Thu Fri Sat; as simply defaulting to C = 1...* . Wouldn't that be C = 0...* ? That said, don't we already have a means of assigning specific values to individual members of an enum? I forget the exact syntax, but I believe that it involves an assignment operator within the enumeration. Mind you, this is from memory: enum Perms { Read = 1, Write = 2, Exec = 4, Fold = 8, Spindle = 16, Mutilate = 32 } ...or something to that effect. Clumsy, sure; but it seems to me that this is exactly the sort of thing that hyper-operators were designed to handle: enum Perms { Read, Write, Exec, Fold, Spindle, Mutilate } »=« (1, 2, 4 ... 32) enum Perms { Read, Write, Exec, Fold, Spindle, Mutilate } »=» (1, 2, 4 ... *) ...or something along those lines. I'll check the exact syntax later, when I have more time; but I wonder if something to this effect is already possible with the language spec as written. -- Jonathan Dataweaver Lang
Re: A common and useful thing that doesn't appear to be easy in Perl 6
One more idea: could you implement the sort of thing being asked for by means of a buffer? That is, what's the difference between the bitset being asked for and a Buf[boolean]? And could those differences be addressed by composing a Buf[boolean] into a more appropriate role? Note also that Perl 6 allows for user-defined array indices. Since strings and buffers borrow array syntax for the purpose of accessing individual components, should it not be possible to define a customized index for a boolean buffer? Something like: my $flags is Buf[boolean]{ Read Write Execute Fold Spindle Mutilate }; Again, I'm not sure as to the exact syntax; but it seems to me that something along these lines should be doable. -- Jonathan Dataweaver Lang
Re: numerics, roles, and naming
Ruud H.G. van Tol wrote: Did you consider discrete? I think that Discrete could work quite well as the role that encapsulates the ways in which Integer and Gauss are alike. It may even be genralizable beyond that, although there might be some discord between theory and practice. (In theory, Boolean is every bit as discrete as Integer is; but in practice, it has no use for most if not all of the methods in Integer that pertain to discreteness (factors, remainders, primes, etc.) -- Jonathan Dataweaver Lang
Re: numerics, roles, and naming
Darren Duncan wrote: I'm inclined to consider a Discrete to be broad enough to include Boolean, as well as every single enum type in general; it would also include Order, say. So I would also then add a more specific something, say DiscreteNumeric. There are discrete things that are not ordered (such as gaussian integers), and there are ordered things that are not discrete (such as real numbers or strings). As well, I was using the term Discrete as shorthand for DiscreteNumber, just as Real can be thought of as shorthand for RealNumber: the role's purpose, regardless of name, is to mandate methods that are mostly unique to integer math (e.g., infix:%). As such, it would be silly to apply the role to, say, an enum of the days of the week: Thursday % Tuesday should not equal Sunday; it should be nonsense. And with that in mind, the role (whatever it's called) should not be composed into Boolean, even conceptually: while Boolean values can be mapped to numeric values, they are not inherently numeric, any more than strings are. Never mind the fact that there's no practical application for such things as infix:% when talking about a class with two possible values. More generally, we need to be careful to keep anything new firmly grounded in the practical. If we introduce a Discrete role, it should be because doing so allows us to do something more easily (taking into account the effort involved in writing the role in the first place), or because it makes some task possible that would otherwise be impossible. A role representing discrete numbers might just meet these requirements, in that they let you write functions that depend on being able to, say, factor numbers or find remainders without worrying about what kind of numbers they are. And even here I'm leery, given the fringe status of non-Integer discrete numbers. I'm not at all sure what practical benefit a generic Discrete role would bring to the table. Remember also: we're putting together the Perl 6 core here; we need to show some discretion in terms of what to include vs. what gets farmed out to perl 6 modules. I suspect that gaussian integers belong firmly in the latter camp; as such, they are germane to discussions about core features only to the extent that the core needs to anticipate such things. -- Jonathan Dataweaver Lang
Re: numerics, roles, and naming
Darren Duncan wrote: 2. There doesn't seem to be a role for complex as there is for integer or rational or real or numeric. So, if the boxed Perl complex number is called Complex and the machine native one is called complex or complex128 or whatever, what would one name the role that is common to all of these? I'm definitely in favor of there being a Complex role - not just for the reasons given above, but also to have a common role that applies to a complex number regardless of the coordinate system that's being used to store the value (e.g. cartesian vs. polar). Both should be able to provide you with the real, imaginary, magnitude, and direction components; but classes based off of the cartesian model should be able to do the former two directly and calculate the latter two, and vice versa. A single role that's agnostic about the coordinate system would allow us to use any of these in a function call. For that purpose, I think that the common, underlying role should be called Complex. Following the above pattern, you'd think that Complex would be best used as th role name and so something else is needed for the type, either as some abbreviation, or alternately with additions. Conceivably one could have a complex type defined in terms of any combination of the various real or rational or integer types, such as NumComplex or RatComplex (and FatRatComplex) and IntComplex etc. For practical purposes, I think that the component types for Complex should be standardized as Real - that is, the Complex role should assume that the components do the Real role. As I indicate above, I think that a more significant distinction should be the coordinate system: cartesian complex numbers are essentially optimized for use with addition and subtraction; polar complex numbers are a more efficient choice for multiplication and division; raising a number to a complex exponent works most efficiently if the exponent is cartesian and the result is polar, and vice versa for logs. And so on. For the integer version, my understanding is that number theory already provides a suitable term, Gaussian integer, which is a complex number whose real and imaginary parts are both integers. So I suggest using Gaussian as the name option for an IntComplex. Or maybe better yet for completion sake, make Gaussian a role and something like Gaus the type or something. Hmm... true enough. I'd rather have Gaussian be to Complex as Integral is to Real: a separate role, not necessarily related in any sort of role composition sense, but serving a similar purpose. Note that Gaussian would not have separate cartesian and polar forms; by definition, it operates off of a cartesian coordinate system. While a polar version could exist in theory, it doesn't in practice; and even if it did, it wouldn't be interchangeable with the cartesian version, the way that they are when the components are Real. OTOH, Gaussian definitely has analogs comparable to the differences between Integral vs. Real, in that Gaussian and Integral have the concept of factors and everything that goes with them (e.g., primes, gcf, lcm, remainders, etc.) Perhaps we need a role to encapsulate that notion, much like we have one that encapsulates the notion of order (e.g., before/after). Or would that turn out to be unnecessary clutter, seeing as how we only have two examples of roles that would compose it (Integral and Gaussian), one of which is a highly technical fringe case? Alternately, while we would still need a Complex-specific role, we could possibly avoid a need to explicitly declare some of the composing types if Complex is parameterizable, as AFAIK Rational et al are parameterizable. I'm fine with Complex being parameterizable, as long as Real is the default parameter. 3. I notice that some roles that are longer forms of type names look like nouns, while others look like adjectives. I suppose that adjectives are what you're going after, and the ones that look like nouns such as Boolean and Rational and Real are also adjectives. On the other hand, lots of roles are surely just nouns, such as Failure and Routine. So a question I have is, given the context, is Integral the best name for that role, or would Integer be better? From a layman's view of things, I keep on finding myself wanting to say Integer rather than Integral. That said, it's not that hard to retrain myself; and I do see some benefit to the notion that role names are adjectives while class names are nouns, as long as it's applied consistently to the standard roles. That said, see below. Still: when I first saw Integral, the first thing that came to mind was a calculus operation, not whole numbers. 4. If Integral is better called Integer, or regardless ... Would Numeric be better called Number? Would there by any objection to renaming it such? What are advantages of the former over the latter? Basically, same idea, if we're going more for nouns or
Re: built-in roles/types routine boundary
On Mon, Mar 8, 2010 at 12:40 PM, Darren Duncan dar...@darrenduncan.net wrote: Starting with the context of this piece of Synopsis 2: These types do (at least) the following roles: Class Roles = = Str Stringy Bit Numeric Boolean Integral Int Numeric Integral Num Numeric Real Rat Numeric Real Rational FatRat Numeric Real Rational Complex Numeric Bool Boolean snip So I'm wondering how the existing and anticipated built-in routines/operators/methods/etc are supposed to stratify between all these layers of roles and composing classes. Looking at Synopsis 32 seems to provide some answers, although it looks rather outdated in some respects, I think predating the above table. For example, since you've got the Numeric role, which is composed by integers, including routines that aren't closed over integers such as log, then what routines are left that are just for Integral or Real or Rational? For Integral? There might be remainder-based routines, a concept which only exists for integer math. Also, such things as greatest common factor, or even just factors. But these are all just extensions of the same basic principle: Division is not closed over integers; but instead of banning integer division because the result won't always be an integer, we instead allow it with a best match approximation when the result isn't Integral, and add routines that let us determine which numbers will produce Integrals (e.g., factors), or that produce some sort of Integral representation of the rounding error (e.g., remainders). Similar routines could theoretically exist for Rationals and Reals: if I raise Rational $x to the power of Rational $y, will the result be Rational? If not, what's the nearest Rational value to $x where the result _will_ be Rational? Such routines are not as standard for Rational and Real as they are for Integral (and thus probably aren't suitable for implementation in the Perl library); but the principle remains. As well, all three of Real, Rational, and Integral have a set of operations that Numeric lacks: the comparison operators. Note that Complex does Numeric; but there is no before or after for Complex, so there cannot be a before or after for Numeric. I believe that infix:«before after cmp are supplied by Ordered? (I could be wrong about that.) Whatever it's called, infix:«('', '=', '', '=', '=') are defined in Real, Rational, and Integral, but not in Numeric or Ordered. Likewise, Stringy defines infix:«lt le gt ge leg, but Ordered does not. Or actually, there is just one main thing I want to know right now ... You have roles that look like they're supposed to match one specific class each in particular, such as Boolean for Bool, Integral for Int, etc, ostensibly in case users want to declare their own classes like them. So, would Int actually have any of its own methods, or would they *all* be provided by Integral? Likewise with Bool and Boolean? And so on. My expectation is that all of Int's methods are supplied by Integral; all of Bool's methods are supplied by Boolean; all of Complex's methods are supplied by Numeric; all of Num's methods are supplied by Real; all of Rat's and FatRat's methods are supplied by Rational; and all of Str's methods are supplied by Stringy. Conversely, Bit's methods are supplied by both Integral and Boolean. Mind you, this is only in terms of which methods must the class implement? - which, ultimately, is what role composition is all about. FatRat implements the Rational methods differently than Rat does, and Bit might implement the Boolean methods differently than Bool does. I expect that Stringy, Integral, and Real supply the appropriate default implementations for Str, Int, and Num, respectively. Rational might be a parametric role, with the default implementations handed to Rat and FatRat differing only in terms of which data types they work on; but I could be wrong about this. I expect that Boolean supplies the default implementations for Bool, and I suspect that those implementations _might_ be similar enough to what Bit needs that they can be used there, too. OTOH, I expect that Numeric does not provide the default implementations that are used by Complex. -- Jonathan Dataweaver Lang
Re: The silliness of max()
Moritz Lenz wrote: Please take a look at http://rt.perl.org/rt3/Ticket/Display.html?id=73356: moritz_ rakudo: say max(1..5) p6eval rakudo c05478: OUTPUT«-Inf» * masak submits rakudobug for max(1..5) The weird thing is that it is right, according to the current spec. It says our multi max( Ordering @by, �...@values ) our multi max( Ordering $by, �...@values ) so the range 1..5 is actually bound to @by of the first candidate, leaving *...@values empty, and the default value of -Inf for a max() with no values seems to be quite OK. Of course this is not what the casual reader suspects. My proposed solution is to get rid of the sub form of max() entirely. Any objections? Why not just change the by parameter to be named instead of positional? Frankly, I don't understand why that isn't already the case. -- Jonathan Dataweaver Lang
Re: Gripes about Pod6 (S26)
John Gabriele wrote: Personally, I've always thought that Perl has a very natural feel to it, and deserves a doc markup format that's also natural: [Markdown] (and [Pandoc]'s Markdown has just the right additions, IMO). [Markdown]: http://daringfireball.net/projects/markdown/ [Pandoc]: http://johnmacfarlane.net/pandoc/ I definitely prefer Markdown's approach to inline markup over POD's approach: e.g., _italic_ strikes me as much more legible than Iitalic. That said, Markdown doesn't go far enough in this regard, even with the Pandoc revisions: for instance, there's nothing equivalent to C or R in Markdown. I'm very much in favor of revising Perl 6's documentation system to more closely resemble Markdown; but I'd strongly recommend going through the list of Pod 6 inline tags and seeing how much of that can be reasonably implemented in a Markdown-like fashion. And Markdown gives you nothing in terms of determining how to go about embedding documentation within a code file: for that, you'd still need something along the lines of Pod 6's =begin/=end, =for, and even #=. That said, if a Markdown-like syntax were to get implemented, it might be possible to do away with documentation-specific delimiters, relying instead on the standard comments. I have more thoughts on this; but they'll have to wait for a bit. -- Jonathan Dataweaver Lang
Re: One-pass parsing and forward type references
Larry Wall wrote: But also note that there are several other ways to predeclare types implicitly. The 'use', 'require', and 'need' declarations all introduce a module name that is assumed to be a type name. Just to clarify: it's possible to define a module within a file, rather than as a file; and in fact the usual means of defining classes and roles is an example of this, since they are specialized kinds of modules. Correct? So if I' understanding this correctly, you should be able to say something like: use Foo; class Bar { ... has Foo $x ... } class Foo { ... } ...where the dots are stand-ins for irrelevant code. In effect, use tells the compiler that Foo is a noun, so that the parser knows the proper way to handle it. It also looks for the definition of Foo; but will it start screaming bloody murder if it can't find the definition right away? Have I failed to correctly tell it where to look for the definition? (i.e., do I need to say something like use ::Foo to let the parser know that the definition is in this file?) -- Jonathan Dataweaver Lang
Re: Custom errors on subsets?
Perhaps you could create an error function that temporarily sets the default error message (does perl 6 still have the $! variable?) and returns false; so: subset Filename of Str where { $_ ~~ :f or error ( No such file: '$_' ) } Of course, that's a rather narrowly-defined function, as it's intended only for use in one situation - that is, where a boolean test is likely to be used by the parser to determine whether or not Something Bad needs to happen. I can't think of any case other than custom error messages for subsets where this would happen... Personally, I'd prefer something more along the lines of: subset Filename of Str where { $_ ~~ :f; ERROR { No such file: '$_' } } That is, have the parser look inside where blocks (or any other block that might convert a falsehood to a failure) for an ERROR block that is intended to be executed just as the error is about to be triggered. The primary purpose would be to supply a customized error message (and for that reason, the return value should be a string that can be used as $!); but other possibilities would exist. -- Jonathan Dataweaver Lang
Re: r29381 - docs/Perl6/Spec
On Sat, Dec 19, 2009 at 1:07 PM, pugs-comm...@feather.perl6.nl wrote: for the most generic non-failure undefined value. The CAny type, derived from CMu, is also undefined, but excludes Cjunctions so that autothreading may be dispatched using normal multiple dispatch -rules. The CWhatever type is derived from CAny but nothing else +rules. All user-defined classes derive from the CAny class by default. +The CWhatever type is derived from CAny but nothing else is derived from it. That's cool with me; but if you're going to introduce a default derivation, you should also provide a means to explicitly not do it that way. What if I need to make a new type that, like junctions, should not derive from Any, but isn't a junction? Is it that explicitly deriving from a type that's already outside of Any (such as Mu or junction) automatically disables the implicit Any derivation? -- Jonathan Dataweaver Lang
Re: Comments on S32/Numeric#Complex
Dave Whipp wrote: Moritz Lenz wrote: Dave Whipp wrote: [cut] Contrast with Rat which has both separate accessors and the nude method (a name that could possibly be improved to avoid adult-content filters) suggestions welcome. Attempting to generalize: what we want is an operator that extracts a Seq of values from an object based on a positive criteria. For string objects, this description matches the Ccomb method. Generalizing: my @words = $line.comb( /\S+/ ); my ($num, $denom) = $num.comb( :Ratio ); my ($mag, $phase) = $z.comb( :Complex::Polar ); my ($re, $im) = $z.comb( :Complex::Cartesian ); my ($x, $y) = $vector.comb( [1,0], [0,1] ); I like the idea of a general mechanism for producing a list of an object's attributes; but I don't think that .comb() is the way to go about it. Rather, I'd use .^attr(). my ($num, $denom) = $num.^attr; # $num.WHAT == Ratio; my ($mag, $phase) = Complex::Polar($z).^attr; my ($re, $im) = Complex::Cartesian($z).^attr; my ($x, $y) = $vector.^attr »·« ( [1, 0], [0, 1] ); -- Jonathan Dataweaver Lang
Re: Comments on S32/Numeric#Complex
Dave Whipp wrote: Jon Lang wrote: my ($num, $denom) = $num.^attr; # $num.WHAT == Ratio; my ($mag, $phase) = Complex::Polar($z).^attr; my ($re, $im) = Complex::Cartesian($z).^attr; my ($x, $y) = $vector.^attr »·« ( [1, 0], [0, 1] ); If I'm reading this right, the .^attr is exposing implementation details of the object to get its components. To my mind that is not desirable. The reason that HOW is spelled in allcaps is because it can be used in undesirable ways. In particular, whedn you introspect an object, you're looking at its implementation details. And really, my whole point is that the implementation details are (conceptually) the only thing that distinguishes Complex::Polar from Complex::Cartesian. More on this below. And I think there's a Math error in the 4th line: you don't need the components of a vector to do a dot product with that vector -- so it is just my ($x, $y) = $vector «·« ( [1, 0], [0, 1] ); True enough. Which makes me wonder if all of them are just the dot-product of an object with a role (i.e. it uses the .^attr of the role, not the object): The role may not have a .^attr; in particular, I'd expect the following to be true: role Complex { ... method re() { ... } method im() { ... } method abs() { ... } method arg() { ... } } # no has declarations class Complex::Cartesian does Complex { has $re, $im; ... } class Complex::Polar does Complex { has $abs, $arg; ... } There's another problem with my proposal, namely the fact that introspection of a package's component parts shouldn't be expected to preserve the order of said components. But setting that aside for the moment: Complex.^attr ought to return an empty list, since no attributes were declared in it; Complex::Polar.^attr ought to return a magnitude and an argument (i.e., an angle); and Complex::Cartesian.^attr ought to return a real value and an imaginary value. -- Jonathan Dataweaver Lang
Re: Comments on S32/Numeric#Complex
On Wed, Dec 16, 2009 at 2:10 PM, Dave Whipp d...@dave.whipp.name wrote: The definition of the Complex type seems a little weak. A few things: To get the Cartesian components of the value there are two methods (re and im). In contrast there is just one method polar to return the polar components of the value I'm not sure that this asymmetry is a good thing. Contrast with Rat which has both separate accessors and the nude method (a name that could possibly be improved to avoid adult-content filters) The next thing I notice is that the return value of polar is defined as a Seq (as is the return value of nude), with an English-language definition of that the (exactly) two members of the sequence are. Surely it is possible in a perl6 signature to define the return value more formally, something like: our multi method polar (Complex $nim: -- [ Real $mag where 0..Inf, Real $angle where -π ..^ π ]) is export { ... } Finally, anyone using complex numbers probably wants a conjugate method and/or operator postfix:* almost as much as they want unary-minus: $mag = sqrt( $z * $z* ); All good points. IMHO, what we want is a role that defines four separate accessors (two for cartesian coordinates and two for polar coordinates); a coercion constructor (i.e., it accepts any object that does the role, and returns an object using an implementation to be defined by the class); a postfix:* method; and the usual stuff. And we want a pair of classes, one of which implements the role using cartesian coordinates and another that implements it using polar coordinates. I forget if Perl still allows you to use a fully-defined role as a class; if so, handle the cartesian implementation within the Complex role, with the ComplexPolar class overriding enough of that definition to make it polar instead of cartesian. -- Jonathan Dataweaver Lang
Re: But vs. With
On Thu, Dec 3, 2009 at 6:38 PM, David Green david.gr...@telus.net wrote: I'm wondering whether we can make use of the contrary sense implied by the word but, and have it apply specifically to cases where something is being overridden. In cases where there isn't something to override we could use a different word, such as with. Don't restrict but. Instead, I could see a with infix op that works like but, but with the additional restriction that it cannot change existing behavior; conversely, but _can_ change existing behavior, but doesn't have to. So with becomes the safe version of run-time composition, guaranteeing that whatever you mix in won't disturb existing behavior, and but becomes the unsafe version that you can fall back on when you need to change said behavior. I do wonder, though, whether with should fail if it detects a conflict, or if it should silently resolve any such conflicts in favor of the pre-existing methods. I suppose you could allow for both, with the default being fail on conflict and an adverb being available to force it to quietly resolve the dispute. -- Jonathan Dataweaver Lang
Re: r29111 - docs/Perl6/Spec
Moritz Lenz wrote: Given the above, if one wants to construct a full-precision rational value in terms of 3 Int values analogous to a mantissa and radix and exponent, what is the best way to write it in Perl 6? For example, say I want the following expression to result in a FatRat because presumably that's the only type which will represent the result value exactly: 45207196 * 10 ** -37 How should that be spelled out in terms of 3 integers? why 3? Because three attributes let you define them all as the same kind of int, instead of one having twice as many bits in it as the other: has int128 $whole, int128 $numerator, int128 $denominator vs. has int256 $numerator, int128 $denominator This matters when you reach the upper end of the low-level integer types, such that there is no longer an available integer type that has twice as many bits as the denominator type. But as you say, this is an implementation detail. The important thing for the Spec to note is that user expectations require Rational types to be able to handle a whole number part that's at least as large as the denominator part. Right now, the spec is addressing this in terms of implementation details: it assumes that a Rational will store exactly two numbers, representing the numerator and the denominator, and that the numerator must have twice as much storage space reserved for it as the denominator has. Why twice as much? So that no matter how large the denominator is, the numerator will be large enough to store a whole number part that's at least as large. The doubled bits isn't an end to itself, but merely a means to a more fundamental end. -- Jonathan Dataweaver Lang
Re: unusual invocants
Jonathan Worthington wrote: Ovid wrote: I was asking the special case where: 1. A class consumes two (or more) roles 2. Each roles provides a method with an identical signature 3. The methods are not equivalent and neither role can rely on the other's method With that, you have roles which cannot be composed. You must rewrite one (bad if you don't own it), or omit one.. When a role is composed into a class, it does quite literally become as if it were declared within the class itself (appears directly in the methods list), but equally does not lose its lexical scoping relationship with the role it was declared in either. Would it help to say that when a method declared within a role invokes another method, then we first search the methods within that role's lexical scope? Therefore: role Drinking { method buy_beer() { self.go_to_bar(); ... } method go_to_bar() { ... } } role Gymnastics { method go_to_bar() { } } class DrunkGymnast does Drinking does Gymnastics { method go_to_bar() { # something to resolve the conflict here } } This way, the method buy_beer will always consider methods in its lexical scope first and thus find the role's go_to_bar rather than the one in the class. Of course, if the role's lexical scope had no methods of that name declared within it we'd go elsewhere. This is close to what I've been suggesting in terms of checking which hat the object is wearing (or, alternately, which role it is performing). The main difference is that the final say _must_ be given to the class, because only the class knows enough about the implementation to be sure to do the right thing. For instance, what if you want the DrunkGymnast who goes to the bar in the Drinking sense to automatically be given a citation for doing so? class DrunkGymnast is the place where this issue must be addressed. Or worse: if you have her go_to_bar in the Drinking sense, you set a flag that indicates that she's drunk; and if you have her go_to_bar in the Gymnastics sense while she's drunk, the call should fail. This can only be done if you can define two distinct go_to_bar methods within the class, because Perl no longer has a want mechanism that would allow one method to handle both cases. This is where my proposal for disambiguating the two of them according to the invocant comes in. Ovid need not be right about his statement #2: while the two methods have the same short names (e.g., go_to_bar) and accept the same arguments (e.g., none), they don't necessarily have the same signatures, because they can use the invocant's type to address the in the Drinking sense and in the Gymnastics sense concept that I was using in the previous paragraph. As such, the two methods can have the same names and the same parameter lists, but still have different signatures (and thus different long-names): go_to_bar:(Drinking:) and go_to_bar:(Gymnastics:). The trick would lie in making the compiler smart enough to DWIM in most cases (by figuring out for itself which sense you mean), and in providing an easy-to-use means of explicitly choosing a sense to cover the remaining cases. I have some more thoughts on this; but I'm on a time crunch at the moment, and would really like to get some feedback on the above before proceeding further: have I missed anything in my reasoning? -- Jonathan Dataweaver Lang
Re: unusual invocants
TSa wrote: Jon Lang wrote: I have some more thoughts on this; but I'm on a time crunch at the moment, and would really like to get some feedback on the above before proceeding further: have I missed anything in my reasoning? I fully understand what you mean, I hope. But note that all instances of the class that does the two roles do both roles. So the object at hand can't select the dispatch target. So it has to come from the *environment* of the call. I consider this as very problematic because essentially you have to import that into the object so that it can be carried for a while---this is what you call wearing a role hat. We should keep the class dispatch as simple as possible and not mix in the environment of the call into the meaning of an object! Usually, I'd agree with you - and even here, I'd say that if you can somehow resolve the dilemma without reference to the environment, that would be preferable. However, the only options that appear to be available without it are the two that Ovid outlined: rewrite one of the roles, or omit one of them. Both of these options become impractical once you account for the likes of CPAN: * Rewriting one of the roles may not be possible if the programmer doesn't own either of the offending roles; and even if it is possible, it likely involves a massive search-and-replace operation that isn't easily automated. * Omitting one of the roles is reasonable as long as you can guarantee that the overall concepts that the roles represent shouldn't be mixed (as is arguably the case for the traditional Dogwood example); but it's less than satisfactory when the only reason they can't be mixed is that each role's author made an unfortunate naming choice for one of the methods. My proposal isn't perfect, either: if an established routine fails to place the appropriate hat on the schizophrenic object, the environment-based disambiguation won't DWIM and the programmer will be forced to explicitly resolve the conflict before passing the object into that routine. Still, I don't get the same sense of it being a potential show-stopper the way that I get from the alternatives. But, as always, the devil's in the details. Perhaps someone _can_ provide a means of rewriting one of the roles in a way that won't break anything (the interface, the compiler's back, or the programmer's mind). And it may turn out that my proposal is unworkable once we start looking into the details of how it would be implemented. You mentioned that my approach involves importing a bit of the environment into the object for a while. How might this be done in a way that won't wreak havoc? One possibility would be to hide it away as a trait of WHAT, and then look for that trait when it comes time to disambiguate the schizo invocants: sub party(Drinking $x) { # $x.WHAT:role = Drinking ... $x.go_to_bar; ... # same as $x.go_to_bar:(Drinking:) } sub compete(Gymnast $x) { # $x.WHAT:role = Gymnast ... $x.go_to_bar; ... # same as $x.go_to_bar:(Gymnast:) } sub joke($x) { $x.WHAT:role is not set ... $x.go_to_bar; ... # can't be resolved without more information given Gymnast $x { # $x.WHAT:role = Gymnast ... joke($x); ... # the joke is about a Gymnast's bar. } Likewise, a method that originated in Drinking (such as .buy_beer) would set self.WHAT:role to Drinking, thus resulting in any call to .go_to_bar getting the right method from the class. (Thanks for the example, Jonathan; I hadn't thought of that rather obvious case.) If DrunkGymnast replaces .buy_beer or adds a new method that calls .go_to_bar, it won't automatically have knowledge of which hat it should be wearing; but that's OK, because it's expected to know about both hats, and can explicitly don the right one before (or when) calling the conflicted method. It's only those environments that can't be expected to know about the dual possibilities that concern me. What other problems might arise, and how might they be solved? -- Jonathan Dataweaver Lang
lvalue methods
I recently attempted to write a sample mutable role that made use of a number of lvalue methods, and I had a bear of a time getting it to work. Could we arrange for a more intuitive option to be available? For example, allow the programmer to pass a writer code block in through the rw trait, and assume that the default codeblock is a reader codeblock. Something like: method x() is rw( { $.x = $_ } ) { return $.x } The idea is that if this is being called as an rvalue, the { return .x } block would be called, but if it's being called as an lvalue, the { .x = $_ } block would be called. The above example is of course trivial. A more serious example might be one based off of a coordinate system: role point { has Num $x, Num $y; method angle() is rw( { $.x = .r * cos($_); $.y = .r * sin($_) } ) { return atn($.y/$.x) } method r() is rw( { $.x = $_ * cos(.angle); $.y = $_ * sin(.angle) } ) { return sqrt($.x * $.x + $.y * $.y ) } } This strikes me as being much more readable than the current approach of explicitly returning a proxy object. I'd even be fine if the above were treated as syntactic sugar for the creation of a proxy object - that is, have: method x() is rw( { $.x = $_ } ) { return $.x } be exactly equivalent to something like: method x($val) is rw { return new Proxy: FETCH = method { return $.x }, STORE = method { $.x = $_ } } ...but without the programmer having to worry about how to access the role's attributes from within the proxy object. -- Jonathan Dataweaver Lang
Re: Aliasing methods in CPAN roles
Raphael Descamps wrote: I personally don't understand why we don't have a exclude and alias operator in Perl 6 but I have not read all the synopses and don't have an overview. I don't think that it's explicitly spelled out anywhere; but the reason is fairly straightforward: exclude and alias would break the interface. Take Stringy as an example: when a class says does Stringy, it's making certain promises about its syntax and semantics: e.g., it will have a method say, and method say should result in sending a string of text to an output stream. Thus, any routine that asks for Stringy $x as one of its parameters should be able to put $x.say in its code and get the expected results. But if Foo does Stringy but excludes or aliases .say, a routine that asks for a Stringy $x but receives a Foo $x will run into problems the moment $x.say shows up in its code. If .say was excluded, the semantics are no longer available at all. If it was aliased, the semantics are still available under another name; but that does the routine no good, because it has no idea what the new name is, or even that it exists. Either way, $x.say will not do what the routine intended it to do. The interface is broken. -- Jonathan Dataweaver Lang
unusual invocants
In Aiasing methods in CPAN roles, David Green wrote: Jon Lang wrote: David Green wrote: I would expect that role Logging { method log(Numeric $x:) {...} } means the invocant is really of type Numeric Logging, without Logging having to do Numeric. On the other hand, I can see that strictly that might not make sense, so perhaps I really do need to create a compound NumLog type first, so I can have method log(NumLog:)? I think you should need to do this. That's cumbersome, though. I don't want to create some new type, that happens to do Numeric and Logging (in addition to other stuff it might do); I want to affect everything else that does both roles. That is, I don't want my special log() method to work only for other types that explicitly do NumLog; I want it to work for any type that directly does Numeric does Logging. But if Logging doesn't do Numeric, why should it be expected to provide a method that assumes that it does? -- Jonathan Dataweaver Lang
Re: Aliasing methods in CPAN roles
Raphael Descamps wrote: In the original traits paper the aliasing is not deep: to respect the flattening property, the semantic of the role must not change, so aliasing a recursive method will call the original method. It's a known theoretical weakness of the traits paper and freezing roles try to solve this problem. It's a problem that doesn't exist if you don't alias. However, you run into another problem; namely, what to do if two roles provide semantically incompatible definitions for the same method. To be fair, ailasing doesn't solve the problem either, for the reasons that I outlined in my last post (i.e., aliasing breaks the interface). And freezing roles doesn't solve the problem either; it just specifies which role is broken in the combined interface. As far as I can tell, there are only two solutions that actually solve the problem: don't compose two roles that have incompatible methods, or find a way for the incompatible definitions to coexist under the same name. The former approach works off of the theory that if the names are the same, the semantics ought to be compatible; and thus incompatible semantics are a sign of poor design of the base roles. In an environment where the programmer has the ability to rewrite everything with which he's dealing, this makes a great deal of sense. But as Richard pointed out, CPAN is a counterexample to this: it is unreasonable to assume that two modules imported from CPAN, written in isolation by different authors, will never provide conflicting roles due to nothing more than conflicting naming conventions - roles that, in concept, ought to be able to be used together. As I understand things, Richard's proposed solution is to alias one of the offending methods during the import, effectively rewriting the source module to use a different name for the offending method, for the sole purpose of exporting to the target application. IMHO, this only works if you follow the chain of compositions all the way and alias everything. That is: role Foo { method x; } role Bar does Foo { method x; } role Baz does Foo { method x; } If you want to alias Bar.x on import, there should be an implicit aliasing of Foo.x as well, which would lead to the implicit aliasing of Baz.x too. It's the only way to avoid broken interfaces: you need to change all related interfaces to remain compatible with the one that you change, both up and down the composition chain. Needless to say, this strikes me as impractical, due to the effort involved in figuring out what needs to be aliased and what doesn't. Another possibility would be to borrow a page from XML Namespaces, which addressed a similar problem: allow the programmer to require imported elements to be referenced in terms of the module from which they were imported. E.g.: use Kennel prefix Foo; # imports role Dog use Forest prefix Bar; # imports role Tree class Dogwood does Foo-Dog does Bar-Tree { ... } my $dogwood is Dogwood; $dogwood.Foo-bark; $dogwood.Bar-bark; The idea here is that prefix Foo and prefix Bar cause every name that gets imported from that module to be prefixed with that string. So class Dogwood wouldn't have a bark method: it would have a Foo-bark method and a Bar-bark method. IOW, the above would be equivalent to: role Foo-Dog { ... method Foo-bark { ... } ... } role Bar-Tree { ... method Bar-bark { ... } ... } class Dogwood does Foo-Dog does Bar-Tree { ... } my $dogwood is Dogwood; $dogwood.Foo-bark; $dogwood.Bar-bark; -- Jonathan Dataweaver Lang
Re: unusual invocants
David Green wrote: Jon Lang wrote: In Aiasing methods in CPAN roles, David Green wrote: I don't want my special log() method to work only for other types that explicitly do NumLog; I want it to work for any type that directly does Numeric does Logging. But if Logging doesn't do Numeric, why should it be expected to provide a method that assumes that it does? Well, I don't want all objects that do Logging to do Numeric; I just want to have custom methods for those that do happen to do both. ...which strikes me as a perfect argument for putting those methods in a role that does both. If I can put ad hoc compound types into a signature, e.g. foo(Numeric Logging) instead of foo(NumLog), then why shouldn't it be possible to define a method that way? Or conversely, should compound types in signatures be disallowed, and forced to use NumLog/whatever also? Because a method is part of a role, and ought to abide by the same terms by which the role abides. If Logging doesn't do Numeric, it shouldn't have any methods in it that won't work unless it does. -- Jonathan Dataweaver Lang
Re: Aliasing methods in CPAN roles
David Green wrote: Jon Lang wrote: This implies that both Logging and Math do Numeric, since the invocant ought to be of a type that the class does. I would expect that role Logging { method log(Numeric $x:) {...} } means the invocant is really of type Numeric Logging, without Logging having to do Numeric. On the other hand, I can see that strictly that might not make sense, so perhaps I really do need to create a compound NumLog type first, so I can have method log(NumLog:)? I think you should need to do this. Or can I create a method outside of any role: role Numeric {...} role Logging {...} method log(Numeric Logging $x:) {...} (of course, that might be implicitly creating an anonymous compound type for me...) Last I checked, all methods must be members of a class or role. I think that what you're actually looking for (for the purpose of illustration) is Logging::log:(Numeric $x:) and Numeric::log:(Numeric $x:). Oh, yes! If $x does Numeric and $x does Logging, then it has a class that has already encountered the potential conflict and resolved it in some way. For example: class Baz does Numeric does Logging { method log(Numeric $x:) {$x.Numeric::log;} method log(Logging $x:) {$x.Logging::log;} } #`Baz postpones the decision until it knows which role it's being asked to play: Numeric or Logging. Baz illustrates my proposal: if $x is a Baz, it will need to check the context to see if it's supposed to be acting like a Numeric or like a Logging, and will act accordingly - or it will complain about ambiguity if it can't figure out which role to play. And the definition for Baz works because Logging does Numeric. I suppose given that I want Logging's method log(Numeric Logging:) rather than its log(Any Logging:), the second method there should really be: method log(Numeric Logging $x:) {$x.Logging::log;} I suppose that that would work, too. (The only way to have the same sig twice would be something like if Logging defined a special version of log() for Numeric objects, while Numeric defined a special log() for Logging objects -- but semantically that ought to mean the same thing in both cases, so we do want a single method to handle that.) And if you limit yourself to referencing types that the method's role does, this won't be an issue. If you can't tell by the routine's signature, my own preference would be to make it explicit by means of a given block: given Logging $x { .log } # logs like a Logging given Numeric $x { .log } # logs like a Numeric I also thought given sounded good for this, but it would have to work differently from a normal given: if $x doesn't do Logging, then it needs to skip the block. (Also, it looks very close to casting: given Logging($x). Maybe something a bit more visually distinctive would be helpful, something like given $x as Logging, etc.?) IMHO, given $x { ... } is effectively syntactic sugar for $x - $_ { ... }, and given Numeric $x { ... } would be syntactic sugar for $x - Numeric $_ { ... }. If $x doesn't do Numeric, the default behavior should be a fail. $x - Numeric $n { ... ; $n.log ; ... } What I like about this is using a sig to apply the context, so no new syntax is needed. (But I'll suggest something new for - in general: what if $x - Numeric with no $n variable were shorthand for $x - Numeric $x is rw, i.e. a shorthand that used the same variable name inside the block as the one being passed in? That would be useful in cases like this where we don't particularly want to rename $x.) It wouldn't always be workable; for instance, @a - Numeric, Stringy { ... } would grab the first two element of @a and would put them into parameters; but there would be no obvious names to assign to those parameters. -- Jonathan Dataweaver Lang
Re: Aliasing methods in CPAN roles
David Green wrote: Aha, so the bark:(Dog:) syntax identifies the method by its signature as well, thus distinguishing it from the .bark:(Tree:) method. This works fine when the sigs can distinguish the invocants, which is very common. However, I could have ambiguous methods even including the signatures. Suppose I have a Logging role that provides a log() method for printing some info about a variable. In particular, I have method log(Numeric $x:) { ... } because I want to handle Nums specially (say, round them off before printing). Meanwhile, suppose I also have Math::log(Numeric $x:). So you have Logging::log:(Numeric $x:), and you have Math::log:(Numeric $x:). This implies that both Logging and Math do Numeric, since the invocant ought to be of a type that the class does. (And incidentally, this brings up another issue: as written, Math isn't a class; it's a module. Modules generally don't do roles, assuming that they even can.) Note further that in the setting, you actually have Math::log:(Numeric $x). Modules usually don't have methods, and so their routines generally don't have invocants. I think that what you're actually looking for (for the purpose of illustration) is Logging::log:(Numeric $x:) and Numeric::log:(Numeric $x:). Continuing on with that: If $x does Numeric and does Logging, then $x.log won't be able to decide which method to call, unless maybe it's in a sub like foo(Numeric $x) that can know to provide Numeric context to $x. If $x does Numeric and $x does Logging, then it has a class that has already encountered the potential conflict and resolved it in some way. For example: class Foo does Numeric does Logging { method log(Numeric $x:) {$x.Numeric::log;} } # Foo picks out the method from Numeric. class Bar does Numeric does Logging { method log(Numeric $x:) {$x.Logging::log;} } # Bar picks out the method from Logging. class Baz does Numeric does Logging { method log(Numeric $x:) {$x.Numeric::log;} method log(Logging $x:) {$x.Logging::log;} } #`Baz postpones the decision until it knows which role it's being asked to play: Numeric or Logging. If $x is a Foo, then $x.log will always behave like Numeric::log; if $x is a Bar, then $x.log will always behave like Logging::log. Baz illustrates my proposal: if $x is a Baz, it will need to check the context to see if it's supposed to be acting like a Numeric or like a Logging, and will act accordingly - or it will complain about ambiguity if it can't figure out which role to play. And the definition for Baz works because Logging does Numeric. You cannot define a class that does Logging and does Numeric without defining at least one log method, because they conflict; and a class must somehow resolve all such conflicts. Outside foo, or inside a sub like bar(Any $x), I need some other way to indicate which log method I mean. $x.log:(Numeric:) won't work here, because both roles provide a method with that name and signature. As I indicated above, it will work, because $x.WHAT will have addressed the matter already. In the Foo and Bar cases, it addresses the matter by picking one or the other and preventing access to the one it doesn't pick; this is a viable stratagem if Logging and Numeric are semantically similar (and, seeing as how Logging does Numeric, they probably are). In the Baz case, it addresses the matter by making two options available according to the role being played: Numeric or Logging. All you have to do then is to somehow indicate which role is being played. If you can't tell by the routine's signature, my own preference would be to make it explicit by means of a given block: given Logging $x { .log } # logs like a Logging given Numeric $x { .log } # logs like a Numeric But I could see other alternatives: .log given Logging $x; # assumes the inclusion of a given statement modifier. $x - Numeric $n { ... ; $n.log ; ... } $x.log:(Logging:); The point is that you're never going to have two different log:(Numeric:) methods in the same class. -- Jonathan Dataweaver Lang
Re: Freezing role methods
Ovid wrote: The only way to handle this appears to be renaming one of the x() methods and trying to track down all code which relies on it and changing it. This essentially violates the problem we're trying to solve with traits, er, roles. In short, under the original traits model, you have roles you can't compose together. The paper argues that in languages which have public and private methods, that the composing class is allowed to decide which x() method it needs (if any) and that it can *freeze* the other x() method. That is to say, the x() in question would become private and statically bound to the invocants to ensure that they're always calling the correct x(). How would Perl 6 approach this issue? The fundamental problem is that there are times when you need both versions of a given method to be available, but you don't want to rename either of them. This leads to a namespace clash. The initial possibility that springs to mind would be to use longnames to disambiguate between the two options - specifically, by means of the invocant: role T1 { method foo() } role T2 { method foo() } class C does T1 does T2 { method foo(T1 $self:) { $self.T1::foo() } method foo(T2 $self:) { $self.T2::foo() } } ...or something to that effect. You'd still have a disambiguation issue, in that you'd somehow need to specify which hat an object of class C is wearing when you try to call the method. (I like this approach because it requires you to explicitly identify that the class is deferring the disambiguation, rather than having it silently occur behind the scenes.) Much of this could be handled implicitly, by means of which role was requested when the object was passed into the current block: sub bar (T1 $x) { ... } sub baz (T2 $x) { ... } my C $x; bar $x; Since bar is expecting an object that does T1, code within bar should resolve the ambiguity involving foo in favor of foo:(T1:) - that is, within the lexical scope of sub bar, $x is wearing its T1 hat. Ditto with baz and T2. In other cases, there may be no way to implicitly disambiguate. In those cases, there would need to be an explicit way to decide which hat the object is wearing. My gut instinct would be to use the same syntax as is used to coerce an object into a particular class, but with a role name instead of a class name. It differs from coercion in that it wouldn't actually change the underlying object; all it would do would be to decide which role to favor when resolving disputes of this sort. In short, resolve the dilemma by allowing the class the option of deferring the disambiguation until the method is called, and then to try to resolve it first by means of the overall context in which the call is made. This Schrodinger's method approach doesn't fix everything; but I suspect that it should usefully handle the majority of problems that arise. -- Jonathan Dataweaver Lang
Re: Freezing role methods
David Green wrote: Or to look at it the other way around: Since we refer to things by name, those names have to be unique everywhere; so let's start out with long, fully-qualified names everywhere: $dog.Dog::bark(), $tree.Tree::bark(), $i.Int::succ, etc. Now everything's fine -- except that our fingers are getting tired from all that typing. We want to use shortcuts to say things like $dog.bark, because there's only one place that $dog can legitimately find a bark() method, and that's in the Dog class, so both we and Perl can easily figure out what is meant. On the other hand, $dogwood.Dog::bark cannot be simplified by leaving out the Dog:: because then it would be ambiguous. But if we look at it as starting with full names everywhere, and seeing what we can leave out (rather that starting with short names and having to add stuff in), I think it's not surprising. On the gripping hand, if we have a function train(Dog $d), then we can safely assume that within the lexical scope of train, $d is supposed to be treated as a Dog. So within that lexical scope, it should be safe to leave off the Dog::. If you pass $dogwood into this method, the ambiguity between Dog::bark and Tree::bark gets resolved in favor of the former; so $d.bark _still_ barks like a Dog, even though $d is actually a Dogwood. That's what I was meaning when I talked about wearing hats: while it's within the train() sub, $dogwood is wearing its Dog hat and barks like a Dog. I really don't think that deferring the decision works. The freezing technique described in the paper allows the consumer, C, to statically bind the method foo() in the methods in the appropriate role which call it. The problem with freezing some methods into private ones is that those methods weren't meant to be private; if my role provides a .bark method, I need to be able to call it. And more to the point, subs that aren't expecting a Dogwood should still be able to accept it in its role as a Dog, call .bark, and expect it to bark like a Dog. -- Jonathan Dataweaver Lang
Re: Freezing role methods
David Green wrote: Jon Lang wrote: David Green wrote: On the other hand, $dogwood.Dog::bark cannot be simplified by leaving out the Dog:: because then it would be ambiguous. On the gripping hand, if we have a function train(Dog $d), then we can safely assume that within the lexical scope of train, $d is supposed to be treated as a Dog. So within that lexical scope, it should be safe to leave off the Dog::. Yes; and then my question from last time is whether the sig (Dog $d) soft-casts the arg such that the non-doggy bits of $d still remain, e.g. if inside train() we call a function chop(Tree $t), chop() will unambiguously see the Tree-half of the original Dogwood object. Or will it be hard-cast such that the non-doggy bits are simply lost? (And if so, does an ordinary cast Foo($d) do the same thing, or is one hard and one soft, etc.?) Here, we need a bit of a clarification: are we talking roles or classes? Real example: Numeric is a role; Num is a class. Both can be used in signatures; but only classes can be used to create objects. That is, my Num $x; works; but my Numeric $x; doesn't. As such, you cannot coerce an object to a role; you can only coerce it to a class that does that role. And when passing parameters, you don't coerce the object at all. You smart-match the prospective object against the criteria provided by the signature to determine whether or not it's acceptable. ...which is a long-winded way of saying that it would be like a soft cast: all of the object's capabilities remain intact after being passed as a parameter; the only thing that would change would be that the lexical scope inside the routine would show a preference for the Dog-like features of the object. If you asked for a Dog, it's reasonable to assume that you were given a Dog. And the way I see it working, this preference would only show up in one very specific circumstance: namely, when the object in question has multiple methods that are distinguished from each other by their invocant types. When in a lexical scope that shows a preference for $dogwood to play the role of a Dog, a call to $dogwood.bark() would result in MMD looking at bark:(Dog $dogwood:) and bark:(Tree $dogwood:) and choosing the former. When in a lexical scope where the preference is for $dogwood as a Tree, it would resolve the decision in favor of the latter. And if neither or both are preferred roles for $dogwood, it would fail on account of too much ambiguity. Another clarification: there's a subtle but important difference between $dogwood.bark:(Dog:).() and $dogwood.Dog::bark(). The former calls a Dogwood method that has an invocant that does Dog; the latter calls a Dog method. That is: $dogwood.bark:(Dog:).(); # calls Dogwood::bark:(Dog:) $dogwood.Dog::bark();# calls Dog::bark:() And because of the flattening nature of role composition, the latter doesn't work: after you have composed Dog and Tree into Dogwood, objects that are based on Dogwood no longer have access to the methods provided by Dog or Tree; they only have access to the methods that Dogwood provides. (Caveat: if Dogwood doesn't explicitly provide a method corresponding to something found in Dog or Tree, it does so implicitly.) This is perhaps the most crucial difference between role composition and class inheritance: once role composition is complete, you can ignore the implementation details of the roles that were composed; all that matters is the implementation of the role or class into which they were composed. However, I expect that my Dog $d = $dogwood would strip out everything else, on the grounds that you explicitly requested a pure Dog object. Otherwise you could have said my $d = Dog($dogwood) or maybe my $dogwood.^WHAT $d = $dogwood instead. With my Dog $d = $dogwood, $d is a Dog that was initialized using values gleaned from $dogwood. -- Jonathan Dataweaver Lang
Re: Freezing role methods
Darren Duncan wrote: Jon Lang wrote: Here, we need a bit of a clarification: are we talking roles or classes? Real example: Numeric is a role; Num is a class. Both can be used in signatures; but only classes can be used to create objects. That is, my Num $x; works; but my Numeric $x; doesn't. As such, you cannot coerce an object to a role; you can only coerce it to a class that does that role. Bad example. Both of those would work. Otherwise one of the main reasons for roles to exist, which is to be able to declare a container $x and say that it may hold anything that does role Y, wouldn't be possible. Perhaps a better example is Num.new(...) works but Numeric.new(...) doesn't. -- You are, of course, correct. I think that what I meant to say was my $x is Num vs. my $x is Numeric. -- Jonathan Dataweaver Lang
Overloading Roles
Consider a Range role that is parameterized (i.e., Range of T is a perfectly valid thing to do). According to the spec, the definition of Range depends on the nature of T: * If the lower bound is Numeric, certain coercion rules are attempted on the upper bound; otherwise, the two boundaries must have the same type. ** Speculation: if the lower bound is a Whatever, the boundary type should be determined by the upper bound; if both are Whatever, treat it as Numeric? * if the boundary type has a .succ method, then the Range can provide a RangeIterator; otherwise, it can't. Concerning that last one: would it be reasonable to have a Discrete role that provides a .succ method, and then overload the Range role? E.g.: role Range[Ordered ::T] { ... } role Range[Ordered Discrete ::T] { ... method iterator ( - RangeIterator ) { ... } } If so, then this approach might also be used to handle the special behavior that comes with Numeric types: role Range[Ordered Numeric ::T] { ... } -- Jonathan Dataweaver Lang
Re: generality of Range
yary wrote: I'm confused between using ranges to generate a lazy list and using them as criteria to match against. Indeed. It was my understanding that there was a recent change to Ranges so that they now exist primarily to be used as matching criteria. If you wish to generate a list, the preferred approach these days is the ... infix operator: 1 .. 100 # the range of values between 1 and 100, inclusive. 1, 2 ... 100 # a list of integers. The ability to generate a lazy list using a Range object is now of secondary importance, and should not be a required feature anymore. In particular, :by was removed from Range. -- Jonathan Dataweaver Lang
Re: r28597 - docs/Perl6/Spec/S32-setting-library
How do pred and succ work when given Complex values? More generally: if Complex does Numeric, then Numeric doesn't include Ordered (or whatever it's called), because Complex doesn't do Ordered. As such, you can't used Numeric for any function that depends on the value being Ordered. On Sun, Oct 4, 2009 at 10:15 AM, pugs-comm...@feather.perl6.nl wrote: @@ -255,7 +284,7 @@ =item IStandard Trig Functions - Num multi method func ( Num $x: TrigBase $base = $?TRIGBASE ) is export + Nuermic multi method func ( Nuermic $x: TrigBase $base = $?TRIGBASE ) is export typos: s[Nuermic] = Numeric where Ifunc is one of: sin, cos, tan, asin, acos, atan, sec, cosec, cotan, asec, acosec, @@ -281,14 +310,58 @@ =item atan2 - our Num multi method atan2 ( Num $y: Num $x = 1 ) - our Num multi atan2 ( Num $y, Num $x = 1 ) + our Nuermic multi method atan2 ( Nuermic $y: Nuermic $x = 1 ) + our Nuermic multi atan2 ( Nuermic $y, Nuermic $x = 1 ) More typos: s[Nuermic] = Numeric -- Jonathan Dataweaver Lang
Re: r28597 - docs/Perl6/Spec/S32-setting-library
Moritz Lenz wrote: Jon Lang wrote: typos: s[Nuermic] = Numeric You do have a pugs commit bit, don't you? A what? AFAICT, I don't have any way of editing the Synopses; all I can do is to comment on what I find. -- Jonathan Dataweaver Lang
Re: r28523 - docs/Perl6/Spec/S32-setting-library
On Wed, Sep 30, 2009 at 11:58 PM, pugs-comm...@feather.perl6.nl wrote: Author: moritz Date: 2009-10-01 08:58:00 +0200 (Thu, 01 Oct 2009) New Revision: 28523 Modified: docs/Perl6/Spec/S32-setting-library/Numeric.pod Log: [S32::Num] More thoughts on Inf/NaN Complex, and on comparing Complex and Real numbers Also bring the goodness of the newly defined Numeric and Real roles to some of the signatures. Modified: docs/Perl6/Spec/S32-setting-library/Numeric.pod === --- docs/Perl6/Spec/S32-setting-library/Numeric.pod 2009-10-01 02:34:54 UTC (rev 28522) +++ docs/Perl6/Spec/S32-setting-library/Numeric.pod 2009-10-01 06:58:00 UTC (rev 28523) @@ -175,9 +175,12 @@ =item roots - (in Num) method roots (Num $x: Int $n -- List of Num) is export + (in Num) method roots (Numeric $x: Int $n -- List of Num) is export -Returns a list of all C$nth (complex) roots of C$x +Returns a list of all C$nth (complex) roots of C$x. Returns CNaN if +C $n = 0 , itself if C$n == 0, and is free to return a single CNaN Shouldn't this be C $n 0 ? Also, I'm not sold that this should return List of Num; I'd expect it to return a List of Numeric, with the possibility (and, indeed, likelihood) that subsequent roots will be Complex. +if C$x is CNaN or CInf, or in case of complex numbers if one of the +components is. Ideally, the complex numbers case should be a moot point: if one of a complex number's components is NaN or Inf, then the complex number should be, too (with NaN taking precedence over Inf in the two cases where one component is NaN and the other is Inf). Exception: when a complex number's arg is Inf, the complex number should be NaN: the magnitude may be known, but the direction is completely indeterminate. =item cis @@ -207,6 +210,16 @@ =head2 Complex +CComplex is an immutable type. Each CComplex object stores two numbers, +the real and imaginary part. For all practical purposes a CComplex with +a CNaN in real or imaginary part may be considered a CNaN itself (and +C(NaN + 1i) ~~ NaN is CTrue). I'm not sure that I feel comfortable locking CComplex into rectilinear coordinates as its internal storage method, as there will be cases where the code operates more smoothly if you're using polar coordinates to store the numbers: we should leave the inner workings up to the Parrots to decide. But whichever approach gets used, if either component is NaN, then the complex number should also be NaN. -- Jonathan Dataweaver Lang
Re: object possible representations (was Re: r28523 - ...)
Darren Duncan wrote: Jon Lang wrote: I'm not sure that I feel comfortable locking CComplex into rectilinear coordinates as its internal storage method, as there will be cases where the code operates more smoothly if you're using polar coordinates to store the numbers: we should leave the inner workings up to the Parrots to decide. But whichever approach gets used, if either component is NaN, then the complex number should also be NaN. I'm not sure if the idea is applicable to Perl 6 because Perl 6 already has an alternative but ... One of the features of my Muldis D language is called possreps (possible representations) where you may define more than one alternative set of attributes for a data type (and if more than one, you also define functions to map between each attribute set) and then the implementation can choose for itself which of those representations (or it can pick yet another one of its own) is the actual one used physically behind the scenes and which is virtual, and the user could use either as if it were the real one. What Perl 6 could do with this concept is for example it can define for some classes multiple possible object attribute sets, so users know they can use any of those, and then each Perl 6 implementation can choose what to do natively. So the Perl 6 spec can and should enumerate the various reasonable alternative sets of attributes that a Complex object could have, and the Parrots can choose which to use internally, or could use more than one on a case-by-case basis. Note that ideally this would be a feature that user-defined classes can use, and not just language built-in ones. This sounds a bit like how the multi keyword applies to Perl 6 routines to define several routines that share one name. Perhaps there's a way to say multi class, letting you define several classes that are different implementations of the same thing, with each class definition within the multi class being a possrep. I'm not exactly sure how this would work (you'd need some way to distinguish between the different class definitions, much like multi routines each have a unique long name even though they share the same short name); but it strikes me as being more in keeping with the nature of Perl than nesting several possrep blocks within a single class definition. Perhaps a multi class would involve some sort of implicit version control, with each class definition being given a slightly different version? (Do we still have proto routines to go along with multi routines? If so, you could use a proto class to define common features shared by all of the implementations, such as identifying which roles the multi class does.) Whatever mechanism gets established, the basics would involve being able to establish more than one possible implementation for a class, combined with an ability to identify each implementation's relative strengths and weaknesses so that the compiler has a way to choose which one to use. Now in Muldis D this system is strict and requires that one can round-trip between any 2 possreps and have identical attribute values to what one started with, so the Complex example where conversion would by nature be approximate wouldn't work there; but in Perl or a language where nonidentical round-trips are allowed, this may work for Complex too. But then the implementation would have to always use the same physical representation for all objects of the same class, or else it wouldn't always DWIM when some one tries an exact equality test with objects. If only there was a way for Perl to track exact values for irrational numbers like it does for rationals, rather than trying to approximate them with Num; then one _could_ set up a round trip between rectilinear and polar coordinates that preserves the original values (in theory, at least; you'd still have to figure out how to address the 0 = 2 * pi problem). -- Jonathan Dataweaver Lang
Re: object possible representations (was Re: r28523 - ...)
Some further thoughts: Essentially, this could be done as an extension of the versioning system. The difference between possrep versioning and normal versioning would lie in the means by which the possrep dimension would be resolved if not specified. Namely, the compiler would make the decision based on the natures of the various classes and the preferences of the various function calls. To illustrate, let's say that we have two implementations for Complex: one that's optimized for rectilinear coordinates, and another that's optimized for polar coordinates. class Complex:optrect { ... } class Complex:optpolar { ... } ...where opt is short for optimized implementation. Both implementations of Complex would be able to use rectilinear and polar accessors; indeed, the assumption is that both are capable of handling the exact same interfaces, differing only in terms of how well they handle various aspects thereof. A routine's signature could then include a request for one or the other - say, something like: sub foo(Complex:optpolar) { ... } This would not _require_ that a Complex:optpolar be provided; only that a Complex be provided. But if I were to say my Complex $x;, followed by a large number of foo $x calls, the compiler might choose to implement $x as a Complex:optpolar. More radically, the sig might be able to provide a priority number as well as an option name: e.g., 0 for this is just a suggestion; 1 for it's strongly recommended that you supply this implementation; and 2 for do whatever it takes to supply this implementation. So: sub foo(Complex:optrect 1) { ... } sub bar(Complex:optrect 0) { ... } ...Would mean that if you try to hand foo a Complex:optpolar, foo will coerce it into a Complex:optrect before using it; whereas bar would accept it as is. But if the compiler sees that a lot of bar $x calls are coming up, and $x is currently a Complex:optpolar (or it's at the declarator and no implementation preference has been given), it might convert $x to a Complex:optrect before it gets to the first of them, just to smooth the way. -- Jonathan Dataweaver Lang
Re: r28528 - in docs/Perl6/Spec: . S32-setting-library
On Thu, Oct 1, 2009 at 9:53 AM, pugs-comm...@feather.perl6.nl wrote: The Perl 6 equivalent to Perl 5's Ceval {...} is Ctry {...}. (Perl 6's Ceval function only evaluates strings, not blocks.) -A Ctry block by default has a CCATCH block that handles all +A Ctry block by default has a CCATCH block that handles all fatal exceptions by ignoring them. If you define a CCATCH block within the Ctry, it replaces the default CCATCH. It also makes the Ctry keyword redundant, because any block can function as a Ctry block OK; so any block with a CATCH block in it is effectively a 'try' block... our multi method warn ( Object $o: ) is export -Prints a warning to C$*ERR, which is usually finds C$PROCESS::ERR. See -CSynopsis 16: IPC / IO / Signals for details. +Throws a resumable warning exception, which is considered a control +exception, and hence is invisible to most normal exception handlers. +The outermost control handler will print the warning to C$*ERR +(which is usually finds C$PROCESS::ERR; see CSynopsis 16: IPC / +IO / Signals for details). After printing the warning, the exception +is resumed where it was thrown. To override this behavior, catch the +exception in a CONTROL block. A quietly {...} block is the opposite of a +try {...} block in that it will suppress any warnings but pass fatal +exceptions through. ...while any block with a CONTROL block in it is effectively a 'quietly' block. Right? If so, could this be spelled out in S04, immediately after the discussion about 'try'? -- Jonathan Dataweaver Lang
Re: updated num/str/etc roles/types (was Re: r28502 ...)
Darren Duncan wrote: These generally look like good changes, but I have a few points on which I'd like clarification or to make suggestions. +Perl supports generic types through what are called roles +which represent capabilities or interfaces. These roles +are generally not used directly as object types. For instance +all the numeric types perform the CNumeric role, and all +string types perform the CStringy role, but there's no +such thing as a Numeric object. Common roles include: + + Stringy Please clarify; does Stringy mean a dense homogeneous sequence of primitives in general, meaning that both strings of characters and strings of integers are covered (as with a Perl 5 string) or does it just mean characters? It's a role, which means to me that it's form over function; interface rather than implementation. As such, I'd expect to make Stringy things that are built out of stuff other than characters. If need be, consider making it a parametric role, with a type that defaults to characters. Therefore I recommend that you add Blob to the list of types that does Stringy. In general, a Blob would be a string of bits but it could also be used as a string of bytes etc when its length in bits is an appropriate multiple of 8 say. Stringy operations like the ~ infix should work on Blob too as those aren't specific to characters. (For that matter, maybe infix ~ should also work on arrays or other Positional-doers to mean list-stitching, eg $ary3 = $ary1 ~ $ary2, unless you have another better way to do that or it would confuse people.) Likewise, an analogy to substr() should work on Blob. I'd rather keep infix:~ out of Positional, as you can already do that using infix:,. But I agree about the Blob. + Numeric + Real + Integral + Callable + Positional + Associative +CRat and CNum both do the CReal role. You should add CInt to this list of things that do CReal. No; you should note that CIntegral does CReal. Likewise, you should note that CReal does CNumeric. + Str Perl string (finite sequence of Unicode characters) Bit Perl single bit (allows traits, aliasing, undef, etc.) Int Perl integer (allows Inf/NaN, arbitrary precision, etc.) + Num Perl number (approximate Real) + Rat Perl rational (exact Real) Complex Perl complex number So, now that we have the Numeric role (or the Real role) to be a catch-all label for things that are numeric, does this mean that the Num type now consists specifically of approximate real numbers, conceptually meaning that all Num are floating-point now, rather than Num being Rat plus extra as it seemed before? I think it would be useful for Num to be specifically float semantics all the time, just as Rat is the opposite, as this would help with some predictability. And users who don't care what they get can now use Real in their routine signatures etc rather than Num as the catch-all for real numbers. As well, both Num and Complex should be Numeric, solving the long-standing dilemma concerning Real and Complex numbers in Perl. You might also want to note Ordered (or whatever it's called) as a common role in Perl; Real does Ordered, but Numeric and Complex do not. On a tangent, I suggest renaming S32/Str.pod to S32/Stringy.pod as we now have a name of what Str and Buf both are (and Blob could go in there too). On another tangent, since I'm not sure that Blob literals have been defined in Perl 6 yet, I suggest something that combines aspects of numeric and character string literals, meaning a radix prefix plus string quotes; for example: 0b'1100100101' 0o'57013' 0x'DEADBEEF' :2'1100100101' :8'57013' :16'DEADBEEF' So what about custom delimiters? q:21100100101 q:8[57013] q:16~DEADBEEF~ -As with CHash types, CPair and CMapping are mutable in their +As with CHash types, CPair and CPairSet are mutable in their values but not in their keys. (A key can be a reference to a mutable object, but cannot change its C.WHICH identity. In contrast, the value may be rebound to a different object, just as a hash element may.) So given that PairSet is mutable as a whole (while PairValSet is immutable), can you please clarify the difference between PairSet and Hash, both of which have immutable keys and mutable values? Back when it was Mapping, I was under the impression that the difference involved whether or not the component Pairs were ordered - that is, a Mapping was Positional as well as Associative. I could be wrong. -- Jonathan Dataweaver Lang
Re: updated num/str/etc roles/types (was Re: r28502 ...)
Darren Duncan wrote: Jon Lang wrote: So what about custom delimiters? q:21100100101 q:8[57013] q:16~DEADBEEF~ Well, sure, if its useful; the idea is to amalgam numeric and Str syntax. However, because a Blob literal presumably just has 0..9,A-Z,_ characters in its payload, one of the main uses of custom delimiter flexibility, which is avoiding conflicts with payload elements, isn't necessary. True enough. OTOH, I've also used custom delimiters for visual distinction. -As with CHash types, CPair and CMapping are mutable in their +As with CHash types, CPair and CPairSet are mutable in their values but not in their keys. (A key can be a reference to a mutable object, but cannot change its C.WHICH identity. In contrast, the value may be rebound to a different object, just as a hash element may.) So given that PairSet is mutable as a whole (while PairValSet is immutable), can you please clarify the difference between PairSet and Hash, both of which have immutable keys and mutable values? Back when it was Mapping, I was under the impression that the difference involved whether or not the component Pairs were ordered - that is, a Mapping was Positional as well as Associative. I could be wrong. I was never under the assumption that Mapping was Positional; it was an immutable Hash essentially, and both were associative not ordered. So Mapping was renamed to PairValSet, and PairSet was added as a mutable alternative, hence how the latter differs from Hash is the question. I think only Capture et al are both associative and ordered. If you want an ordered list of Pair, I don't think that has its own type otherwise, but you can parameterize one from Seq/Array/etc. Note that before this most recent change, the document read as As with CHash types, CPair and CMapping are mutable in their values but not in their keys. Now it reads as As with CHash types, CPair and CPairSet are mutable in their values but not in their keys. I may be wrong about what the difference between a Mapping and a Hash used to be; but the above says that Mapping was mutable in its values, not immutable; and that it was replaced by PairSet, not Pair. Presumably, there was already something in place to differentiate a Mapping from a Hash; and whatever that difference was, it still applies to PairSet vs. Hash (which would possibly make PairSet a poor choice of names, depending on the difference). -- Jonathan Dataweaver Lang
Re: r28339 - docs/Perl6/Spec
On Mon, Sep 21, 2009 at 12:01 PM, pugs-comm...@feather.perl6.nl wrote: @@ -65,9 +65,9 @@ The basic underlying concept is that a Parcel behaves much like a list, but it doesn't enforce any context, in a way that no flattening -or coercion is made. When you use the Positional API on a Parcel, it -will include all the listed items, no matter they look like named -arguments or positional arguments. In example: +or coercion is done. When you use the Positional API on a Parcel, it +will include all the listed items, wether they look like named +arguments or positional arguments. For example: 1, 2, :ab the second line should be: will include all of the listed items, whether they look like named -- Jonathan Dataweaver Lang
Re: S26 - The Next Generation
Not actually S26; but closely related: should $=POD and .WHY be read-only? Also, should there be other Pod variables besides $=POD? If so, which ones? Back on the subject of S26: should declarator blocks and aliases be able to introspect the object with which they're associated? That is, should you be able to say things like A.WHAT or A.^methods? (If so, be sure never to say A.WHY.) -- Jonathan Dataweaver Lang
Re: S26 - The Next Generation
Damian Conway wrote: Raiph elucidated: I was thinking it would be possible to reference (compiler) variables representing eg. the name and sig of a block being parsed, or a block or declaration which has just been parsed, or which is just about to be parsed, and that simply referencing these variables would be ok and would save the need to create explicit named anchors. Well, that certainly *is* possible in Pod, which will definitely have access to any compile-time Perl variables, including the following usually bits of information: $?FILE Which file am I in? $?LINE Which line am I at? ?ROUTINE Which routine am I in? ?BLOCK Which block am I in? $?SCOPE Which lexical scope am I in? $?PACKAGE Which package am I in? $?MODULE Which module am I in? $?CLASS Which class am I in? (as variable) $?ROLE Which role am I in? (as variable) $?GRAMMAR Which grammar am I in? Huh. Would you be able to do something like: =begin pod Welcome to $?FILE. ...and have it interpolate the file's name? Or would you need some special markup for this, such as: =begin pod Welcome to A$?FILE. Or would you have to alias the variable and then refer to it? -- Jonathan Dataweaver Lang
Re: S26 - The Next Generation
Damian Conway wrote: Jon Lang kept his promise: I promised some further thoughts; here they are: Much appreciated. You're welcome. As written, declarator aliasing attaches the alias to a piece of code, and draws both the name and the alias from that. What about using a special case of the declarator block for this? That is: class Database::Handle { #=alias has IO $!handle; #=alias my Bool method open ($filename) {...} #=alias =for para Note that the Amethod method of class Aclass stores the resulting low-level database handle in its private Ahas attribute. } or: class Database::Handle { #= has IO $!handle; #= my Bool method open ($filename) {...} #= =for para Note that the Amethod method of class Aclass stores the resulting low-level database handle in its private Ahas attribute. } Definitely interesting ideas, especially the second one. My concern would be that they compete with the #= blocks which might also be needed on such declarations. I don't think that there will be a problem. First, #= is easy enough to distinguish from #=; I don't foresee any confusion. Second, your existing rules for #= already allow for multiple such blocks to be attached to one thing, with the rule being that you append the latter ones to the former ones: #= Class Foo class Foo { #= a sample class used to illustrate. #= This particular class has nothing in it. } ...results in the equivalent of: =for pod Class Foo a sample class used to illustrate. This particular class has nothing in it. With the ability to attach multiple declarator blocks to a single declarator, it should be trivial to replace any one of them with a declarator alias: #= class Foo { #= Class Foo #= a sample class used to illustrate. #= This particular class has nothing in it. } There _is_ a question about when the alias becomes available: #= Class Aclass class Foo { #= a sample class used to illustrate. #= This particular class has nothing in it. #= Xthis assigns to the 'class' declarator alias. Would Aclass in the first line become 'Foo', or would it be whatever Aclass was before that line? My later suggestion of an empty A mitigates this problem by making such references less frequent in practice; but it doesn't eliminate it. My personal preference would be for it to refer to 'Foo'; but that would involve postponing the evaluation of Foo's WHY block until all possible relevant data has been collected. Regardless of what syntax you use for declarator aliasing, I'd also recommend some sort of numbering scheme if you alias more than one declarator of the same type in the same lexical scope: It's definitely an issue I hadn't considered properly. However, I think the correct solution is not numbering (which is always fraught with problems when subsequent maintenance adds an extra declarator in the middle), but rather naming. Like so: I tend to agree. I only proposed numbering as a way of being able to access different declarators without having to explicitly label them. I can definitely understand if this option gets dropped as being too error-prone with regard to maintenance. =alias class Database::Handle { =alias has IO $!handle; =alias open my Bool method open ($filename) {...} =alias close my Bool method close() {...} =for para Note that the Aopen method of class Aclass stores the resulting low-level database handle in its private Ahas attribute, while the Aclose method closes that handle. } The problem with this example is that '=alias name' isn't a declarator alias; it's a block alias. (I don't have a problem with the underlying concept that you're trying to illustrate.) So Aopen would be 'my Bool method open($filename) {...}', when what you'd be looking for in a named declarator alias would be 'open'. (And it might not even be that, unless you loosen the syntactic requirements for a block alias: there are no subsequent curly braces to define how much gets aliased.) Which brings me to: If you adopt the declarator block basis for declarator aliasing, you could even let the documenter choose his own names: class Database::Handle { #= has IO $!handle; #= my Bool method open ($filename) {...} #=m1 my Bool method close () {...} #=m2 This would be a way to do a named declarator alias, for distinguishing between multiple aliases to the same type of declarator. Indeed, you might end up making extensive use of embedded named declarator aliases (ENDAs? :P ), since as soon as you reach the close-bracket, you have the rest of the line available for other uses (such as declarator blocks): class Database::Handle
Re: Synopsis 02: Range objects
On Mon, Aug 31, 2009 at 12:42 AM, TSa thomas.sandl...@vts-systems.de wrote: HaloO, Jon Lang wrote: '' and '=' numify their arguments before comparing them. 'lt' and 'le' stringify their arguments before comparing them. 'before' compares its arguments without any coercion. Note that there's no equivalent to '='. This last one is !after and !before is '='. Only when total ordering is involved. -- Jonathan Dataweaver Lang
Re: Synopsis 02: Range objects [recap]
On Thu, Aug 27, 2009 at 2:59 AM, Jon Langdatawea...@gmail.com wrote: Michael Zedeler wrote: Jon Lang wrote: As for Str, I'm not sure that we should go so far as to say that you _can't_ create RangeIterators over them, so much as to say that the default step algorithm is defined only for single-character strings, and fails if you give it anything else. In particular, the programmer should be allowed to enable Str-based RangeIterators by explicitly supplying his own step algorithm. That is: 'aa' .. 'zz' # Error in list context: default stepper rejects multi-character endpoints 'aa' .. 'zz' :by(stepper) # custom stepper overrides default concerns The difference between this and the triple dot-operator is that we provide an upper bound (and are forced to use the :by-adverb). Is it worth the while? It _does_ give you an upper bound, which ... doesn't do. This is only a half-formed thought at the moment, so please bear with me: maybe Ranges should extend the triptych that exists with comparison operators. That is, you have before and after, lt and gt, and and ; you also have cmp, leg, and =. Perhaps .. should be treated as the numeric operator, and equivalent Str and generic operators should be supplied separately. I'd be inclined to spell the generic Range operator - the one corresponding to before/after/cmp - as to. I'm not sure how the Str-based one ought to be spelled. With .., there should be automatic coercion of both endpoints to numbers, just as there is with and . With to, there should be no coercion at all, just like before after, and cmp. And just like .. should nummify, the to operator should stringify? Sounds nice. No. Technically, there should be three versions: a generic version that does no coercion; the version that nummifies; and the version that stringifies. I can only think of two names to use; so unless someone else can come up with a viable third name, we have to do without one of the three. The one that stringifies is the most expendible, since one can always explicitly stringify when no coercion is implicitly done, but there's no way _not_ to stringify if it _is_ implicitly done. And stringified ranges aren't nearly as important to have as numified ones are. -- Jonathan Dataweaver Lang -- Jonathan Dataweaver Lang
Re: Synopsis 02: Range objects
smuj wrote: TSa wrote: HaloO, David Green wrote: For certain discrete ordered types, like Int, both ways work out the same, and since Ints are the most common and most obvious use for Ranges, it's easy to overlook the confusion. The case with strings is a good example: it really doesn't make sense that a value not produced by a range nevertheless lies between its endpoints. Why not have a separate Interval type? I see no problem when a Range matches for values which are not produced by a RangeIterator. I expect 2.5 ~~ 1..5 to be true even though 2.5 is not in 1,2,3,4,5. I suspect that the double meaning of Ranges is going to confuse some people and bite others. If things stay as they are, I hope that the use of :by will be flagged as a syntax error if used in literal Range smart matching. Of course, that doesn't help the unsuspecting when variables are being used, ala 2.5 ~~ $myrange. Another possibility is that literal Range smartmatching works as is in the absence of :by (that is, with a Range), but becomes a set membership test in its presence (i.e., with a RangeIterator). Or not; see below. (For the record, 2.5 ~~ '!'..5 is also true on my system, although I don't know why! I certainly wouldn't expect it though :) One explanation would be that it's comparing the String 2.5 to the String-terminated Range !..5. Since 2 falls between ! and 5, so does 2.5. The same applies for 'aaa' ~~ 'aa'..'az'. I find this quite natural. Not sure if you're saying that's something you'd like or if you think that that's something already there. It doesn't match for me using recent(ish) Rakudo. Of course, that could just be me! :) I'd personally prefer it if Ranges just did lists, including when smart matching, but had an interval method or such like for explicit matching against the endpoints, e.g. 2.5 ~~ interval(1..5) # or 2.5 ~~ $myrange.interval I don't like the Huffman encoding: does $x come after $a and before $b? is a common test, and so should be short. I'd rather require you to force it into list context if your goal is to test for set membership. In fact, that might be a clean way of handling its dual nature: in item context, it behaves as a Range object; in list context, it behaves as the RangeIterator. So: 2.5 ~~ 1..5 # true: equivalent to 2.5 ~~ 1 = $_ = 5. 2.5 ~~ @(1..5) # false: equivalent to 2.5 ~~ (1, 2, 3, 4, 5). Incidently, this first example is why I think that Range is intimately related to the various order-related operators, and in particular before and after: its most common use outside of generating sequential lists is to provide a shorthand for $min before $_ before $max and similar range-testing expressions. -- Jonathan Dataweaver Lang
Re: Synopsis 02: Range objects
On Thu, Aug 27, 2009 at 2:36 PM, Mark J. Reedmarkjr...@gmail.com wrote: I think $a = $^x = $b is short enough, and lets you choose between and = on both ends and without having to remember how many dots each maps to. How many dots? Note that there are three sets of comparison operators: '' and '=' numify their arguments before comparing them. 'lt' and 'le' stringify their arguments before comparing them. 'before' compares its arguments without any coercion. Note that there's no equivalent to '='. I'm unclear as to which of these cases '..' is currently like, if any; it may be an unholy hybrid of all three. But for the sake of argument, I'll assume that it's currently like '' and '='. $a ~~ 1..5 # $a ~~ 1 = $_ = 5 $a ~~ 1^..5 # $a ~~ 1 $_ = 5 $a ~~ 1..^5 # $a ~~ 1 = $_ 5 $a ~~ 1^..^5 # $a ~~ 1 $_ 5 What's so hard about that? And if '..' is like 'before', it can do things that can't easily be done otherwise: $a ~~ 1..5 # 1 before $_ before 5 || $_ === 1 | 5 -- Jonathan Dataweaver Lang
Re: Synopsis 02: Range objects
smuj wrote: So you're saying you'd like things to stay exactly as they are at the moment!? :-) Not quite. I'd like to see the effects of context spelled out more clearly than they are; and I'd like a revision so that '..' numifies its endpoints while a new 'to' operator doesn't. That is, restrict '..' to cases when you're defining a range of numbers, and use 'to' to handle all other cases. It might also be nice to have a stringifying version; perhaps 'be', using the same everything's an acronym naming convention used by other stringifying operators (e.g., 'lt' is less than, 'le' is 'less than or equal to', 'leg' is less than, equal to, greater than) - in this case, 'be' would be 'beginning to end'. At the very least, this would avoid the inevitable questions about why there isn't a stringifying version. :) That said, it may not be good for much more than that. -- Jonathan Dataweaver Lang
Re: Synopsis 02: Range objects
On Thu, Aug 27, 2009 at 2:34 PM, Larry Wallla...@wall.org wrote: On Thu, Aug 27, 2009 at 02:21:12PM -0700, Jon Lang wrote: : 2.5 ~~ 1..5 # true: equivalent to 2.5 ~~ 1 = $_ = 5. Current specced behavior for Range objects. : 2.5 ~~ @(1..5) # false: equivalent to 2.5 ~~ (1, 2, 3, 4, 5). Not by current rules; which say the left side matches the list 1..5 as a whole. We don't do implicit junctifying of lists anymore, and haven't for several years. Which points to the correct Perl 6 utterance for that: 2.5 ~~ any(1..5) # false Wherein, as you suggest, the 1..5 in list context does in fact iterate the range to produce individual values. You're right, of course. I keep getting tripped up on those details... -- Jonathan Dataweaver Lang
Re: Synopsis 02: Range objects [recap]
Michael Zedeler wrote: Proposed changes: It shouldn't be possible to construct RangeIterators over Str (apart from single length strings) or Complex using the Range operator (..). I'd go one step further with Complex, to say that Range isn't a useful concept at all so long as before and after are undefined. As for Str, I'm not sure that we should go so far as to say that you _can't_ create RangeIterators over them, so much as to say that the default step algorithm is defined only for single-character strings, and fails if you give it anything else. In particular, the programmer should be allowed to enable Str-based RangeIterators by explicitly supplying his own step algorithm. That is: 'aa' .. 'zz' # Error in list context: default stepper rejects multi-character endpoints 'aa' .. 'zz' :by(stepper) # custom stepper overrides default concerns Next open question: What about Ranges using different types in each endpoint? 1.5 .. 10 :by(0.5) (Rat .. Int) 0 .. 7 Should they be coerced - and in that case to what? If we don't coerce them, what should be returned? This is only a half-formed thought at the moment, so please bear with me: maybe Ranges should extend the triptych that exists with comparison operators. That is, you have before and after, lt and gt, and and ; you also have cmp, leg, and =. Perhaps .. should be treated as the numeric operator, and equivalent Str and generic operators should be supplied separately. I'd be inclined to spell the generic Range operator - the one corresponding to before/after/cmp - as to. I'm not sure how the Str-based one ought to be spelled. With .., there should be automatic coercion of both endpoints to numbers, just as there is with and . With to, there should be no coercion at all, just like before after, and cmp. -- Jonathan Dataweaver Lang
Re: S26 - The Next Generation
I promised some further thoughts; here they are: As written, declarator aliasing attaches the alias to a piece of code, and draws both the name and the alias from that. What about using a special case of the declarator block for this? That is: class Database::Handle { #=alias has IO $!handle; #=alias my Bool method open ($filename) {...} #=alias =for para Note that the Amethod method of class Aclass stores the resulting low-level database handle in its private Ahas attribute. } The rules for what gets aliased would be the same as the rules for what gets annotated. This is more compact than the =alias directive sans arguments approach, as you can put the alias on the same line as the declarator to which it is bound. The downside is that it runs opposite to what declarator blocks usually do: instead of attaching some Pod to the ambient code, it attaches a piece of the ambient code to Pod. That, and alias is appearing in the declarator block where the Pod parser would be expecting content. Perhaps you could use some other symbol to distinguish a declarator alias from a declarator block: e.g., #= represents a declarator alias, while #= represents a declarator block. So: class Database::Handle { #= has IO $!handle; #= my Bool method open ($filename) {...} #= =for para Note that the Amethod method of class Aclass stores the resulting low-level database handle in its private Ahas attribute. } Regardless of what syntax you use for declarator aliasing, I'd also recommend some sort of numbering scheme if you alias more than one declarator of the same type in the same lexical scope: =alias class Database::Handle { =alias has IO $!handle; =alias my Bool method open ($filename) {...} =alias my Bool method close() {...} =for para Note that the Amethod1 method of class Aclass stores the resulting low-level database handle in its private Ahas attribute, while the Amethod2 method closes that handle. } If you adopt the declarator block basis for declarator aliasing, you could even let the documenter choose his own names: class Database::Handle { #= has IO $!handle; #= my Bool method open ($filename) {...} #=m1 my Bool method close () {...} #=m2 =for para Note that the Am1 method of class Aclass stores the resulting low-level database handle in its private Ahas attribute, while the Am2 method closes that handle. } This would be more robust, in that you could rearrange the components of the block without getting the aliases mixed up. It might even be worthwhile to make the names mandatory. You might even allow a second parameter which could (for example) be used to engage in introspection of the attached thing, thus allowing you to alias aspects of it other than its name. But I'd consider this to be part of the Pod extensibility, rather than a core feature. An example: my Bool method open ($filename) {...} #=m1 #=m1-type Type =para Am1 is a Am1-type. Result: Copen is a Cmethod. -- An unrelated possibility would be to allow empty A tags in a declarator block, with 'A' being replaced with the name of the declarator to which the block is attached: class Database::Handle { #=[the A class handles a database.] has IO $!handle; #=[the A attribute identifies the database to be handled.] my Bool method open ($filename) {...} #=[the A method opens the database.] } This would attach the CDatabase::Handle class handles the database. to class Database::Handle, the C$!handle attribute identifies the database to be handled. to $!handle, and the Copen method opens the database. to method open. -- Jonathan Dataweaver Lang
Re: Synopsis 02: Range objects
Michael Zedeler wrote: The obvious (default) choice for a step size would be the precision of the more precise of the two values. So 0.0001 in your example above. Well... maybe. How do you specify the intended precision, then? If I want the values from 1 to 2 with step size 0.01, I guess that writing 1.00 .. 2.00 won't be sufficient. Trying to work out the step size by looking at the precision of things that are double or floats doesn't really sound so feasible, since there are a lot of holes in the actual representation, so 1.0001 may become 1.0, yielding very different results. It could be really nice to come up with something dwimmy, but I can't really se any really good candidates, when it comes to floating point numbers and strings. For floating point numbers, assume a default step size of 1, just like integers; use the :by adverb to specify a different step size, either by supplying a floating point number to be added in or by supplying a block that generates the next step when fed the current one. So: 1.00 .. 2.00 # 1.00, 2.00 1.00 .. 2.00 :by .01 # 1.00, 1.01, 1.02, ..., 1.98, 1.99, 2.00 Also, I want to second David Green's point: we're not talking Range and Interval here; we're talking Range and Series. A Series would be a kind of Range that has the additional ability of generating a list. The :by adverb would be a property of a Series, but not a Range. Using Num for your endpoints would result in a Series; using Complex for your endpoints should result in an error: Complex numbers don't have a viable definition of before or after, let alone between. -- Jonathan Dataweaver Lang
Re: Synopsis 02: Range objects
Mark J. Reed wrote: On Tue, Aug 25, 2009 at 5:58 PM, Jon Langdatawea...@gmail.com wrote: Also, I want to second David Green's point: we're not talking Range and Interval here; we're talking Range and Series. But a series refers to a more general concept than a discrete range. I still think Range and Interval fit better. IME, range and interval are largely interchangeable terms. The only time that they aren't is when range is used in contrast to domain; and even there, it still doesn't refer to a list of discrete values. That's generally referred to as a sequence; unfortunately, that's a term that Perl has already co-opted. using Complex for your endpoints should result in an error: Complex numbers don't have a viable definition of before or after, let alone between. Slight overstatement, IMO. Sure, complex numbers don't form an ordered field: given three numbers, z0, z1, and z2, you can't ask if z0 z1 or z0 z2, at least not without imposing some artificial ordering rule. Even without defining an ordering, though, you can meaningfully ask whether z0 lies within or outside the rectangle formed by z1 and z2, which is a viable (if nonlinear) definition of between. You can only get a Boolean answer, but it's a valid question. It's also every bit as artificial as the ordering rules that can be imposed. It would be just as valid to ask whether z0 lies on the line segment that runs between z1 and z2, or within the smallest circle that includes z1 and z2. And if you _do_ establish an artificial ordering rule, it's also perfectly valid to ask if z0 is after z1 and before z2 (or vice versa, if z2 is before z1). That's just nitpicking, though. It's perfectly reasonable to fail() if someone tries to construct a Range/Series/Interval out of Complex numbers. We can use a different class for complex rectangles if we need them. Agreed. -- Jonathan Dataweaver Lang