我有点异国情调。我需要比较函数,而不是它们的“起源”而不是“实例”。这就是我的意思:
(define-values (a b c d) (values #f #f #f #f))
(define (f x)
(let ([g (λ (y) (printf "Please tell ~a this is ~a\n" x y))]
[h (curry printf "Don't tell ~a this is ~a\n" x)])
(if a
(set! b g)
(set! a g))
(if c
(set! d h)
(set! c h))))
(f "me")
(f " me")
(a "possible")
(d "impossible")
(equal? a b) ; <==== Is it possible to compare these guys
(equal? c d) ; <==== to get #t in both cases?
在这两种情况下,我们得到两个不同的“实例”函数(即使捕获了不同的值),但两者都在源代码的相同位置声明。当然,获取这些函数正文的实际文本将解决问题,但是这里的其他答案告诉我在Racket中这是不可能的。是否有一些技巧可以帮助我?
修改: 这不是关于函数理论等价的问题。这完全是技术问题,而非Racket在编译代码中的函数表示。因此,它可以重新制定,例如,以下列方式:我可以从“用户”代码中获取某些例程的行号吗?我认为这应该是可行的,因为Racket调试器以某种方式获得它。
答案 0 :(得分:1)
如果你控制了制作这些功能的代码,即使没有球拍内部的支持也可以完成。如果你保留一个表示特定lambda的计数器(或某个标识符),它可以在一个结构中包含不同的闭包,这个结构可以从宏扩展中具有相同的标识。这是一个演示:
#lang racket
;; makes a procedure object that can have other data connected to it
(struct proc (id obj)
#:property prop:procedure
(struct-field-index obj)
#:methods gen:custom-write
[(define (write-proc x port mode)
(display (format "#<procedure-id-~a>" (proc-id x)) port))])
;; compares the ids of two proc objects if they are proc objects
(define (proc-equal? a b)
(and (proc? a)
(proc? b)
(= (proc-id a) (proc-id b))))
;; extends equal?, candidate to provide
(define (equal*? a b)
(or (proc-equal? a b)
(equal? a b)))
;; the state we keep
(begin-for-syntax
(define unique-proc-id-per-code 0))
;; a macro that changes (lambda* ...) to
;; (proc expansion-id (lambda ...))
(define-syntax (lambda* stx)
(let ((proc-id unique-proc-id-per-code))
(set! unique-proc-id-per-code (add1 unique-proc-id-per-code))
#`(proc #,(datum->syntax stx proc-id) (lambda #,@(datum->syntax stx (cdr (syntax-e stx)))))))
;; test with making a counter
(define counter-from
(lambda* (from)
(lambda* ()
(begin0
from
(set! from (add1 from))))))
;; evaluatin the outer shows it has id 0
counter-from ; ==> #<procedure-id-0>
;; make two counters that both use the inner lambda
(define from10 (counter-from 10))
(define from20 (counter-from 20))
;; both have the same expansion id
from10 ; ==> #<procedure-id-1>
from20 ; ==> #<procedure-id-1>
;; they are not equal?
(equal? from10 from20) ; ==> #f (different object instances of proc)
;; but they are procedure-equal?
(proc-equal? from10 from20) ; ==> #t (same id, thus came from same macroexpansion)
免责声明:我更像是一个策划者,而不是一个敲诈者,所以这或许可以更优雅地完成,我不知道这将给予什么样的惩罚。