1 ポイント 投稿者 GN⁺ 2023-08-09 | 1件のコメント | WhatsAppで共有
  • Rakuは、Python、J、Frink、Excelの数学作業における隙間を埋める電卓言語の候補として検討され、短い実験だけでも非常に強力だが奇妙な言語という印象を与えた
  • Unicode記号、英数字の中置演算子、リスト積・zip・リデュース・累積、~~マッチャー、...シーケンスのように、演算子中心の表現力が広い
  • ユーザーは中置演算子だけでなく、circumfix/postcircumfix演算子まで定義でき、結合性も左・右結合を超えてチェーン結合・リスト結合まで指定できる
  • マルチディスパッチは型シグネチャだけでなく、whereのランタイム述語でも分岐し、関数シグネチャとその中のパラメータも第一級の値として扱える
  • 大規模コードベースの保守には負担が大きそうだが、使い捨てスクリプト・計算・個人用ツールのような小規模プログラミングには魅力的で、ドキュメント、WindowsのREPL、コンパイル速度、sigilのミスが主な障壁になっている

Rakuを見てみたきっかけと第一印象

  • RakuはかつてPerl 6として知られていた言語である
  • 動的言語への不満を書いた後、何人かのユーザーがRakuを勧めてきたため、数学作業に使う電卓言語として適しているかを確かめるために見てみた
  • これまではPython、JFrink、Excelを組み合わせて使っていたが、それぞれに大きな欠点があった
  • 数日間試した後の印象は、「本当に賢いグレムリンたちが、ほかのグレムリンたちから大量のフィードバックを集めて設計した言語」に近かった

独特な演算子体系

  • RakuはUnicode演算子を積極的に使う
    • 集合に含まれるかどうかはで確認する
    • もある
  • 英数字の中置演算子も許可している
    • 文字列の繰り返し演算子はx
    • 関数合成はo
  • リストの組み合わせも短い記号で表現する
    • Xはリストの直積を作る
    • Xfは直積の各要素にfを適用する
    • Zfはzip方式で同じことを行う
  • 中置演算子fに対して、[f]はリストをリデュースし、[\f]は累積結果を作る
    • [+] <1 2 3 4 5>15
    • [\+] <1 2 3 4 5>(1 3 6 10 15)

~~マッチャーと...シーケンス

  • ~~は複数種類の比較を1つの構文で扱うマッチャーとして使われる
    • "abc" ~~ "abc"は文字列の一致を確認する
    • "abc" ~~ Strは文字列型かどうかを確認する
    • "abc" ~~ {.chars == 3}は長さが3かどうかを検査する
    • "abc" ~~ /^b/abcbで始まるかを確認する
  • ...は前の値からパターンを捉えてシーケンスを作る
    • 0,1,2...100から10まで1ずつ増える
    • 0,2,4...10は偶数シーケンスになる
    • 1,2,4...101 2 4 8のような増加パターンに従う

ユーザー定義演算子

  • Rakuは一部の言語のように中置演算子を定義できるだけにとどまらず、circumfixpostcircumfix演算子も作れる
  • たとえばsub circumfix:<[∀ zz>($inner){sum($inner)}のように囲み演算子を定義し、内部の値を合計できる
  • ベクトルの内積のように見えるpostcircumfix演算子も定義可能である
    • sub postcircumfix:<| ⟩>(@left, @inside){[+] (@left Z* @inside)}
    • <1 2 3>|<4 5 6>⟩32
  • 演算子の結合性も多様に指定できる
    • 一般的な左結合・右結合の中置演算子を定義できる
    • x < y < zx < y && y < zのように解釈されるチェーン結合を指定できる
    • a op b op cop(a, b, c)になるリスト結合もサポートする

マルチディスパッチとランタイム条件分岐

  • Rakuはマルチディスパッチをサポートし、異なる型シグネチャを持つ複数の関数定義から適切なものを選ぶ
  • 例の関数fは引数の組み合わせに応じて異なる動作をする
    • スカラーと配列を受け取ると、配列の各要素にスカラーを足す
    • 配列とスカラーを受け取る場合もサポートする
    • 2つの配列を受け取ると、Z+で各要素を足す
  • さらに独特なのは、値のランタイム述語でもディスパッチできる点である
    • multi my_abs(Int $x where {$x > 0}) {$x}
    • multi my_abs(Int $x) {-$x}
  • 関数のシグネチャは第一級の値であり、シグネチャ内のパラメータも第一級の値である

小さな機能が生む広い表面積

  • MAIN関数を定義すると、そのパラメータが自動的にCLIフラグに変換される
  • オブジェクトには、あらかじめ提供されているメソッドが非常に多い
    • List objectは、すべての順列、すべてのk-組合せ、すべてのスライディングウィンドウを得るメソッドを提供する
  • Junctionsは、一度に複数の比較を行うための独特な値の形式である
    • 1|2any(1, 2)に展開され、1 < 1|2が成立する
    • 1&2all(1, 2)に展開され、1 !< 1&2が成立する
  • どんな中置演算子でも、前に!を付ければ否定演算子にできる
  • Rakuは$kebab-caseという名前と中置の減算を同時に持つ言語に見え、sigilがx-yを区別できるようにしていると推測される
  • regex syntaxはPerl 5との後方互換性がない
    • 30年間、各言語はPCRE「標準」に従ってきたが、Perl 6はそれを捨てた

まだ見ていない領域と小規模での魅力

  • 見てきた内容は、電卓用途を中心とした一部の機能にすぎない
  • まだオブジェクトシステム、パッケージ、grammarsは学んでいない
  • 関数本体でsamewithが同じ関数を新しい引数で再度呼び出す機能のように、抜けている機能も多い
  • Rakuのレガシーコードベースを保守しなければならないなら非常に大変そうだが、In The Smallプログラミングには強力に見える
    • 使い捨てスクリプト
    • 計算
    • 個人用ツール
    • 最初に望んでいた種類の作業

不満と期待

  • ドキュメントが非常に不足しており、記号への依存度が高いため検索しにくい
    • ドキュメントが不足している言語をいくつも学んだ経験があっても、Rakuはそれよりはるかに大きく複雑なため、モチベーションが下がる可能性がある
  • WindowsでREPLにUnicodeを入力するとクラッシュする
  • コンパイラもかなり遅く、小さなファイルでも0.5秒以上かかり、反復作業がつらい
  • sigil体系が不便である
    • $x@xの代わりに書いてしまい、問題をデバッグするのに30分費やした事例がある
  • 全体としてRakuは気に入っており成功してほしいが、時間とともにコンパイル時間とドキュメントが改善されることを期待している

1件のコメント

 
GN⁺ 2023-08-09
Hacker Newsの意見
  • プログラミング言語を2次元空間に配置するなら、軸はどれだけ驚かせるかと、驚いたときに楽しいか/ひどいかになり得る
    普通の言語はたいてい「ほとんど驚かせないが、たまに驚かせても楽しい」左下にあるべきだと暗黙に期待されるが、Rakuは珍しく空いている左上を堂々と目指している感じがする。「変でしょ? かっこよくない?」という態度に近い

    • その軸は主観的なのが問題。楽しくもひどくもあり得るものがある。以前 document.write = function ... のようなJavaScriptを書いたことがあり、必要なことは達成できたという点では楽しかったが、同時にかなりひどかった
    • 大学の課題でパーサーを作らなければならなかったときにRakuのgrammar機能を知り、ほとんどすべてを代わりにやってくれてチートコードのように感じたが、それでも楽しかった
    • もともとはPerl 6だったのだから、Perl開発者たちが他の言語とまったく似ていない言語を望んだとしても驚きではない
      Perlにも「楽しい驚き」が多くあり、Rakuは主にPerlのひどい驚きを取り除こうとした設計だったのだと思う
    • で集合に含まれるかどうかを確認するというくだりで、どういう意味か分かった
      0,2,4...10(0 2 4 6 8 10) になるが、1,2,4...10(1 2 4 8) になるのは「OEISで次の数を探しているのか?」という気分になる
    • Rakuは段落が進むほどだんだん右上、つまり驚きがあり、かつひどい領域へ向かっているように見えた
  • Rakuは言語としては興味深いが、一部のイディオムが頭に入りにくい
    AppleScriptが自然言語のように見せようとして奇妙に感じられたのと同じように、mysaysubgather のような自然言語風の要素と、@ のような記号、モジュール宣言など、外部の人にはビザンチン的に見える構文上の決定が混ざっている。99 bottlesの例も論理的には追えるが、直感的に見つけるのは難しい。記号が多く、文脈によって過負荷される感じがするので、自然言語パーサーのようにRakuが最適そうな作業であっても、自分で使いたいとは思わない
    https://examples.raku.org/categories/module-management/Fletc...

    • Perlをやったことがないように見える。Perlのバックグラウンドがあれば、その構文のかなりの部分、特に配列を表す @ シジルはかなり見慣れているはず
    • Bashを見るときも同じように感じる
  • Rakuでいちばん好きな機能は、整数除算と10進リテラルがどちらも有理数型である Rat を返す点
    誰もが浮動小数点がいまいちだと分かっているが、実際にそこから抜け出そうとする言語はほとんどなく、Rakuでは科学的記数法を使って初めて浮動小数点リテラルになる

    • Common LispSchemeのような、もっと古い言語も、IEEE 754浮動小数点を嫌う人たちに見つけてもらうのを待っている
      これらは有理数や複素有理数まで含む数値階層を持っており、任意精度数も当然サポートしている。組み合わせ可能性は素晴らしい
    • これは実際には悪い機能に近い。Rat の表現が大きくなりすぎると自動的に浮動小数点に変わるため
      1/10Rat だが、1/100000000000000000000Num になる。昇格されない FatRat もあるが、デフォルトではない
    • Schemeの数値階層は、正確な表現を何十年もきちんと扱ってきた
      だから「不正確な浮動小数点を明示的に要求していないのに使う方式から脱した」というより、そもそもそんな状態だったことがなかったと見るのが正しい
    • Racketも違う言い方をするだろう。ちゃんと動作する
      (/ 1.0 3.0)0.3333333333333333(/ 1 3)1/3(- (+ 0.1 0.2) 0.3)5.551115123125783e-17 になる
    • これが良いことなのかは確信がない。10進/有理数型と浮動小数点をいつ使うべきかは分かるが、個人的なPythonコードでは Decimal() より float() の呼び出しのほうがはるかに多い
      お金を直接扱う場合でなければ、ほとんど常に浮動小数点が望む選択肢だ
  • Rakuのドキュメントが「本当にひどい」とは感じなかった。むしろ公式ドキュメントサイトが概念ドキュメントとAPIドキュメントの両方を含むワンストップの資料であることに感心した
    https://docs.raku.org/
    概念ドキュメントの出発点としては、このページがとても優れている: https://docs.raku.org/language

    • ここ数年Rakuを使っているが、ドキュメントは素晴らしくもあり、不足もしている
      ある内容の大半はよく書かれていて有用なサンプルコードもあるが、まったく文書化されていなかったり、単純な場合しか扱っていなかったりする部分に時々出会う。特にモジュールシステムが最大の問題で、モジュール/パッケージの区別はModulesページを読むだけでは理解しにくい。インポートされる名前空間と宣言された名前空間が異なり得る一方で、コンパイラが見つけるにはディレクトリ構造が名前空間と一致していなければならない、という点は有用で奇妙に筋が通っているが、実際に触って学ぶ必要があった
    • それはPerl文化のため。Perl FAQとマニュアルページは、Perlを使うプログラマーたちの気質のおかげで最高水準で、機知に富み、簡潔で、奇妙だった
    • Perlのマニュアルページはいつも素晴らしかった
  • RakuのかっこいいUnicode演算子には、すべてASCII代替表記がある
    たとえば の代替表記は (elem)!(elem)(cont)!(cont) である
    https://docs.raku.org/language/unicode_ascii#Other_acceptabl...

    • 自分なら間違いなくASCII版を使うと思う
  • 言語をよく知る前に出てくる典型的な批判が、今も繰り返されているように思う。昔は Perl の「ラインノイズ」だったし、今では Raku がUnicode 演算子をためらいなく使う、というような話になっている。
    とはいえこれは任意で、画面上でコードを小さく表現力豊かに見せるために自分でも使ってみた。慎重で創造的な Unicode の使い方にはよく合っている。シジルが嫌いだという反応もよくあるが、Perl のスイスアーミー・チェーンソーのような表現力が好きで Raku/Perl 6 を使ってきたし、Raku は Perl らしさを二乗したような感じだ。整理されていて表現力が高く、古き良き Perl の上に巨大な機能の山が積み上がっている。ドキュメントも良いが継続的な手入れは必要で、Perl のドキュメントと比べると基準は非常に高い。

    • 非 ASCII 演算子はどうやって入力するのか気になる。特殊なキーボード配列なのか、エディタが特定のシーケンスを自動変換するのか、生の Unicode エスケープを使うのか分からない。
      数文字を節約するためにこうするのは複雑で、あまり意味がないように見える。
  • 構文糖でいっぱいのプログラミング言語がどんな姿になるのか、ときどき気になっていたが、これで分かった。
    「ひどいのに妙に惹かれる、目を離せない、もっと見せてくれ」という感じだ。

    • 最近の複数の Advent of Code で優勝した人が作った趣味言語 noulith が気に入るかもしれない。
      GitHub の紹介には “slaps roof of [programming language]* this bad boy can fit so much [syntax sugar] into it.” とある。直近の Advent of Code でもその言語を使って優勝している: https://github.com/betaveros/noulith
    • Raku の Grammars を知るまで待ってみて。
    • モダン C++を見るたびに同じ反応になる。
  • Raku がもともと Perl 6 として始まり、多くの設計思想が Perl 的な考え方から来ている点は覚えておく価値がある。
    文字列の繰り返し用の x 演算子にすぐ反応しているのを見ると、著者は Perl と Raku の歴史をよく知らないように見えるが、それは Perl では何十年も前からそうだった。

    • 本文に「正規表現の構文は Perl 5 と後方互換ではない。30年間、各言語が PCRE の『標準』に従ってきたのに、Perl 6 はそれをただ全部捨てた」という文があるので、少なくともある程度は知っているようだ。
    • 最初の脚注に、Raku は以前 Perl 6 として知られていたと書かれている。
    • 「Perl6/Raku は Perl 5 とまったく違う」という誇張は膨らみすぎている。
      理由もなく Perl 6 と呼ばれたわけではないし、ほぼ同じ Perl チームが開発した。Perl 5 をかなり使ったことがある人なら、Perl6/Raku の遺産ははっきり見える。Raku のオブジェクトモデル全体も、CPAN の Perl 5 モジュールである Moose.pm を少し強力にしたバージョンに近い。
  • 正直、Perl 5/PCRE の正規表現構文はひどい。
    それが存在する理由も、昔の正規表現構文では (? が構文エラーだったため、任意の意味に再定義できただけだ。Raku は、正規表現が何を表現すべきか分かった今、最初から正気の正規表現言語を設計しようとする試みだ。代替案は、これからさらに30年 (?:this|(?>or that)) のようなものに閉じ込められることだ。

    • ひどいというより解読不能な黒魔術で、理解すると格好いい。
      Perl には長いこと触っていないが、今でも正規表現はよく使う。
    • 同意するが、本当に便利ではある。
  • ある意味では確かにグレムリンだ。奇妙で複雑だが、生産性を高めてくれる道具が好きだ。
    ただし「大きなプログラム vs 小さなプログラム」という比較には同意しない。あまり賢明でない人は、それが大きな作業には悪い言語だという意味に受け取るかもしれないが、実際には他の言語と同じくらい良いか、それ以上かもしれない。問題は他のグレムリン言語と同じく、うまく使うには知恵が必要だということだ。たとえば $x@x を混同する人は、似た言語を十分使ってきた人ならほとんどいない。シジルはコードを読むときに変数の単純な型、Raku ではインターフェースをすぐ知らせてくれるので、むしろ楽になるし、同じ変数名前空間を別のシジルで有用に使える。奇妙に見え、不要な文字のように見え、意味を知る必要はあるが、生活を楽にしてくれることがある: https://www.perl.com/article/on-sigils/
    問題は、自分が何をしているのかよく分かっていない人たちに生じる。そういう人たちにとって、このグレムリン言語は生きた悪夢になり得るし、ボウリングのバンパー、浮き輪、ケブラー手袋、安全ヘルメット、GPS のような保護装置がたくさん必要だ。グレムリン言語で摩天楼を建てられないという意味ではなく、事故を起こしやすい非グレムリンには建てられないだけで、賢いグレムリンなら建てられる。

    • 「この道具は十分に上手い人だけが使える」という考え方は、巨大な設計上の臭いだと思う。
      道具は、チームが必要な仕事をより良く、またはより速くこなせるよう助けるために存在する。ジュニアをふるい落としたり、自分の自尊心を満たしたりするために不必要に複雑な道具を使うなら、その道具は組織の他の人たちにとって助けではなく、武器に近い。