Centenary Sequences with Raku
Part 3

Not True, or Not

by Arne Sommer

Centenary Sequences with Raku - Part 3: Not True, or Not

[100.3] Published 4. November 2020.

See also: The Introduction | Part 1: Raku Part 2: Arithmetic and Geometric Sequences

True and False

022. True Forever
A Sequence can deliver the same value over and over again. The number 1 will evaluate to True in Boolean context, so we can set up a True Forever Sequence like this:

(1, 1 ... Inf)                                                          # 022
> say (1, 1 ... Inf)[^30];
(1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1)

Using Inf as the upper limit may lead you to think that we are expecting the values to grow bigger and bigger. That is certainly not the case here, but that is quite alright.

This does not work, even if the values are lower than the upper limit:

> say (1, 1 ... 2)[^10];
(Nil Nil Nil Nil Nil Nil Nil Nil Nil Nil)

Using -Inf does work, though it is unwise:

> say (1, 1 ... -Inf)[^30];
(1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1)

023. Truly True Forever
You may want the real True value instead:

This does not work:

> say (True, True ... Inf)[^10];
(True 1 1 1 1 1 1 1 1 1)

Using a rule works:

(True, !!* ... Inf)                                                     # 023a
> say (True, !!* ... Inf)[^10];
(True True True True True True True True True True)

We start with True. The next value uses * to access the previous value (True). We cannot use * on its own, but applying the Negating Operator ! twice, to get back to True, works:

But it is better to enforce Boolean context with the ? or so operators:

(True, so * ... Inf)                                                    # 023b
> say (True, so * ... Inf)[^10];
(True True True True True True True True True True)
(True,  ? * ... Inf)                                                    # 023c
> say (True, ? * ... Inf)[^10];
(True True True True True True True True True True)

See docs.raku.org/routine/so for more for more information about the Boolean Context Operator so.

See docs.raku.org/routine/? for more for more information about the Boolean Context Operator ?.

The gather/take construct can also be used here:

gather { loop { take True }}                                            # 023d
> say gather { loop { take True }}[^10]
(True True True True True True True True True True)
> my $true := gather { loop { take True }};
> say $true[^10];
(True True True True True True True True True True)

Binding vs Assignment

Note the usage of binding (with :=) to a scalar, instead of the normal assignment to an array. The latter will enforce non-lazy context, and will go on forever:

> my @true = gather { loop { take True }};  # Will run forever

It is possible to ensure lazy context, with the lazy keyword, so that we can use an array:

> my @true = lazy gather { loop { take True }};  # Works
> say @true[^10];
(True True True True True True True True True True)

See docs.raku.org/routine/:= for more information about the Binding Operator :=.

See docs.raku.org/language/statement-prefixes#index-entry-lazy_(statement_prefix)-lazy for more information about lazy.

024. False Forever
We can do the same with 0 and False, as we did with 1 and True above:

> (0, 0 ... Inf)                                                        # 024
> say (0, 0 ... Inf)[^25];
(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)

025. Truly False Forever
(False, !!* ... Inf)                                                    # 025a
> say (False, !!* ... Inf)[^10];
(False False False False False False False False False False)
(False, so * ... Inf)                                                   # 025b
> say (False, so * ... Inf)[^10];
(False False False False False False False False False False)
(False, ? * ... Inf)                                                   # 025c
> say (False, ? * ... Inf)[^10];
(False False False False False False False False False False)
gather { loop { take False }}                                           # 025d
> say gather { loop { take False }}[^10];
(False False False False False False False False False False)

026. Flip Flopper
A Sequence that alternates between the values 1 and 0 is easy to set up with gather/take:

gather { loop { take 1; take 0 }}                                       # 026
> say gather { loop { take 1; take 0 }}[^10];
(1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0)

027. Flip Flopper, Truly
It is even easier with True and False:

(True, !* ... Inf)                                                      # 027a
> say (True, !* ... Inf)[^10];
(True False True False True False True False True False)

With gather/take:

gather { loop { take True; take False }}                                # 027b
> say gather { loop { take True; take False }}[^10];
(True False True False True False True False True False)

028. A Negatively Biased Flip Flopper
We can favour a certain outcome. Here we get False 2/3 of the time:

gather { loop { take True; take False; take False }}                    # 028a
> say gather { loop { take True; take False; take False }}[^12];
(True False False True False False True False False True False False)

(There was en error in the example above, spotted by Владимир Никитов. Fixed 6. November).

We can get the same with a Sequence, with a little care:

(True, False, ( * == * ) ... Inf)                                       # 028b
> say (True, False, ( * == * ) ... Inf)[^12];
(True False False True False False True False False True False False)

029. A Positively Biased Flip Flopper
As above, as a Sequence. Here we get True 2/3 of the time:

gather { loop { take True; take True; take False }}                     # 029a
> say gather { loop { take True; take True; take False }}[^12];
(True True False True True False True True False True True False)

As a Sequence, with even more care:

(True, True, False, ( * != * ) ... Inf)                                 # 029b
> say (True, True, False, ( * != * ) ... Inf)[^12];
(True True False True True False True True False True True False)

030. Flipped Sign
Do you want the nagative version of the number every other time?

(1, -* ... inf)                                                         # 030
> say (1, -* ... Inf)[^20];
(1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1)

True(ly) Random

All the Sequences shown so far are reproducible. They give the same result every time you generate them.

We'll conclude this part with some random sequences. The are not sequences in a mathematical sense, but can be useful in a real life situation.

031. A Random Flip Flopper
A Sequence that changes its mind all the time can be useful:

gather { loop { take (True, False).pick }}                              # 031a
> say gather { loop { take (True, False).pick }}[^10];
(True True True True True False False False False False)
> say gather { loop { take (True, False).pick }}[^10];
(False True True False False False True False False False)

The name is in honour (or actually the opposite) of what is described in the Wikipedia Flip-flop_(politics) article.

Note that the generated sequence is random, but once generated a value at a given index stays the same - as shown below:

> my $random := gather { loop { take (True, False).pick }};
> say $random[^6];  # -> (True False True True False True)
> say $random[^6];  # -> (True False True True False True)

We can achieve the same with a Sequence:

( { (False, True).pick } ... Inf )                                      # 031b
> say ( { (False, True).pick } ... Inf )[^10];
(True False True False True True True False False True)
> say ( { (False, True).pick } ... Inf )[^10];
(True True False False True True True True False True)

032. A Random Sequence
You are certainly not restricted to Boolean values. Here we get random numbers from 1 to 100, both included:

gather { loop { take (1..100).pick }}                                   # 032a
> say gather { loop { take (1..100).pick }}[^15];
(22 15 90 28 22 38 14 31 82 82 59 30 18 60 37)
> say gather { loop { take (1..100).pick }}[^15];
(34 98 10 94 14 73 56 14 80 93 79 29 2 7 73)

As a Sequence:

( { (1..100).pick } ... Inf )                                           # 032b
> say ( { (1..100).pick } ... Inf )[^15];
(93 3 82 77 90 89 6 67 16 75 3 53 35 44 2)
> say ( { (1..100).pick } ... Inf )[^15];
(59 94 71 69 33 29 30 89 76 14 28 99 18 35 80)

But enough of that. Entropy may not be your cup of tea.

The Next Part

Part 4: Primes and Fibonacci.