Lispには、他のプログラミング言語で採用されていない特別な機能がまだありますか?


35

Lispには、他のプログラミング言語で採用されていない特別な機能がまだありますか?

Lispとは、すべてのLispプログラミング言語全体を意味します。私はLispがどれほど素晴らしいかを聞いてきましたが、多くの言語がLispに触発されたことを知っています。しかし、Lispには、他の言語では実行できない排他的なデザイン機能がまだありますか?

私が質問した理由は、最近、私自身アマチュアプログラマーである私はただ楽しみのためにClojureを学び始めたので、その結果、私はLisp関連の投稿やコメントをたくさん見つけたということです。しかし、他の最新のプログラミング言語は、条件、再帰、ファーストクラスの市民としての機能など、すでにLispから多くのアイデアを採用し盗んでいます。さらに、多くの言語でメタプログラミングを行うこともできます。

私は何かを見逃し、「Lispはまだ違う」のですか?

あるいは、他の現代言語がLispからすべての優れた部分を盗んだため、括弧Lispの世界を掘り下げる必要がなく、「Lispは違っていた」ので、私は幸運です。


3
あなたの研究を共有することは誰にとっても役立ちます。試したことと、それがニーズに合わなかった理由を教えてください。これは、あなたが時間をかけて自分自身を助けようとしていること、明白な答えを繰り返すことから私たちを救うこと、そして何よりもあなたがより具体的で関連性のある答えを得ることを助けることを示しています。質問方法
-gnat

3
@gnat Thxアドバイスを求め、質問を更新しました:)
iceX

10
1つの問題は、言語がLisp機能の特定のサブセット(S式やマクロなど)を取得すると、それがLispであると主張することです。(これらの人々によると)どの非Lisp言語もこれらの機能を持つことはできないという結果になります。

9
丸括弧のみがすべてをグループ化する唯一の形式である他の言語はないと思います:
Doc Brown

家族としてのLispはそれほどユニークではないかもしれませんが、多くのLisp方言(Racket、CL、Scheme、Clojure)はまだ多くの便利でユニークな機能を提供します。
ダニエル・グラッツァー

回答:


28

このタイプの質問の標準的な参照は、Paul GrahamのWhat Made Lisp Differentです。執筆時点でこの記事によると、広く利用できないLispの残りの2つの主要な機能は次のとおりです。

8.シンボルの木を使用したコードの表記

9.言語全体が常に利用可能です。読み取り時、コンパイル時、および実行時の間に実際の区別はありません。読み取り中にコードをコンパイルまたは実行し、コンパイル中にコードを読み取りまたは実行し、実行時にコードを読み取りまたはコンパイルできます。

解説は各ポイントに対応し、その機能が利用できる一般的な言語を挙げています。

8(9)がLispマクロを可能にするものですが、おそらく(a)それらの括弧、または同様に悪いものが必要なため、そして(b)その最終的な電力増分を追加する場合、 、あなたはもはや新しい言語を発明したと主張することはできませんが、Lispの新しい方言を設計しただけです。-)

この記事は2002年に最後に改訂され、過去11年間に多種多様な新しい言語が存在し、その一部はこれらのLisp機能をすべて設計に組み込むことに注意してください。


2
これらの機能は、Lisp(および直接派生したバリアント)に固有のものではなく、かなり長い間使用されていません。
ドナルドフェローズ

21
@iceX:JavaScriptとLisp、Smalltalk、Self、Newspeak、APL、Factor、Forthなどの言語の違いは、JavaScriptではプログラムが「死んだ」ということです。テキストファイルです。実行中のプログラムを強制終了し、テキストファイルを編集してから、プログラムの完全に新しいコピーを起動します。他の(いわゆる「ライブ」環境)では、実行中のプログラムを停止することはありません。実行中のプログラム自体は、実行中に他のオブジェクトを操作するのと同じ方法で操作するメモリ内のオブジェクトのセットです。(注:これはClojureには当てはまりませんが、ほとんどの古いLispはこの方法で行います。)
ヨルグW

2
@JörgWMittagうわー...だから、Clojure、Clojurescript、lispyscriptのようなプログラミング言語は、Common Lispのように旧式のLispのようにコードを変更できないため、実際には「本当のLisp」ではありません。しかし...変更できない場合...なぜコード操作を目的としていたと思われるS式を使用するのが面倒なのか...(私は深い暗いウサギの穴に落ちたような気がします)
iceX

4
@iceX:evalHaskellのTemplate Haskellなど、多くの言語にメタプログラミングがあります。Lispの(ほぼ間違いなく)ユニークな点は、データ、コード、メタコードの表現が同じであるということです-構文だけでなく、実際には同じことです。
ダンマー

2
@iceX Evalはその一部にすぎませんが、すべてではありません。Lispでは、コンパイル時にコードを実行できます。読み取り時にコードを実行できます。はい、clojureはLispのダイナミズムをすべてサポートし、マクロ、リーダーマクロ、evalを備えています。また、実行中のプログラムにREPLをアタッチしてその場で変更する機能も備えています。
ストーンメタル

15

質問は答えるのが難しいものです。誰かがLispで利用できる特定の機能を持っていないことを知るためにすべての言語を知る必要があるので、以下は私が経験した言語に基づいています。

私の頭上では、条件は他の言語では見たことがないものです。「例外」を考えてください。ただし、コールスタックが解かれていない場合、および呼び出し元が例外値をリカバリサイトに送信できるが、ハンドラと例外のソースの間のコールスタック乱すことはありません。公平を期すために、これは実際には継続の特別なアプリケーションであるため、RubyとSchemeは(少なくとも)これ行うことができます。

規則/ homoiconicityからLispのマクロシステムの利点が、Scalaは2.12で安定した機能として、それらを組み込むことを計画している、テンプレートHaskellは似たような機能を主張します。Lispよりも構文的に複雑になると私は主張しますが、コンパイル時のコード生成は関係ありません。

考えてみると、しかし、フォームの直接的な構築はLispで利用できるマクロの1種類にすぎません。コンパイラーやリーダーのマクロに相当するものは他のどこにも見たことがありません。

いくつかの方言(例:SBCL)の完全で再開可能なプロセスイメージを保存する機能はクールですが、これもユニークではありません。Smalltalkは何十年もそれを行ってきました。

他の多くの言語では、配列を返すときに構造化代入を許可していますが、# 'valuesおよび#' multiple-value-bind / let-valuesアプローチは、Common LispおよびSchemeに固有のようです(「通常の」構造化も行うことができます) )。Perlの「wantarray」は、関数がスカラー、リスト、またはvoidコンテキストで呼び出されているかどうかを判断できるため、同様の方法で戻り値を調整できますが、外部で「true」の複数の戻り値を見たことはありませんScheme / CLの。

言語の機能に関しては、おそらく他の言語ではできないことをLispでできることあまりないでしょう(完全性をチューリングすることはそのままです)。しかし、それ、コードが独自のデータ構造で表現される言語であり、Big Idea™(コードはデータ)を比較的扱いやすいものにします。


3
Scalaマクロは、LispマクロやTHマクロ、Scheme衛生マクロなどよりもはるかに強力ではありません。同様に強力なシステムがMetaLuaとConvergeにあります。
SKロジック

4

何十年も経った今、私はLisp専用のものはないと思います。しかし、今日でも、Lispの外では見つけるのが難しい興味深いことがたくさんあります。頭に浮かぶいくつかのこと:

  • 洗練されたメタプロトコル(つまり、CLOS)を備えた高品質のオブジェクトシステムは、あまり人気がありません。
  • マルチメソッドは時々どこかでポップアップしますが、ほとんどの人はそれについて聞いたことはありません。
  • 他の人が指摘したように、条件システムは一般的な例外処理メカニズムと比較して非常に洗練されています。
  • 言語のセマンティクス(eval)のコンパクトな表現、言語を定義し、簡単な深い適応(SICPを参照)に使用できるようにする権限付与アプローチ-現在の一般的な言語の「eval」関数は、単に同じプロパティを共有しません。

最後に、言語そのものについてではなく、Lispの歴史の一部となり、やがて失われてしまったLispから学ぶべきことがたくさんあります。たとえば、Interlisp、Symbolics Generaなど... Generaに手を触れたことがない場合は、このcomp.lang.lisp スレッドを参照してください。KentPitmanが、「EmacsはGeneraのZmacsの薄い影に過ぎない」と説明しています。 Zmacsが含まれていた強力なLispシステムを持ち、それはLispマシン上で実行されました。


マルチメソッドディスパッチが実行時に動的に解決され、オーバーロードされたメソッドを使用するよりもはるかに遅いという事実を除いて、ほとんどすべての現代の命令型言語の標準機能であるオーバーロードされたメソッドと区別するマルチメソッドの良い説明を見たことはありませんコンパイル時に解決されます。
メイソンウィーラー14

それらには重要な違いがあります。あなたはその上のトラブルの発見リソースである場合は、いつでも...ここで新しい質問を作成することができます
チアゴ・シウバ

ジュリアにはマルチメソッドがあり、Haskellのパラメトリック多相性はマルチメソッドに似ています。多くの言語でマルチメソッドをシミュレートする方法があります。条件システムは、特に私が本当に欲しいものです(編集して続行しますが、C#デバッガーで見ましたが)。
aoeu256

4

必ずしも特定の単一の機能ではありません。それは全体のルックアンドフィールであり、特定の機能セットがどのように連携するかです。

JavaScriptまたはJavaには、Lispの多くの機能(仮想マシン、コンパイラ/エバリュエーター、ガベージコレクションなど)があります。しかし、たとえばJavaScriptにはシンボリックプログラミング部分がなく、数学的な機能が欠けています(内部的にはフロートしかありません)、エラー処理などがありません。

多くのCommon Lispシステムは、ソフトウェアを長時間再起動することなく、さまざまなメタプログラミング手法を使用してさまざまな次元でLisp言語を拡張することにより、新しいソフトウェアを段階的に拡張する開発方法に最適化されています。したがって、柔軟性と拡張性が必要ですが、同時に堅牢である必要があります。プログラムをクラッシュさせることなく、言語を変更します(マクロは基本的にユーザーがコンパイラを拡張する方法です)。

現在、JavaScriptのようなものは、プログラム(通常はWebブラウザー)の拡張にも使用されています。しかし、ほとんどの場合、一部のOOPハッカーを除き、JavaScriptでのメタプログラミングはあまり行われていません。

例:

コンピュータ代数の領域向けの一般的な高度な数学ソフトウェアは、主に2つの方法で実装できます。C言語でエンジンを記述し、Mathematicaのような特殊な言語を使用するか、より高度なLisp方言を使用します。Common LispのMacsyma / Maxima、Standard LispのReduce、Common Lispの公理

(Pythonで書かれたものもあります。)

Common Lisp上で動作するAxiomのような機能セットを提供するシステムは多くありません。

これらのタイプのアプリケーションでLispを魅力的なものにしたのは、高度な基本数学(bignum、比率など)、シンボリック計算、対話型コンパイラなどの機能が混在していることです。レベル言語。そうすれば、典型的なLispシステムの50%以上を実装できます。


2

私の知る限りではありません。ForthはLispと同じくらい簡単に動的です。おそらく、Forthの動的コードは通常のForthコードのように見えますが、Lispマクロは通常のLispコードとは異なる機能を使用する傾向があるためです(少なくともClojureでは、マクロの外で構文引用符を使用したことはありません)結果として、それらは通常のLispコードとは本当に異なって見えます。動的なForthの例として、Forthでコメントを実装する方法を以下に示します

: (   41 word drop ; immediate
( That was the definition for the comment word. )
( Now we can add comments to what we are doing! )

1
Forthのように楽しいように思えますが、おそらくスタックベースであり、すべてが反転しているために、私は常に絶望的に不透明で扱いにくいと感じました。
ロバートハーベイ

2
好奇心から、「言語の主要部分から分離」とはどういう意味ですか?Lispのマクロは、マクロが定義された時点で定義されたすべての関数に完全にアクセスできます。これらの関数はいずれも、マクロが展開されるフォームを構築するために使用できます。これには、データベースやサーバーから取得した情報が含まれる場合があります。あなたのコメントの例は、(defmacro comment(&rest body))として定義できますか?
ダニーウッズ

1
@DannyWoodsマクロは通常のコードのようには見えません。少なくともclojureでは、通常のコードでは珍しいシンタックスクォート、アンクォートスプライシングなどを頻繁に使用するため、通常のコードからマクロコードを伝えることができます。私が与えたコードの例は、すぐにわかるまでは通常のコードのように見えます。私の答えを読み直すと、表現が不十分です。
ストーンメタル

1
@stonemetal心配はありませんが、Common LispでもClojureでも、構文の引用に関してマクロ固有のものは何もないことに注意してください。(あなたが唯一、その構文の引用を決定するために一度か二度これをしなければならないが、良いことです!)これは、通常の関数定義で式をバッククォート持っていることが時には便利だし、マクロ本体は、手動で平野リストを構築することができます
ダニー・ウッド

1
公平を期すために、カスタムリーダーマクロを登録することで、Lispでも同じことができます。
fjarri

2

Lispには多くの方言があり、それぞれに独自の機能セットがあります。他の言語に採用されることはほとんどありません。私のお気に入りの機能は、より「スパゲッティスタック」であるのInterlisp

スパゲッティスタックはクロージャのようなものですが、ステロイドを使用しています。現在の関数だけでなく、スタック全体のコンテキスト全体を保存します。これらは任意に作成でき、スタックコンテキストの階層が得られることを除いて、co-routineに似ています。


それを知りませんでした、あなたの答えをありがとう:)
iceX

7
これはSchemeの継続と同じですか?
ニコラムサッティ

1
「スパゲッティスタック」である@NicolaMusattiは、Schemeに似た継続(それらを作成した関数が返された後に呼び出すことができる)の一般的な実装戦略です。
アレックスD 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.