Re: How to make a new operator.

2012-03-25 Thread Damian Conway
 At least in #perl6 I've never seen anybody try to write an auto-deduced
 sequence, and fail because of floating-point errors.

Except for Martin's 1, sqrt(2), 2...8

But, yes, the widespread use of Rats rather than Nums
means only the edgiest of edge-cases fails. And as you get
an explicit Failure when it does happen, at least people will
know when the numerical computations don't work as hoped.

Damian


Re: Floating-point equality (was Re: How to make a new operator.)

2012-03-25 Thread Moritz Lenz
On 03/25/2012 06:55 AM, Moritz Lenz wrote:
 I don't know if the majority of the perl6-language posters have realized
 it yet, but both Perl 6 and the its implementations are quite mature
 these days. Mature enough that such proposals should be prototyped as
 modules, and thoroughly tested on lots of existing code before taken
 into consideration for

... inclusion into the spec.

Sometimes I do finish my sentences with several hours delay, sorry for that.

Cheers,
Moritz


Re: Not-so-smart matching (was Re: How to make a new operator.)

2012-03-25 Thread yary
I also like agreement, conformance... In a situation like this, I
reach for a thesaurus- very useful when looking for just the right
name for a variable/method name/way to describe a concept. Here's a
grab bag to start with:

accord, agree, conformance, conformation, conformity, congruence,
congruity, consensus, consonance, correspondence, harmony, unison
agree, fit, correspond, compeer, meet, gibe, pair, mate, twin, cope with, touch

Fit, correspond, congruity, harmonize seem like other good
descriptions for the concept. Fit is especially good due to its
brevity, and congruence is good due to the use of ~~ as the smartmatch
aka congruence/fitness/agreement/harmonizing/correspondence/conformance
operator.

(Bikeshed?)

-y



On Sun, Mar 25, 2012 at 12:35 AM, David Green david.gr...@telus.net wrote:
 On 2012-March-21, at 6:38 pm, Daniel Carrera wrote:
 The idea of smart-matching a function just doesn't quite fit with my brain. 
 I can memorize the fact that smart-matching 7 and foo means evaluating 
 foo(7) and seeing if the value is true, but I can't say I understand it.

 Maybe it just needs a better name.  Match implies that two (or more) things 
 are being compared against each other, and that's how smart-matching started 
 out, but it's been generalised beyond that.  The underlying .ACCEPTS method 
 suggests acceptance... but that's too broad (a function can accept args 
 without returning true).  Agreement fits, in the sense of that [food] 
 agrees with me, but I think it suggests equality a bit too strongly.  
 Accordance?  Conformance?  Validation?  That seems a good match (ahem) 
 for the concept: ~~ checks whether some value is valid (or desired?) 
 according to certain criteria.  The obvious way to validate some value 
 against a simple string or number is to compare them; or against a pattern, 
 to see if the value matches; but given a function, you check the value by 
 passing it to the function and seeing whether it says yea or nay.

 I'm not sure validation or validity is the best name, but it conforms 
 better to what smart-matching does.  Or conformance  Hm.  But 
 terminology that sets up the appropriate expectations is a good thing.


 -David



Re: Not-so-smart matching (was Re: How to make a new operator.)

2012-03-25 Thread Damian Conway
yary suggested:

 In a situation like this, I reach for a thesaurus

The standout from that list for me is: 'consonance'.
Second favorite is: 'gibe' or 'jibe'.

But the underlying operation is .ACCEPTS(),
so perhaps the operation should be referred to
as acceptance or acceptibility.

Damian


Re: How to make a new operator.

2012-03-24 Thread Larry Wall
On Fri, Mar 23, 2012 at 07:14:51PM +1100, Damian Conway wrote:
: For example:
: 
: 1, 1.0001, 1.0002 ... *
: 
: won't deduce a correct arithmetic sequence either (on most hardware).

Actually, that one works fine in both niecza and rakudo, since those are Rats.

Larry


Re: How to make a new operator.

2012-03-24 Thread Damian Conway
 Actually, that one works fine in both niecza and rakudo, since those are Rats.

Oh, that's good to hear.

It doesn't change my underlying argument however. Any operations
performed on genuine floats are going to lose precision, and if we're
using such operations to infer relationships (such as equality or
sequence) then we ought to take the loss of precision we're causing
into account when deciding outcomes.

Which seems to mean either (a) making it a compiletime error to request
sequence inferences on floats , or (b) comparing the differences and
quotients within the sequence inference with a larger epsilon (or using
interval arithmetic).

Damian


Floating-point equality (was Re: How to make a new operator.)

2012-03-24 Thread David Green
On 2012-March-23, at 12:01 am, Damian Conway wrote:
 [...] we ought to allow for the inevitable loss of significant digits within 
 the two preliminary division ops, and therefore compare the results with an 
 suitably larger epsilon.
 That would not only be computational more justifiable, I suspect it might 
 also produce more least surprise. ;-)

I think that comparisons for floating-point values should take some kind of 
'significance' adverb and complain if it's missing.  Having to be explicit 
makes for the least surprise of all.

   π == 22/7   # error
   π == 22/7 :within(0.002)# true
   π == 22/7 :within(0.2)  # false

Probably with something like 'use epsilon :within(0.0002)' as way to declare 
the fuzziness for a given scope if you have a lot of comparisons.  And of 
course you could use (the equivalent of) 'use epsilon :within(0)' to say, I 
know what I'm doing, just give me straight what I ask for and I'll take the 
consequences.

Alternatively, maybe have float-comparisons give an error or warning, and 
introduce an approximation operator: π == ~22/7 :within($epsilon).  (Except 
~ is already taken!)


[I was going to suggest that as a way to handle stopping points in a sequence: 
1, 3, 5 ... ~10, but that still wouldn't work without treating the Num::Approx 
values as a special case, which defeats the purpose.  Though with a postfix up 
from operator, you could say: 1, 3, 5 ... 10^.]


-David



Not-so-smart matching (was Re: How to make a new operator.)

2012-03-24 Thread David Green
On 2012-March-21, at 6:38 pm, Daniel Carrera wrote:
 The idea of smart-matching a function just doesn't quite fit with my brain. I 
 can memorize the fact that smart-matching 7 and foo means evaluating foo(7) 
 and seeing if the value is true, but I can't say I understand it.

Maybe it just needs a better name.  Match implies that two (or more) things 
are being compared against each other, and that's how smart-matching started 
out, but it's been generalised beyond that.  The underlying .ACCEPTS method 
suggests acceptance... but that's too broad (a function can accept args 
without returning true).  Agreement fits, in the sense of that [food] agrees 
with me, but I think it suggests equality a bit too strongly.  Accordance?  
Conformance?  Validation?  That seems a good match (ahem) for the concept: 
~~ checks whether some value is valid (or desired?) according to certain 
criteria.  The obvious way to validate some value against a simple string or 
number is to compare them; or against a pattern, to see if the value matches; 
but given a function, you check the value by passing it to the function and 
seeing whether it says yea or nay.  

I'm not sure validation or validity is the best name, but it conforms 
better to what smart-matching does.  Or conformance  Hm.  But 
terminology that sets up the appropriate expectations is a good thing.


-David



Re: How to make a new operator.

2012-03-24 Thread Moritz Lenz


On 03/23/2012 09:14 AM, Damian Conway wrote:
 it means we cannot do the same fuzziness for the endpoint,
 
 Except that we will be encouraging people to use: * = $END
 as their standard endpoint pattern, which will provide
 most of the necessary fuzz.

and which will still surprise those people who are surprised
by floating point inaccuracies.

 This discussion makes me think that maybe
 deducing geometric sequences is too much magic as well.
 
 Geometric sequence inference is fine on Ints and Rats.
 
 But, if we can't perform inferences involving Nums in a sound numerical
 way (and it may well be that we can't, without taking a noticeable
 performance hit), then I think that we would be better off limiting the
 deduction of *both* arithmetic and geometric sequences to starting lists
 that contain only Ints and Rats.

Floating point numbers *can* represent a huge number of commonly used
values without errors, and you can do error-free arithmetic operations
on many of them. Excluding Nums from automatic deduction feels like an
unnecessary pessimization or stigmatization, especially if you consider
that writing a number like 0.001 in your program gives a Rat by default
not a Num.

Most of the time you only get a Num in Perl 6 if you consciously decide
to write one, in which case you should also be well aware of the
limitations of FP math.

At least in #perl6 I've never seen anybody try to write an auto-deduced
sequence, and fail because of floating-point errors.

Cheers,
Moritz


Re: Floating-point equality (was Re: How to make a new operator.)

2012-03-24 Thread Moritz Lenz


On 03/25/2012 05:59 AM, David Green wrote:
 On 2012-March-23, at 12:01 am, Damian Conway wrote:
 [...] we ought to allow for the inevitable loss of significant digits within 
 the two preliminary division ops, and therefore compare the results with an 
 suitably larger epsilon.
 That would not only be computational more justifiable, I suspect it might 
 also produce more least surprise. ;-)
 
 I think that comparisons for floating-point values should take some kind of 
 'significance' adverb and complain if it's missing.  Having to be explicit 
 makes for the least surprise of all.
 
π == 22/7   # error
π == 22/7 :within(0.002)# true
π == 22/7 :within(0.2)  # false

Note that neither 22/7 nor 0.002 are floating-point values.

I don't know if the majority of the perl6-language posters have realized
it yet, but both Perl 6 and the its implementations are quite mature
these days. Mature enough that such proposals should be prototyped as
modules, and thoroughly tested on lots of existing code before taken
into consideration for

Niecza supports operator adverbs, and supports them on user-defined
operators, so there's nothing to stop you from trying it.

Cheers,
Moritz


Re: How to make a new operator.

2012-03-23 Thread Damian Conway
Patrick correctly observed:

 On Rakudo on my system, sqrt(2) indeed produces a Num,
 but since floating point arithmetic doesn't result in
 sqrt(2) / 1 == 2 / sqrt(2), no geometric sequence is deduced
 and the sequence fails with unable to deduce sequence.

Although, arguably, that might be considered a bug.

Not that sqrt(2) / 1 should == 2 / sqrt(2) of course, but that, when
deducing a sequence we know we're comparing quotients, so we ought to
allow for the inevitable loss of significant digits within the two
preliminary division ops, and therefore compare the results with an
suitably larger epsilon.

That would not only be computational more justifiable,
I suspect it might also produce more least surprise. ;-)

Damian


Re: How to make a new operator.

2012-03-23 Thread Moritz Lenz
On 03/23/2012 07:01 AM, Damian Conway wrote:
 Patrick correctly observed:
 
 On Rakudo on my system, sqrt(2) indeed produces a Num,
 but since floating point arithmetic doesn't result in
 sqrt(2) / 1 == 2 / sqrt(2), no geometric sequence is deduced
 and the sequence fails with unable to deduce sequence.
 
 Although, arguably, that might be considered a bug.
 
 Not that sqrt(2) / 1 should == 2 / sqrt(2) of course, but that, when
 deducing a sequence we know we're comparing quotients, so we ought to
 allow for the inevitable loss of significant digits within the two
 preliminary division ops, and therefore compare the results with an
 suitably larger epsilon.
 
 That would not only be computational more justifiable,
 I suspect it might also produce more least surprise. ;-)

But unless we twist smartmatching semantics for that purpose, it means
we cannot do the same fuzziness for the endpoint, condemning people to
write infinite loops instead of failing fast.

So I'm firmly against such magic. All the previous iterations of the
sequence operator had some additional degrees of magic, and we've come
to regret all of them. This discussion makes me think that maybe
deducing geometric sequences is too much magic as well.

Cheers,
Moritz


Re: How to make a new operator.

2012-03-23 Thread Moritz Lenz
On 03/23/2012 05:30 AM, Patrick R. Michaud wrote:
 On Fri, Mar 23, 2012 at 03:03:09PM +1300, Martin D Kealey wrote:
 Question: do we support
 
  1, 2i, -4 ... 256
 
 I think this ought to work, but for some reason Rakudo on my system
 hangs whenever I try it.

The problem was that infix:!= hung with Complex numbers, because it
was defined for each numeric type, but the Complex candidate was
missing. Thus the most general candidate called .Numeric on its
arguments, re-dispatched, and looped infinitely.

Fixed in 2012.03-3-g4a247b1, and tested in S32-num/complex.t.
This also fixes the sequence 1, 2i, -4 ... 256.

Cheers,
Moritz


Re: How to make a new operator.

2012-03-23 Thread Damian Conway
 But unless we twist smartmatching semantics for that purpose,

No!

Please, no.

;-)


 it means we cannot do the same fuzziness for the endpoint,

Except that we will be encouraging people to use: * = $END
as their standard endpoint pattern, which will provide
most of the necessary fuzz.


 So I'm firmly against such magic.

But that's the point: it's not magic. It's correct numerical computation
under the limitations of floating-point arithmetic. As discussed in
every numerical computing textbook for the last half a century.

Note that this problem occurs for *arithmetic* deductions as well.
If either number is floating point, some loss of precision in the
difference between them is almost inevitable, especially if the two
numbers are very close.

For example:

1, 1.0001, 1.0002 ... *

won't deduce a correct arithmetic sequence either (on most hardware).

In fact that example would be slightly more likely to imply a geometric
sequence, since a division operation loses fewer significant digits than
a subtraction when the arguments are both so close to 1.0)


 This discussion makes me think that maybe
 deducing geometric sequences is too much magic as well.

Geometric sequence inference is fine on Ints and Rats.

But, if we can't perform inferences involving Nums in a sound numerical
way (and it may well be that we can't, without taking a noticeable
performance hit), then I think that we would be better off limiting the
deduction of *both* arithmetic and geometric sequences to starting lists
that contain only Ints and Rats.

Damian


Re: How to make a new operator.

2012-03-23 Thread Patrick R. Michaud
On Thu, Mar 22, 2012 at 11:07:08AM -0500, Bruce Gray wrote:
 Well, it works in Niecza. It does not (yet) work in Rakudo:
   15:25 Util perl6: my @squares := 0, (- *@a { @a.elems ** 2 })
 ... *; say ~@squares[^11];
   15:25 p6eval ..niecza v15-4-g1f35f89: OUTPUT0 1 4 9 16 25 36 49
 64 81 100NL
   15:25 p6eval ..rakudo 1a468d: OUTPUT0 0 0 0 0 0 0 0 0 0 0NL

It now works in Rakudo, as of 2012.03-5-g69920db:

my @squares = 0, (- *@a { @a.elems ** 2 }) ... *; say @squares[^11];
   0 1 4 9 16 25 36 49 64 81 100

Also @_ now DTRT again:

 my @squares = { @_ ** 2 } ... *;  say @squares[^11];
0 1 4 9 16 25 36 49 64 81 100

 my @triangle = 1, { @_[*-1] + @_ + 1 } ... *;  say @triangle[^11]
1 3 6 10 15 21 28 36 45 55 66

Note that Rakudo also doesn't require a binding operation for the array... 
assignment of detectably infinite lists (indicated here by the final 
Whatever term) is supported.

Pm


Re: How to make a new operator.

2012-03-22 Thread Daniel Carrera
On 22 March 2012 04:59, Jonathan Lang datawea...@gmail.com wrote:
 My understanding is if you want to count by threes, starting at 2 and ending 
 at 14, you should be able to write:

   2, 5 ... 14

That certainly looks very intuitive, and it is similar to what I would
write in an email. The only annoyance is that I have to do a bit of
mental arithmetic. But I guess that's ok. Especially since most of the
time you'd probably want to write 2,5...* anyway.

 So:

    1, 3 ... 13 # same as 1,3,5,7,9,11,13
    1 ... 10 # same as 1,2,3,4,5,6,7,8,9,10
    1, 2, 4 ... 100 # same as 1,2,4,8,16,32,64


That last one doesn't work on Rakudo :-(

 Meanwhile, using Whatever for the test condition means keep the series going 
 indefinitely:

    1, 3 ... * # every positive odd number.
    1 ... * # all counting numbers.
    1, 2, 4 ... * # all powers of 2.


Yeah, and those are very convenient.


 And using '...^' instead of '...' changes the default final test condition 
 from ' $n' to '= $n':

    1, 3 ...^ 13 # same as 1,3,5,7,9,11
    1 ...^ 10 # same as 1,2,3,4,5,6,7,8,9
    1, 2, 4 ...^ 100 # same as 1,2,4,8,16,32,64


Ok. I hadn't thought of doing that.


 In short, what Damian is talking about is the more powerful and reliable use 
 of the syntax; but the above approach (assuming it has been properly 
 implemented) is a more intuitive use that covers the most common cases.  Make 
 common things easy, and make uncommon things possible.


Yeah.


 Likewise, using Whatever in conjunction with operators is there to provide an 
 intuitive way to calculate the next term from the previous one(s):

    1, *+2 ... 13 # start at 1, step by 2s, stop at 13.
    1, 1, *+* ... * # each new term is the sum of the previous two.

Oh! That second one is cool. a one line implementation of the
Fibonacci sequence.

Cheers,
Daniel.
-- 
I'm not overweight, I'm undertall.


Re: How to make a new operator.

2012-03-22 Thread Carl Mäsak
Jonathan Lang (), Daniel ():
 So:

    1, 3 ... 13 # same as 1,3,5,7,9,11,13
    1 ... 10 # same as 1,2,3,4,5,6,7,8,9,10
    1, 2, 4 ... 100 # same as 1,2,4,8,16,32,64

 That last one doesn't work on Rakudo :-(

And it never will. Note that 100 is not a power of 2, and that the
goal needs to match exactly. This is because smartmatching is used,
not some other comparison. The sequence will continue to generate
numbers until the number 100 is generated, which never happens. Rakudo
loops forever on this one, as per spec.

If you're wondering why things are factored in this way, it's because
previous versions of the spec that tried to special-case 100 to work
in cases like the above, ended up not working out. It turned out that
the unification of infix:... and smartmatching was what did work. It
has the slight drawback that we have to educate users to write * =
100 instead of 100 in the case of not-exactly-matching goal states.
But it's still a net win, because this unified semantics works better
than anything we had before.

// Carl


Re: How to make a new operator.

2012-03-22 Thread Daniel Carrera
On 22 March 2012 11:02, Carl Mäsak cma...@gmail.com wrote:
    1, 2, 4 ... 100 # same as 1,2,4,8,16,32,64

 That last one doesn't work on Rakudo :-(

 And it never will. Note that 100 is not a power of 2, and that the
 goal needs to match exactly. This is because smartmatching is used,
...
 If you're wondering why things are factored in this way, it's because
 previous versions of the spec that tried to special-case 100 to work
 in cases like the above, ended up not working out. It turned out that
 the unification of infix:... and smartmatching was what did work. It
 has the slight drawback that we have to educate users to write * =
 100 instead of 100 in the case of not-exactly-matching goal states.
 But it's still a net win, because this unified semantics works better
 than anything we had before.

But that's a bit of a problem if I *don't* want a value higher than 100.

 2,4,8... * = 100
2 4 8 16 32 64 128

There is no simple formula I can use at the end to get the sequence to
stop where I want. So I have to do something like:

my @a = 2,4,8... * = 100;
@a.pop
# Use @a


Cheers,
Daniel.
-- 
I'm not overweight, I'm undertall.


Re: How to make a new operator.

2012-03-22 Thread Moritz Lenz


On 03/22/2012 11:51 AM, Daniel Carrera wrote:
 On 22 March 2012 11:02, Carl Mäsak cma...@gmail.com wrote:
1, 2, 4 ... 100 # same as 1,2,4,8,16,32,64

 That last one doesn't work on Rakudo :-(

 And it never will. Note that 100 is not a power of 2, and that the
 goal needs to match exactly. This is because smartmatching is used,
 ...
 If you're wondering why things are factored in this way, it's because
 previous versions of the spec that tried to special-case 100 to work
 in cases like the above, ended up not working out. It turned out that
 the unification of infix:... and smartmatching was what did work. It
 has the slight drawback that we have to educate users to write * =
 100 instead of 100 in the case of not-exactly-matching goal states.
 But it's still a net win, because this unified semantics works better
 than anything we had before.
 
 But that's a bit of a problem if I *don't* want a value higher than 100.

Then exclude it: 2, 4, 8 ...^ *  100

Cheers,
Moritz


Re: How to make a new operator.

2012-03-22 Thread Daniel Carrera
On 22 March 2012 12:06, Moritz Lenz mor...@faui2k3.org wrote:

 But that's a bit of a problem if I *don't* want a value higher than 100.

 Then exclude it: 2, 4, 8 ...^ *  100

Ok...  I looked up what you did. I see how it works. Thanks.


Related questions:  What types of sequences can Perl 6 recognize?


-- 
I'm not overweight, I'm undertall.


Re: How to make a new operator.

2012-03-22 Thread Carl Mäsak
Daniel ():
 Related questions:  What types of sequences can Perl 6 recognize?

As covered by Jonathan Lang earlier in this thread (though it was
perhaps easy to miss), Perl 6 auto-detects arithmetic sequences (same
additive difference each time) and geometric sequences (same
multiplicative factor applied each time). Two terms are enough to seed
the first kind; three terms are necessary for the second kind.

If you supply three terms that follow neither an arithmetic or a
geometric sequence (and doesn't contain a Callable as its last term),
Perl 6 throws up its hands and doesn't try to guess.

If you ask me, auto-detecting arithmetic and geometric sequences, but
nothing else, is pretty much the sweet spot. We don't want to put more
in CORE. The one that comes up most often as a suggested addition is
the sequence of primes. Mostly just to mess with people who try it.
:-)

// Carl


Re: How to make a new operator.

2012-03-22 Thread Bruce Gray

On Mar 21, 2012, at 11:49 PM, Jonathan Lang wrote:

What I want to know is whether there's a way to define a step  
function that's based in part or in whole on the current term's  
index.  For example, how would I use infix:... to generate the  
perfect squares between 0 and 100?  Namely,  
'0,1,4,9,16,25,36,49,64,81,100'.  For example, is Perl 6 set up to  
try to pass the current element's index into the step function by  
means of a named parameter?


I would hope for something like:

  - :index { $index * $index } ... 100

or

  1, *+:index ... * # 1,3,6,10,15,21,28,36,45,...

(Note: I _don't_ expect the above to work as is; they're merely  
intended to convey a rough idea of what I _do_ want.)


If not, how _would_ I generate these lists?



In real life, you would just use this:
   my @squares = map { $_ * $_ }, 0..10;
or, for an infinite list, use a binding instead of an assignment:
   my @squares := map { $_ * $_ }, 0..*;
But you were asking about ... specifically :^)

I have run into the same need for something like :index, while
playing with RosettaCode tasks like Continued_fraction.
Your squares example will be clearer than the RC tasks.

At first, I tried to trick the compiler, by *binding* the list to an
array, then referring to that bound array from within the closure.
   my @squares := 0, { @squares.elems ** 2 } ... *;
This worked, but only as an artifact of the then-current Rakudo
implementation. It is not specced to work, and I was told in
freenode/#perl6 not to rely on that behavior.

On freenode/#perl6, I was pointed to part of the spec that I had  
overlooked.

The sequence operator is defined in S03:
   http://perlcabal.org/syn/S03.html#List_infix_precedence
Buried in its definition is this gem:
   http://perlcabal.org/syn/S03.html#line_1884
   The function may also be slurpy (n-ary), in which case all
   the preceding values are passed in (which means they must
   all be cached by the operator, so performance may suffer,
   and you may find yourself with a space leak).

That means that this will work:
   sub sq_gen (*@a) { @a.elems ** 2 };
   my @squares = 0, sq_gen ... {$_ = 100};
   say ~@squares;
(Note that the asterisk in *@a is mandatory)
or, infinitely:
   sub sq_gen (*@a) { @a.elems ** 2 };
   my @squares := 0, sq_gen ... *;
   say ~@squares[^11];

Great! However, I wanted to do it inline, without a separately-defined  
sub.
If it wasn't for that required asterisk, then I could use a  
placeholder variable to do this:

   my @squares = 0, { @^a.elems ** 2 } ... {$_ = 100};
FAIL! (Niecza)
   Unhandled exception: Nominal type check failed in binding '@a' in  
'ANON'; got Int, needed Positional


The last piece of the puzzle is the arrow sub syntax, more commonly
seen in for loops:
   my @squares = 0, (- *@a { @a.elems ** 2 }) ... {$_ = 100};
Or, more concisely:
   my @squares = 0, - *@a { +@a ** 2 } ... * = 100;

This works!

Well, it works in Niecza. It does not (yet) work in Rakudo:
	15:25 Util perl6: my @squares := 0, (- *@a { @a.elems ** 2 }) ...  
*; say ~@squares[^11];
	15:25 p6eval ..niecza v15-4-g1f35f89: OUTPUT0 1 4 9 16 25 36 49  
64 81 100NL

15:25 p6eval ..rakudo 1a468d: OUTPUT0 0 0 0 0 0 0 0 0 0 0NL

For your second example (1,3,6,10,15,21,28,36,45,...), it would look  
like this:

my @triangle = 1, (- *@a { @a[*-1] + @a.elems + 1 }) ... {$_ = 45};
Note that this particular sequence is just the triangle numbers, which
has a shorter form via triangular reduce:
   my @triangle = [\+] 1..9;

After writing all the above, it occurred to me that the use of @_ should
implicitly define a closure as slurpy/n-ary. That would remove the need
for the arrow, and make the code much less ugly.
Also, the first value (0) might be unnecessary. The spec says that it
should not be required when the closure is 0-ary, but I think that
should also be true for slurpy/n-ary closures.
These work in Niecza:

my @squares := { @_ ** 2 } ... *;

my @triangle := 1, { @_[*-1] + @_ + 1 } ... *;

--
Hope this helps,
Bruce Gray
(Util of PerlMonks)



Re: How to make a new operator.

2012-03-22 Thread Jon Lang
On Thu, Mar 22, 2012 at 9:07 AM, Bruce Gray bruce.g...@acm.org wrote:

 On Mar 21, 2012, at 11:49 PM, Jonathan Lang wrote:

  What I want to know is whether there's a way to define a step function
 that's based in part or in whole on the current term's index.  For example,
 how would I use infix:... to generate the perfect squares between 0 and
 100?  Namely, '0,1,4,9,16,25,36,49,64,81,**100'.  For example, is Perl 6
 set up to try to pass the current element's index into the step function by
 means of a named parameter?

 I would hope for something like:

  - :index { $index * $index } ... 100

 or

  1, *+:index ... * # 1,3,6,10,15,21,28,36,45,...

 (Note: I _don't_ expect the above to work as is; they're merely intended
 to convey a rough idea of what I _do_ want.)

 If not, how _would_ I generate these lists?



 In real life, you would just use this:
   my @squares = map { $_ * $_ }, 0..10;
 or, for an infinite list, use a binding instead of an assignment:
   my @squares := map { $_ * $_ }, 0..*;


True enough.


 But you were asking about ... specifically :^)


Yes, I was.


 On freenode/#perl6, I was pointed to part of the spec that I had
 overlooked.
 The sequence operator is defined in S03:
   
 http://perlcabal.org/syn/S03.**html#List_infix_precedencehttp://perlcabal.org/syn/S03.html#List_infix_precedence
 Buried in its definition is this gem:
   
 http://perlcabal.org/syn/S03.**html#line_1884http://perlcabal.org/syn/S03.html#line_1884
   The function may also be slurpy (n-ary), in which case all
   the preceding values are passed in (which means they must
   all be cached by the operator, so performance may suffer,
   and you may find yourself with a space leak).


Interesting; it never occurred to me to try to retrieve the current index
by slurping in all of the previous elements and counting them.


 After writing all the above, it occurred to me that the use of @_ should
 implicitly define a closure as slurpy/n-ary. That would remove the need
 for the arrow, and make the code much less ugly.
 Also, the first value (0) might be unnecessary. The spec says that it
 should not be required when the closure is 0-ary, but I think that
 should also be true for slurpy/n-ary closures.


Agreed: starting values should only be mandatory when dealing with a step
function that definitely requires them.


 These work in Niecza:

my @squares := { @_ ** 2 } ... *;


And this is rather elegant, syntactically (though not so much in the
performance department).

-- 
Jonathan Dataweaver Lang


Re: How to make a new operator.

2012-03-22 Thread Moritz Lenz

Am 22.03.2012 17:07, schrieb Bruce Gray:

I have run into the same need for something like :index, while
playing with RosettaCode tasks like Continued_fraction.


If you want the index, don't use series. It's easy enough to access the 
array elements yourself. You can do something like


my @a := (1..*).map: - $i {
$i ** 2 + @a[$i - 1] // 0;
};

to access previous elements.  You can even use 'last' inside the map 
block to get out of the loop.




Well, it works in Niecza. It does not (yet) work in Rakudo:
15:25 Util perl6: my @squares := 0, (- *@a { @a.elems ** 2 }) ... *;
say ~@squares[^11];
15:25 p6eval ..niecza v15-4-g1f35f89: OUTPUT0 1 4 9 16 25 36 49 64
81 100NL
15:25 p6eval ..rakudo 1a468d: OUTPUT0 0 0 0 0 0 0 0 0 0 0NL


higher-arity sequences are a known regression in rakudo, 
S03-sequence/limit-arity-2-or-more.t currently isn't run.




After writing all the above, it occurred to me that the use of @_ should
implicitly define a closure as slurpy/n-ary.


It shouldn't only, it does already (in all rakudo pugs niecza).
The future is already here, it's just unevenly distributed.


Cheers,
Moritz


Re: How to make a new operator.

2012-03-22 Thread Martin D Kealey
On Thu, 22 Mar 2012, Carl Mäsak wrote:
 Jonathan Lang (), Daniel ():
     1, 2, 4 ... 100 # same as 1,2,4,8,16,32,64
 
  That last one doesn't work on Rakudo :-(

 And it never will. Note that 100 is not a power of 2, and that the goal
 needs to match exactly. This is because smartmatching is used, not some
 other comparison. The sequence will continue to generate numbers until the
 number 100 is generated, which never happens. Rakudo loops forever on this
 one, as per spec.

Hmmm, so it's likely that most times you get a Num rather than an Int or
Rat, those won't stop either?

1, 7 / 6.0 ... 2
1, sqrt(2), 2 ... 8

Question: do we support

1, 2i, -4 ... 256

 If you're wondering why things are factored in this way, it's because
 previous versions of the spec that tried to special-case 100 to work in
 cases like the above, ended up not working out. It turned out that the
 unification of infix:... and smartmatching was what did work. It has the
 slight drawback that we have to educate users to write * = 100 instead of
 100 in the case of not-exactly-matching goal states. But it's still a net
 win, because this unified semantics works better than anything we had
 before.

Sounds to me like AscendingArithmeticIteratorInclusiveTerminalSmartMatch
could do the same thing as normal SmartMatch except when the LHS is an
IteratorOf{X} and the RHS is an {X}, for X in {Int, Rat, Num} and possibly
other comparable (orderable) types, when  would be implied.

Likewise for AscendingArithmeticIteratorExclusiveTerminalSmartMatch (=)
DescendingArithmeticIteratorInclusiveTerminalSmartMatch () and
DescendingArithmeticIteratorExclusiveTerminalSmartMatch (=).

-Martin


Re: How to make a new operator.

2012-03-22 Thread Patrick R. Michaud
On Fri, Mar 23, 2012 at 03:03:09PM +1300, Martin D Kealey wrote:
 On Thu, 22 Mar 2012, Carl Mäsak wrote:
  Jonathan Lang (), Daniel ():
      1, 2, 4 ... 100 # same as 1,2,4,8,16,32,64
  
   That last one doesn't work on Rakudo :-(
 
  And it never will. Note that 100 is not a power of 2, and that the goal
  needs to match exactly. 
 
 Hmmm, so it's likely that most times you get a Num rather than an Int or
 Rat, those won't stop either?
 
   1, 7 / 6.0 ... 2
   1, sqrt(2), 2 ... 8

The expression 7/6.0 produces a Rat, so the first sequence properly 
stops at 2.

On Rakudo on my system, sqrt(2) indeed produces a Num,
but since floating point arithmetic doesn't result in
sqrt(2) / 1 == 2 / sqrt(2), no geometric sequence is deduced 
and the sequence fails with unable to deduce sequence.

 Question: do we support
 
   1, 2i, -4 ... 256

I think this ought to work, but for some reason Rakudo on my system
hangs whenever I try it.  The following does work in Rakudo:

 say 1, { $^x * 2i } ... 256
1 0+2i -4+0i -0-8i 16+-0i 0+32i -64+0i -0-128i 256+-0i

The fact that the auto-deduced sequence hangs probably needs to be
filed as a bug report for Rakudo.

Pm


Re: How to make a new operator.

2012-03-21 Thread Moritz Lenz


On 03/21/2012 09:07 PM, Daniel Carrera wrote:
 Hello,
 
 Is it possible to create a new range operator ':' such that:
 
 a:b is the same as a..b  (this is the easy part)
 
 a:b:c is a range from 'a' to 'b' by steps of 'c'. For example, 2:15:3
 == 2,5,8,11,14

That can be done by giving the new infix:: operator list associativity
(niecza already supports this)

 :b is the same as 0..b

create a new prefix operator... except that that prefix : is already
taken for constructing pairs

 a: is the same as a..Inf

create a postfix:: operator... except that postfix : is already taken
as invocant marker

 ::c is the same as 0:Inf:c

create a prefix::: operator. Except that this collides with existing
syntax...

 : is the same as 0..Inf

create a term::.


There are hooks for all of that, but it requires you to come up with a
new syntax that doesn't collide heads-on with lots of existing grammar
rules.

Cheers,
Moritz


Re: How to make a new operator.

2012-03-21 Thread Daniel Carrera
Hi Moritz

 a:b is the same as a..b  (this is the easy part)

 a:b:c is a range from 'a' to 'b' by steps of 'c'. For example, 2:15:3
 == 2,5,8,11,14

 That can be done by giving the new infix:: operator list associativity
 (niecza already supports this)

Can you explain or give me a link that explains how to do that? I can
figure out a little bit on my own:

multi sub infix::( Int $a, Int $b ) {
 #  This is the case 'a:b'
}

multi sub infix::( Range $a, Int $b ) {
 #  Is this correct?
 #  I'm thinking that a:b:c could be interpreted as (a:b):c so it
is Range : Int.
 # Am I on the right track?
}


 :b is the same as 0..b

 create a new prefix operator... except that that prefix : is already
 taken for constructing pairs

Ok. I hadn't realized that you could define the same symbol as prefix,
infix and postfix... So.. ignoring the fact that : conflicts with
existing syntax, I could do this:

multi sub infix::( Int $a, Int $b )  { ... }
multi sub infix::( Range $a, Int $b ) { ... }
multi sub prefix::( Int $a ) { ... }
multi sub postfix::( Int $b ) { ... }

Right?

 : is the same as 0..Inf

 create a term::.

Ok.


 There are hooks for all of that, but it requires you to come up with a
 new syntax that doesn't collide heads-on with lots of existing grammar
 rules.

Thanks. I'll see if I think of something that feels natural but
doesn't collide with anything. One option is to just use the existing
.. operator:

multi sub prefix:..( Int $b ) { 0..$b }
multi sub postfix:..( Int $a ) { $a..Inf }

Only problem is that something like 2..10..3 might be confusing.

Hmm... I must have made a mistake here somewhere... After defining
these functions, the traditional range '2..10' doesn't work anymore. I
suppose that my new functions have a higher precedence than the
traditional .. operator. I tried to fix this, but I failed:

multi sub prefix:..( Int $b ) is looser(infix:cmp) { 0..$b }

So, I'm not doing this right.

Cheers.
Daniel.
-- 
I'm not overweight, I'm undertall.


Re: How to make a new operator.

2012-03-21 Thread Damian Conway
 Is it possible to create a new range operator ':' such that:

Do you need to?


 a:b:c is a range from 'a' to 'b' by steps of 'c'.

Perl 6 already has: $a,*+$c...* =$b

E.g. 2, 5 ...^ *=15   2,5,8,11,14


 :b is the same as 0..b

Perl 6 already has ^$b

e,g, ^100  0..99


 a: is the same as a..Inf

Perl 6 already has $a..* or $a...*

e.g. 3..*  3,4,5,6,


 ::c is the same as 0:Inf:c

Perl 6 already has:  0,$c...*

e.g. 0,3...*  0, 3, 6, 9, 12


 : is the same as 0..Inf

Perl 6 already has: ^Inf  0,1,2,3,4,5,


Damian


Re: How to make a new operator.

2012-03-21 Thread Carl Mäsak
Daniel (), Damian ():
 : is the same as 0..Inf

 Perl 6 already has: ^Inf  0,1,2,3,4,5,

Hah, Damian made an off-by-one error! Oh wait...

// Carl


Re: How to make a new operator.

2012-03-21 Thread Carl Mäsak
Damian (), Daniel ():
 Perl 6 already has:  0,$c...*

 e.g. 0,3...*  0, 3, 6, 9, 12

 Interesting... but it doesn't seem to work in Rakudo Star (2012.02):

 @(2,5..10)
 2 5 6 7 8 9 10

 :-(

Keep in mind that infix:.. will listify to the kind of
one-step-at-a-time range that was produced above, whereas infix:...
is its more DWIMmy cousin and would take the above as counting three
steps at a time.

It would also produce an infinite list, because by the rules you need
the RHS of infix:... to match exactly, and 10 is not in the infinite
list 2, 5, 8, 11, 14... Which is why you'd need to write something
like * = 10.

// Carl


Re: How to make a new operator.

2012-03-21 Thread Damian Conway
 Interesting... but it doesn't seem to work in Rakudo Star (2012.02):

 @(2,5..10)

You need three dots, not two.

Damian


Re: How to make a new operator.

2012-03-21 Thread Daniel Carrera
On 21 March 2012 22:50, Carl Mäsak cma...@gmail.com wrote:
 It would also produce an infinite list, because by the rules you need
 the RHS of infix:... to match exactly, and 10 is not in the infinite
 list 2, 5, 8, 11, 14... Which is why you'd need to write something
 like * = 10.

Ok, so infix:... isn't what I wish for either... Can you help me
understand Damian's example?

$a,*+$c...* =$b


I see a lot of Perl magic here and I have no idea what any of it does.
What does the first star do? And the plus sign?

I tried to guess what the = does by experimentation, but I can't make
heads or tails of it:

 2..100 = 5
True

 2...100 = 5
2

Also, I'm only now learning what ... does. I thought it was just the
yada yada yada operator, but now I see that it makes an object
called List(), which clearly is different from both Range() and
Array()...

Btw, I just found the section in S09 covering multi-dimensional arrays
and the semicolon operator. I'll go read it now...

One unrelated question: Is there a way to ask an object what methods
it supports? That would make it easier for me to experiment. For
example, just now I have been looking for the methods supported by the
Range object (to see how I'd obtain the beginning and end points of a
range) and haven't found anything.

Cheers,
Daniel.
-- 
I'm not overweight, I'm undertall.


Re: How to make a new operator.

2012-03-21 Thread Damian Conway
 Ok, so infix:... isn't what I wish for either... Can you help me
 understand Damian's example?


Breaking down that example:

$a,  # Start at $a
*+$c # Generate next number via: sub($prev_num} { $prev_num + $c }
...  # Repeat until...
* =$b   # ...this sub matches: sub($prev_num) { $prev_num = $b }

* used as an argument to an operator is a shorthand for constructing
subroutines,
where the * represents the subroutine's argument.


Damian


Re: How to make a new operator.

2012-03-21 Thread Daniel Carrera
On 22 March 2012 00:08, Brandon Allbery allber...@gmail.com wrote:

 * + $c --- the next value is the current value plus $c.  (* means
 Whatever, and generally refers to the current value of something.  In this
 case, we're specifying how to make a new value given a current value.  You
 can think of it as a way to make an anonymous function.  In Haskell this
 would be (+ c) or \x - x + c; in Python, lambda x: x + c; in Perl 5,
 sub {$_[0] + $c}.  The meaning of * is context dependent, though; when
 accessing array elements, for example, * refers to the end of the array, so
 @arr[* - 1] means the second last element of @arr.)


Interesting... a lambda expression...

 my add3 = * + 3
WhateverCode.new()

 add3(2)
5


Cool... this actually works... But I notice that to use 'add3' in the
list construction I need to put an ampersand:

 2, add3 ... 14
2 5 8 11 14


Still... the fact that this works is neat.



 * = $b --- this determines where the sequence ends:  when the current value
 is greater or equal to $b.


So...  after the ... you have an anonymous function that has to
return 'True' for the sequence to end? Seems strange, but it works:

# A function that always returns True = List of one item.
 2,5...True
2


So if I want to go from $a to $b by steps of $c, the correct recipe would be:

$a, *+$c ... * = $b - $c

With this information, I can write something like this:

sub infix:|( Range $r, Int $c ) {
my ($a, $b) = $r.bounds;
return $a, *+$c ... * = $b - $c
}

(2..10)|3   == 2, 5, 8

This would look better if I removed the parenthesis, but I'm having
trouble telling Rakudo that this infix operator is looser than the ..
operator:

sub infix:|( Range $r, Int $c ) is looser( infix:.. ) {
...
}
No applicable candidates found to dispatch to for 'trait_mod:is'.



 haral:6704 Z$ ./perl6 -e 'say (2, 4 ... 10).^methods'

Thanks. That's very useful.

 The .^ operator runs a method on the object's metaobject, which determines
 how it associates with its class and roles.  The metaobject is available via
 the HOW method, but is not something you can print or etc.; working with it
 directly is somewhat painful, which is why .^ exists.

Ok.


-- 
I'm not overweight, I'm undertall.


Re: How to make a new operator.

2012-03-21 Thread Solomon Foster
On Wed, Mar 21, 2012 at 7:52 PM, Daniel Carrera dcarr...@gmail.com wrote:
 * = $b --- this determines where the sequence ends:  when the current value
 is greater or equal to $b.

 So...  after the ... you have an anonymous function that has to
 return 'True' for the sequence to end? Seems strange, but it works:

 # A function that always returns True = List of one item.
 2,5...True
 2

It actually smartmatches whatever is on the right hand side against
the sequence, and stops when the smartmatch returns True.  It just
happens that you smartmatch an anonymous function, it executes the
function and returns its result.

In particular, note that True there is not an anonymous function, it's
just the value True.  You'd need to say { True } to get an anonymous
function which returns True.

Examples:

2, 5 ... 11 # smartmatch is true when you hit 11
2, 5 ... True # stop right away
2, 5 ... False # never stop
2, 5 ... * # shorter way of saying never stop
2, 1, 1/2 ... Num # stop when the number switches from a Rat to a Num
'a' ... /f/ # stop when the regular expression matches

-- 
Solomon Foster: colo...@gmail.com
HarmonyWare, Inc: http://www.harmonyware.com


Re: How to make a new operator.

2012-03-21 Thread Daniel Carrera
On 22 March 2012 01:13, Solomon Foster colo...@gmail.com wrote:
 It actually smartmatches whatever is on the right hand side against
 the sequence, and stops when the smartmatch returns True.  It just
 happens that you smartmatch an anonymous function, it executes the
 function and returns its result.

I see... I still find this a little confusing. The idea of
smart-matching a function just doesn't quite fit with my brain. I can
memorize the fact that smart-matching 7 and foo means evaluating
foo(7) and seeing if the value is true, but I can't say I understand
it.


 Examples:

 2, 5 ... 11 # smartmatch is true when you hit 11
 2, 5 ... True # stop right away
 2, 5 ... False # never stop
 2, 5 ... * # shorter way of saying never stop
 2, 1, 1/2 ... Num # stop when the number switches from a Rat to a Num
 'a' ... /f/ # stop when the regular expression matches

Interesting.


Cheer,
Daniel.
-- 
I'm not overweight, I'm undertall.


Re: How to make a new operator.

2012-03-21 Thread Jonathan Lang
My understanding is if you want to count by threes, starting at 2 and ending at 
14, you should be able to write:

   2, 5 ... 14

That is, the list-building operator looks at the previous two or three terms 
preceding it to determine where to start and what step function to use, and 
then looks at the first term following it to determine where to stop.  The use 
of lambda functions in the immediately preceding and following terms provides a 
means to explicitly define the step function and the test condition, 
respectively; but Perl 6 is supposed to be smart enough to intuit linear step 
functions from two strictly numeric prior terms, geometric step functions from 
three such terms, and a test condition that stops the series at ' $n' from a 
numeric right term.  

So: 

1, 3 ... 13 # same as 1,3,5,7,9,11,13
1 ... 10 # same as 1,2,3,4,5,6,7,8,9,10
1, 2, 4 ... 100 # same as 1,2,4,8,16,32,64

and

2, 5 ... 14 # same as 2,5,8,11,14

Meanwhile, using Whatever for the test condition means keep the series going 
indefinitely:

1, 3 ... * # every positive odd number.  
1 ... * # all counting numbers.
1, 2, 4 ... * # all powers of 2.

And using '...^' instead of '...' changes the default final test condition from 
' $n' to '= $n':

1, 3 ...^ 13 # same as 1,3,5,7,9,11
1 ...^ 10 # same as 1,2,3,4,5,6,7,8,9
1, 2, 4 ...^ 100 # same as 1,2,4,8,16,32,64

In short, what Damian is talking about is the more powerful and reliable use of 
the syntax; but the above approach (assuming it has been properly implemented) 
is a more intuitive use that covers the most common cases.  Make common things 
easy, and make uncommon things possible. 

Likewise, using Whatever in conjunction with operators is there to provide an 
intuitive way to calculate the next term from the previous one(s):

1, *+2 ... 13 # start at 1, step by 2s, stop at 13.
1, 1, *+* ... * # each new term is the sum of the previous two.
1, 1, infix:+ ... * # same as last one.

Re: How to make a new operator.

2012-03-21 Thread Jonathan Lang
What I want to know is whether there's a way to define a step function that's 
based in part or in whole on the current term's index.  For example, how would 
I use infix:... to generate the perfect squares between 0 and 100?  Namely, 
'0,1,4,9,16,25,36,49,64,81,100'.  For example, is Perl 6 set up to try to pass 
the current element's index into the step function by means of a named 
parameter? 

I would hope for something like:

- :index { $index * $index } ... 100

or

1, *+:index ... * # 1,3,6,10,15,21,28,36,45,...

(Note: I _don't_ expect the above to work as is; they're merely intended to 
convey a rough idea of what I _do_ want.)

If not, how _would_ I generate these lists?