Hello Jacinta,
Perl6 code should be much simpler than what you are trying. There is no
need to use a state variable or a binding.
I'm not sure how to use a maximum in the sequence, so I didn't.
The Fibonacci sequence can be generated in a single line as
1, 1, &[+] ... *
or as
1, 1, *+* ... *
in your code.
So the question is how to apply your constraints, viz. a certain number
of terms or a maximum.
The best thing when trying to experiment with perl6 is to use REPL,
which you get by just typing perl6 in to a terminal.
Below is my output; my terminal gives me ">" to say its waiting for input
So
$ perl6
> say (1, 1, &[+] ... *)[0 .. 20]
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946
The Fibonacci sequence is in the () and the [0..20] gives me the first
21 values
By the way I tried just
say 1, 1, &[+] ... *
and the terminal hung. Got to put a stop on the sequence.
Now we need to get terms to a maximum, and you wanted to use gather/take, so
> say gather for 1, 1, &[+] ... * { last if $_ > 20000; take $_ }
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946
17711
The sequence is after the 'for' and the test is inside the {}, with
'take' snapping up all values of the sequence that pass the filter
> say (gather for 1, 1, &[+] ... * { last if $_ > 20000; take $_ })[0
.. 19]
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765
This puts the two idioms together, implementing a maximum value of 20000
and a maximum number of terms.
You could avoid the magic $_ with a pointy block, eg.
gather for 1, 1, &[+] ... * -> $s { last if $s > 20000; take $s }
but I'm an old perl fan and I like the default variable $_ .
You want it in a subroutine?
> sub Fib ( :$max-value, :$max-no-terms ) {( gather for 1, 1, &[+] ...
* -> $s { last if $s > $max-value; take $s } )[0 .. $max-no-terms] }
sub Fib(:max-value(:$max-value), :max-no-terms(:$max-no-terms)) { ... }
> say Fib(:max-no-terms(35),:max-value(20000) )
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946
17711
Note that Fib uses named parameters, not positional parameters. See the
: in the definition line.
Also notice how the named parameters were passed as pairs :xxx(yyy) when
calling Fib. The = sign was not used.
Also no need to use an explicit return, because the value of a block is
the value of the last line in the block, which in the Fib sub is
truncated gather.
There is probably a shorter way. But the fundamental thing is the way to
code the Fibonacci sequence.
Hope this helps.
Richard
On 12/12/2013 11:05 AM, Jacinta Richardson wrote:
G'day folk,
I'm slowing working through some basic exercises to get a feel for
Perl 6. I'm currently trying to create a fibonacci sequence stopping
at a maximum value, or a set number of terms...
I've written this:
use v6;
sub MAIN($terms = 35, $maximum = 4_000_000) {
my @sequence = gather for fibonacci($maximum) -> $number {
state $count = 0;
take $number if $number < $maximum && $count++ < $terms;
};
say @sequence;
}
sub fibonacci($maximum) {
my @numbers := 0, 1, *+* ... * < $maximum;
return @numbers;
}
with the sequence generator kindly inspired by
http://justrakudoit.wordpress.com/2010/12/29/perl-6-fibonacci-versus-haskell/
but I can't get this to compile. The syntax highlighter is telling me
something's wrong because say @sequence is all blue, instead of say
appearing as a keyword, and the compiler says
===SORRY!===
Confused at line 19, near "}\n\nsub fib"
It's obvious I've done something wrong, but I just can't work out what
it is. Can someone show me that which will be more obvious to me when
I know more Perl 6?
Thanks,
Jacinta