1

例如,我能否实现一个规则,将遵循模式 '1..4' 的每个字符串更改为数组 [1,2,3,4]?在 JavaScript 中:

//here you create a rule that changes every string that matches /$([0-9]+)_([0-9]+)*/
//ever created into range($1,$2) (imagine a b are the results of the regexp)
var a = '1..4';
console.log(a);
>> output: [1,2,3,4];

当然,我很有信心这在大多数语言中是不可能的。我的问题是:是否有任何语言可以做到这一点?或者有没有人提出过类似的建议?这个东西有一个“名字”,我可以用谷歌搜索更多信息吗?

4

4 回答 4

3

是的。Common Lisp(和某些其他 lisp)具有“阅读器宏”,允许用户重新编程(增量)输入流和实际语言结构之间的映射。

http://dorophone.blogspot.com/2008/03/common-lisp-reader-macros-simple.html

如果您想在对象级别上进行操作,您将需要使用一个调试/内存管理框架来跟踪所有对象,并在每个评估步骤上处理规则(讨厌)。这似乎是您可以硬塞进smalltalk的那种东西。

于 2012-09-04T20:15:54.007 回答
3

CLOS(通用 Lisp 对象系统)允许重新定义活动对象。

最终,您需要两件事来实现这一点:

  1. 访问正在运行的系统的AST(抽象语法树),以及
  2. 访问正在运行的系统的对象。

您将要研究元对象协议和使用它们的语言,然后是 MOP 的实现和执行这些程序的环境。

基于图像的系统将是最容易修改的(例如,Lisp,可能是 Smalltalk)。

基于映像的系统存储正在运行的系统的快照,允许完全关闭和重新启动、重新定义整个环境,包括现有对象及其定义等。)

于 2012-09-04T20:48:07.550 回答
3

修改语言本身属于反射和元编程的范畴。它被称为行为反射。它不同于在应用程序级别(例如类、方法)而不是在语言级别运行的结构反射。对行为反思的支持因语言而异。

我们可以将语言变化大致分为两类:

  1. 修改语言本身的语义(即规则)的更改(例如重新定义方法查找算法),
  2. 修改语法的更改(例如,您的语法“1..4”来创建数组)。

对于案例 1,某些语言通过称为元对象的特殊对象将应用程序的结构(结构反射)及其实现的内部工作(行为反射)暴露给应用程序本身。元对象是其他隐含方面的具体化,然后变得可显式操作:应用程序可以修改元对象以重新定义其结构的一部分或语言的一部分当涉及到语言更改时,重点通常是修改消息发送/方法调用,因为它是面向对象语言的核心机制。但同样的想法也可以应用于暴露语言的其他方面,例如字段访问、同步原语、foreach 枚举等,具体取决于语言。

对于情况 2,程序必须以合适的数据结构表示,以进行修改。对于 lisp 系列的语言,程序操作列表,程序本身可以表示为列表。这被称为同音性,对于元编程很方便,因此类 lisp 语言的灵活性。对于其他语言,它们的表示通常是 AST。在编译或类加载期间,可以使用宏、预处理器或挂钩来转换或重写程序的表示。

然而,1 和 2 之间的界限是模糊的。句法变化可能会修改语言的语义。例如,我可以使用适当的 getter 和 setter 重写所有字段访问,并在那里执行额外的逻辑,比如实现事务内存。我是对什么是字段访问进行了语义更改,还是仅仅更改了语法?此外,还有其他的构造落在线条之下。例如,代理和#doesNotUnderstand陷阱是在一定程度上模拟消息发送的具体化的流行技术。

Lisp 和 Smalltalk 在元编程领域非常有影响力,我认为以下两个项目/平台对于每个项目/平台的代表都很有趣:

  • Racket,一种类似 lisp 的语言,专注于从语言中发展语言
  • Helvetia,一个 Smalltalk 扩展,通过利用宿主环境的 AST 将新语言嵌入宿主语言。

我希望你喜欢这个,即使我没有真正解决你的问题;)

您所需的更改需要修改创建文字的方式。这是 AFAIK 通常不暴露给应用程序。我能想到的封闭工作是Virtual Values for Language Extension,它处理了 Javascript。

于 2012-09-06T07:38:13.480 回答
0

Ruby 允许您扩展类。例如,此示例将功能添加到 String 类。但是您可以做的不仅仅是向类添加方法。您也可以覆盖方法,但定义一个已经定义的方法。您可能希望使用alias_method保留对原始方法的访问。

将所有这些放在一起,您可以在 Ruby 中重载构造函数,但在您的情况下,有一个问题:听起来您希望构造函数返回不同的类型。根据定义,构造函数返回其类的实例。如果你只是想让它返回字符串“[1,2,3,4]”,那很简单:

class string
  alias_method :initialize :old_constructor
  def initialize
    old_constructor
    # code that applies your transformation
  end
end

但是如果这是你想要的,没有办法让它返回一个数组。

于 2012-09-04T20:19:08.460 回答