【问题标题】:Could a concatenative language use prefix notation?连接语言可以使用前缀表示法吗?
【发布时间】:2012-03-21 10:31:35
【问题描述】:

Concatenative languages 有一些非常有趣的特性,例如能够组合不同数量的函数,并且能够分解出函数的任何部分。然而,许多人不屑一顾,因为它们使用了后缀表示法,而且很难阅读。另外,波兰人可能不喜欢人们倒着使用他们精心制作的符号。

那么,可以有前缀符号吗?如果是,那么取舍是什么?

我知道它是如何工作的,但我没有使用连接语言的经验,所以我可能遗漏了一些东西。基本上,一个函数将以相反的顺序被评估,而值将从堆栈中以相反的顺序被拉出。为了证明这一点,我将比较后缀和前缀的样子。以下是一些使用传统后缀表示法的连接表达式。

5 dup *                             ! Multiply 5 by itself
3 2 -                               ! Subtract 2 from 3
(1, 2, 3, 4, 5) [2 >] filter length ! Get the number of integers from 1 to 5
                                    ! that are greater than 2

表达式从左到右求值:在第一个示例中,5 被压入堆栈,然后dup 复制堆栈顶部的值,然后* 将堆栈顶部的两个值相乘.函数首先从堆栈中提取最后一个参数:在第二个示例中,当调用 - 时,2 位于堆栈顶部,但它是最后一个参数。

这是我认为前缀符号的样子:

* dup 5
- 3 2
length filter (1, 2, 3, 4, 5) [< 2]

表达式从右到左计算,函数首先从堆栈中拉出它们的第一个参数。请注意前缀过滤器示例如何与其描述更接近,并且看起来与应用样式相似。我注意到的一个问题是考虑因素可能没有那么有用。例如,在后缀表示法中,您可以从3 2 - 中分解出2 - 来创建一个subtractTwo 函数。在前缀表示法中,您可以从- 3 2 中分解出- 3 来创建一个subtractFromThree 函数,这似乎没什么用。

除非有任何明显的问题,否则使用前缀表示法的连接语言可能会赢得不喜欢后缀表示法的人的青睐。任何见解都值得赞赏。

【问题讨论】:

  • 组合在后缀表示法中看起来更好,你按照数据流的顺序编写它。这感觉不自然和尴尬——既不适用也不连接。
  • 但是对于习惯于看到函数名后跟参数的人来说,这种风格不是更吸引人吗?过滤器示例看起来与其对应的 Haskell 非常相似,只是它不需要任何时髦的组合运算符或括号。谓词很尴尬,但也许有办法让它看起来更好。
  • 这是一个范式转换,总有一些事情你需要习惯。这与函数式与命令式相同——来自后者的人将习惯于变量是可变的并且动作总是按顺序发生,但这并不是改变函数式语言基本属性的论据。切换到连接后,后缀感觉很自然。
  • 存在混合语言。 F# 结合了函数式、过程式和面向对象的范例。如果数据以相反的方式流动是在连接语言中使用前缀表示法的唯一大问题,那么我认为这是让那些认为后缀成为破坏交易的人享受连接语言的其他好处的好方法。那么谁知道呢?也许有一天他们会意识到数据与函数调用一起流动更有意义。
  • 您写谓词 [&lt; 2] 最后而不是列表之前的任何具体原因?

标签: programming-languages postfix-notation factor-lang concatenative-language


【解决方案1】:

当然,如果你的话仍然是固定的,那么这只是从右到左执行标记的问题。

只是因为 n-arity 函数,前缀表示法意味着括号,而且只是因为希望人类的“阅读顺序”与执行顺序相匹配,作为堆栈语言意味着后缀。

【讨论】:

  • 感谢简单客观的回答。我也很好奇权衡是什么,但这更像是一个假设和主观的讨论。
  • 至于权衡:我相信对于固定数量的单词,就机器而言,前缀和后缀是完全等价的。您可以从字面上翻转事物或反向执行。人类可能会关心,这取决于他们是自上而下还是自下而上的人:) 例如,有些人喜欢看“如果 x 做 y”,而另一些人更喜欢“当 x 做 y”。我个人就像没有前向引用
  • ...甚至没有争论。所以后缀很好。但我认为这只是一个没有本质区别的偏好。也许机器和我都应该读“向后”:)
  • 我确实看到了你指出的非交换操作的问题,试图将 args 保持在中缀顺序。您的 3 2 - 将变为 - 2 3,但仍然意味着 3 - 2 以保持“连接”属性。尽管如此,在中缀中思考只是人类的惯例。在小学早期,孩子们在 2 上面写 3,左边是 -。如果他们后来没有在前缀中钻取中缀,也许他们会对前缀感到满意。另一个旁白:在他的 colorForth 中,Chuck Moore 实际上选择用 2 3 反转减法顺序 - 意思是 3 - 2。现在这只是 疯狂,但是嘿,为什么不呢? :)
  • 是的,或者另一种方法是保持固定数量但允许集合作为参数类型(使用分隔语法)。例如,Joy 使用方括号列表(和引号)和花括号集合来做到这一点,但没有参数分隔符。
【解决方案2】:

我现在正在编写这样一种语言,到目前为止,我喜欢使用前缀表示法的一些副作用。语义基于Joy:

  • 文件从左到右解析,但从右到左执行。
  • 通过扩展,定义必须它们的使用点之后。
  • 作为一个很好的副作用,cmets 只是被删除的列表。

下面是阶乘函数,例如:

def 'fact [cond [* fact - 1 dup] [1 drop] dup]

我还发现在编写代码时更容易推理代码,但我在级联语言方面没有很强的背景。这是我对列表的 map 函数的(可能是天真的)推导。 'nb' 函数会丢弃一些东西并用于 cmets。 'stash [f]' 弹出一个临时文件,在堆栈的其余部分运行 'f',然后将临时文件推回。

def 'map [q [cons map stash [head swap i] dup stash [tail dup]] [nb] is_cons nip]
nb [map [f] (cons x y) -> cons map [f] x f y
    stash [tail dup]    [f] (cons x y)       = [f] y (cons x y)
    dup                 [f] y (cons x y)     = [f] [f] y (cons x y)
    stash [head swap i] [f] [f] y (cons x y) = [f] x (f y)
    cons map            [f] x (f y)          = cons map [f] x f y

    map [f] [] -> []]

【讨论】:

    【解决方案3】:

    我刚读完Om Language

    似乎正是你在说什么。从它的描述(强调我的):

    Om 语言是:

    • 一种新颖的、最简单的连接、同形编程和算法符号语言,具有:
      • 最少的语法,仅包含三个元素。
      • 前缀表示法,其中函数操作程序本身的其余部分。 [...]

    它还表示它还没有完成,并且会经历很大的变化。

    不过,它似乎在工作,并且作为概念证明非常有趣。

    【讨论】:

      【解决方案4】:

      我想象一种没有堆栈的连接前缀语言。它可以调用函数,然后它们自己会解释代码,直到获得所有需要的操作数。然后解释器将调用下一个函数。它只需要一个内存结构——结果。其他所有内容都可以在执行时从源代码中读取。您可能已经注意到,我说的是解释型语言,而不是编译型语言。

      【讨论】:

      • 有趣的想法。您将如何处理多个中间结果?就像在前缀表达式- + 1 1 + 3 3 中一样,您将如何跟踪+ 1 1+ 3 3 的结果?
      • 我不知道。查看 XY,一种使用队列而不是堆栈的连接语言。还有一些其他语言可以参考。
      猜你喜欢
      • 1970-01-01
      • 2015-02-13
      • 2012-11-07
      • 2020-07-17
      • 2017-03-02
      • 2020-07-20
      • 2021-05-03
      • 2011-01-03
      • 1970-01-01
      相关资源
      最近更新 更多