3 ポイント 投稿者 GN⁺ 23 일 전 | 1件のコメント | WhatsAppで共有
  • Rustスタイルの構文を使いつつ Goランタイム上で動作する 小型言語で、両言語の長所を組み合わせた形
  • 代数的データ型パターンマッチングHindley-Milner型システムデフォルトの不変性などにより 安全性と表現力を強化した構造
  • Goパッケージの直接importパイプライン演算子tryブロックtaskベースの並行性により Goエコシステムとの相互運用性を確保
  • コンパイル時のエラー検出明確な診断メッセージLSP対応により 開発者体験とコードの安定性を向上
  • Lisetteコードが読みやすいGoコードに変換され、既存のGoプロジェクトへ自然に統合できる点が中核

Lisette概要

  • LisetteRust構文をベースとし、Goランタイムへコンパイルされる小型言語
  • 代数的データ型パターンマッチングnilなしHindley-Milner型システムデフォルトの不変性Goエコシステムとの相互運用性を特徴とする
  • cargo install lisette コマンドでインストール可能で、Goの fmtioos などのパッケージを直接importして利用できる

なじみのある構文

  • Rustに近い構文構造を持つ
    • enummatch による パターンマッチングをサポート
    • structimpl ブロックで メソッド定義が可能
  • 式指向言語であり、iflet、ブロックなどはすべて値を返す
  • チェイニングとラムダをサポートし、環境変数の処理や文字列操作を簡潔に表現できる
  • インターフェースとジェネリクスをサポートし、interface 定義や T: Trait 制約によるジェネリック関数を記述できる
  • if let および let else 構文により Option 型を簡潔に扱える

安全性

  • Goランタイムで起こりうるエラーをコンパイル時に検出

    • match 文ですべてのパターンが処理されていない場合はエラー
    • nil は使用不可で、欠損値は Option<T> で表現
    • Result の戻り値を無視すると警告
    • 非公開型を公開APIで露出すると警告
    • 不変変数を可変引数として渡すとエラー
    • 構造体フィールドの欠落はコンパイルエラー
    • 診断メッセージは 具体的なコード位置と修正提案をあわせて提供
    • LSP(Language Server Protocol) 対応により、VSCode、Neovim、Zed など主要エディタで利用可能

使いやすさ

  • Goとの相互運用性を重視して設計
  • パイプライン演算子(|>) で関数チェイニングを簡潔に表現
  • tryブロックによりエラー伝播を単純化
  • 並行性taskChannel を使い、Goの goroutine に近い形で実装
  • シリアライズ属性(attribute) により JSON フィールド名、省略、文字列変換、検証タグなどを指定可能
  • panic 復旧のための recover ブロックを提供し、Result 型で安全なエラー処理が可能
  • defer 構文をサポートし、リソース解放やトランザクションのロールバックを保証

透過的なコンパイル結果

  • Lisetteコードは 明確で読みやすいGoコードへ変換される
    • OptionResult 型はそれぞれ lisette.Optionlisette.Result 構造体へ変換
    • match 構文は Go の条件文へ変換され、各分岐を処理
    • ? 演算子は内部的に Result 検査コードへ置き換え
  • 例として、classify 関数は Option<int> を受け取り、Goの明示的な条件文へ変換され、combine 関数は Result を検査するGoコードへ変換される

追加情報

  • 公式リポジトリ: github.com/ivov/lisette
  • MITライセンスで公開されており、2026年時点で Iván Ovejero が開発

1件のコメント

 
GN⁺ 23 일 전
Hacker News のコメント
  • 著者と話してみて、実際にこの言語を使ったわけではないが、Lisette は興味深く、Goより明らかに改善された言語に見える
    ただし、Goの限界を完全に克服するのは難しいとも思う。たとえば、Goのインターフェース型に由来する typed nil 問題は Lisette では Option で扱われるが、二重アンラップ(Some(Some(h)))が不格好になりうる
    また、Goの defer 方式は依然として扱いづらく、RAIIのような自動リソース解放にはならない
    TypeScript が JavaScript を補完できたのは、ブラウザで実行可能な代替がなかったからで、今は WASM があるので状況が違う
    そのため、「Rust があるのに、なぜ Go を Rust のようにするのか?」という疑問を持つ。ただ、Lisette はその中間地点を狙っているようだ
    結局のところ Lisette は、既存の Go コードベースを改善したい人や、Go ランタイムを使い続けたい人に向いた言語に見える
    私が気になるのは、「次のファイルを Go の代わりに Lisette で書くにはどう始めればよいのか」という クイックスタートガイド がないことだ
    関連ブログ記事: Go is still not good

    • Go は GC ベースの並行ランタイム を提供する点で、今なお独自性がある
      複雑な参照グラフを扱う問題領域では GC が不可欠であり、Go はユーザーモードのスタック構造のおかげで効率的なメモリモデルを持つ
    • GC 言語では開発速度がはるかに速い。Rust と Python でチャットボットを作ったが、Rust の経験があっても Python のほうがずっと速かった
      Go はこうした 高速な CLI ツール の作成にも向いている — 例: wordle-tui
    • Go は言語としては奇妙な点が多いが、コンパイルターゲット としては優れている
      文法が単純で、クロスプラットフォーム対応、ランタイムと GC を内蔵し、“errors as values” の構造、グリーンスレッド、高速な AOT コンパイラなど、多くの利点がある
      Go の defer は有用だが、エラー処理とスコープ規則 はぎこちない
    • ブログで触れられていた「Go は NULL を二度も誤って作ってしまった言語」という表現が印象的だった
      TypeScript もこの問題を解決できておらず、むしろもっと悪い。そこで自分で Option 型パッケージ を作って NPM に公開した → fp-sdk
    • Rust の async は GC がないため Go より不便だ。この点だけでも Go ランタイムを選ぶ理由になる
  • Go にコンパイルされる言語はすでにいくつもある — XGo, Borgo, Soppo など

    • Borgo と Lisette は (T, error) の戻り値を Result 型 に単純置換しているが、これは意味的に完全に同一ではない
      たとえば io.Reader.Read(n!=0, io.EOF) が正常終了を意味するので、単純にエラーとして扱うと誤動作につながる
    • コンパイルエラーが ターゲット言語からソース言語へどう伝えられるのか が気になる
  • Lisette の エラーメッセージ品質 は印象的だ。“help” のヒントが実際に役に立ちそうに感じられる
    ただ、Go に変換されたコードが冗長になりうるので、ランタイムエラー時に Go コード側でデバッグしなければならない点が心配だ
    また、既存の Go コードから Lisette を呼び出す方向も難しそうに見える
    Lisette が実験的な言語なのか、それとも実際のプロダクションを目指しているのか気になる

    • 開発者本人の回答: lis run --debug オプションを使うと、Go コードに //line source.lis:21:5 コメントが挿入され、スタックトレースが元の Lisette コードにマッピング される
      LSP はコンパイル時エラーを .lis ファイル基準で処理する
      現時点では Go から Lisette を呼び出す機能はないが、Lisette から Go パッケージをインポート する機能が優先されている
      最初は実験だったが、プロダクションレベルの言語 へ発展させることが目標だ
  • Rust に似た文法をなぜそのまま採用しなかったのか気になる
    例: import "foo.bar" の代わりに use foo::barBar.Baz => の代わりに Bar::Baz => など
    Rust を知っている人は混乱するし、知らない人には Rust への知識移転も起きない

    • こうした文法差は些細なことで、本質は Rust の型システムを Go に持ち込む ことだ
      intfloat64 は Go の型命名規則に従ったものだ
    • 複数の言語を行き来していると、文法の類似性のほうがかえって 混乱を招く。たとえば PHP で + ではなく . を使うことをよく忘れる
    • 自分も最初は TypeScript ベースの Rust スタイル言語を作ろうとしたが、結局 Rust 自体が思ったほど難しくない と気づいた
    • GC 言語で Rust スタイルのメモリモデルを実装するのは 非常に不自然 だ。各オブジェクトが独立したアドレス空間を持つようなもので、複雑になる
    • Lisette は Rust から 着想を得た言語 であって、Rust そのものになろうとしているわけではない。主なターゲットは Go 開発者
  • Go ランタイムは良いが、言語そのものは 無骨で、改善する意志がないように見える
    だからトランスパイラを使うほどなら、よほど Go が嫌いなのだろう

  • Rust や Rust 系言語が struct と method を分離 している理由が気になる
    なぜ struct の中にメソッドを直接定義できないのか不思議だ

    • Rust では struct のフィールドが auto-trait に影響するので、フィールドをひと目で見渡せることが重要だ
      また impl ブロックは struct とは異なる ジェネリック制約 を持てるため、複数定義できる
      最後に、Rust はデータの 形(Shape) を中心に考えるよう設計された言語だ
    • 個人的には impl ブロックは Go のメソッドに近く感じられ、どちらが優れているとまでは言えない
  • Python のように見えるのに Rust や Go にコンパイルされる言語があったら本当に素晴らしいと思う

    • Mojo は Swift の生みの親が作った Python 構文ベースの高性能言語
    • Spy は C にコンパイルされる初期の試みで、Nim も同系統の成熟した言語だ
    • Nim は Python に似た文法に 静的型システム を備え、wasm や C など多様なターゲットにコンパイルされる
    • Static Python Skill は Python を静的コンパイルしようとする試みだ
    • Grumpy は Google 製の Python→Go トランスパイラだったが、9年間更新がない(Python 2.7 対応)
  • Lisette は Go の単純さと Rust の複雑さのあいだで 良いバランスを取った言語 に見える
    コンパイル速度が Go より大幅に遅くなる理由があるのか、また Rust の機能のうち何を意図的に除外しているのか気になる
    例: borrow checking、データ型、async など

  • Go は学びやすいが機能不足な言語だ
    Lisette はその 隙間を埋める言語 に見えるので興味深い
    TypeScript が JavaScript を拡張したように、Go に 表現力のある型システム厳格なコンパイラ を加えれば、優れたバックエンド言語になるだろう
    個人的な提案としては、TypeScript フロントエンドとの 型共有 をサポートしてほしい。これが TypeScript がバックエンドでも人気な理由の一つでもある

  • Rust の安全性と Go の単純さのあいだで悩むインフラ自動化開発者として、Rust の使い勝手 を Go ランタイムの上に載せるという発想は非常に魅力的だ
    今後もプロジェクトの進展を追い続けるつもりだ