向我解释连接语言,就像我是一个8岁的孩子

时间:2009-05-25 16:07:45

标签: programming-languages concatenative-language

我读过Wikipedia article on concatenative languages,现在我比起初时更加困惑。 : - )

用愚蠢的人来说什么是串联语言?

7 个答案:

答案 0 :(得分:18)

在普通编程语言中,您可以自由定义变量,并使用这些变量作为参数调用方法。这些很容易理解但有些限制。通常,很难重用现有方法,因为您根本无法将现有变量映射到方法所需的参数,或者方法A调用另一种方法B,如果只能替换对B的调用,则A对您来说是完美的。打电话给C。

连接语言使用固定数据结构来保存值(通常是堆栈或列表)。没有变数。这意味着许多方法和函数具有相同的“API”:它们处理其他人留在堆栈中的内容。加上代码本身被认为是“数据”,即编写可以修改自身或接受其他代码作为“参数”(即作为堆栈中的元素)的代码是很常见的。

这些属性使这些语言非常适合链接现有代码以创建新内容。内置了重用。您可以编写一个接受列表和一段代码的函数,并为列表中的每个项调用代码。这将适用于任何类型的数据,只要它的行为类似于列表:数据库的结果,图像中的一行像素,字符串中的字符等。

最大的问题是你没有暗示发生了什么。只有几种数据类型(列表,字符串,数字),所以一切都映射到它。当您获得一条数据时,通常不关心它是什么或它来自何处。但这使得通过代码跟踪数据很难看到发生了什么。

我认为成功使用这些语言需要一定的心态。它们不适合所有人。

[编辑] Forth有一些渗透但不是那么多。您可以在任何现代激光打印机中找到PostScript。所以他们是小众语言。

从功能层面来看,它们与LISP,类C语言和SQL相同:所有这些都是Turing Complete,因此您可以计算任何东西。这只是你需要编写多少代码的问题。有些东西在LISP中更简单,有些在C中更简单,有些在查询语言中更简单。除非你有上下文,否则“更好”的问题是徒劳的。

答案 1 :(得分:14)

首先,我要对Norman Ramsey的断言进行反驳,即没有理论。

连接语言理论

连接语言是一种函数式编程语言,默认操作(当两个术语并排时会发生什么)是函数组合而不是函数应用程序。它是如此简单。

因此,例如在SKI Combinator Calculus(最简单的函数语言之一)中,两个并排的术语相当于将第一个术语应用于第二个术语。例如:S K K相当于S(K)(K)

使用连接语言S K K相当于Haskell中的S . K . K

那么重要的是什么

纯粹的连接语言具有有趣的特性,即术语评估的顺序无关紧要。使用拼接语言(S K) KS (K K)相同。这不适用于SKI微积分或任何其他基于功能应用的函数编程语言。

这一观察结果之一的一个原因很有意思,因为它揭示了在根据功能组成而不是应用表达的代码评估中进行并行化的机会。

现在是现实世界

支持高阶函数的基于堆栈的语言的语义可以使用连接微积分来解释。您只需将每个术语(命令/表达式/子程序)映射为一个函数,该函数将函数作为输入并将函数作为输出返回。整个程序实际上是一个单一的堆栈转换函数。

现实情况是,在现实世界中事物总是被扭曲(例如,FORTH有一个全球字典,PostScript做评估顺序很重要的奇怪事情)。大多数实用的编程语言并不完全符合理论模型。

最后的话

我认为一个典型的程序员或8岁的人不应该担心串联语言是什么。我也没有发现它对于鸽子洞编程语言特别有用,因为它是X型或Y型。

答案 2 :(得分:5)

在阅读http://concatenative.org/wiki/view/Concatenative%20language并借鉴了我记得在十几岁时与Forth一起摆弄的一点点时,我相信关于拼接编程的关键在于:

  • 根据特定数据堆栈上的值查看数据
  • 和函数根据在同一数据堆栈上弹出/推送值来操作东西

从以上网页查看以下引用:

  

有两个术语被抛出   堆栈语言和   连接语言。两者都定义   相似但不相等的类别   语言。但在大多数情况下,   它们完全相同。

     

今天广泛使用的大多数语言   是应用语言:中心   语言中的构造是某种形式   函数调用,函数是什么   应用于一组参数,其中   每个参数本身就是结果   一个函数调用,一个名字   变量或常数。在堆栈中   语言,函数调用由   只需写下名字   功能;参数是隐含的,   他们必须已经在   在进行通话时堆叠。该   函数调用的结果(如果有的话)   然后在堆栈之后留在堆栈中   函数返回,为下一个   功能消耗,等等。   因为简单地调用函数   通过提及他们的名字没有任何   附加语法,Forth和Factor   将函数称为“单词”,因为   在语法中他们真的是公正的   词语的

这与将其功能直接应用于特定变量的应用语言形成对比。

示例:添加两个数字。

适用语言

int foo(int a, int b)
{
    return a + b;
}

var c = 4;
var d = 3;
var g = foo(c,d);

连接语言(我编写了,应该与Forth相似......;)

push 4
push 3
+
pop

虽然我不认为连接语言=堆栈语言,正如作者在上面指出的那样,它看起来很相似。

答案 3 :(得分:4)

我认为主要的想法是1.我们可以简单地通过加入其他程序来创建新程序。

此外,2。程序的任何随机块都是有效的功能(或子程序)。

好旧的纯RPN Forth具有这些属性,不包括任何随机的非RPN语法。

在程序1 2 + 3 *中,子程序+ 3 *取2个args,得到1个结果。子程序2取0个args并返回1个结果。任何块都是一个功能,这很好!

您可以通过将两个或更多其他物品混合在一起来创建新功能,可选择使用一点胶水。如果类型匹配,它将最有效!

这些想法非常好,我们重视简单。

它不仅限于RPN Forth风格的串行语言,也不限于命令式或函数式编程。这两个想法也适用于图形语言,其中程序单元可能是例如函数,过程,关系或过程。

在通信流程网络中,每个子网络都可以像流程一样行事。

在数学关系图中,每个子图都是有效的关系。

这些结构是“连接的”,我们可以以任何方式将它们分开(绘制圆圈),并以多种方式将它们连接在一起(绘制线条)。

嗯,这就是我的看法。我确信我已经错过了连接阵营中许多其他好的想法。虽然我热衷于图形编程,但我很专注于连接。

答案 4 :(得分:1)

我对连接编程的实用(和主观)定义(现在,你可以避免阅读其余内容):

- >极端方式的函数组合(使用RPN语法):

( Forth code )
: fib
  dup 2 <= if
    drop 1
  else
    dup 1 - recurse
    swap 2 - recurse +
  then ;

- &GT;一切都是功能,或者至少可以是一个功能:

( Forth code )
: 1 1 ; \ define a function 1 to push the literal number 1 on stack

- &GT;参数是通过函数隐式传递的(好吧,它似乎是默认编程的定义),但是,这在Forth:

a b c

可能在Lisp中:

(c a b)
(c (b a))
(c (b (a)))

因此,生成含糊不清的代码很容易...... 你可以编写在堆栈上推送xt(执行令牌)的定义,并为&#39;执行&#39;:

定义一个小别名
( Forth code )
: <- execute ; \ apply function

所以,你得到:

a b c <- \ Lisp: (c a b)
a b <- c <- \ Lisp: (c (b a))
a <- b <- c <- \ Lisp: (c (b (a)))

答案 5 :(得分:0)

您无法解释某种语言,只需获得一种语言(最好Factor)并尝试some tutorials on it。教程优于Stack Overflow答案。

答案 6 :(得分:0)

对于你的简单问题,这是一个主观和有争议的答案。

我查看了这篇文章和几个相关的网页。网页上说自己没有真正的理论,所以难怪人们很难找到一个精确且易于理解的定义。我想说,目前,无用将语言分类为“连接”或“非连接”。

对我来说,这个术语看起来像Manfred von Thun一个可以挂帽的地方,但可能对其他程序员没用。

虽然PostScript和Forth值得研究,但在Manfred von Thun的Joy编程语言中我没有看到任何非常新的或有趣的东西。事实上,如果你在 Techniques for Embedding Postfix Languages in Haskell 上阅读Chris Okasaki的论文,你可以尝试所有这些东西,相对于Joy而言,它是完全主流的。

所以我的答案是没有简单的解释,因为没有成熟的理论来源于连接语言的概念。 (正如爱因斯坦和费曼所说,如果你不能向大学新生解释你的想法,你就不会真正理解它。)我会更进一步说,虽然研究其中一些语言,如Forth和PostScript,是一个充分利用时间,试图找出人们说“串联”时的确切含义可能是浪费你的时间。