Re: Synopsis 02: Range objects

2009-08-31 Thread TSa

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 '='.

Regards, TSa.
--
The unavoidable price of reliability is simplicity -- C.A.R. Hoare
Simplicity does not precede complexity, but follows it. -- A.J. Perlis
1 + 2 + 3 + 4 + ... = -1/12  -- Srinivasa Ramanujan


Re: Synopsis 02: Range objects

2009-08-31 Thread Jon Lang
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

2009-08-28 Thread David Green

On 2009-Aug-27, at 3:11 pm, Mark J. Reed wrote:
Given how easy chained relational ops make explicit range checking  
with endpoints, e.g.

$a = $x = $b
I'd be perfectly happy with a Range smartmatching only the elements  
that you get out of the RangeIterator.


Yes -- although sometimes that would require separating out the $a and  
the $b parts, which is why having something to mean between would be  
handy.



On 2009-Aug-27, at 11:08 am, TSa wrote:
Note that order is not a prerequisite for a notion of range and  
range iteration. I think of ranges more like set and set iteration.


Except the meaning of the word range and the spec both indicate  
order: (S03) A star on both sides prevents any type from being  
inferred other than the COrdered role.  Instead, can't the existing  
series operator take on the series aspects of ..?


... can take a function on the RHS that generates new values, or it  
can take * to generate an arithmetic or geometric sequence.  If only a  
single value is given as the LHS, it could use .succ, so 1...* or  
a...* would work like C.. does.


I think the reason C... doesn't take a value other than * as the RHS  
is because of the problem of how to figure out whether the series will  
ever reach that value or not.  But that's easy to figure out in the  
case of an arithmetic or geometric sequence, so 1, 3, 5 ... 99 should  
be OK, and 1, 3, 5 ... 100 should probably be an error.  Maybe * ||  
100 as an endpoint could mean go on forever or until hitting this  
value.


Similarly, it's simple to figure out whether .succ applied to strings  
will reach the endpoint or not.  For an arbitrary function, it's not  
so easy.  However, each type could have a you can't get there from  
here function for figuring out whether an endpoint is part of a  
series or not; if the endpoint passes that test, then you can use it;  
if it doesn't, or if there is no such function that can tell you, the  
only valid endpoint is *.


The :by adverb as applied to C... could take a value, which would be  
added (or handled according to the appropriate type when not dealing  
with Nums) just like it was with ..; or :by could take a block,  
which would run that function.  So 1 ... {foo} would be short for  
1 ... *||Nil :by({foo}).


This way all the series stuff is gathered together, and a Range can  
simply represent a pair of starting and ending points without trying  
to be a list iterator as well.  I expect its main use would be meaning  
between: $foo ~~ $range.  If a Range is not a Series, then there's  
no confusion as to whether being in the range means being in the  
series or not.



S03:
Alternately, we could treat an ellipsis as special when it follows a  
comma to better support traditional math notation.


That seems like an easy mistake to make, so treating it specially  
would be a good quirk.




-David



Re: 1.23 becomes Rat (Re: Synopsis 02: Range objects)

2009-08-28 Thread James Cloos
 Karl == Karl Brodowsky lis...@brodowsky.com writes:

Karl - or should there be a new numeric type similar to Rat that is always
Karl having powers of 10 as denominator (like BigDecimal in Java or
Karl LongDecimal for Ruby or decimal in C# or so)? 

If so, please use something compatable with ieee 754 decimal floats, so
that they can be used when running on hardware which supports them.

Even w/o such hardware, gcc (at least) has support for software
emulation of _Decimal32 and _Decimal64 (and _Decimal128?).

-JimC
-- 
James Cloos cl...@jhcloos.com OpenPGP: 1024D/ED7DAEA6


Re: Synopsis 02: Range objects

2009-08-28 Thread James Cloos
 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.
 
Michael Well... maybe. How do you specify the intended precision, then? If I
Michael want the values from 1 to 2 with step size 0.01, I guess that writing

Michael 1.00 .. 2.00

The parser would have to note the precision as represented.  On systems
which have ieee-754 decimal floats that will be automatic (1., 1.0,
1.00, etc all have different representations in 754 decimal floats); it
would not be a bad idea for Perl to keep track of that for all numerics.

 Complex .. Complex should have a defined meaning in p6.

Michael there is no natural ordering of complex numbers, and without
Michael some ordering, you may be able to decide what should be in the
Michael list to return, but not which order to use.

[I'm merging stuff here.]  Indeed, for interval arith it isn't ordering
but inclusion which is relevant.  If order is of value, it seems that it
would have to be imposed.  I can imagine that some people will want to
zigzag from the point closest to (−∞,−∞) to the point closest to (+∞,+∞),
whereas others might prefer to start at the point with the least r,
sweeping θ through either [0°,360°) or (−π,π] or [−π,π) or 

Michael I believe that anything we put into Perl 6 should have obvious
Michael use cases and fall natural into place in the domain that the
Michael construct in question belongs to.

That is reasonable.

Michael but I must admit that I'd prefer if Complex .. Complex was left
Michael undefined in the Perl 6 core, leaving it up to anyone to
Michael specify it later.

BTW, it I should have written a disc with diameter running between the
two points rather than specifying an enclosing circle.

It is true that when I think of p6, I think of more than core.

But I would like support for interval arithmetic as ingrained in the p6
culture as, say, regexps.  The set of problems which would benefit from
widespread use of efficient interval techniques is significant.

All that said, it may be the case that the .. syntax, though useful for
specifying intervals, may not be preferred by those doing such coding.
The may prefer a ± syntax, or something like ΤεΧ’s strech and shrink
syntax for glue.

-JimC
-- 
James Cloos cl...@jhcloos.com OpenPGP: 1024D/ED7DAEA6


Re: Synopsis 02: Range objects

2009-08-28 Thread TSa (Thomas Sandlaß)
On Thursday, 27. August 2009 23:58:51 Jon Lang wrote:
 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.

Yeah, sometimes orthogonality of features is too much of a good thing!


Regards, TSa.
-- 
The unavoidable price of reliability is simplicity -- C.A.R. Hoare
Simplicity does not precede complexity, but follows it. -- A.J. Perlis
1 + 2 + 3 + 4 + ... = -1/12  -- Srinivasa Ramanujan


Re: Synopsis 02: Range objects [recap]

2009-08-27 Thread Ruud H.G. van Tol

Timothy S. Nelson wrote:

I think a Complex range only makes sense if you provide 4 endpoints, 
not 2, but I haven't been following the conversation, so I'll leave it 
up to the Complex number experts :).


  (start-angle, start-length)
  :by(angle-step, length-factor)

--
Ruud


Re: Synopsis 02: Range objects [recap]

2009-08-27 Thread Michael Zedeler

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

2009-08-27 Thread Michael Zedeler

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: Synopsis 02: Range objects

2009-08-27 Thread Mark J. Reed
Shouldn't it autopromote to Bignum at that point?

On 8/27/09, Michael Zedeler mich...@zedeler.dk wrote:
 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.






-- 
Sent from my mobile device

Mark J. Reed markjr...@gmail.com


Re: Synopsis 02: Range objects [recap]

2009-08-27 Thread Jon Lang
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

2009-08-27 Thread TSa

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. The same applies for 'aaa' ~~ 'aa'..'az'. I find this
quite natural. Note that order is not a prerequisite for a notion of
range and range iteration. I think of ranges more like set and set
iteration. I'm going to post my take on the complex case elsewhere in
this thread.


Regards, TSa.
--
The unavoidable price of reliability is simplicity -- C.A.R. Hoare
Simplicity does not precede complexity, but follows it. -- A.J. Perlis
1 + 2 + 3 + 4 + ... = -1/12  -- Srinivasa Ramanujan


Re: Synopsis 02: Range objects

2009-08-27 Thread TSa

HaloO,

Michael Zedeler wrote:

James Cloos wrote:

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.


We should not think of complex ranges as areas. The thing used in
complex analysis is the path along which you integrate. OTOH circles
are the two dimensional equivalents of intervals.


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 have stated elsewhere that order is not necessary. A notion of
distance suffices. The direction of iteration is well defined
by the complex step size.


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.


The complex case should result in the numeric case when given real
numbers as bounds and step size. So my proposal for complex range
iteration is to use complex addition to generate the next candidate
and complex distance to check whether it is closer to the endpoint
or not. The only drawback I see is that 1.2 .. 5 then iterates up
to 5.2 not 4.2 as in the order based approach. But I don't consider
this a bad outcome because the endpoint isn't hit in both cases and
5.2 is closer ;)

Applying the above metric procedure to complex range matches is
however a bit more problematic because the direction from start
to end is not necessarily the same as that given by the step size.
Since the step size should be ignored in real matches we should do
so in the complex case as well and check whether the number in
question lies on the line from start to end. Problem is how accurate
this check shall be. IOW, what is the line width of the range?
I would add an eps parameter to the range creating operator with
a default around 1e-10. This would be useful for real ranges with
excluded ends as well. Actually this parameter should be a relative
error not an absolute one.

Another idea is to make matches succeed in the intersection of the
two circles around the endpoints through the other endpoint. E.g.
then 2+i ~~ 1..3 is true and 2+2i ~~ 1..3 is false. This works for
reals such that 1..3 is the intersection of -1..3 and 1..5 which
are the one dimensional circles of radius 2 around 1 and 3 respectively.
Note that this metric definition of interval can be generalized to
vector spaces of arbitrary dimension where one intersects hyperspheres
around two points. One can also generalise to non-euclidean metrics,
of course. Perhaps even a string distance function might work.

Regards, TSa.
--
The unavoidable price of reliability is simplicity -- C.A.R. Hoare
Simplicity does not precede complexity, but follows it. -- A.J. Perlis
1 + 2 + 3 + 4 + ... = -1/12  -- Srinivasa Ramanujan


1.23 becomes Rat (Re: Synopsis 02: Range objects)

2009-08-27 Thread Karl Brodowsky

Larry Wall wrote:

Another note, it's likely that numeric literals such as 1.23 will turn
into Rats rather than Nums, at least up to some precision that is
pragmatically determined.
  
Doing these as Rat would avoid a  lot of the precision issues that 
floating point
arithmetic has all the time.  It will actually work perfectly well with 
addition, because
the denominator is always a small power of 10, so that is true for the 
sum as well.
Multiplying might be an issue, because the denominator becomes a large 
power of 10,
but I think that that can be handled pretty well, unless the 
multiplication is really performed

to an extent that the result uses significant amounts of memory.
But as soon as division is occuring, these rational numbers tend to 
develop denominators
that are not powers of 10 any more.  Combining this with some 
multiplications and additions
this may result in huge numerators and denominators that are somewhat 
expensive to handle.


So what would happen after such a long calculation:

- would the Rats somehow know that they are all derived from Rats that 
were just used instead of floats because of being within a pragmatically 
determined precision?  Then the result of * or / could just as 
pragmatically become a floating point number?
- would the Rats grow really huge numerators and denominators, making it 
expensive to work with them?
- would the first division have to deal with the conversion from Rat to 
floating point?
- or should there be a new numeric type similar to Rat that is always 
having powers of 10 as denominator (like BigDecimal in Java or 
LongDecimal for Ruby or decimal in C# or so)? 

Even in this last case the division is not really easy to define, 
because the exact result cannot generelly be expressed with a 
denomonator that is a power of 10.

This can be resolved by:
- requires additional rounding information (so writing something like 
a.divide(b, 10, ROUND_UP) or so instead of a/b
- implicitely find the number of significant digits by using partial 
derivatives of f(x,y)=x/y

- express the result as some kind of rational number
- express the result as some kind of floating point number.


Regards

Karl




Re: Synopsis 02: Range objects

2009-08-27 Thread smuj

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.


(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 :)



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'm new in town though, so I'll happily admit that I don't know the full 
implications of such a change. Having context-insensitive Ranges DWIM's 
better to me, but DWIMery, like beauty, is clearly in the eye of the 
beholder! :)


Cheers,
--
smuj


Re: Synopsis 02: Range objects

2009-08-27 Thread Mark J. Reed
Given how easy chained relational ops make explicit range checking
with endpoints, e.g.

$a = $x = $b

Imd be perfectly happy with a Range smartmatching only the elements
that you get out of the RangeIterator.

On 8/27/09, smuj s...@iol.ie 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.

 (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 :)

 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'm new in town though, so I'll happily admit that I don't know the full
 implications of such a change. Having context-insensitive Ranges DWIM's
 better to me, but DWIMery, like beauty, is clearly in the eye of the
 beholder! :)

 Cheers,
 --
 smuj


-- 
Sent from my mobile device

Mark J. Reed markjr...@gmail.com


Re: Synopsis 02: Range objects

2009-08-27 Thread Jon Lang
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

2009-08-27 Thread Mark J. Reed
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.

But I do like your list context for list behavior idea.  I would
support that happily.

On 8/27/09, Jon Lang datawea...@gmail.com wrote:
 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


-- 
Sent from my mobile device

Mark J. Reed markjr...@gmail.com


Re: Synopsis 02: Range objects

2009-08-27 Thread smuj

Jon Lang wrote:

smuj wrote:

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.



So you're saying you'd like things to stay exactly as they are at the 
moment!? :-)


--
smuj


Re: Synopsis 02: Range objects

2009-08-27 Thread Jon Lang
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

2009-08-27 Thread Jon Lang
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

2009-08-27 Thread Larry Wall
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.

Larry


Re: Synopsis 02: Range objects

2009-08-27 Thread Jon Lang
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

2009-08-27 Thread Brandon S. Allbery KF8NH

On Aug 27, 2009, at 17:48 , Jon Lang wrote:
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?


.. vs. ... operators, I presume.

--
brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allb...@kf8nh.com
system administrator [openafs,heimdal,too many hats] allb...@ece.cmu.edu
electrical and computer engineering, carnegie mellon universityKF8NH




PGP.sig
Description: This is a digitally signed message part


Re: Synopsis 02: Range objects [recap]

2009-08-26 Thread Michael Zedeler

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]

2009-08-26 Thread Jon Lang
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: Synopsis 02: Range objects

2009-08-26 Thread Karl Brodowsky

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.


Regards,

Karl




Re: Synopsis 02: Range objects [recap]

2009-08-26 Thread Timothy S. Nelson

On Wed, 26 Aug 2009, Michael Zedeler wrote:


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 (..).


	I haven't been following the conversation, but I've had an idea -- 
maybe it should be possible to construct a RangeIterator if an ordered set is 
provided.  For example, if the ordered set was '0'.. '9', then the 
RangeIterator would know that the thing went '0' .. '9', '10' .. '19', '20', 
etc, whereas if the ordered set was 'a' .. 'z' then it could be something like 
'a' .. 'z', 'aa', 'ab' ... 'az', 'ba'...


	I realise that maybe the first set should've been '1' .. '0' instead, 
but the general idea is the thing at the moment.


	I wrote all this, and then saw Jon Lang's idea of providing steppers, 
which is also good.


	I think a Complex range only makes sense if you provide 4 endpoints, 
not 2, but I haven't been following the conversation, so I'll leave it up to 
the Complex number experts :).


HTH,


-
| Name: Tim Nelson | Because the Creator is,|
| E-mail: wayl...@wayland.id.au| I am   |
-

BEGIN GEEK CODE BLOCK
Version 3.12
GCS d+++ s+: a- C++$ U+++$ P+++$ L+++ E- W+ N+ w--- V- 
PE(+) Y+++ PGP-+++ R(+) !tv b++ DI D G+ e++ h! y-

-END GEEK CODE BLOCK-



Re: Synopsis 02: Range objects

2009-08-25 Thread David Green

On 2009-Aug-24, at 4:17 pm, Daniel Ruoso wrote:

Em Seg, 2009-08-24 às 23:50 +0200, Michael Zedeler escreveu:

The most elegant solution would be if the data types themselves
indicated their capabilities.

One thing I think you missed entirely is the fact that the infix:..
operator is a multi sub, so it falls to regular dispatch semantics,


But Michael's point was not about what's *possible*, but rather what's  
*reasonable*.  Given that Ranges can act in two ways that lead to  
inconsistency, it would be less confusing to separate the list-kind  
from the interval-kind.


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?


A Range might get implicitly cast to an Interval by using its  
endpoints; that leaves us open to the same confusion, although the  
context would help.

# Assuming infix:between (Any, Interval)
say 5 between [1, 10];
say 5 between 1 .. 10;

say 'aaa' ~~ 'aa' .. 'ba';  # false
say 'aaa' between aa ba;  # true
say 'aaa' between 'aa'..'ba';   # hm...


Come to think of it, the word range suggests ordering (like the  
related word rank), so perhaps Range is the right name for the  
interval-type, and Series should be the type that produces a series  
of values that may or may not have an innate ordering.  (For example,  
you could produce a Complex series with: 5+5i .. 10+10i :by(1+1i).)




-David



Re: Synopsis 02: Range objects

2009-08-25 Thread Michael Zedeler

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

2009-08-25 Thread Jon Lang
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

2009-08-25 Thread Mark J. Reed
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.

 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.

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.

-- 
Mark J. Reed markjr...@gmail.com


Re: Synopsis 02: Range objects

2009-08-25 Thread Jon Lang
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


Re: Synopsis 02: Range objects

2009-08-25 Thread Larry Wall
On Tue, Aug 25, 2009 at 02:58:05PM -0700, Jon Lang wrote:
: 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

Note that your :by adverb is malformed; it must be :by(.01), or it's
parsed as a boolean :by followed by a term.

Another note, it's likely that numeric literals such as 1.23 will turn
into Rats rather than Nums, at least up to some precision that is
pragmatically determined.

: 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.

We already make this distinction in the spec.  A Range means an
interval, possibly annotated with a step, but this is meaningless
unless the range is iterated.   An attempt to use such a Range in a
list produces a RangeIterator, which yields a series of values.

However, the name series operator is already reserved to mean
infix:... rather than infix:...  So your second example above
basically turns into this series:

1.00 ... { $_ + 0.01 if $_  2.00 };

except that 1.00 .. 0.00 produces (), not 1.00.  A more exact
translation might be

() ... - $x = (1.00-0.01) { $x + 0.01 if $x  2.00 };

I am currently assuming such loops will default to Rat rather than
Num for numbers that aren't too far off the beaten path, where
on the beaten track is defined as rats that fit into a pair of
int64s or so, that is, which can be represented with rat64.

Larry


Synopsis 02: Range objects

2009-08-24 Thread Michael Zedeler

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

2009-08-24 Thread Daniel Ruoso
Em Seg, 2009-08-24 às 23:50 +0200, Michael Zedeler escreveu:
 The most elegant solution would be if the data types themselves 
 indicated their capabilities.

One thing I think you missed entirely is the fact that the infix:..
operator is a multi sub, so it falls to regular dispatch semantics, in a
way that any new class can export its own version of it with the desired
semantics...

 my $range = 1.14 .. 1.82 :by {* + 0.01};

Including mandatory named arguments...

 Another option is to provide a completely different operator for 
 constructing Intervals.

The other thing you're missing is that Range is a role, not a class,
which means that any type can behave like a range even if it provides a
completely different behavior, which might include

method list {
  fail This type of Range cannot be used as a list...
}

daniel