Printing mathematical series concisely in Raku

Mathematical series, take for example the consecutive sequence represented here as an array:

my @seq = my $a=0, {++$a} ... *;
for @seq[^10].kv {state $f=0; ($^k < 4 or $^k > 7) ?? say "a$^k =  "  ~ $^v !! (say "..." if $f ne 1; $f=1) };

Prints:

a0 =  0
a1 =  1
a2 =  2
...

a8 =  8
a9 =  9

My questions: 1- Is there a simple way to drop just the first element i.e. a0 = 0 from the printed output?

2- Could this code be made more idiomatic?

Thank you.

A barebones solution

Let's start with a very simple solution for printing a gist of a sequence. It doesn't deal with the specifics you've added to your question but it's a good starting point:

sub seq-range-gist ( @seq ) {
  my @pairs = @seq.pairs;
  join "\n", @pairs.head(3)».gist, '...', @pairs.tail(2)».gist
}

Unlike .kv, which converts its invocant into the form key1, value1, key2, value2, key3, value3, ..., i.e. 6 elements if its invocant contains 3 elements, .pairs converts its invocant into the form key1 => value1, key2 => value2, key3 => value3, ....

I used .pairs instead of .kv partly because it meant I could just use ».gist later on in the code to effortlessly get a nice key1 => value1 display for each element. We'll modify that below but this is a good idiomatic start.

The .head and .tail calls are the idiomatic way to create small lists of the first and last N elements from an invocant list (provided it's not lazy; more about that in a mo).

Given this initial solution, say seq-range-gist (0,1 ... Inf)[^10] displays:

0 => 0
1 => 1
2 => 2
...
8 => 8
9 => 9

Next, we want to be able to "drop just the first element ... from the printed output". Unfortunately say seq-range-gist (0,1 ... Inf)[1..9] displays:

0 => 1
1 => 2
2 => 3
...
7 => 8
8 => 9

We want the number on the left of the => to retain the numbering of the original sequence. To enable this we split the underlying sequence from the range that we want extracted. We add a second parameter/argument @range, and append [@range] to the second line of the sub:

sub seq-range-gist ( @seq, @range ) {
  my @pairs = @seq.pairs[@range];

Now we can write say seq-range-gist (0,1 ... Inf), 1..9 to display:

1 => 1
2 => 2
3 => 3
...
8 => 8
9 => 9

In your question you used the format aINDEX = VALUE rather than INDEX => VALUE. To allow customization of the gist, we add a third &gist routine parameter/argument and invoke that instead of the built in .gist method:

sub seq-range-gist ( @seq, @range, :&gist ) {
  my @pairs = @seq.pairs[@range];
  join "\n", @pairs.head(3)».&gist, '...', @pairs.tail(2)».&gist
}

Note how the "method" invocations in the body of seq-range-gist sub are now .&gist, not .gist. The syntax .&foo invokes a sub &foo (which is typically invoked by writing just foo), passing the invocant on the left of the . as a $_ argument to the sub.

Note also that I've made the &gist parameter a named one by preceding it with a :.

So now say seq-range-gist (0,1 ... Inf), 1..9, gist => { "a{.key} = {.value}" } displays:

a1 =  1
a2 =  2
a3 =  3
...
a8 =  8
a9 =  9
Adding polish

The rest of this answer is bonus material for readers who care about polish.

say seq-range-gist (0, 1, 2, 3), ^3 displays:

0 => 0
1 => 1
2 => 2
...
1 => 1
2 => 2

Oops. And even if there were more pairs than the head and tail combined, so at least we didn't get repeated lines, it'd still be pointless using the head, ..., tail approach to elide just one or two elements. Let's change the last statement in the sub body to eliminate these issues:

  join "\n",
    @pairs < $head + $tail + 3   # Of course, the 3 is a bit arbitrary
      ?? @pairs».&gist
      !! (@pairs.head($head)».&gist, '...', @pairs.tail($tail)».&gist)

Next, it would be nice if the sub did something useful if called without a range or gist. We can mostly fix that by giving the @range and &gist parameters suitable defaults:

sub seq-range-gist (
  @seq,
  @range = @seq.is-lazy ?? ^100 !! ^@seq,
  :&gist = { .gist }
) {

If @seq is not lazy, then @range defaults to the full range of @seq. If @seq is infinite (in which case it's also lazy), then the upto 100 default is fine. But what if @seq is lazy but yields less than 100 defined values? To cover this case we append .grep: *.value.defined to the @pairs declaration:

  my @pairs = @seq.pairs[@range].grep: *.value.defined;

Another simple improvement would be optional head and tail parameters, leading to a final polished solution:

sub seq-range-gist (
  @seq,
  @range = @seq.is-lazy ?? ^100 !! ^@seq,
  :$head = 3,
  :$tail = 2,
  :&gist = { .gist }
) {
  my @pairs = @seq.pairs[@range].grep: *.value.defined;
  join "\n",
    @pairs <= $head + $tail + 2
      ?? @pairs».&gist
      !! (@pairs.head($head)».&gist, '...', @pairs.tail($tail)».&gist)
}

Newest solved Question Printing mathematical series concisely in , Newest solved Question Printing mathematical series concisely in Raku - currentinfo.net (currentinfo.net). submitted 7 days ago by currentinfo. The amount of syntax and features in Raku make it a rich and powerful language, but also very complex. Printing mathematical series concisely in Raku. 11.

You can skip the first N values on any Iterable or Sequence with skip:

for (^5).skip(3) {
    .say
}
# 3
# 4

If you don't specify a number, it will skip only one element.

To compute a constant of calculus(A treatise on multiple ways , Of course, because Raku's static typing is gradual, the code would still work exactly enhancing how a timed object is stringified and printed ( method Str and method gist ). Using this sequence instead of 1. I truly love that about Raku: not only does it allow you to write code that's concise, expressive,� Coverage tests for Raku modules? by JJ Merelo. How to implement around by Patrick Spek. Reading text files by every n-th line by Tao Wang. Printing mathematical series concisely by Lars Malmsteen. Meanwhile on Twitter. Six slots left by JJ Merelo. Promoting Perl in #raku by Elizabeth Mattijsen. No more kicking cans by Elizabeth Mattijsen.

This might be a bit more idiomatic:

my @seq = 0, *+1 ... *;
say @seq[^4], @seq[7..10]

You don't need to use a lexical variable within the sequence; either Whatever or placeholder variables can safely be used within sequences. Then you can simply select the elements of the sequence you want printed. Which returns «(0 1 2 3)(7 8 9 10)␤»

Doing math with Raku, Sequences�. A sequence is an enumerated collection of objects in which repetitions are allowed, and also a first-class data type in Raku called Seq. 3 Perl 6 by example P6-101. A basic introductory example of a Perl 6 program. Suppose that you host a table tennis tournament. The referees tell you the results of each game in the format Player1 Player2 | 3:2, which means that Player1 won against Player2 by 3 to 2 sets.

Raku method Routines, (From Sequence, Blob). method, Supply. (From Supplier, Promise method, concise. (From Backtrace). method, condition method, print-nl. (From IO:: Handle� 8th with: a: nextrow \ a -- a len [ ( drop [1] ), ( drop [1,1] ), ( ' n:+ y 1 slide 1 push ) ] swap 2 min caseof ; ;with with: n: .x \ n -- dup [ ( drop ), ( drop "x

[PDF] Raku One-Liners 2, Getting the most of Raku's expressive syntax for your daily routines. � Andrew After that step, we get another sequence which we can print line by line In some other cases you will get all values instead of a concise output. Carter Lecture Series – Established in 1986, the family of the late state Senator and Mrs. Clem M. Hamilton formed the Hamilton Lecture Series to honor their parents. When the Honorable Jimmy Carter spoke in 1989, the Hamilton Series was to end, but former President Carter was so impressed with the theme and purpose of the lectures that he

This banner text can have markup.. web; books; video; audio; software; images; Toggle navigation

Comments
  • @DanBron Thank you for the comment. I've just edited and elaborated on the the original post.
  • The minimal solution works quite fine and it's also decently idiomatic. In my solution I had to resort to a 'flag' variable to reckon with the ... part causing it look more like a C program. So this answers both parts of my question, really. As for the 'comprehensive' solution, it looks a bit intimidating, really.
  • Thanks for your feedback and accepting my answer @LarsMalmsteen. That said, I've entirely rewritten my answer and feel it's much better. I've dropped the 'comprehensive' solution -- I'd gone far off into the weeds with that! -- but I've also completely rewritten the "minimal solution" and accompanying explanation. I did so mostly for other later readers but you might get some value out of reading the new answer.
  • The skip seems to remove just the ouput i.e. the element with the 0th index (a0) remains. I've tried @seq:delete and it just replaced the 0th element with (Any)
  • Indeed. The skip will just act as if the skipped elements do not exist. This may or may not be what you want :-)
  • When I put the skip in between so that it reads: for @seq[^10].skip(0).kv it literally doesn't skip the 0th element and it doesn't matter if I give as the argument to skip1 or 2, it just distorts the out furthermore. I need a practical way to remove the 0th element from ground up.
  • Perhaps for @seq[^10].kv.skip(2) is what you're looking for?
  • Yes that does the job. Actually I tried putting the skipafter the .kv but using arguments other than 2, so it didn't work. Thank you for the solution.
  • Thank you for the answer. The whateveroperator is refreshening but the series / sequence output doesn't address the main issue. I'd like to print the series as they are seen on math texbooks, i.e. with ... notation in between.