例外的なプログラミング言語 Hurl
(hurl.wtf)- Hurlは一般的な分岐や反復の代わりに、例外処理だけで制御フローを構成する実験的プログラミング言語
- Nicole Tietz-SokolskayaとRecurse Centerの友人たちとの会話から始まり、サイトでは使い方のドキュメント、サンプル、デバッグ案内、Q&Aを提供している
- 紹介ページの推薦文は「monstrosity is beautiful」「Certified unhinged™」のように、意図的に冗談めいた雰囲気を前面に出している
- Hurlとサイトのソースコードは公開されているが、メールでパッチを送るにはパッチの権利譲渡が必要
- ライセンスはAGPL-3.0、GAL-1.0、商用ライセンスのいずれかを選ぶ方式で提供される
例外処理だけを残した言語実験
- Hurlはひとつの目的のために作られた: 例外処理ベースの制御フローだけで構成された言語が可能かを探ること
- アイデアはNicole Tietz-SokolskayaとRecurse Centerの友人たちとの会話から生まれたもので、友人たちの身元は「品位のため」に公開していない
- サイトではHurlの使い方ドキュメントとサンプル、デバッグ案内、Q&Aを提供している
冗談のように見えるが実際に公開されたプロジェクト
- 紹介ページにはHurlの性格を示す推薦文が掲載されている
- “This monstrosity is beautiful, and I must never touch it”
- “Certified unhinged™!”
- “is "🤮" an available quote?”
- 追加の推薦文を載せたい場合はNicoleにメールを送る必要があり、引用掲載への明示的な同意が必要
ソースコードとライセンス条件
- Hurl言語とこのサイトのソースコードは Hurl's repo で公開されている
- バグや誤りを見つけた場合はメールでパッチを送れるが、パッチに関するすべての権利を譲渡しなければならない
- 再ライセンスと商用ライセンスの可能性を維持するための条件
- プロジェクトは次の3つのライセンスのいずれかで利用できる
-
AGPL-3.0
- GAL-1.0: Gay Agenda License
- 商用ライセンス
- ライセンス検討の過程では joke licenses と unfortunate licenses も考慮されたが、最終的に上記3つのライセンスが採用された
-
1件のコメント
Hacker Newsのコメント
プログラミング言語を設計するなら、include/import では 名前空間 を強制し、可能ならトップレベルの副作用も防ぐべきだと思う
let foo = include "lib/foo.hurl"のように受け取り、foo.init()を呼ぶ形にすれば推論がはるかにしやすい逆に
include "lib/foo.hurl" // side effectsの後にbaz(buz)が出てくると、関数や変数が標準ライブラリ由来なのか、どこかで include されたものなのか分かりにくいimport "foo/bar"ならfoo.*またはbar.*を使えるべきで、bazz.*が出てきてはいけない。Go をまさに思い出すVSCode もプラグインと LSP で似たことはできるが、かなり見劣りする。コードナビゲーションが遅すぎて VSCode では仕事にならない
こうした提案は、その手のツールがないときにだけ有用なのだろうか。少なくともプロの環境では、そうしたツールなしでやっていくのは不可能に思える
foo.init()に 引数 を渡せるし、素の import ではそれができないだからといってこのプロジェクトに価値がないという意味ではなく、むしろアート作品だと思う
Ruby を fork して
requireがシンボルテーブルを上書きしないようにしたことがあるが、Ruby のエコシステムは 共有されたグローバル可変状態 に依存しすぎているように思えて、結局 Ruby 自体への興味を失った例外は呼び出し元と呼び出される側の 契約 を把握しにくくし、コードの結合度も高めるので、昔から好きではない
Go や Rust のように戻り値で処理する方式のほうを好む。ざっと眺めた限り、この言語にその問題を解決する要素があるのかはよく分からない
IDE が関数の未捕捉例外をすべて動的に把握し、例外が投げられうる場所へジャンプできるなら、このモデルも悪くないかもしれない。ただ、結合度をどう扱うのかは分からないし、制御フローグラフは極端に不安定になりそうだ
ただし Java では、
RuntimeExceptionを継承していない限り、関数が投げうる例外は関数シグネチャの一部になる。そういう場合、シグネチャに追加せずに例外を投げるとコンパイルできないJava のこの条件は、IDE が未捕捉例外を報告するのをずっと容易にしているが、ランタイム例外でないなら静的解析で解ける問題でもある
一方で、標準化された
Ok/Errラップ値を返す方式は、ツール支援と開発者の利便性の両方の面でより単純に見える違いは、例外伝播方式ではコンパイラがやってくれる ボイラープレート を自分で手書きしなければならない点だけだ
2024年にまともに動く頭を持った人が、なぜそんなことを手でやりたがるのか、まったく理解できない
使っていた間は、デバッガなしで 根本原因 を見つけるのがずっと苦痛だった
tossの例は「関数の外へ複数の値を渡すのに主に使い、必須ではないがかわいい」とされているが、役に立たないどころか 再開可能なジェネレータ を実装しているもちろん、即座に再開する以外のことをさせようとすると、かなり面白くなりそうだ。コードベース全体を
tossの内側と外側のスタックで構成すればいいだけだreturnがハンドラ側に レキシカルスコープ されていなければならないたとえば Python ではどこからでも
next()を呼べるこれは副チャネルでコールバックを渡すのに近い。
tossがそのコールバックを呼び、returnは文字通りそこから返るだけだ他の言語なら本当に有用な機能なのに、ここでは捨ててもよいかわいい機能のように扱っているのが、ちょっとしたジョークなのかと思った
yieldのようなもの?Hurl は Smalltalk や Common Lisp 風の 条件システム にかなり近く見える
スタックの巻き戻しと再開は、可能なリスタートのうちの 2 つにすぎない: https://gigamonkeys.com/book/beyond-exception-handling-condi...
プロジェクトそのものとは別に、もっと多くのものがドメインに .wtf 拡張子 を使えば、世界はより良くなると固く信じている
これは 代数的効果 の弱い形のように聞こえるが、こういう言語や、それで何ができるのかを見るのはやはり面白い
代数的効果が基本的に Hurl の
tossキーワードのようなものなら、どういう点でtossより強力なのか気になる面白い思考実験だ
自分は例外が本当に嫌いで、例外のない言語がほしい
例外は現代の
gotoだMaybe/OptionとEffect/Resultがある以上、例外を投げて、それがどこで処理されるかを頭の中で追跡しなければならない理由はほとんどない代数的効果がさらに人気を集め、すでに十分複雑なフロントエンド JS にまで影響を与えるのではないかと少し心配している。制御フローのために「例外」を投げる方式を奨励するからだ
これがすべて非同期/同期の 色問題 を避けるためだというなら、個人的にはまったく見合わない
うわ、これは嫌だ。でも奇妙なことに、ほとんどエレガントな面もある
頭の中でモデル化するのは非常に難しいが、それでもそう思う
もう少し真面目に言うと、再開可能な例外と再開不可能な例外について、文法的に異なる
catch構文があってほしい。そうすれば、returnが最も近い直前の例外の throw 側へ制御フローを戻すのかどうかという 文法上の曖昧さ がなくなるそして標準ライブラリは普通の値返し関数へ逃げるべきではない。自分で作ったものを食べて胃もたれしたからといって、食べない理由にはならない
hurlされたものは捕まえられるが、tossされたものは捕まえられない、という理解で合っているのだろうか? 慣れるには少し時間がかかりそうだそれと、どれだけ Hurl を書いたら人に tosser と呼ばれ始めるのかも心配だ
Tossは興味深い言語構造のように聞こえる。スタックをたどって例外ハンドラを探し、そこから元の位置に戻って、何もなかったかのように実行を再開するこの構造なら、ランタイムで 追加の動作を注入 できそうだ
普通のオブジェクト指向コードではサービスコンストラクタを通じて依存性注入をするが、
tossは「toss ハンドラ」でそれを可能にするものなのか?https://koka-lang.github.io/koka/doc/book.html#why-handlers
詳しくは知らないが、こういう形でランタイムに動作を注入できることは知っている
Resume Nextに似ている