Raku'da matematiksel serileri kısaca yazdırma


9

Matematiksel seriler, örneğin burada bir dizi olarak temsil edilen ardışık diziyi ele alalım:

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) };

Baskılar:

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

a8 =  8
a9 =  9

Sorularım: 1- Sadece ilk öğeyi a0 = 0yazdırmak için bırakmanın basit bir yolu var mı ?

2- Bu kod daha deyimsel hale getirilebilir mi?

Teşekkür ederim.


@DanBron Yorum için teşekkürler. Orijinal yayında yeni düzenlemeler yaptım.
Lars Malmsteen

Yanıtlar:


2

Barebone çözümü

Bir sekansın özünü yazdırmak için çok basit bir çözümle başlayalım. Sorunuza eklediğiniz özelliklerle ilgilenmiyor, ancak iyi bir başlangıç ​​noktası:

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

.kvInvocanını forma dönüştürenlerin aksine , key1, value1, key2, value2, key3, value3, ...invocan 3 element içeriyorsa 6 element, .pairsinvosanını forma dönüştürür key1 => value1, key2 => value2, key3 => value3, ....

Bunun .pairsyerine .kvkısmen kullandığım ».gistiçin, kodda daha sonra key1 => value1her öğeye zahmetsizce güzel bir ekran almak için kullanabileceğim anlamına geliyordu . Bunu aşağıda değiştireceğiz, ancak bu iyi bir deyimsel başlangıç.

.headve.tail çağrılar bir invocant listeden ilk ve son N elemanlarının küçük listeleri oluşturmak için deyimsel yoludur (o tembel değil sağlanan; daha bu konu hakkında bir mo).

Bu ilk çözüm verildiğinde aşağıdakileri say seq-range-gist (0,1 ... Inf)[^10]görüntüler:

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

Daha sonra, "sadece ilk öğeyi ... basılı çıktıdan düşürmek" istiyoruz. Ne yazık ki say seq-range-gist (0,1 ... Inf)[1..9]görüntüler:

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

Solundaki sayının =>orijinal dizinin numaralandırmasını korumasını istiyoruz . Bunu etkinleştirmek için temel diziyi ayıklamak istediğimiz aralıktan ayırırız. İkinci bir parametre / bağımsız değişken ekliyoruz ve alt @rangeöğenin [@range]ikinci satırına ekliyoruz :

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

Şimdi say seq-range-gist (0,1 ... Inf), 1..9görüntülemek için yazabiliriz :

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

Sorunuzda biçimi kullanmak aINDEX = VALUEyerine kullandınız INDEX => VALUE. Gist'in özelleştirilmesine izin vermek için üçüncü bir &gistrutin parametre / argüman ekliyoruz ve bunu yerleşik .gistyöntem yerine çağırıyoruz :

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

seq-range-gistSub gövdesindeki "yöntem" çağrılarının şimdi nasıl olduğuna .&gistdikkat edin .gist. Sözdizimi .&foobir çağırır alt &foo (tipik olarak, sadece yazılı çağrılır foosolunda invocant geçen) .bir şekilde $_alt argüman.

Ayrıca &gistparametrenin bir ile başlayarak adlandırılmış bir tane yaptığımı unutmayın :.

Şimdi say seq-range-gist (0,1 ... Inf), 1..9, gist => { "a{.key} = {.value}" }görüntülenir:

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

Lehçe ekleme

Bu cevabın geri kalanı lehçeyi önemseyen okuyucular için bonus materyal.

say seq-range-gist (0, 1, 2, 3), ^3 görüntüler:

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

Hata. Ve kafa ve kuyruktan daha fazla çift olsa bile, en azından tekrarlanan çizgiler alamadık, head, ..., tailsadece bir veya iki elementi elide etme yaklaşımını kullanmak yine de anlamsız olurdu . Bu sorunları ortadan kaldırmak için alt gövdedeki son ifadeyi değiştirelim:

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

Sonra, alt aralık veya gist olmadan çağrılırsa yararlı bir şey yapsaydı iyi olurdu. Bunu çoğunlukla @rangeve &gistparametrelerine uygun varsayılanlar vererek düzeltebiliriz :

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

Eğer @seqbir değil tembel sonra, @rangetam kapsamlı varsayılan @seq. Eğer @seqbir sonsuz (bu durumda o da tembeldir), sonra 100 kadar varsayılan gayet iyi. Peki ya @seqtembel ancak 100'den az tanımlanmış değer verirse ne olur ? Bu vakayı kapsamak .grep: *.value.definediçin @pairsbildirime ekliyoruz:

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

Başka bir basit gelişme, isteğe bağlı kafa ve kuyruk parametreleri olacak ve nihai cilalı bir çözüme yol açacaktır:

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)
}

Minimum çözüm oldukça iyi çalışıyor ve aynı zamanda terbiyeli bir deyim. Benim çözümümde, ...daha çok bir C programına benzemesine neden olan kısmı hesaba katmak için bir 'bayrak' değişkenine başvurmak zorunda kaldım . Yani bu sorumun her iki bölümüne de cevap veriyor. 'Kapsamlı' çözüme gelince, gerçekten biraz korkutucu görünüyor.
Lars Malmsteen

Geri bildiriminiz ve @LarsMalmsteen yanıtımı kabul ettiğiniz için teşekkür ederiz. Bununla birlikte, cevabımı tamamen yeniden yazdım ve daha iyi olduğunu hissediyorum. 'Kapsamlı' çözümü düşürdüm - bununla birlikte yabani otların içine gittim! - ama aynı zamanda "asgari çözümü" ve beraberindeki açıklamayı tamamen yeniden yazdım. Bunu daha sonra diğer okuyucular için yaptım ama yeni cevabı okurken biraz değer kazanabilirsiniz.
19'da raiph

7

Sen ilk N değerleri atlayabilir herhangi Iterable veya Sequencebirlikte skip:

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

Bir sayı belirtmezseniz, yalnızca bir öğe atlanır.


skip0 indeksi (a0) kalıntılarıyla sadece çıktıya yani elemanını kaldırmak gibi görünüyor. Denedim @seq:deleteve 0'ıncı elementin yerini aldı(Any)
Lars Malmsteen

Aslında. skipAtlanan elemanları yoktur sanki sadece hareket edecektir. İstediğiniz gibi olabilir veya olmayabilir :-)
Elizabeth Mattijsen

Ben koyduğunuzda skipbu yüzden okur ikisinin arasında: for @seq[^10].skip(0).kvo kelimenin tam anlamıyla 0 unsuru atlamak değildir ve bunun önemi ben argüman olarak verirsen gelmez skip1 veya 2, sadece ayrıca dışarı bozan. 0. elemanı sıfırdan kaldırmak için pratik bir yola ihtiyacım var.
Lars Malmsteen

1
Belki for @seq[^10].kv.skip(2)de aradığın şey nedir?
Elizabeth Mattijsen

Evet bu işi yapar. Aslında ben skipsonra koymak denedim .kvama 2 dışında argümanlar kullanarak, bu yüzden işe yaramadı. Çözüm için teşekkürler.
Lars Malmsteen

7

Bu biraz daha deyimsel olabilir:

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

Sekans içinde sözcüksel bir değişken kullanmanıza gerek yoktur; ya Whateverda yer tutucu değişkenler sekanslar içinde güvenle kullanılabilir. Ardından, dizinin yazdırılmasını istediğiniz öğelerini seçmeniz yeterlidir. Hangi döndürür«(0 1 2 3)(7 8 9 10)␤»


Cevap için teşekkür ederim. whateverOperatör refreshening ancak seri / dizi çıkışı ana konuyu ele vermez. Diziyi matematik ders kitaplarında görüldüğü gibi yazdırmak istiyorum, yani aralarında ...gösterim ile.
Lars Malmsteen

@LarsMalmsteen, Tamam, bunu düzenleyeceğim
jjmerelo
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.