Lispのような構文拡張メカニズムを備えたプログラミング言語[非公開]


20

Lispの知識は限られています(暇なときに少し学ぼうとしています)が、Lispマクロを理解する限り、Lisp自体で記述することで、新しい言語構造と構文を導入できます。これは、Lispコンパイラ/インタプリタを変更せずに、新しい構成をライブラリとして追加できることを意味します。

このアプローチは、他のプログラミング言語のアプローチとは大きく異なります。たとえば、Pascalを新しい種類のループまたは特定のイディオムで拡張する場合、言語の構文とセマンティクスを拡張してから、コンパイラにその新しい機能を実装する必要があります。

Lispファミリー以外のプログラミング言語(Common Lisp、Scheme、Clojure(?)、Racket(?)など)以外に、言語内で言語を拡張する同様の可能性を提供するプログラミング言語はありますか?

編集

長時間の議論を避け、答えを具体的にしてください。何らかの方法で拡張できるプログラミング言語の長いリストの代わりに、概念的な観点から、拡張メカニズムとしてのLispマクロに固有のものと、どの非Lispプログラミング言語がいくつかの概念を提供するかを理解したいそれは彼らに近いです。


6
Lispには、通常のマクロ以外に別のトリックがあります。「リーダーマクロ」を使用すると、実行時にパーサー構文をキャプチャして拡張できるため、言語の基本的なトークン構造も制御されます。
ddyer

@ddyer:ありがとう、私はそれについて知りませんでした:私の読書リストに追加される別のトピック。
ジョルジオ

Rubyのメタプログラミングがこれに対応できると思っています。
リグ

1
あなたの質問は矛盾しています。最初にリストを求め、次に概念情報を求めます。

私はリストを求めていますが、一般的なものではありません(何らかの方法で拡張できるプログラミング言語だけではありません)。これはあまりにも一般的だからです。Lispに似た方法で拡張できる言語について知りたい(拡張機能は、ある種のメタ言語ではなく、拡張するのと同じ言語を使用して定義される)。PéterTörök、Thomas Eding、SK-logic、Mechanical snailの答えは、私が考えていたものに最も近いようです。それでも、すべての答えを注意深く読む必要があります。
ジョルジオ

回答:


19

Scalaはこれも可能にします(実際、新しい言語の構成要素、さらには完全なDSLの定義をサポートするように意図的に設計されました)。

関数型言語で一般的な高階関数、ラムダ、カリー化のほかに、これを可能にする特別な言語機能がいくつかあります*:

  • 演算子なし-すべてが関数ですが、関数名には「+」、「-」、「:」などの特殊文字を含めることができます
  • 単一パラメータのメソッド呼び出しでa.and(b)はドットと中括弧を省略できます。つまりa and b、中置形式と同等です
  • 単一パラメータの関数呼び出しでは、通常の中括弧の代わりに中括弧を使用できます-これは(カリー化と一緒に)次のような記述を可能にします

    val file = new File("example.txt")
    
    withPrintWriter(file) {
      writer => writer.println("this line is a function call parameter")
    }
    

    where withPrintWriterは、2つのパラメーターリストがあり、両方とも単一のパラメーターを含むプレーンメソッドです

  • by-nameパラメータを使用すると、ラムダの空のパラメータリストを省略でき、次のようなmyAssert(() => x > 3)短い形式で呼び出しを記述できます。myAssert(x > 3)

サンプルDSLの作成については、無料の書籍 『Scalaのプログラミング』の第11章「Scalaのドメイン固有言語」で詳しく説明しています。

* これらはScalaに固有のものではありませんが、少なくともあまり一般的ではないようです。しかし、私は関数型言語の専門家ではありません。


1
+1:興味深い。これは、構文を拡張するために新しいクラスを定義でき、メソッドシグネチャが副産物として新しい構文を提供することを意味しますか?
ジョルジオ

@Giorgio、基本的にははい。
ペテルトレック

リンクはもう機能しません。
ネイトグレン

13

Perlでは、言語の前処理が可能です。これは、言語の構文を根本的に変更する程度まで頻繁に使用されることはありませんが、一部の...奇妙なモジュールで見ることができます:

また、perlがPythonで書かれたように見えるコードを実行できるようにするモジュールもあります。

perl内のこれに対するより現代的なアプローチは、Filter :: Simple(perl5のコアモジュールの1つ)を使用することです。

これらの例はすべて、「Mad Doctor of Perl」と呼ばれているDamian Conwayに関係していることに注意してください。perl内の驚くほど強力な機能であり、言語を思いのままにひねります。

perlfilterには、これと他の代替物に関するドキュメントがあります。


13

ハスケル

Haskellには、「テンプレートHaskell」と「準引用」があります。

http://www.haskell.org/haskellwiki/Template_Haskell

http://www.haskell.org/haskellwiki/Quasiquotation

これらの機能により、ユーザーは通常の方法以外で言語の構文を劇的に追加できます。これらはコンパイル時にも解決されますが、これは(少なくともコンパイルされた言語の場合は)大事なことだと思います[1]。

以前、Haskellで準引用符を使用して、Cに似た言語で高度なパターンマッチャーを作成しました。

moveSegment :: [Token] -> Maybe (SegPath, SegPath, [Token])
moveSegment [hc| HC_Move_Segment(@s, @s); | s1 s2 ts |] = Just (mkPath s1, mkPath s2, ts)
moveSegment _ = Nothing

[1]それ以外の場合、以下は構文拡張としての資格がありますrunFeature "some complicated grammar enclosed in a string to be evaluated at runtime"


3
Haskellには、独自の演算子の作成や、ラムダ関数と組み合わせた自動カリー化など、基本的にカスタム構文を可能にする他の機能もあります(たとえば、の典型的な使用方法を考慮してくださいforM)。
Xion

カレーやカスタムオペレーターは資格がないと正直に思います。それらは言語をきちんと使用することを許可しますが、言語に/ new /機能を追加することを許可しません。THとQQが行います。厳密な意味では、THとQQは、意図されたとおりに動作するという意味ではどちらも行いませんが、コンパイル時に本当に「言語外」になることができます。
トーマスエディング

1
「それ以外の場合は、構文拡張として適格です...」:非常に良い点。
ジョルジオ

12

Tclには、拡張可能な構文をサポートする長い歴史があります。たとえば、次のループの実装は、3つの変数(停止するまで)を基数、その正方形、およびキューブに対して繰り返します。

proc loopCard23 {cardinalVar squareVar cubeVar body} {
    upvar 1 $cardinalVar cardinal $squareVar square $cubeVar cube

    # We borrow a 'for' loop for the implementation...
    for {set cardinal 0} true {incr cardinal} {
        set square [expr {$cardinal ** 2}]
        set cube [expr {$cardinal ** 3}]

        uplevel 1 $body
    }
}

これは次のように使用されます。

loopCard23 a b c {
    puts "got triplet: $a, $b, $c"
    if {$c > 400} {
        break
    }
}

技術のこの種は、Tclプログラミングで広く使用されており、それをやっての鍵は、sanelyあるupvaruplevelコマンド(upvarバインドローカル変数に別のスコープで指定された変数、およびuplevel他のスコープでスクリプトを実行します:両方のケースでは、1ことを示しています問題のスコープは呼び出し側のものです)。また、データベースと結合するコード(結果セットの各行に対していくつかのコードを実行する)、GUIのTk(コールバックをイベントにバインドするため)などで多く使用されます。

ただし、これは実行される処理のほんの一部です。組み込み言語はTclである必要さえありません。それは事実上どんなものでも構いません(ブレースのバランスをとる限り-それが真実でなければ構文的に恐ろしいものになります-これはプログラムの大多数です)そしてTclは必要に応じて埋め込まれた外国語にただディスパッチできます。これを行う例には、Cを組み込んでTclコマンドおよびFortranと同等のコマンドを実装することが含まれます。(ほぼ間違いなく、すべてのTclの組み込みコマンドは、ある意味でこの方法で実行されます。つまり、実際には言語そのものではなく、単なる標準ライブラリです。)


10

これは部分的にはセマンティクスの問題です。Lispの基本的な考え方は、プログラムはそれ自体が操作可能なデータであるということです。SchemeのようなLispファミリーで一般的に使用される言語では、パーサーの意味で新しい構文を実際に追加することはできません。すべてスペースで区切られた括弧で囲まれたリストです。コア構文はほとんど機能しないため、ほとんどすべてのセマンティック構造を作成できます。Scala(以下で説明します)も同様です。変数名の規則は非常に自由であるため、(同じコア構文規則内にとどまりながら)簡単にDSLを作成できます。

これらの言語は、実際にはPerlフィルターの意味で新しい構文を定義することはできませんが、DSLを構築し、言語構成要素を追加するために使用できる十分に柔軟なコアを備えています。

重要な共通機能は、言語によって公開される機能を使用して、組み込みのものと同様に機能する言語構成を定義できることです。この機能のサポートの程度はさまざまです。

  • 多くの古い言語は、組み込みで提供さのような機能sin()round()など、独自のものを実装するためにどのような方法なし。
  • C ++は限定的なサポートを提供します。例えば内蔵キャスト(のようなキーワード一部static_cast<target_type>(input)dynamic_cast<>()const_cast<>()reinterpret_cast<>())テンプレート関数を使用してエミュレートすることができ、そのブースト用途のためlexical_cast<>()polymorphic_cast<>()any_cast<>()、...
  • Javaは(制御構造を内蔵しているfor(;;){}while(){}if(){}else{}do{}while()synchronized(){}strictfp{})あなたが独自に定義することはできません。代わりに、Scalaは、便利な制御構造のような構文を使用して関数を呼び出すことができる抽象構文を定義し、ライブラリはこれを使用して、新しい制御構造を効果的に定義します(react{}アクターライブラリなど)。

また、NotationパッケージでMathematicaのカスタム構文機能を見るかもしれません。(技術的にはLispファミリーにありますが、通常のLispの拡張性と同様に、いくつかの拡張機能が異なって実行されます。)


2
違う。Lisp では、実際にあらゆる種類の新しい構文を絶対に追加できます。この例のように:meta-alternative.net/pfront.pdf-Lispマクロにすぎません。
SKロジック

これは、DSLを構築するために特別に設計された言語で実装されているようです。もちろん、このような機能も提供するLispファミリーの言語を作成できます。その機能は、一般的に使用されるLisp(たとえばScheme)でサポートされるコアLispアイデアではないということです。明確にするために編集されました。
機械式カタツムリ

この「DSLを構築するための言語」は、非常に典型的で最小限のLispの上に構築されたマクロのコレクションです。を使用して、他のLispに簡単に移植できます(defmacro ...)。実際、私は現在、楽しみのためにこの言語をラケットに移植しています。しかし、S式の構文はほとんどの有用なセマンティックsには十分すぎるため、これはあまり有用ではないことに同意します。
SKロジック

また、SchemeはCommon Lispと何の違いもありません。R6RSからは公式に、そして非公式には長年にわたり、(define-macro ...)同等の機能を提供します。
SKロジック

8

Rebolはあなたが説明しているように聞こえますが、少し横向きです。

特定の構文を定義するのではなく、Rebolのすべては関数呼び出しです-キーワードはありません。(はい、本当に定義ifwhileたい場合は再定義できます)。たとえば、これは次のifステートメントです。

if now/time < 12:00 [print "Morning"]

ifは、条件とブロックの2つの引数を取る関数です。条件が真の場合、ブロックが評価されます。ほとんどの言語のようですね。ブロックはデータ構造であり、コードに限定されません-これは、たとえばブロックのブロックであり、「コードはデータ」の柔軟性の簡単な例です。

SomeArray: [ [foo "One"] [bar "Two"] [baz "Three"] ]
foreach action SomeArray [action/1: 'print] ; Change the data
if now/time < 12:00 SomeArray/2 ; Use the data as code - right now, if now/time < 12:00 [print "Two"]

構文規則に固執できる限り、この言語を拡張することは、ほとんどの場合、新しい関数を定義すること以外の何ものでもありません。たとえば、Rebol 3の機能をRebol 2にバックポートしているユーザーもいます。


7

Rubyには非常に柔軟な構文があり、「言語自体の中で言語を拡張する」方法だと思います。

例はrakeです。Rubyで書かれており、Rubyですが、makeのように見えます

いくつかの可能性を確認するために、キーワードRubyおよびmetaprogrammingを検索できます。


13
「柔軟な構文」は「拡張可能な構文」とはまったく異なります。Rubyでプログラミングしてからかなりの時間が経ちましたが、Rakeは組み込みの構文をうまく設計して使用しているように見えます。つまり、これは例ではありません。
トーマスエディング

2
それは親切ではなく、程度の問題ではありませんか?構文のいくつかの側面を拡張できるが他の側面は拡張できない「拡張可能な構文」言語と、「柔軟な構文」言語をどのように区別しますか?
来るストーム

1
行がぼやけている場合、Cが拡張可能な構文をサポートしていると見なされるように、行を押し戻しましょう。
トーマスエディング

あなたの例をリンクするには、ここに線を引きます。拡張可能な構文を持つ言語は、makeのように見えるrakeを作成できます。柔軟な構文を備えた言語を拡張して(ha、言語の融合が優れている)、メイクファイルをコンパイルおよび実行できます。程度の問題であなたのポイントはしかし良いものです。一部の言語では、Makeをコンパイルできますが、Pythonはコンパイルできません。そして、他のものは両方を可能にします。
クレイトンスタンレー

Makeファイルを処理するためのチューリング完全な言語を作成できる必要があります。構文の柔軟性は、それがどれほど難しいかを超える要因ではありません。
リグ

7

あなたが話している方法で構文を拡張すると、ドメイン固有の言語を作成できます 質問を言い換えるのにおそらく最も便利な方法は、ドメイン固有の言語を適切にサポートしている他の言語はどれでしょうか?

Rubyには非常に柔軟な構文があり、rakeなど、多くのDSLが栄えています。Groovyには多くの利点があります。また、より直接Lispマクロに類似しているAST変換も含まれています。

統計計算用の言語であるRを使用すると、関数で引数を評価せずに取得できます。これを使用して、回帰式を指定するためのDSLを作成します。例えば:

y ~ a + b

「k0 + k1 * a + k2 * bの形式の行をyの値に合わせる」という意味です。

y ~ a * b

「フォームk0 + k1 * a + k2 * b + k3 * a * bの行をyの値に合わせる」ことを意味します。

等々。


2
GroovyのAST変換は、LispまたはClojureマクロと比較して非常に冗長です。たとえば、groovy.codehaus.org / Global + AST + Transformationsにある20行以上のGroovyの例は、Clojureで1行の短い行に書き換えることができます(例: `(this(println〜message)))。それだけでなく、Groovyページにjarをコンパイルしたり、メタデータやその他のものを書いたりする必要もありません。
ヴォルグヴァンガイア

7

Convergeはもう1つの非リスピーなメタプログラミング言語です。そして、ある程度、C ++にも適合します。

おそらく、MetaOCamlはLispからかなり遠いです。まったく異なるスタイルの構文拡張性を備えていますが、それでも非常に強力なものについては、CamlP4をご覧ください

NemerleはLispスタイルのメタプログラミングを備えた別の拡張可能な言語ですが、Scalaなどの言語に近いものです。

また、Scala自体もまもなくそのような言語になります。

編集:最も興味深い例-JetBrains MPSを忘れました。Lispishから遠く離れているだけでなく、ASTレベルで直接動作するエディターを備えた非テキストプログラミングシステムですらあります。

Edit2:更新された質問に答えるために-Lispマクロにはユニークで例外的なものは何もありません。理論的には、どの言語でもこのようなメカニズムを提供できます(プレーンCでも実現しました)。必要なのは、ASTへのアクセスと、コンパイル時にコードを実行する機能です。いくつかのリフレクションが役立つ場合があります(タイプ、既存の定義などに関するクエリ)。


あなたのScalaリンクは、提案されたマクロは「Scalaの構文を変更できない」と明示的に述べています。(興味深いことに、これはその提案とC / C ++プリプロセッサマクロの違いとしてリストされています!)
ruakh

@ruakh、はい、Converge and Template Haskellと同じアプローチです-マクロアプリケーションは明示的にマークされており、「通常の」構文と混合することはできません。ただし、内部には任意の構文を使用できるため、おそらく拡張可能な構文です。残念ながら、「非lisp」要件により、オプションはこのような言語に制限されます。
SKロジック

「プレーンCでもやった」:これはどのように可能ですか?
ジョルジオ

@Giorgio、もちろんコンパイラーを変更しました(マクロとインクリメンタルモジュールコンパイルを追加しました。これは実際にはCにとって自然なことです)。
SKロジック

ASTへのアクセスが必要な理由
エリオットゴロホフスキー

6

Prologでは、同じ名前の複合語に翻訳される新しい演算子を定義できます。たとえば、これはhas_cat演算子を定義し、リストにアトムが含まれているかどうかをチェックするための述語として定義しますcat

:- op(500, xf, has_cat).
X has_cat :- member(cat, X).

?- [apple, cat, orange] has_cat.
true ;
false.

これxfhas_cat後置演算子です。を使用fxすると、接頭辞演算子になりxfx、2つの引数を取る中置演算子になります。Prologでの演算子の定義の詳細については、このリンクを確認してください。


5

TeXはリストから完全に欠落しています。みんな知ってるでしょ?次のようになります。

Some {\it ``interesting''} example.

…制限なしで構文を再定義できることを除いて。言語のすべての(!)トークンに新しい意味を割り当てることができます。ConTeXtは、中括弧を角括弧に置き換えたマクロパッケージです。

Some \it[``interesting''] example.

より一般的なマクロパッケージLaTeXは、\begin{environment}…\end{environment}構文を追加するなど、目的に合わせて言語を再定義します。

しかし、それで終わりではありません。技術的には、トークンを再定義して以下を解析することもできます。

Some <it>“interesting”</it> example.

はい、絶対に可能です。一部のパッケージは、これを使用して小さなドメイン固有の言語を定義します。たとえば、TikZパッケージは技術図面の簡潔な構文を定義します。これにより、次のことが可能になります。

\foreach \angle in {0, 30, ..., 330} 
  \draw[line width=1pt] (\angle:0.82cm) -- (\angle:1cm);

さらに、TeXはチューリング完全であるため、文字通りすべてをTeXで実行できます。かなり無意味で非常に複雑であるため、これがその潜在能力を最大限に発揮するのを見たことはありませんが、トークンを再定義するだけで次のコードを解析可能にすることは完全に可能です(ただし、これはおそらく、パーサーの物理的な限界構築方法):

for word in [Some interesting example.]:
    if word == interesting:
        it(word)
    else:
        word

5

Booを使用すると、構文マクロを使用してコンパイル時に言語を大幅にカスタマイズできます。

Booには「拡張可能なコンパイラパイプライン」があります。つまり、コンパイラは、コンパイラパイプラインの任意の時点でコードを呼び出してAST変換を実行できます。ご存じのとおり、JavaのGenericsやC#のLinqなどは、コンパイル時の単なる構文変換であるため、非常に強力です。

Lispと比較して、主な利点は、これがあらゆる種類の構文で機能することです。BooはPythonにヒントを得た構文を使用していますが、おそらくCまたはPascal構文を使用して拡張可能なコンパイラを作成できます。また、マクロはコンパイル時に評価されるため、パフォーマンスの低下はありません。

Lispと比較した場合の欠点は次のとおりです。

  • ASTでの作業は、S式での作業ほどエレガントではありません
  • マクロはコンパイル時に呼び出されるため、ランタイムデータにアクセスできません。

たとえば、これは新しい制御構造を実装する方法です。

macro repeatLines(repeatCount as int, lines as string*):
    for line in lines:
        yield [| print $line * $repeatCount |]

使用法:

repeatLines 2, "foo", "bar"

コンパイル時に、次のように変換されます。

print "foo" * 2
print "bar" * 2

(:残念ながら、ブーイングのオンラインドキュメントは常に絶望的に古くなっても、このような高度なものをカバーしていない私が知っている言語のための最良のドキュメントがこの本です。http://www.manning.com/rahien/


1
この機能のWebドキュメントは現在壊れており、私は自分でBooを書いていませんが、見落とされたら残念だと思いました。modのフィードバックに感謝し、空き時間に無料の情報を提供する方法を再検討します。
ダン

4

Mathematicaの評価は、パターンマッチングと置換に基づいています。これにより、独自の制御構造を作成したり、既存の制御構造を変更したり、式の評価方法を変更したりできます。たとえば、次のような「ファジーロジック」を実装できます(少し簡略化)。

fuzzy[a_ && b_]      := Min[fuzzy[a], fuzzy[b]]
fuzzy[a_ || b_]      := Max[fuzzy[a], fuzzy[b]]
fuzzy[!a_]           := 1-fuzzy[a]
If[fuzzy[a_], b_,c_] := fuzzy[a] * fuzzy[b] + fuzzy[!a] * fuzzy[c]

これは、事前定義された論理演算子&&、|| ,!の評価をオーバーライドします。および組み込みIf句。

これらの定義は関数定義と同じように読むことができますが、実際の意味は次のとおりです。式が左側で説明したパターンと一致する場合、右側の式に置き換えられます。次のように独自のIf節を定義できます。

myIf[True, then_, else_] := then
myIf[False, then_, else_] := else
SetAttributes[myIf, HoldRest]

SetAttributes[..., HoldRest] 評価者に、パターンマッチングの前に最初の引数を評価する必要があるが、パターンが一致して置換されるまで残りの評価を保持するように指示します。

これはMathematica標準ライブラリ内で広く使用されており、例えばD式を取りそのシンボリック導関数に評価する関数を定義します。


3

Metaluaは、これを提供するLuaと互換性のある言語およびコンパイラです。

  • Lua 5.1ソースおよびバイトコードとの完全な互換性:クリーンでエレガントなセマンティクスと構文、驚くべき表現力、優れたパフォーマンス、ほぼ普遍的な移植性。 -Lispの方言またはTemplate Haskellが提供するものとパワーが似ている完全なマクロシステム。操作されたプログラムは
    、ソースコード、抽象的な構文ツリー、または
    それらの任意の組み合わせのいずれかで、タスクに適したものと見なすことができます。
  • 動的に拡張可能なパーサー。他の言語とうまく調和する構文でマクロをサポートできます。

  • 言語拡張のセット。すべて通常のメタロマクロとして実装されます。

Lispとの違い:

  • マクロを作成していないときに開発者をマクロで悩まさないでください。マクロを作成していない95%の時間に、言語の構文とセマンティクスが最適です。
  • 開発者にこの言語の慣習に従うよう奨励します。誰も耳を傾けない「ベストプラクティスの暴言」だけでなく、Metalua Wayの記述を容易にするAPIを提供することによって。仲間の開発者による読みやすさは、コンパイラによる読みやすさよりも重要であり、達成がより困難です。このため、尊敬される慣習の共通セットを持っていることは大いに役立ちます。
  • しかし、自分が喜んで処理するすべての力を提供してください。LuaもMetaluaも強制的な束縛と規律に陥っていないので、あなたが何をしているのかを知っていれば、言語は邪魔になりません。
  • おもしろいことが起こったときにそれを明らかにします。すべてのメタ操作は+ {...}と-{...}の間で起こり、視覚的に通常のコードからはみ出します。

アプリケーションの例は、MLに似たパターンマッチングの実装です。

参照:http : //lua-users.org/wiki/MetaLua


Luaは確かにLispではありませんが、「相違点」のリストは非常に疑わしいものです(関連する項目は最後の項目のみです)。そして、もちろん、Lispコミュニティは、95%の時間でマクロを書いたり使ったりしてはいけないという暴言に同意しません-Lispの方法は、95%の時間、コース。
SKロジック

2

拡張可能な言語を探しているなら、Smalltalkを見てみるべきです。

Smalltalkでは、プログラミングする唯一の方法は実際に言語を拡張することです。IDE、ライブラリ、または言語自体に違いはありません。それらはすべて絡み合っているので、Smalltalkはしばしば言語ではなく環境と呼ばれます。

Smalltalkでスタンドアロンアプリケーションを記述するのではなく、代わりに言語環境を拡張します。

チェックアウトhttp://www.world.st/をリソースや情報の一握りのために。

Smalltalkの世界への入り口の方言としてPharoをお勧めします:http : //pharo-project.org

お役に立てば幸いです!


1
興味深いですね。
トーマスエディング

1

ゼロからコンパイラ全体を記述することなく、カスタム言語を作成できるツールがあります。たとえば、コード変換ツールであるSpoofaxがあります。入力文法と変換ルール(非常に高レベルの宣言的な方法で記述された)を入力し、Javaソースコード(または他の言語、十分に気をつければ)を生成できますあなたが設計したカスタム言語から。

したがって、言語Xの文法を取り、言語X '(カスタム拡張を含むX)および変換X'→Xの文法を定義することが可能になり、SpoofaxはコンパイラX '→Xを生成します。

現在、私が正しく理解している場合、C#サポートが開発されている(または私が聞いた)Javaの最適なサポートです。ただし、この手法は静的な文法を持つすべての言語に適用できます(たとえば、おそらくPerlではありません)。


1

Forthは、拡張性の高い別の言語です。多くのForth実装は、アセンブラーまたはCで書かれた小さなカーネルで構成され、残りの言語はForth自体で書かれています。

また、Forthに触発され、この機能を共有するFactorなどのスタックベースの言語もいくつかあります。


0

Funge-98

Funge-98の指紋機能を使用すると、言語の構文とセマンティクス全体を完全に再構築できます。ただし、実装者が、ユーザーがプログラムで言語を変更できる指紋メカニズムを提供する場合のみ(これは、通常のFunge-98構文およびセマンティクス内で実装することが理論的に可能です)。もしそうなら、文字通りファイルの残りの部分(またはファイルの任意の部分)をC ++またはLisp(または彼が望むもの)として動作させることができます。

http://quadium.net/funge/spec98.html#Fingerprints


以前の回答に追加するのではなく、なぜこれを個別に投稿したのですか?
-gnat

1
FungeはHaskellとは何の関係もないからです。
トーマスエディング

-1

探しているものを取得するには、これらの括弧と構文の欠如が本当に必要です。いくつかの構文ベースの言語が近づいているかもしれませんが、それは真のマクロと全く同じものではありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.