Perl 6でのゴルフのヒント


16

Perl 6でゴルフをするための一般的なヒントは何ですか?少なくともPerl 6に固有のゴルフ問題全般のコーディングに適用できるアイデアを探しています(たとえば、「コメントの削除」は答えではありません)。回答ごとに1つのヒントを投稿してください。

Perl 6はPerl 5ではないため、この質問は重複していません。Perl 5ゴルフのヒントのほとんどは、Perl 6には当てはまりません。

回答:


9

subリテラルを避けてください。多くの場合、単純{}にコードブロックに使用できます。たとえば、次のコードを書かないでください。

sub ($a){$a*2}

代わりに、ブロック構文を使用してください。これはまた、あなたが使用することができます$_@_%_あなただけの単一の変数が必要な場合は、プレースホルダ変数、。さらに必要な場合は$^a$^b変数などを使用できます。

{$_*2}

また、特定のまれなケースでは、どのようなコードでも使用できます(特に単純な式がある場合)。*プレースホルダ引数に置き換えられます。

* *2

8

Perl 6には、カテゴリNdNl、および  Noのすべての Unicode文字を有理数リテラルとして使用できるという非常に奇妙な機能があります。これらのいくつかは、ASCIIで数値を書き出すよりも短いものです。

  • ¼(2バイト)より短い.25か、1/4(3バイト)。
  • ¾(2バイト)より短い.75か、3/4(3バイト)。
  • (3バイト)は1/16(4バイト)よりも短い。
  • 𐦼(4バイト)は11/12(5バイト)より短いです。
  • 𒐲(4バイト)は216e3(5バイト)より短いです。
  • 𒐳(4バイト)は432e3(5バイト)より短いです。

これのフォローアップとして、複数の数字および/またはマイナスの場合でも、Unicode指数を使用することもできます:say (3² + 4², 2²⁰, 5⁻²)==> (25 1048576 0.04)。このように悪用できるUnicodeの完全なリストは、docs.perl6.org / language / unicode_texasにあります。
ラミリーズ

8

入力を読み取るための関数を学びます。Perl 6には、ARGVまたはSTDIN(ARGVで何も指定されていない場合)からの入力を簡単に読み取ることができる多くの興味深い関数があり、正しく使用するとコードを短縮できます。それらをファイルハンドルメソッドとして呼び出す場合、特定のファイルハンドルでそれらを強制的に動作させることができます(たとえばSTDIN、から読み取りますが、ARGVで引数を読み取る必要がある場合に便利です)。

get

この関数は1行を取得し、自動的にそれを切り刻むため、必要はありません。これは、1行だけを読む必要がある場合に便利です。

lines

この関数は、ファイルまたはSTDINからすべての行を取得します。これは遅延リストなので、で使用するとfor、必要なものだけが読み取られます。例えば。

say "<$_>"for lines

slurp

これは、ファイル全体またはSTDINを読み取り、結果を単一の文字列として返します。


そのバグが修正されました-とき知らないがsay "<$_>" for lines機能するようになりました

5

警告:テキストの壁が近づいています。時間の経過とともに集めた小さなトリックがたくさんあります。

匿名ブロックとしてソリューションを書く

これについてはすでに述べましたが、繰り返し申し上げます。TIOではmy $f =、ヘッダーに書き込み、ブロックを適切なコードに書き込み、フッターをで開始でき;ます。これは、仕事を成し遂げるためのはるかに短い方法のようです(入力を読むことを気にする必要がないので、引数で与えられます)。

もう1つの良い方法は、-nまたは-pスイッチを使用することですが、TIOで機能させる方法を見つけられませんでした。

引数を渡すためにコロン構文を使用します

つまり、ではなく、1文字を保存thing.method(foo,bar)できますthing.method:foo,bar。残念ながら、明らかな理由で結果に対して別のメソッドを呼び出すことはできないため、ブロック内の最後のメソッドにのみ使用するのが理にかなっています。

$_できる限り使用する

このため、いくつかの個別の引数よりも単一のリスト引数を使用した方がよい場合があります。アクセスするとき$_、あなただけのドットで開始することにより、その上のメソッドを呼び出すことがあります。例えば.sortに等しいです$_.sort

ただし、各ブロックは独自のを取得する$_ため、外側のブロックのパラメーターは内側のブロックに伝播しません。内部ブロックからメイン関数のパラメーターにアクセスする必要がある場合、...

使用^できない場合は変数を使用します$_

次のよう^に、シギルと変数名の間にを挿入します$^a。これらはブロック内でのみ機能します。コンパイラーは、まずブロック内にあるこれらの数をカウントし、辞書式にソートしてから、最初の引数を最初の引数に割り当て、2番目の引数を2番目の引数に割り当てます。^唯一の変数の最初の発生に使用される必要があります。したがって{$^a - $^b}、2つのスカラーを取り、それらを減算します。重要なのはアルファベット順だけなので{-$^b + $^a}、同じことも同じです。

先のとがったブロック構文(のような->$a,$b {$a.map:{$_+$b}}^を使用したい場合は、メインブロックで使用しないfor each引数(のような{$^b;$^a.map:{$_+$b}})を使用して、ブロックの先頭に偽のステートメントを書く方がはるかに良いです(注ゴルフへのより良い方法はこれです{$^a.map(*+$^b)}。コンセプトを誇示したかっただけです)

オペレーターのドキュメントを注意深く読んでください

演算子は非常に強力であり、多くの場合、それらは物事を成し遂げるための最短の方法です。特に、メタ演算子(引数として演算子を取る演算子)[][\]X<</ >>Zあなたの注意の価値があります。meta-opは別のmeta-opを引数としてXZ%%使用できることを忘れないでください(私がここで使用したように)。>>メソッド呼び出しにも使用できます。これは、マップよりもはるかに安くなる可能性があります(@list>>.methodではなく@list.map(*.method)、注意してください、それらは同じではありません!)。そして、最後に、あなたはバイナリ使用する前に、<< >>念頭に置いて、クマZしばしば非常に少ない文字で同じことをしますが。

互いに多くのメタ操作を積み重ねる場合、角括弧を使用して優先順位を指定できます[]。コンパイラーを混乱させるほど多くの演算子を積み重ねるとき、それはあなたを救います。(それはあまり頻繁には起こりません。)

最後に、Bool、Int、またはStrに強制する必要がある場合は、メソッド.Bool.Intおよびを使用せず.Str、演算子?+およびを使用してください~。または、さらに良いことに、それらを算術式に入れてIntなどに強制するだけです。リストの長さを取得する最短の方法は+@listです。リストの長さの2のべき乗を計算したい場合は、言うだけで正しい2**@listことを行います。

自由な状態変数を使用し$@かつ%

各ブロックで$(または@または%)が出現するたびに、光沢のある新しいスカラー(または配列、またはハッシュ)状態変数(ブロックの呼び出し間で値が保持される変数)を参照します。ソースコードで1回だけ参照する必要がある状態変数が必要な場合、これら3つはあなたの大きな友達です。(ほとんどの場合$。)たとえば、逆数学サイクルの課題では、によってインデックス付けされた配列から周期的に演算子を選択するために使用できます$++%6

サブフォーム使用mapgrepら。

ことを意味します:むしろやるmap {my block},listよりlist.map({my block})。使用するlist.map:{my block}ことに成功した場合でも、これら2つのアプローチは同じバイト数で実行されます。そして、多くの場合、メソッドを呼び出すときはリストを括弧で囲む必要がありますが、サブルーチンを呼び出すときは必要ありません。したがって、サブアプローチは常に優れているか、少なくともメソッドアプローチと同じです。

ここでの唯一の例外はmapgreppedやpedなどのオブジェクトがinにある場合$_です。その後、.map:{}明らかにビートmap {},$_

利用ジャンクション(&および|)の代わりに、&&||

明らかに、1バイト短くなっています。一方、それらはブールコンテキストに強制されることによって折りたたまれなければなりません。これは、常にを使用して実行できます?。ここで、!opboolコンテキストを強制しop、結果を使用および無効にするメタ操作に注意する必要があります。

あなたがリストを持っていて、接合にそれを有効にする場合は、使用しないでください[&][|]。代わりにとを使用.anyしてください.all.noneジャンクションopsによってそれほど簡単に模倣できないものもあります。


1
私が考える&&||やはり短絡に便利ですか!
ASCIIのみ

@ASCIIのみ:はい、確かにそうです。
ラミリーズ

4

変数に使用されるスペースを削減する

これにはいくつかの部分があります。

空白を削除

を使用して宣言された変数はmy、通常my、変数名との間にスペースを入れずに宣言できます。my @aはと同等my@aです。

シギルレス変数を使用する

次のように、バックスラッシュを使用して変数を宣言し、変数名の前にあるシギルを削除できます。

my \a=1;

(残念ながら、スペースを削除することはできません:()

これは、後でそれらを単なる変数名として参照できるため便利です。

 a=5;
 a.say

基本的に、コードの他の場所で変数を複数回使用する場合、これによりバイトが節約されます。欠点は、変数を初期化する必要があることです。

使用$!して$/

これらの事前宣言された変数は、通常、それぞれ例外と正規表現の一致に使用されますが、を使用して定義する必要はありませんmy

$!=1;
$/=5;

特に便利なのは$/、配列として使用し、ショートカットの$後に数字を入力して$/配列の要素にアクセスすることです。

$/=100..200;
say $5;  #105
say $99; #199

2

...代わりに使用first

通常、何らかの条件&fに一致する最初の番号を検索する場合は、次のように表すことができます。

first &f,1..*

ただし、代わりに...演算子を使用できます。

+(1...&f)

から開始する必要がある場合0-1、代わりにを使用できます+

@aconditionを持つリストの最初の要素のインデックスが必要な場合&f、通常は次のようにします。

first &f,@a,:k

代わりに:

(@a...&f)-1

(または、インデックスを0にする場合は、その逆)。同様に、条件に合格する最初の要素までのすべての要素を取得できます。

これの欠点は、ある時点でリスト条件を渡さなければならないことです。そうしないと、...オペレーターはリストの末尾から外挿しようとし、ほとんどの場合エラーをスローします。また、シーケンスの一部として解釈されるため、左側でWhateverコードを使用することもできません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.