Synopsis 02: Range objects
Hi Perl 6 people. I've been looking closely at the definition of the Range class in S02 and the current Rakudo implementation, and I have some comments... It seems that there are two intended uses for this class: Range A pair of Ordered endpoints Lets call the above the interval definition. The |..| operator now constructs a |Range| object rather than merely functioning as an operator. Both sides are in item context. Semantically, the |Range| acts like a list of its values to the extent possible, but does so lazily, unlike Perl 5's eager range operator. And this one the list definition. It seems fair enough to demand that a class supports both the concept of being able to tell whether some value is between two endpoints (even supporting open ranges) as well as being a lazy list in disguise, but this concept only works on countable domains. The most common example is 1 .. 100, which represents both an object that can tell whether some other Integer is between 1 and 100 (inclusive) as well as the list of numbers from 1 to 100. But there are problems if you try extending it to other data types that model over-countable things, such as real numbers. The Range 1.0001 .. 2.15 makes sense as an interval definition, but there can hardly be a useful list definition without defining a step size, at least, making it possible to use step sizes less than one. This issue also surfaces when working with strings. As far as I can see, Rakudo has some other comparison operation, which means that Ranges using String endpoints are not dwimmy in the sense I'd expect: say @(a .. ax).perl; # expands to a .. z, aa .. ax say @(aa .. b).perl; # expands to the empty list As far as I can see, the ordering is like so: sub { $^a.chars cmp $^b.chars || $^a cmp $^b } The code below shows that Rakudo does not currently use lexicographical comparison, which may be surprising. say 'aaa' cmp 'aa'; say 'aaa' cmp 'ba'; say 'aaa' ~~ 'aa' .. 'ba'; The output is: 1 -1 0 The last 0 should be 1 if using normal lexicographical ordering, just like cmp does. It is necessary to consider the data types that we want to use as interval endpoints and carry out some sort of analysis of their domains. The basic requirements are: For the interval definition: there must be an obvious ordering relation, so we can do $a cmp $b on any $a and $b of the given data type. For the list definition: for any value $a of the given datatype, it must be possible to come up with some $b, where no $c exists so $a $c $b. Now for a short analysis of the different data types used as end points: Integers - both interval and list definitions are ok. Str - using lexicographical comparison permits only the interval definition. Using the different comparison operator above permits both, but results in counter-intuitive interval definition. Num - using numerical comparison permits only the interval definition. It should be easy to come up with a way to specify step sizes to support list definition. Complex - neither definitions are possible. I am unsure about how this can be solved, apart from extracting the interval definition to a super class to Range (we could call it an Interval). The backside is that the class returned by the .. operator depends on the operands: Int .. Int - Range Str .. Str - Interval Complex .. Complex - undef, exception or some other bad thing. DataTypeA .. DataTypeB - undef, exception or some other bad thing. The most elegant solution would be if the data types themselves indicated their capabilities. So if the given class has a cmp method working on the same data type, the .. can construct an Interval. If the given class has a next method (my name for a method returning the next value), the .. can even construct a Range. If you want to construct an Interval using non-countable things, you should then be able to provide your own next replacement. Maybe like so: my $range = 1.14 .. 1.82 :by {* + 0.01}; Another option is to provide a completely different operator for constructing Intervals. Darren Duncan brought this up before. See http://osdir.com/ml/perl6-language/2009-02/msg00422.html Regards, Michael Zedeler.
Re: Synopsis 02: Range objects
James Cloos wrote: Michael == Michael Zedeler mich...@zedeler.dk writes: Michael The Range 1.0001 .. 2.15 makes sense as an interval definition, but Michael there can hardly be a useful list definition without defining a step Michael size, at least, making it possible to use step sizes less than one. 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. If they were specified in hex float syntax, such as 0x1.01P0 .. 0x3.123P0, then the (default) step should be 0x0.001P0 (which is the same as saying 1.00390625 .. 3.071044921875 with a step size of 0.000244140625). Fair enough, but again - I guess they are translated straight to some internal representation where the information in this notation would be lost. Just like it would be in decimal notation. Michael Complex .. Complex - undef, exception or some other bad thing. Complex .. Complex should have a defined meaning in p6. A definition which is easy to compute would be the set of points contained by the square which has opposite corners at the two specified points. But is that useful? Complex numbers are mostly for mathematics, so I guess we have to look in that domain for a good use case. In that domain there is no natural ordering of complex numbers, and without some ordering, you may be able to decide what should be in the list to return, but not which order to use. I believe that anything we put into Perl 6 should have obvious use cases and fall natural into place in the domain that the construct in question belongs to. This means we have to come up with a design (there currently is no specification of Complex .. Complex), some kind of use case to as justification and finally a validation that ensures that the design is consistent with other things in the language. An example of an obvious inconsistency is ranges on strings compared to how cmp works. A better definition would be the set of points contained by the circle which has a diameter running between the two points. In that case, you'd really need a step size, since circles tend bend :-) Also, I'd like to see an obvious and intuitive ordering. In both cases, of course, including the points actually on the 1-manifold. Either choice has the same meaning on the real axis as .. generates when given real args, and is useful for interval arithmetic. Something for which p6 is well suited. I'll go and get my old topology book and see what I can find there, but I must admit that I'd prefer if Complex .. Complex was left undefined in the Perl 6 core, leaving it up to anyone to specify it later. Regards, Michael.
Re: Synopsis 02: Range objects [recap]
Thanks to everyone who has posted their thoughts on Ranges. Here are the conclusions I have drawn: Ranges are for checking whether something is within a given interval. RangeIterators are for iterating over elements in a Range with a given step size using :by. We discussed using Series or Sequence in place of RangeIterator, but Series seems too general and Sequence has already been taken. Up to this point, there are no changes to the spec afaik. Proposed changes: It shouldn't be possible to construct RangeIterators over Str (apart from single length strings) or Complex using the Range operator (..). 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? Regards, Michael Zedeler.
Re: Synopsis 02: Range objects [recap]
Jon Lang wrote: 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. Agreed. I should have written that as part of the proposal as well. 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? 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. And just like .. should nummify, the to operator should stringify? Sounds nice. Regards, Michael.
Re: Synopsis 02: Range objects
Karl Brodowsky wrote: Michael Zedeler schrieb: 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. That is a general problem of floats. We tend to write them in decimal notation, but internally they use a representation which is binary. And it is absolutely not obvious what the precision of 1.0001 might be. There could be a data type like LongDecimal in Ruby or BigDecimal in Java, that actually has a knowlegde of its precision and whose numbers are fractions with a power of 10 as the denominator. But for floats I would only see the interval as reasonably clear. Even a step of 1 is coming with some problems, because an increment of 1 does not have any effect on floating point numbers like 1.03e300 or so. Yes. Exactly my point. By the way, do we want to warn if someone writes 1e300 .. 1e301 :by(1) given that the number implementation yields 1e300 + 1 == 1e300? Regards, Michael.
Re: generality of Range
Hi Darren. Darren Duncan wrote: In a project of mine I'm looking to use Perl 6 Range values to represent continuous interval values in the most generic manner possible, meaning that the endpoint values could literally be of any type at all. [...] for a realistic example: my $a = ['Foo', 17] ^.. ['Foo', 23]; ... I would expect $a to be a Range and to be able to get those arrayrefs out of it. [...] Bottom line, is my example line with the ['Foo',17] valid Perl 6 or not, and if not then what could be done about it? The short version is that your example shouldn't be valid Perl 6, because both ordering and successor functions are missing. Look in synopsis 02 and 03 for documentation, but note that this particular corner of Perl 6 IMHO still is in flux. My opinion is that for any domain (integers, real numbers, strings, complex numbers, two-element arrays consisting of a string and a number (your example) and anything else you can come up with), you have two requirements that must be met in order to be able to create a well defined Range: 1. There must be a compare operator that can decide which of two objects from the given domain is the greatest (for strings, ge and for numbers ). Lets call it . 2. There must be a successor function, so that given an object from the given domain, say a, successor(a) returns one and only one value from the same domain. 3. Given b = successor(a), there is no c so that b c a (using the same operator as above). And finally, if there are multiple, competing variations for the same domain, I say that they should be left out of Perl 6. Also, in what Synopsis is it documented what the methods are to extract the endpoints et al from a Range object. Or what are they called? Here is some meta-help: if you ever have a Perl 6 object and need to know its methods and attributes, use the introspection API. There is a description here: http://rakudo.org/node/51 Regards, Michael.
Re: r28597 - docs/Perl6/Spec/S32-setting-library
Moritz Lenz wrote: Jon Lang wrote: How do pred and succ work when given Complex values? By adding/substracting 1 from the real part, I'd say. Don't know if that actually makes sense. It doesn't, because succ should always give the next, smallest possible element given some ordering relation. Neither does it make sense for real numbers. Same thing applies to pred. It may be necessary to move methods in the Numeric class that require ordering and countability to somewhere else. You do have a pugs commit bit, don't you? If you find errors, feel free to correct them in the synopsis. I do. If anyone doesn't object, I'd be happy to move the methods down to a subclass (or -role) - at least in the spec (not sure what to do with the code as of now). Regards, Michael.
Re: r28597 - docs/Perl6/Spec/S32-setting-library
David Green wrote: On 2009-Oct-4, at 2:07 pm, Moritz Lenz wrote: Michael Zedeler wrote: It doesn't, because succ should always give the next, smallest possible element given some ordering relation. Where's that definition from? The dictionary. =) It would be confusing to have a successor method for something that isn't orderable and discrete. An ordered continuous type like Real could have .inc and .dec; it just happens that in the common case of Ints, .succ and .inc mean the same thing. Complex could have an .inc method, but I don't think there's any especially obvious choice (because .inc probably wants an ordered type). Would it add 1? or 1+i? Better to spell it out explicitly. Well, Real implies ordering (at least to me ;-), I don't think we have a class or role for countability. A Discrete role would be useful, but is Set good enough for that? Sets could be acting as domains for things such as Integers, so we are on two different abstraction levels there (having Integer implement Set would probably never make much sense, but an Integer object can be part of a Set). Integers, strings and other types have a succ and pred method, but you could say that they draw upon a set (acting as their domain) when they decide the successor and predecessor of any given element. In mathematical terms it makes sense, but I am aware that from an implementation perspective, it sounds somewhat odd. It does, however solve some of the current problems that we have with iterating on Ranges and various other things. Also, the domain should define how to compare objects and could provide details about whether the set is finite, countable or uncountable. Does anyone know if there has been any prior discussions of such an approach? I started changing the spec, but decided against it since I have some 10 years of design discussion to catch up on first. Links to prior discussions will be greatly appreciated. Regards, Michael.
Domains? [Re: r28597 - docs/Perl6/Spec/S32-setting-library]
yary wrote: ... Also, the domain should define how to compare objects and could provide details about whether the set is finite, countable or uncountable. ... Sounds like a role Domain that provides methods (off the top of my head)- ordering - returns Nil if the domain is unordered, or a method implementing cmp if it is ordered succ, pred- returns Nil if the domain is uncountable, or method implementing next item, prior item if countable. Exactly. count - returns Inf if it's an infinite domain, or count of objects if finite. What if counting is an expensive operation? In most cases, the developer will know whether the domain is infinite and just hardwire the result to Inf. Then the .. operator can accept anything that does Domain where ordering is non-Nil, and the ... operator can add the condition that succ/pred are non-Nil. Yes. Moreover, I have realized that Domains can solve a lot of other problems, such as collations. In English, it makes sense to write something like 'a' .. 'z' but the Danish and Swedish counterparts are 'a' .. 'z' followed by 'æ', 'ø', 'å' (Danish) and 'a' .. 'z' followed by 'ä', 'ö', 'å' (Swedish) since there is only one 'z' in unicode (for obvious reasons), collation is something separate from the charset, which can be provided in a domain. Also, encoding magical month names becomes easy (the double parens here are casting to a domain): my $month = ((DateDomain['en_US', '%b']))'Jan'; $month++; say $month; # Feb ...and even... my $date = ((DateDomain['en_US', '%D']))'01/14/2001'; $date++; say $date; # 01/15/2001 Also, this is an extension of the notion of subtypes, augmenting it with ordering and some other relations. Next question is whether the domain shouldn't also provide arithmetic. There is a lot of plumbing to do to fully use this concept, but I believe it could be really useful. Regards, Michael. where
Re: Suggested magic for a .. b
On 2010-07-16 18:40, 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. I'd like to suggest that we re-define this operator on strings as follows: [cut] Ab .. Be defines the ranges: A B andb c d e This results in a counting sequence (with the most significant character on the left) as follows: Ab Ac Ad Ae Bb Bc Bd Be Currently, Rakudo produces this: Ab, Ac, Ad, Ae, Af, Ag, Ah, Ai, Aj, Ak, Al, Am, An, Ao, Ap, Aq, Ar, As, At, Au, Av, Aw, Ax, Ay, Az, Ba, Bb, Bc, Bd, Be which I don't think is terribly useful. I have been discussing the Range operator before on this list, and since it often becomes the topic of discussion, something must be wrong with it. What started it all, was the intention to extend the operator, making it possible to evaluate it in list context. Doing so has opened pandoras box, because many (most? all?) solutions are inconsistent with the rule of least surprise. For instance, when considering strings, writing up an expression like 'goat' ~~ 'cow' .. 'zebra' This makes sense in most cases, because goat is lexicographically between cow and zebra. So we have a nice ordering of strings that even extends to strings of any length (note that the three words used in my example are 3, 4 and 5 letters). As you can see, we even have a Range operator in there, so everything should be fine. What breaks everything is that we expect the Range operator to be able to generate all values between the two provided endpoints. Everything goes downhill from there. With regard to strings, lexicographical ordering is the only prevailing ordering we provide the developer with (apart from length which doesn't provide a strict ordering that is needed). So anyone using the Range operator would assume that when lexicographical ordering is used for Range membership test, it is also used for generation of its members, naturally leading to the infinite sequence cow cowa cowaa cowaaa ... cowb cowba cowbaa For some reason (even though Perl6 supports infinite lists) we are currently using a completely new construct: the domain of strings limited to the lenght of the longest operand. This is counter intuitive since 'cowbell' ~~ 'cow' .. 'zebra' but 'cow' .. 'zebra' does not produce 'cowbell' in list context. Same story applies to other types that come with a natural ordering, but have an over countable domain. Although the solutions differ, the main problem is the same - they all behave counter intuitive. 5.0001 ~~ 1.1 .. 10.1 but 1.1 .. 10.1 does not (and really shouldn't!) produce 5.0001 in list context. I'd suggest that if you want to evaluate a Range in list context, you may have to provide a hint to the Range generator, telling it how to generate subsequent values. Your suggestion that the expansion of 'Ab' .. 'Be' should yield Ab Ac Ad Ae Bb Bc Bd Be is just an example of a different generator (you could call it a different implementation of ++ on Str types). It does look useful, but by realizing that it probably is, we have two candidates for how Ranges should evaluate in list context. The same applies to Numeric types. My suggestion is to eliminate the succ method on Rat, Complex, Real and Str and point people in the direction of the series operator if they need to generate sequences of things that are over countable. Regards, Michael.
Re: Suggested magic for a .. b
On 2010-07-27 23:50, Aaron Sherman wrote: PS: On a really abstract note, requiring that ($a .. $b).reverse be lazy will put new constraints on the right hand side parameter. Previously, it didn't have to have a value of its own, it just had to be comparable to other values. for example: for $a .. $b - $c { ... } In that, we don't include the RHS in the output range explicitly. Instead, we increment a $a (via .succ) until it's= $b. If $a were 1 and $b were an object that does Int but just implements the comparison features, and has no fixed numeric value, then it should still work (e.g. it could be random). Now that's not possible because we need to use the RHS a the starting point when .reverse is invoked. This is exactly why I keep writing posts about Ranges being defunct as they have been specified now. If we accept the premise that Ranges are supposed to define a kind of linear membership specification between two starting points (as in math), it doesn't make sense that the LHS has an additional constraint (having to provide a .succ method). All we should require is that both endpoints supports comparison (that they share a common type with comparison, at least). To provide expansion to lists, such as for $a .. $b - $c { ... }, we should use type coercion semantics, coercing from Range to Sequence and throw an error if the LHS doesn't support .succ. Writing ($a .. $b).reverse doesn't make any sense if the result were a new Range, since Ranges should then only be used for inclusion tests (so swapping endpoints doesn't have any meaningful interpretation), but applying .reverse could result in a coercion to Sequence. Writing for ($a .. $b).reverse - $c { ...} may then blow up because it turns out that $b doesn't have a .succ method when coercing to sequence (where the LHS must have an initial value), just like for $a .. $b - $c { ... } should be able to blow up because the LHS of a Range shouldn't have to support .succ. Regards, Michael.
Re: Suggested magic for a .. b
On 2010-07-28 06:54, Martin D Kealey wrote: On Wed, 28 Jul 2010, Michael Zedeler wrote: Writing for ($a .. $b).reverse - $c { ...} may then blow up because it turns out that $b doesn't have a .succ method when coercing to sequence (where the LHS must have an initial value), just like for $a .. $b - $c { ... } should be able to blow up because the LHS of a Range shouldn't have to support .succ. Presumably you'd only throw that except if, as well, $b doesn't support .pred ? Yes. It should be .pred. So ($a .. $b).reverse is only possible if $b.pred is defined and $a.gt is defined (and taking an object that has the type of $b.pred). If the coercion to Sequence is taking place first, we'll have to live with two additional constraints ($b.lt and $a.succ), but I guess it would be easy to overload .reverse and get rid of those. Regards, Michael.
Re: Suggested magic for a .. b
On 2010-07-29 00:24, Dave Whipp wrote: Aaron Sherman wrote: On Wed, Jul 28, 2010 at 11:34 AM, Dave Whipp d...@dave.whipp.name 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 { ... } As others have pointed out, this has some problems. You can't implement 0..* that way, just for starters. I'd say that' a point in may favor: it demonstrates the integers and strings have similar problems. If you pick items from an infinite set then every item you pick will have an infinite number of digits/characters. In smart-match context, a..b includes aardvark. It follows that, unless you're filtering/shaping the sequence of generated items, then almost every element (a..b).Seq starts with an infinite number of as. Consistent semantics would make a..b very not-useful when used as a sequence: the user needs to say how they want to avoid the infinities. Similarly (0..1).Seq should most likely return Real numbers -- and thus (0..1).pick(*) can be approximated by (0..1).pick(*, :replace), which is much easier to implement. I agree that /in theory/ coercing from Range to Sequence, the new Sequence should produce every possible value in the Range, unless you specify an increment. You could argue that 0 and 1 in (0..1).Seq are Ints, resulting in the expansion 0, 1, but that would leave a door open for very nasty surprises. In practise, producing every possible value in a Range with over-countable items isn't useful and just opens the door for inexperienced programmers to make perl run out of memory without ever producing a warning, so I'd suggest that the conversion should fail unless an increment is specified. The general principle would be to avoid meaningless conversions, so (1 .. *).Seq (1 .. *).pick should also just fail, but with finite endpoints, it could succeed. The question here is whether we should open for more parallelization at the cost of simplicity. I don't know. So either you define some arbitrary semantics (what those should be is, I think, the original topic of this thread) or else you punt (error message). An error message has the advantage that you can always do something useful, later. I second that just doing something arbitrary where no actual definition exists is a really bad idea. To be more specific, there should be no .succ or .pred methods on Rat, Str, Real, Complex and anything else that is over-countable. Trying to implement .succ on something like Str is most likely dwimmy to a very narrow set of applications, but will confuse everyone else. Just to illustrate my point, if we have .succ on Str, why not have it on Range or Seq? Let's just play with that idea for a second - what would a reasonable implementation of .succ on Range be? (1 .. 10).succ --?-- (1 .. 11) (1 .. 10).succ --?-- (2 .. 11) (1 .. 10).succ --?-- (1 .. 12) (1 .. 10).succ --?-- (10^ .. *) Even starting a discussion about which implementation of .succ for Range (above), Str, Rat or Real completely misses the point: there is no definition of this function for those domains. It is non-existent and trying to do something dwimmy is just confusing. As a sidenote, ++ and .succ should be treated as two different things (just like -- and .pred). ++ really means add one everywhere and can be kept as such, where .succ means the next, smallest possible item. This means that we can keep ++ and -- for all numeric types. Coercing to Sequence from Range should by default use .succ on the LHS, whereas Seq could just use ++ semantics as often as desired. This would make Ranges completely consistent and provide a clear distinction between the two classes. Getting back to 10..0 Yes, I agree with Jon that this should be an empty range. I don't care what order you pick the elements from an empty range :). Either empty, the same as 0 .. 10 or throw an error (I like errors :). Regards, Michael.
Re: Suggested magic for a .. b
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 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. 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. I second the above. Ranges are all about comparing things. $x ~~ $a .. $b means is $x between $a and $b?. The only broadly accepted comparison of strings is lexicographical comparison. To illustrate the point: wouldn't you find it odd if 2.01 wasn't in between 1.1 and 2.1? Really? Regards, Michael.
Re: Suggested magic for a .. b
On 2010-07-29 02:19, Jon Lang wrote: 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 am sorry if what I write is understood as an argument against ranges of strings. I think I know too little about Unicode to be able to do anything but point at some issues, I belive we'll have to deal with. The solution is not obvious to me. 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. Yes, but I am sure its due to my lack of understanding of Unicode. Regards, Michael.
Re: Breaking encapsulation by detaching a private-variable-accessing method from one object and calling it on another
On 2010-07-31 20:23, Carl Mäsak wrote: * Today we discovered that it's possible to break encapsulation by detaching a method from an object of one class, and calling that method on an object of another class. Which means that breaking the encapsulation of a foreign class is as easy as creating a custom class with all of the same private attributes, and with a method to print (or otherwise reveal) them. * It is my feeling that such encapsulation-breakage shouldn't be allowed. Do you agree, p6l? I don't really agree. The way OOP is implemented in perl 5 allows breaking encapsulation on many different levels, but I believe this has turned out to be a strength, since it allows you to use in those (very rare?) cases where it is needed. When I found that all objects in perl 6 had fields, I was kind of put off, since it looked to Java-ish. What saves the spirit of perl is that people are still free to hack away (and then there are such roles as postcircumflex that reintroduces the very terse syntax, perl 5 is known for, avoiding the dot-hell of Java). I believe we have a much larger task at hand, which is to write documentation that educates newcomers to use the right tools for the right job. I'd never recommend monkeypatching to a rookie programmer (or those silly .* and .+ method invocators) and I believe we owe people outside the perl community to explain the /intent/ behind the different constructs. Regards, Michael.
Re: Encapsulating the contents of container types
On 2011-08-20 12:02, Damian Conway wrote: Carl asked: * What language components could be provided to put class implementors on the right path so that their classes end up encapsulated by default? Doing nothing should result in the safe behaviour (i.e. full encapsulation). You ought to have to explicitly request anything else. One of the *big* selling points of Perl 6 is the prospect of OO done right. Leaky encapsulation ain't that. Sorry if I am hijacking the thread, but how does the .* and .+ fit into OO done right idea? As I understand it, having a class hierarchy like so: class A { method m { say A.m called } } class B is A { method m { say B.m called } } class C is A { method m { say C.m called } } class D is B is C { method m { say D.m called } } calling D.new().+m(); Produces D.m called B.m called C.m called A.m called Making it an option (and I suspect sometimes even the responsibility) of the caller (reading Calling sets of methods in S12) to choose how dispatch should be done, can hardly be said to be encapsulation (a subset of OO) done right? In other words, any class using .+, .* or $something.WALK( ... ) is - in the best case - violating the responsibilities of its superclasses. The .+ and .* operators still look to me as if someone has been mixing up the chain of responsibility pattern with normal OO method dispatch. On one hand, there is no reason that .* and .+ should use the inheritance hierarchy as the dispatch order if we're looking for some generalized chain of responsibility. On the other hand, explicitly calling each method all the way up the inheritance hierarchy, ignoring the efforts of the individual methods to carry out their specialization of their super classes, just doesn't seem to make any sense. Regards, Michael.
Re: [perl #121454] Can't inline complex constraints in multisub signatures
On 2014-03-29 21:45, Damian Conway wrote: Moritz wrote: To spin the tale further, we need to think about what happens if somebody writes multi foo(1|2e0) { ... } so now we have Int|Num. We could explore the most-derived common ancestor (Cool), or look into role space (Real, Numeric come to mind), or simply error out. Or maybe we need to reconsider the whole idea that it's appropriate to infer type from a smartmatched constraint? [...] In other words specifying a constraint value is a way of applying a smartmatched acceptance test to a parameter, but the type of the acceptance test is typically totally unrelated to the type of the parameter. Which is why it now seems very odd to me that we are currently inferring parameter types from constraint values. I couldn't agree more. This looks like a piece of odd-sized baggage left behind by Moose, where declaring type constraints on attributes is too easily mistaken as actual type declarations. Other languages may provide simple restriction rules for parameter value domains in the shape of types, but in a dynamically typed language, it doesn't make much sense, since there may be conversion paths between the types involved. I'd much more prefer a pure matching language where no assumptions about types are done automatically, forcing me to write explicit type constraints myself, if I believe they are necessary (they should rarely be needed, since having to deal too much with types in a dynamically typed language is counterproductive :-) ). In general - Perl (5) is a great tool because it doesn't force people to deal too much with typing (both implicit and explicit). Lets keep it that way. -- Michael Zedeler 70 25 19 99 mich...@zedeler.dk mailto:mich...@zedeler.dk dk.linkedin.com/in/mzedeler http://dk.linkedin.com/in/mzedeler/ | twitter.com/mzedeler https://twitter.com/mzedeler | github.com/mzedeler https://github.com/mzedeler/
Re: [perl #121454] Can't inline complex constraints in multisub signatures
On 2014-03-31 14:49, Michael Zedeler. wrote: On 2014-03-29 21:45, Damian Conway wrote: Moritz wrote: To spin the tale further, we need to think about what happens if somebody writes multi foo(1|2e0) { ... } so now we have Int|Num. We could explore the most-derived common ancestor (Cool), or look into role space (Real, Numeric come to mind), or simply error out. Or maybe we need to reconsider the whole idea that it's appropriate to infer type from a smartmatched constraint? [...] In other words specifying a constraint value is a way of applying a smartmatched acceptance test to a parameter, but the type of the acceptance test is typically totally unrelated to the type of the parameter. Which is why it now seems very odd to me that we are currently inferring parameter types from constraint values. I couldn't agree more. This looks like a piece of odd-sized baggage left behind by Moose, where declaring type constraints on attributes is too easily mistaken as actual type declarations. Sorry - correction: where declaring type constraints should be where declaring value constraints. -- Michael Zedeler 70 25 19 99 mich...@zedeler.dk mailto:mich...@zedeler.dk dk.linkedin.com/in/mzedeler http://dk.linkedin.com/in/mzedeler/ | twitter.com/mzedeler https://twitter.com/mzedeler | github.com/mzedeler https://github.com/mzedeler/
Re: New parrot feature: reset coros, or not? how to deal with dead coros
Hi Reini. On 2014-10-15 16:21, Reini Urban wrote: Current parrot behaviour for exhausted yields is dying with Cannot resume dead coroutine. parrot coros are designed after lua, but lua does return nil and as 2nd return value announces also cannot resume dead coroutine. most lisp's also behave the same way. As third version the parrot book announced coros to be auto-resetting. This makes no sense to me at all, as coros are usually needed to fetch elements from a lazy list, and when the list is exhausted the state should return to the head of the list automatically? lazy cycling a la ? No auto-reset, please. Just return nil or throw an exception. In other words, make it easy to understand that the coro has been exhausted. It should be next to trivial to reset back to the initial state. The need to automatically reset to initial state is unusual, so don't make it the default. Written by a seasoned user of a fair amount of programming languages. -- Michael Zedeler 70 25 19 99 mich...@zedeler.dk mailto:mich...@zedeler.dk dk.linkedin.com/in/mzedeler http://dk.linkedin.com/in/mzedeler/ | twitter.com/mzedeler https://twitter.com/mzedeler | github.com/mzedeler https://github.com/mzedeler/
Re: Language design
This is another of my points: when presented with all the features in Perl 6 - what is then essential? The essential features - besides being presented up front and center to newbies - are also good candidates for what should go into the core. For instance, why have Complex and Rat numbers in the core? If you're not working in a very specialized field (which probably *isn't* numerical computation), those datatypes are just esoteric constructs that you'll never use. The beauty of Perl 6 is that not only can they be deferred to a module - they may still extend the syntax of Perl 6 once they're loaded. In other words: Perl 6 is perfectly suited to be designed with a tiny core with most features in separate modules, and yet it had been provided with the most feature rich core (*COUGH* bloated *COUGH*) among most languages I know. Regards, Michael. Parrot Raiser wrote Subsets will be absolutely essential, if it is to be possible to learn it with a reasonable amount of time and effort. On 6/16/15, Paweł Murias pawelmur...@gmail.com wrote: I think Perl 6 tries to include too much rather than too little. It will be possible to just use a subset On 16 June 2015 at 10:32, Michael Zedeler mich...@zedeler.dk wrote: On 06/12/15 15:54, Parrot Raiser wrote: Has somebody been following the discussions on types? http://xkcd.org/1537/ :-)* Perl6 has something similar to example 9. Ranges, hyper-operators as well as the invocation operators .+ and .* doesn't make any sense to me. Those constructs made me stop using Perl and look elsewhere. It was a hard decision since I've used the language for at least 15 years. I hope Perl6 regexes will make it far beyond Perl itself and the notion of being able to introduce custom dsl parsed on equal terms as the rest of Perl 6 is really sweet. Regards, Michael. -- Michael Zedeler 70 25 19 99 mich...@zedeler.dk dk.linkedin.com/in/mzedeler | twitter.com/mzedeler | github.com/mzedeler
Re: Language design
Yes. It looks nice that Perl 6 recognizes zero in this way, but the consequence is that each implementation of Perl 6 has to run a gcd algorithm every now and then. I'd be very surprised if the computational complexity of any useful (even approximate) gcd algorithm doesn't scale with the with the size of the denominators, which is why I can't see that it is feasible to use for real numerical applications. I'm not saying that there isn't any alternative to the way other languages implements floats, but Rats in particular seems to require a nondeterministic algorithm in order to be of practical use. Regards, Michael. Aristotle Pagaltzis wrote * Michael Zedeler mich...@zedeler.dk [2015-06-16 18:55]: For instance, why have Complex and Rat numbers in the core? If you're not working in a very specialized field (which probably *isn't* numerical computation), those datatypes are just esoteric constructs that you'll never use. https://www.youtube.com/watch?v=S0OGsFmPW2M
Re: Language design
...and unpredictable performance is a cost you're willing to pay? M. The Sidhekin wrote On Tue, Jun 16, 2015 at 10:02 PM, Michael Zedeler mich...@zedeler.dk wrote: I'm not saying that there isn't any alternative to the way other languages implements floats, but Rats in particular seems to require a nondeterministic algorithm in order to be of practical use. Rats means never having to worry about inaccurate float representations. $ perl -E '$i+=0.1 for 0..1000; say for $i, $i cmp 100.1' # oops … 100.0999 -1 $ perl6 -e 'my $i; $i+=0.1 for 0..1000; .say for $i, $i cmp 100.1' 100.1 Same $ Float inaccuracy is one of the things I'm really looking forward to forgetting. :) Eirik
Re: Language design
I really understand your point. If there was several competing OOP modules, things *could* get really complicated (in my opinion, it isn't the case for perl 5, but it is worth discussing), but it doesn't seem as if anyone has put any effort into defining what needs to be common and what doesn't. Seriously, do you believe that the hyperoperators address the problem, you're referring to? Regards, Michael. Paweł Murias wrote The goal is to avoid everyone using a different not fully compatible version of everything. Like in perl 5 with the bunch of different ways to do objects, signatures etc. Pilling good things on top of each others rather than aiming for an elegant design is what I consider the core idea of Perl. Being able to add language features removes most benefits of a simple design (easy to create tool support). On 16 June 2015 at 21:08, Fields, Christopher J cjfie...@illinois.edu wrote: I like that I can start with a fairly simple subset of Perl 6 but pick up more as I go along, if it’s needed. chris On Jun 16, 2015, at 9:45 AM, Paweł Murias pawelmur...@gmail.com wrote: I think Perl 6 tries to include too much rather than too little. It will be possible to just use a subset On 16 June 2015 at 10:32, Michael Zedeler mich...@zedeler.dk wrote: On 06/12/15 15:54, Parrot Raiser wrote: Has somebody been following the discussions on types? http://xkcd.org/1537/ :-)* Perl6 has something similar to example 9. Ranges, hyper-operators as well as the invocation operators .+ and .* doesn't make any sense to me. Those constructs made me stop using Perl and look elsewhere. It was a hard decision since I've used the language for at least 15 years. I hope Perl6 regexes will make it far beyond Perl itself and the notion of being able to introduce custom dsl parsed on equal terms as the rest of Perl 6 is really sweet. Regards, Michael. -- Michael Zedeler 70 25 19 99 mich...@zedeler.dk dk.linkedin.com/in/mzedeler | twitter.com/mzedeler | github.com/mzedeler
The invocation operators .* and .+
Hi. I know that Perl 6 has a lot of live and let live to it, but is it possible somehow to remove features as well? The latest comment about language design by Parrot Raiser (great name!) had me reflect on why I don't use perl any longer, and here is one of the reasons: class Person { has $.name; method hello { say Hi, I'm $.name (Person); } } class Employee is Person { method hello { say Hello. My name is $.name (Employee); } } class Surfer is Person { method hello { say Whats up, dude? (Surfer); } } class Professor is Surfer is Employee { method hello { say Good day to you, my name is $.name (Professor); } } my $p = Professor.new(name = Alice); $p.*hello; Which outputs Good day to you, my name is Alice (Professor) Whats up, dude? (Surfer) Hello. My name is Alice (Employee) Hi, I'm Alice (Person) This is working exactly as specified in the synopsis, but does Perl 6 NEED anything like this? Just because something is possible doesn't make it an automatic requirement! I know that if I don't like the construct, then I shouldn't use it, but this operator (and .+) is nudging people who really doesn't understand OOP to use the inheritance hierarchy as a function chaining mechanism way beyond what it is intended for. Working with a language means working with code that *other people* has written in that language. I don't want to maintain anything using this operator (or its twin, .+), because I haven't seen just one reasonable use case for it. -- Michael Zedeler 70 25 19 99 mich...@zedeler.dk dk.linkedin.com/in/mzedeler | twitter.com/mzedeler | github.com/mzedeler
Re: The invocation operators .* and .+
Hi Aristotle. On 06/16/15 12:24, Aristotle Pagaltzis wrote: * Michael Zedeler mich...@zedeler.dk [2015-06-16 11:35]: This is working exactly as specified in the synopsis, but does Perl 6 NEED anything like this? Just because something is possible doesn't make it an automatic requirement! Well someone thought they needed it in Perl 5 so they wrote NEXT which provides EVERY:: which does exactly the same thing. C3 dispatch surely has something similar too, natively, I’m just not aware of it. Which is a reasonably good argument for letting others write a *module* for Perl 6 that provides this feature. I don't see why it should be in the core. I haven't seen just one reasonable use case for it. Anyplace you would have to say “if you override this method then make sure to call the overridden method also” (like calling -new up the inheritance tree). Instead of relying on every subclass writer to not screw this up (and leave the object instance in an incoherent state), you use something like these operators to make *sure* a certain method is called all up the inheritance tree as necessary for your de-/init needs. Sorry. Doesn't make sense. class A { sub destroy { ...important cleanup } } class B is A { sub destroy { ...important cleanup... nextall; } } followed by $b.destroy What is it that make this *less* preferable over class A { sub destroy { ...important cleanup } } class B is A { sub destroy { ...important cleanup... } } $b.+destroy. The latter breaks encapsulation. The subclass B has the *full* responsibility to handle the method call. Not the caller. Every modern Perl 5 OO system invents stuff like BUILD and DEMOLISH for this purpose. And one of the points of Perl 6 is not to have to handroll a reasonable OO system as your first step in writing nontrivial systems. So putting these operators right in the language, properly designed, is specifically called for. Show me the precedence for constructs like this in other languages, please. I haven't seen any and I belive it is because they're not necessary. Just because you can’t think of the use of a feature doesn’t mean there isn’t one. Of course. That's why I've brought up the subject for discussion here. Or maybe you are aware of the motivation for these designs and disagree with that desire in the first place? In that case I don’t know what to say; obviously there are plenty of people who do see it as a necessity. I am really not so sure, because I've tried to bring up the subject a couple of times, and every time I get answers from people like you: people who don't need the feature themselves, but refer to it as something someone else probably need. Please show me an example that makes Perl 6 vastly more useful by the addition of this feature. Perl 6 could be great because things like this operator could be deferred to non-core modules, but right now they're in the core and nobody can really explain why. *COUGH* featurecreep *COUGH* Regards, Michael. -- Michael Zedeler 70 25 19 99 mich...@zedeler.dk dk.linkedin.com/in/mzedeler | twitter.com/mzedeler | github.com/mzedeler
Re: Language design
On 06/12/15 15:54, Parrot Raiser wrote: Has somebody been following the discussions on types? http://xkcd.org/1537/ :-)* Perl6 has something similar to example 9. Ranges, hyper-operators as well as the invocation operators .+ and .* doesn't make any sense to me. Those constructs made me stop using Perl and look elsewhere. It was a hard decision since I've used the language for at least 15 years. I hope Perl6 regexes will make it far beyond Perl itself and the notion of being able to introduce custom dsl parsed on equal terms as the rest of Perl 6 is really sweet. Regards, Michael. -- Michael Zedeler 70 25 19 99 mich...@zedeler.dk dk.linkedin.com/in/mzedeler | twitter.com/mzedeler | github.com/mzedeler
Re: Language design
Darren Duncan wrote On 2015-06-16 2:15 PM, The Sidhekin wrote: On Tue, Jun 16, 2015 at 10:52 PM, Michael Zedeler mich...@zedeler.dk wrote: ...and unpredictable performance is a cost you're willing to pay? I don't write performance-critical applications, but even if I did, why would I prefer getting the wrong answer faster? I agree with Sidhekin and similar mentalities. On the range between safety/correctness and speed, a good programming language / tool should always default to the most safe/correct option when the user doesn't specify where on the range they want, and leave it to the power users to explicitly make the trade-off when they know what they're doing. In this case, people who explicitly want floats because of performance rather than exact rationals do indeed count as power users. I'd still pull out the argument that you want the least surprising behavior. Of course, I would prefer being able to add two rational numbers with very large denominators and have the underlying machinery shorten the result for me, but the performance hit is easy to great. Am I missing something here, or wouldn't most people expect addition to be a constant time operation? Imagine a really simple operation: a script that takes a spread sheet, parses it and writes out the weighted average of some of the columns. Anyone would expect that if 40,000 rows takes 1 second to process, then 80,000 takes 2. With Perl 6 not do much. You'd have to switch to power user mode to get that kind of predictability. Normal people are more interested in not being surprised by the answers they get to what should be common-sense questions, such as when adding 10.3 to 14.2. So far, almost every other language has behaved this way, and it has worked. I can see that Rats do solve a problem, but if you'd claim that it is very severe then I'd disagree. This is a minor nuisance that I'd only pay a small price to fix. I should also point out that finance / anything to do with money is an extremely common use case that cares very much about math being exact, its not just esoteric science applications. I doubt that Rats is a complete solution to the problems you have to solve when it come to represent monetary values. My take is you'd need very specific rounding algorithms when you convert to a fixed number of digits. I believe my example with the spread sheet is much more mundane. This all being said, I draw the line where implementing is much more complicated to serve esoteric cases. So for example while exact precision rationals absolutely should be default / part of core, something like symbolic values eg exact representations of irrational numbers, are perfectly valid to, and probably shouldn't, be part of core. Exact rationals are not particularly complicated. Its perfectly reasonable to expect in the core that if someone does math that is known to deal with irrationals in general, that loss of precision then is acceptable. Just to be sure that we are taking about the same thing: An ideal Rat implementation should be able to always output the least possible denominator, right? And if I happen to add some rational numbers that involve, say, very very large prime numbers (intentionally or not), it's clear that the result probably can't be shortened much, but the run time of the underlying algorithm may explode. ..and that is acceptable behavior? ..or did I miss something? M. -- Michael Zedeler 70 25 19 99 mich...@zedeler.dk dk.linkedin.com/in/mzedeler |twitter.com/mzedeler | github.com/mzedeler