Perl 6でゴルフをするための一般的なヒントは何ですか?少なくともPerl 6に固有のゴルフ問題全般のコーディングに適用できるアイデアを探しています(たとえば、「コメントの削除」は答えではありません)。回答ごとに1つのヒントを投稿してください。
Perl 6はPerl 5ではないため、この質問は重複していません。Perl 5ゴルフのヒントのほとんどは、Perl 6には当てはまりません。
Perl 6でゴルフをするための一般的なヒントは何ですか?少なくともPerl 6に固有のゴルフ問題全般のコーディングに適用できるアイデアを探しています(たとえば、「コメントの削除」は答えではありません)。回答ごとに1つのヒントを投稿してください。
Perl 6はPerl 5ではないため、この質問は重複していません。Perl 5ゴルフのヒントのほとんどは、Perl 6には当てはまりません。
回答:
sub
リテラルを避けてください。多くの場合、単純{}
にコードブロックに使用できます。たとえば、次のコードを書かないでください。
sub ($a){$a*2}
代わりに、ブロック構文を使用してください。これはまた、あなたが使用することができます$_
、@_
と%_
あなただけの単一の変数が必要な場合は、プレースホルダ変数、。さらに必要な場合は$^a
、$^b
変数などを使用できます。
{$_*2}
また、特定のまれなケースでは、どのようなコードでも使用できます(特に単純な式がある場合)。*
プレースホルダ引数に置き換えられます。
* *2
入力を読み取るための関数を学びます。Perl 6には、ARGVまたはSTDIN(ARGVで何も指定されていない場合)からの入力を簡単に読み取ることができる多くの興味深い関数があり、正しく使用するとコードを短縮できます。それらをファイルハンドルメソッドとして呼び出す場合、特定のファイルハンドルでそれらを強制的に動作させることができます(たとえばSTDIN
、から読み取りますが、ARGVで引数を読み取る必要がある場合に便利です)。
get
この関数は1行を取得し、自動的にそれを切り刻むため、必要はありません。これは、1行だけを読む必要がある場合に便利です。
lines
この関数は、ファイルまたはSTDINからすべての行を取得します。これは遅延リストなので、で使用するとfor
、必要なものだけが読み取られます。例えば。
say "<$_>"for lines
slurp
これは、ファイル全体またはSTDINを読み取り、結果を単一の文字列として返します。
say "<$_>" for lines
機能するようになりました
警告:テキストの壁が近づいています。時間の経過とともに集めた小さなトリックがたくさんあります。
これについてはすでに述べましたが、繰り返し申し上げます。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
。
map
、grep
ら。ことを意味します:むしろやるmap {my block},list
よりlist.map({my block})
。使用するlist.map:{my block}
ことに成功した場合でも、これら2つのアプローチは同じバイト数で実行されます。そして、多くの場合、メソッドを呼び出すときはリストを括弧で囲む必要がありますが、サブルーチンを呼び出すときは必要ありません。したがって、サブアプローチは常に優れているか、少なくともメソッドアプローチと同じです。
ここでの唯一の例外はmap
、grep
pedやpedなどのオブジェクトがinにある場合$_
です。その後、.map:{}
明らかにビートmap {},$_
。
&
および|
)の代わりに、&&
と||
。明らかに、1バイト短くなっています。一方、それらはブールコンテキストに強制されることによって折りたたまれなければなりません。これは、常にを使用して実行できます?
。ここで、!
op
boolコンテキストを強制しop
、結果を使用および無効にするメタ操作に注意する必要があります。
あなたがリストを持っていて、接合にそれを有効にする場合は、使用しないでください[&]
と[|]
。代わりにとを使用.any
してください.all
。.none
ジャンクションopsによってそれほど簡単に模倣できないものもあります。
&&
と||
やはり短絡に便利ですか!
これにはいくつかの部分があります。
を使用して宣言された変数はmy
、通常my
、変数名との間にスペースを入れずに宣言できます。my @a
はと同等my@a
です。
次のように、バックスラッシュを使用して変数を宣言し、変数名の前にあるシギルを削除できます。
my \a=1;
(残念ながら、スペースを削除することはできません:()
これは、後でそれらを単なる変数名として参照できるため便利です。
a=5;
a.say
基本的に、コードの他の場所で変数を複数回使用する場合、これによりバイトが節約されます。欠点は、変数を初期化する必要があることです。
$!
して$/
これらの事前宣言された変数は、通常、それぞれ例外と正規表現の一致に使用されますが、を使用して定義する必要はありませんmy
。
$!=1;
$/=5;
特に便利なのは$/
、配列として使用し、ショートカットの$
後に数字を入力して$/
配列の要素にアクセスすることです。
$/=100..200;
say $5; #105
say $99; #199
...
代わりに使用first
通常、何らかの条件&f
に一致する最初の番号を検索する場合は、次のように表すことができます。
first &f,1..*
ただし、代わりに...
演算子を使用できます。
+(1...&f)
から開始する必要がある場合0
は-1
、代わりにを使用できます+
。
@a
conditionを持つリストの最初の要素のインデックスが必要な場合&f
、通常は次のようにします。
first &f,@a,:k
代わりに:
(@a...&f)-1
(または、インデックスを0にする場合は、その逆)。同様に、条件に合格する最初の要素までのすべての要素を取得できます。
これの欠点は、ある時点でリストが条件を渡さなければならないことです。そうしないと、...
オペレーターはリストの末尾から外挿しようとし、ほとんどの場合エラーをスローします。また、シーケンスの一部として解釈されるため、左側でWhateverコードを使用することもできません。
say (3² + 4², 2²⁰, 5⁻²)
==>(25 1048576 0.04)
。このように悪用できるUnicodeの完全なリストは、docs.perl6.org / language / unicode_texasにあります。