代码之家  ›  专栏  ›  技术社区  ›  user141335

编译后的语言可以是同形的吗?

  •  27
  • user141335  · 技术社区  · 15 年前

    根据定义这个词 同音的 手段:

    代码和数据的相同表示

    在Lisp中,这意味着可以有一个引用列表并对其进行评估,所以 (car list) 将是功能和 (cdr list) 争论。这可以在编译时发生,也可以在运行时发生,但是它需要一个解释器。

    没有编译时解释器的编译语言也可能是同形的吗?或者同音异象的概念只限于口译员?

    10 回复  |  直到 12 年前
        1
  •  35
  •   Rainer Joswig mmmmmm    15 年前

    “同形”是一种模糊的结构。“代码就是数据”更清晰。

    不管怎样,维基百科上关于“同形”的第一句话并没有那么糟糕。它说 该语言必须具有使用其数据结构的源表示形式。 . 如果我们忘记了“字符串”作为源代码表示(这很简单,对于有一个有用的概念“同形性”也没什么帮助),那么Lisp就有了用于表示源代码的列表、符号、数字、字符串等。eval函数的接口决定了语言正在处理的源代码表示的类型。在这种情况下,lisp,它不是字符串。eval期望通常的各种数据结构和lisp的计算规则决定字符串对自身的计算(因此不会被解释为程序表达式,而只是字符串数据)。一个数字也对其自身进行计算。列表(sin 3.0)是一个符号和数字的列表。评估规则说,这个带有表示函数为第一个对象的符号的列表将作为函数应用程序进行评估。对于数据、特殊运算符、宏应用程序和函数应用程序,有一些类似的评估规则。就是这样。

    清楚地说: 在Lisp中,函数eval是在Lisp数据结构上定义的。 . 它期望一个数据结构,根据它的评估规则对其进行评估,然后再次使用它的数据结构返回结果。

    这与同形性的定义相匹配:源代码使用lisp的数据类型具有本机表示。

    有趣的是: 如何实施评估并不重要 .重要的是它使用lisp数据结构接受源代码,执行代码并返回结果。

    所以 Eval使用编译器是完全合法的 .

    (EVAL code)  =  (run (compile-expression code))
    

    这就是几个Lisp系统的工作原理,有些甚至没有解释器。

    所以,“同形”表示源代码有一个数据表示。它并没有说在运行时必须解释这个源代码,或者执行是基于这个源代码的。

    如果编译了代码,运行时既不需要编译器,也不需要解释器。 . 只有当程序希望在运行时对代码进行评估或编译时才需要这些代码——这通常是不需要的。

    lisp还提供了一个基本函数 将数据的外部表示(s-expressions)转换为数据的内部表示(lisp data)。因此,它还可以用于将源代码的外部表示转换为源代码的内部表示。Lisp不为源代码使用特殊的解析器-因为代码是数据,所以只有读取。

        2
  •  8
  •   dsm    15 年前

    对。Lisp可以编译为本机二进制文件

        3
  •  3
  •   Aiden Bell    15 年前

    在我看来这是个奇怪的问题:

    首先,同形部分是提供给程序员的接口。语言的要点是,它们抽象了一个较低级别的功能,该功能保留了与较高级别表示相同的语义(尽管方法不同)。

    DSM的机器代码点是一个很好的点,但是提供:

    1. 所呈现的语法和语义是同形的
    2. 转换为较低级别的形式(机器代码、解释或其他形式)不会删除任何原始语义。

    为什么较低级别的实现在这里很重要?

    也:

    没有编译时解释器的编译语言

    如果没有某些程序解释它,它将被要求是CPU的本机语言,因此CPU的本机语言将被要求是同形的(或运行代码的虚拟机)。

    没有编译时解释的语言…会受到相当的约束…因为他们不会 完全被编译 .

    但我不是专家,可能会错过要点。

        4
  •  2
  •   BCS    15 年前

    在大多数文字形式中,C是同形的。您可以使用 &functionName 并使用 somePtrCastToFnPtr(SomeArgs) .但是,这是在机器代码级别,如果没有某种库支持,您将发现很难使用它。某种可嵌入的编译器(我似乎记得llvm可以做到这一点)会使它更加实用。

        5
  •  2
  •   David Thornley    15 年前

    通常编译lisp。已经有了使用JIT编译器而不是解释程序的实现。

    因此,对于代码是数据语言,没有必要有一个解释程序(在“不是编译器”的意义上)。

        6
  •  2
  •   fortran    15 年前

    机器代码本身是同形的,所以是的。

    数据或指令只是一个语义问题(也许 他们的记忆)。

        7
  •  1
  •   T.E.D.    15 年前

    问题是,许多处理器将指令和数据区分开,并主动阻止程序修改自己的代码。这种代码以前被称为“退化代码”,被认为是非常糟糕的事情。

    解释器(和vms)没有这个问题,因为它们可以把整个程序当作数据来处理,只有“代码”是解释器。

        8
  •  1
  •   Norman Ramsey    15 年前

    是的;您只需将编译器的副本粘贴到语言运行时中即可。 Chez Scheme 是众多优秀的编译器之一。

        9
  •  1
  •   Kaz    12 年前

    编译只是优化解释。解释器获取一段表示代码的数据,然后“执行”该代码:代码的含义转化为执行路径,数据通过解释器的内部流动。编译器获取相同的数据,将其转换成另一种形式,然后将其传递给另一个解释器:一个在硅(CPU)中实现的解释器,或者一个伪造的解释器(虚拟机)。

    这就是为什么一些Lisp实现不能有Intelpreter的原因。eval函数可以编译代码,然后分支到它。eval和compile不必具有不同的操作模式。(clozure、corman lisp、sbcl是“仅编译器”lisp的示例。)

    开头的数据部分是语言具有同形性的关键,而不是通过编译优化代码的执行。”代码就是数据“意味着” 来源 代码是数据“不是”可执行代码是数据。(当然,可执行代码是数据,但通过数据,我们指的是我们想要操纵的代码的绝大多数首选表示。)

        10
  •  0
  •   Ray    15 年前

    建立在虚拟机(.net clr,jre etc)之上的语言可以使用高级技术,允许动态代码生成。其中之一就是伊勒·韦文。尽管它不如ecmascript/lisp/scheme等的eval那么清楚,但它在某种程度上可以模仿这种行为。

    例如,检查castle dynamicproxy,并查看linqpad、f interactive、scala interactive,了解更多交互示例。