TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

The Meta-Circular Evaluator (2016)

40 pointsby ptrabout 6 years ago

2 comments

triskaabout 6 years ago
That&#x27;s a very interesting topic and nice write-up, thank you for sharing!<p>For comparison, here is a small interpreter for a subset of Prolog, written in Prolog:<p><pre><code> mi([]). mi([G|Gs]) :- clause_(G, Body), mi(Body), mi(Gs). </code></pre> This states that: First, the empty conjunction (of goals) is true, and second, if there is at least one goal left, than the conjunction is true <i>if</i> there is a suitable clause whose body evaluates to true, and the same holds for all remaining goals.<p>For example, we can define append&#x2F;3 as follows in this representation:<p><pre><code> clause_(append([], Ys, Ys), []). clause_(append([X|Xs], Ys, [X|Zs]), [append(Xs,Ys,Zs)]). </code></pre> and then evaluate it with our interpreter:<p><pre><code> ?- mi([append([a,b,c], [d,e], Ls)]). Ls = [a, b, c, d, e]. </code></pre> Characteristically, it also works in other directions. For example:<p><pre><code> ?- mi([append([a,b,c], Rs, [a,b,c,d,e])]). Rs = [d, e]. </code></pre> and also:<p><pre><code> ?- mi([append(As, Bs, [x,y])]). As = [], Bs = [x, y] ; As = [x], Bs = [y] ; As = [x, y], Bs = [] ; false. </code></pre> Now the point: The clauses of the meta-interpreter itself can <i>also</i> be stated in this form, namely as:<p><pre><code> clause_(mi([]), []). clause_(mi([G|Gs]), [clause_(G,Body),mi(Body),mi(Gs)]). </code></pre> Now we only have to define what clause_&#x2F;2 means, which we can do with:<p><pre><code> clause_(clause_(G, Body), []) :- clause_(G, Body). </code></pre> And now we can use our meta-interpreter to evaluate its own code as it interprets a program, arbitrarily deeply layered:<p><pre><code> ?- mi([mi([mi([append([a,b,c],[d,e],Ls)])])]). Ls = [a, b, c, d, e]. </code></pre> Hence, Prolog admits a meta-circular evaluator in at most 5 lines of code. With a better representation for clauses (using list differences), you can reduce the interpreter to 4 lines of code and at the same time make it tail-recursive.
评论 #19294623 未加载
nickdrozdabout 6 years ago
The post is based on SICP, and the author briefly discusses dynamic scoping after finding it in some other blog posts or something. In fact, the first edition of SICP contained a discussion of dynamic scoping. I don&#x27;t know why it was removed from the second edition, because it&#x27;s an interesting and important topic. Dynamic scoping also features in the SICP videos [1], which were produced around the time the first edition came out.<p>[1] <a href="https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=t5EI5fXX8K0&amp;feature=youtu.be&amp;t=1098" rel="nofollow">https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=t5EI5fXX8K0&amp;feature=youtu.be...</a>