是否可以在Scheme中"扩展"函数/ lambda /宏?

Fel*_*ipe 5 inheritance scheme r6rs r5rs r7rs

例如:如果我希望函数equal?识别我自己的类型或记录,我可以添加新的行为equal?吗?没有删除或覆盖旧的?

或者,例如,如果我想使函数"+"接受也字符串?

Lil*_*ung 4

更好的解决方案是通过绑定import来跟踪原始函数,而不是使用。let最好检查参数的类型是否为字符串,而不是数字。使用这两种方法意味着可以组合该技术。

(define +
  (let ((old+ +))
    (lambda args
      (if (string? (car args))
          (apply string-append args)
          (apply old+ args)))))

(define +
  (let ((old+ +))
    (lambda args
      (if (vector? (car args))
          (apply vector-append args)
          (apply old+ args)))))
Run Code Online (Sandbox Code Playgroud)

上面将生成一个+适用于数字、字符串或向量的函数。一般来说,这是一种更具可扩展性的方法。


我能够验证上述内容在 MIT/GNU Scheme、Guile、Racket、Chicken、TinyScheme 和 SCSH 中是否正常工作。然而,在某些实现中,例如Biwa方案,有必要使用set!而不是define. 在 Ikarus 中,set!不能在导入的基元上使用,并且define会弄乱环境,因此需要分两步执行此操作:

(define new+
  (let ((old+ +))
    (lambda args
      (if (string? (car args))
          (apply string-append args)
          (apply old+ args)))))
(define + new+)
Run Code Online (Sandbox Code Playgroud)

请注意,根据R5RSdefineset!在这种情况下应该是等效的:

在程序的顶层,有一个定义

(define <variable> <expression>)
Run Code Online (Sandbox Code Playgroud)

与赋值表达式本质上具有相同的效果

(set! <variable> <expression>)
Run Code Online (Sandbox Code Playgroud)

如果<variable>是绑定的。