例如,如果我想将加法重新定义为乘法:
(define + *)
但也将乘法重新定义为加法而不丢失加法的绑定,我该怎么做?
您可以使用允许您重新定义标准过程的 require 机制。通过这种方式,这些重新定义在 Racket(R5RS 实现)中是可能的。您可以要求标准 + 具有不同的名称(标准 +):
#lang racket
(require
(rename-in racket/base (+ standard+))
)
因此,您可以根据自己的目的将 + 重新定义为新的
(define +
(lambda args
(if (not(null? args))
(apply
(cond
(??? *)
(else standard+))
args)
0)))
在哪里 ???是使用 * 而不是 + 的布尔条件(或只是返回布尔值的函数)。
通过导入,您可以在 Scheme 中切换顶级符号,它需要 R6RS 或更高版本。
#!r6rs
(import (except (rnrs base) + *)
(rename (rnrs base) (* +) (+ *)))
(+ (* 2 3) 4) ; ==> 20
如果您不想使用相同的符号创建自己的语言并且需要通过某种方法访问原始实现符号,您也可以为 import 添加前缀:
#!r6rs
(import (prefix (rnrs base) base:))
(base:define * base:+)
(base:define + base:*)
(+ (* 2 3) 4) ; ==> 20
这个答案类似于 Modestino 的答案,除了他们的答案是针对球拍语言而不是方案语言。
由于这不适用于 R5RS,您可能需要查看Valentin 的回答,因为它是一个很好的解决方法。只要记住让 let 包装整个代码,它将作为 R6RS 重命名的导入工作。
您还可以使用简单let
的方法来绑定之前定义的内容,而不管其他let
定义如何。在 Gambit 方案中:
> (* (+ 2 4) 2) ;; = 2 * (2 + 4)
12
> (let ((confusing #t)(+ *)(* +)) ;; Redefining operations
(* (+ 2 4) 2)) ;; = 2 + (2 * 4)
10