3 ポイント 投稿者 GN⁺ 2024-09-23 | 1件のコメント | WhatsAppで共有
  • Pythonに組み込まれるLisp方言である Hy 1.0.0 が、約12年にわたる断続的な開発と実運用を経てリリースされた
  • Hy 1.x では、文書化された言語要素の 互換性破壊 は major バージョンの増加につながり、CPython 開発者がもはやサポートしない Python バージョンのサポート終了は例外とされる
  • 今後の焦点は、新たなバグ修正、新しい Python バージョンへの互換性追加、既存の Hy 1.x.y コードを壊さない形での Python 新機能のサポート に置かれる
  • あるユーザーは、Hy マクロによって SQLAlchemy ORM の宣言を defmodel 形式に簡潔化する例を挙げ、マクロ展開であるため ランタイムの追加コストがない と説明している
  • MicroPython 上で直接動作するかについては、標準ライブラリの部分集合しかないため難しそうだが、CPython で hy2py に変換したあと MicroPython がサポートする構成だけを使う方法なら可能かもしれない

Hy 1.0.0 リリース

  • Hy 1.0.0 がリリースされた
    • Hy は Python に組み込まれる Lisp方言 である
    • リリースまでほぼ12年にわたり断続的な開発と多くの実運用があった
  • 紹介とドキュメントは Hylang.org で提供されている
  • バージョン履歴は NEWS file で確認できる
  • よりくだけたリリース関連の投稿として HYPE POST もあわせてリンクされている

1.x 互換性ポリシー

  • 今後、文書化された言語部分に対する breaking change は major バージョン番号を引き上げる
  • 例外は、CPython 開発者がすでにサポートしていない Python バージョンのサポートを打ち切る場合である
  • major バージョンの増加が頻繁に発生しないようにする意図が示されている
  • 今後の作業の焦点は次の通り
    • 新たに発生する バグ修正
    • 新しい Python バージョンとの互換性追加
    • 以前の Hy 1.x.y で動作するコードを壊さない形での Python 新機能サポート

Hy マクロ活用例: SQLAlchemy モデル DSL

  • あるユーザーは、Hy で ORM と非同期 Web フレームワークを作っており、どちらも既存ライブラリを活用し、その大半が マクロ で構成されていると説明している
  • SQLAlchemy ORM Quick Start Guide のモデル宣言を、Hy の defmodel マクロでより短く表現する例が示されている
    • UserAddress モデルと関係宣言を Hy の S式形式で記述する
    • defmodel は SQLAlchemy コードへ展開されるマクロなので、ランタイムの追加コスト はない
  • ユーザーは、Hy の内部仕様と API が安定化したことがこうした作業に必要だと述べている

関係宣言とクエリ DSL の議論

  • defmodel の例は複数の関係パターンへ拡張されている
    • one-to-one: 1->1
    • many-to-many: *->*deflinktable
    • timestamp フィールド: :timestamp-create, :timestamp-update
  • 宣言後のオブジェクトは一般的な SQLAlchemy 2.0 ORM オブジェクト なので、データベーススキーマ DSL 部分だけを Hy で書き、それ以外は Python で書ける
  • クエリ DSL はまだ作業中で、fluent interface は S式とあまり相性がよくないと言及されている
  • あるコメントでは、SQL の syntactic order と semantic order が一致するようにすべきだと提案し、Google Research の SQL Has Problems. We Can Fix Them: Pipe Syntax In SQL が紹介されている
  • これに対して、|> のような形式や list comprehension をまねる方法はあり得るが、最終的な設計は小さなアプリを作ってリファクタリングする反復のあとに出てくるだろうと返答している

MicroPython の可能性とリリースへの反応

  • CPython の代わりに MicroPython 上で動作できるかという質問が出た
  • 回答では、MicroPython は Python 標準ライブラリのごく小さな部分集合しか含まないため、直接動作は難しそうだとされている
  • ただし、CPython で hy2py を使って Python コードへ変換したあと、MicroPython がサポートする構成に限定すれば、その出力を実行できる可能性はある
  • リリース当日には、Hylang.org をホスティングしている Web サーバーの日次ユニーク訪問者数が大きく増加したことも確認されている

1件のコメント

 
GN⁺ 2024-09-23
Hacker News のコメント
  • Hy が実際に Python へどう変換されるのかを把握するのが少し難しく、コンパイルされるのかインタープリトされるのかも最初は確信が持てなかった。
    結局 Wikipedia で「Hy は s-expression を Python の**抽象構文木(AST)**に変換し、Python と相互作用できるよう設計された Lisp 方言」という説明を見つけ、GitHub のコードを見るとコンパイラも Python で書かれているようだ: https://github.com/hylang/hy/blob/master/hy/compiler.py
    メインサイトでも「Python に埋め込まれた Lisp 方言」より、「Python AST にコンパイルされる Lisp 方言」と紹介したほうがより明確だと思う。Lisp を埋め込む方法には、インタープリタを付ける、Python バイトコードへコンパイルする、Python ソースコードへ変換するなどいくつもあり、それぞれトレードオフがかなり違う

    • README/GitHub ページにはすでに「Hy は Python に埋め込まれた Lisp 方言であり、Lisp コードを Python AST オブジェクトへ変換するため、Python の世界を Lisp 形式で使える」と書かれている
    • その通り。このコンパイラは Python で書かれていて、Hy はセルフホスティングではない。
      通常、Hy のソースコードは Python AST オブジェクトになり、Python がそれをコンパイルして実行する。ただし Python AST オブジェクトを Python ソーステキストに変えることも可能で、Hy から Python を使ったり Python から Hy を使ったりする相互運用も可能: https://hylang.org/hy/doc/v1.0.0/interop
    • 「埋め込み」という表現は、1つのプロジェクト内で Python と Hy を混在させ、双方向に呼び出せることに由来している。
      最終的にはすべて Python バイトコードになるので、うまく動く
    • 当初の Hy の発表では、Lisp を Python バイトコードへコンパイルして埋め込む点がはっきり示されている。
      下の動画の 16:25 あたりで見られる: https://m.youtube.com/watch?v=1vui-LupKJI
  • Hy は数年かけて成熟する中で、より Lispy でより Pythony でないものにするために構文糖衣や特殊ケースを積み重ねるのではなく、むしろ Python の機能セットに対する薄い構文抽象化に近づいたように思う。
    つまり、別の方法ではまねしにくい核心、特にマクロに集中する方向だ。最近の例では、match は単に Python ネイティブの match で、Python 3.10 より前のバージョン向けのポリフィルもない。以前は foo? が特殊ケースとして is_foo にマングリングされていたが削除され、hy.eval は Python の eval により近い形へ作り直され、unless のような、あれば便利だが中核ではないユーティリティは Hyrule パッケージへ移されることが多い。
    最初は直感に反する方向のように感じたが、Python から Hy に移るときの学習曲線を下げ、Python パッケージと一貫して相互運用しやすくなるという利点が大きい。もしかすると言語メンテナンスを単純化する意図もあるのかもしれないし、記憶では let もまともに作るまでに4回ほど試みていた気がする

    • ある時点で、Python との不要な違いを最小限にすれば、言語のメンテナンスも利用もずっと滑らかになると気づいた。
      Hy コードを書くときも、Hy のドキュメントより Python やサードパーティの Python ライブラリのドキュメントを見ることのほうがはるかに多い。Python を改善できる点はいろいろあると感じていたが、以前のように Clojure に配慮して Truetrue と書けるようにした機能は、単に不要な複雑さだった
  • HYPE POST は本当に良かった。エンタープライズソフトウェアの仕事をしている立場から見ると、風刺のセンスがとても優れている。
    https://github.com/hylang/hy/discussions/2609

  • ついに出たので、これで https://github.com/rcarmo/sushy を整理できそうだ。
    数年かけて少しずつ触ってきたが、Hy をアップグレードするたびに構文の一部が壊れたり、機能が Hyrule パッケージに入ったり出たりして困っていた。
    ちなみに Hy は iPad の https://holzschu.github.io/a-Shell_iOS 内でもかなりよく動く。ただし vim/neovim のシンタックスハイライトは 0.29+ リリースと非同期に追いつく必要がある。
    これまで Fennel と Guile も使ってみたが、Python ライブラリとエコシステムにアクセスできるほうがよい。非同期のおかげで効率的な API 作業もうまくできるし、いくつかの Scheme ではソケット再利用やヘッダーを細かく制御しながら HTTPS を扱うのがいまだに面倒なので、aiohttp を使うほうがはるかに良いと思う

  • 初期のささやかな出発点と比べると、本当に遠くまで来た。
    以前 PyCon で Hy を初めて世に紹介したライトニングトークを見て、その少し後に Paul と会い、初期の Hy バージョンに貢献し始めた。Common Lisp 風の kwargs、内部の一部、ライブラリを1つか2つ担当した。
    遊び心は有用で、特に情熱を保つ助けになる。ハッカーがハッカーらしく振る舞えるし、すべてがビジネスである必要はないという点がいい。もう何年も関わっていないが、プロジェクトが進み続けているのを見るとうれしいし、素晴らしい節目だと感じる

  • Clojure ファンなら、関連して Python 3.8+ を対象にした、Clojure 互換に近い Lisp 方言 Basilisp もある。
    https://github.com/basilisp-lang/basilisp

  • Lispではありませんが、Pythonへトランスパイルされる関数型プログラミング言語という観点では Coconut も興味深いです: https://coconut-lang.org/
    HyやCoconutを実際に使った人たちの体験談が本当に気になります

    • 数年前にCoconutを少し使ってみましたが、当時の印象では、コンパイラが実用的と言えるほど賢くないというものでした
      生成されたコードの先頭にハードコードされた補助関数が大量に付き、同じ内容を普通のPythonで書いた場合よりもプログラムがずっと遅くなりました
      逆にHyは、letのスコープ処理で生じるわずかな間接層や返り値まわりの違いを除けば、人間が手で書きそうなPythonコードにかなり近いコードを生成します。ただしCoconutもかなり時間が経っているので、改善されている可能性はあります
  • おめでとうございます。2つ気になります。REPL駆動開発をサポートしているのか、たとえばコンディションシステムやbreakloopのようなものがあるのかが気になります
    それと、スタンドアロン配布版があるのかも気になります。Pythonの配布自体が面倒なので、理想的にはすべての依存関係を含んだ単一のHyバイナリを1つ配布できるとよいです。静的リンクでも、一時ディレクトリに展開するzipファイルでも構いません

    • スタンドアロン配布版ではありませんが、uvx hy@1.0.0でHy REPLに入れます
      echo '(print "hi hn")' > hi.hy のあとに uvx hy@1.0.0 hi.hy を実行すると、"hi hn" を出力します
      https://docs.astral.sh/uv/guides/tools/#running-tools
      ちなみにuvはPythonバージョンのインストールと管理もできます
    • breakloopが何なのかはよく分かりません。HyはPythonの例外システムを使っており、これはCommon Lispのコンディションシステムというより、伝統的な例外システムに近いものです
      スタンドアロン配布版はありません
    • REPLドキュメントに関連する内容があります: https://hylang.org/hy/doc/v1.0.0/repl
      コードを対話的にデバッグするには、デバッグしたいコードに (.run (hy.REPL :locals {#\* (globals) #\* (locals)})) を入れることができ、Pythonでは import hy; hy.REPL(locals = {\*globals(), \*locals()}).run() のように書けます
      ただし code.interact() と同様に、REPL内でローカル変数を変更しても元のスコープには伝播しません
    • py2app と慎重なハックで、2番目に近いことはやったことがあります
      すべてをバイトコードにコンパイルしたうえで、Pythonの単一ファイル配布ツールを使えます
    • HyはPythonがサポートする機能セットをそのままサポートします。伝統的なステップ実行デバッグや事後デバッグにはかなり向いており、CPythonにはさらに高度な内部フックも多数あります
      しかし、コンディションシステムやhandlers/restartsのようなものはありません
  • あまり真面目でない部分がとても良かったです。もっと多くのプログラミングプロジェクトが奇抜さを受け入れてくれたらいいと思います
    もしかすると、それこそがPythonの伝統を称える最良の方法なのかもしれません

    • 数年前、Hyとドキュメントから遊び心のある要素をかなり取り除きました。気が散るうえ、騒がしいテスト失敗を生んでいたためです
      ただ、ある時点でやりすぎたと思うようになり、最近は遊び心を少し戻そうとしています
  • Hyを断続的に使ってきて、transformerを作ってみようとしてHyで書いた https://github.com/kunalb/orphism も公開しました
    そろそろまた取り出して、ちゃんと動かしてみる時期のようです