你如何在Racket中创造一个价值,以至于没有其他代码可以为那个创造价值equal?
?
我想要这个的原因是在各种其他数据结构中表示占位符。例如,假设我们有一些键值属性集合,如下所示:
'((name . breakfast) (successor . lunch) (predecessor . placeholder))
(define (placeholder? x) (eq? x 'placeholder))
意图是表示breakfast
的前身目前未知,因此,暂时我们在该位置放置一个占位符。我们稍后会用一个真正的前任填写它。以上不太正确,因为没有办法说breakfast
的前身真的是符号'placeholder
。 (同样地,为了表示像“没有一个”这样的特殊事物。)这样的事情可以解决这个问题:
(define placeholder (make-unique-value)
(define (placeholder? x) (eq? x placeholder))
`((name . breakfast) (successor . lunch) (predecessor . ,placeholder))
由于placeholder
是一个特殊的值,你不能无意中通过制作符号'placeholder
来制作另一个。如果独特的placeholder
值不是equal?
,那将是很好的;这样,它也可以作为哈希表中的键 - 或任何地方。关键是你不应该担心“陷阱”。
如果制作一个像#t
或#f
这样的独特价值不是在Racket中这样做的话,我会接受一个表明Rackety方法的答案。
在Racket中执行此操作的最佳方法是创建本地的不透明结构并创建该结构类型的单个实例。由于结构是生成的(即,每个struct
形式的评估产生完全独特的结构类型),该值保证是唯一的。
执行此操作的代码通常如下所示:
(define placeholder
(let ()
(struct placeholder ())
(placeholder)))
这会在placeholder
中创建一个独特的不透明值:
> placeholder
#<placeholder>
> (equal? placeholder placeholder)
#t
> (equal? placeholder #t)
#f
通过使用gensym
,您可以创建一个独特价值的系统。
例如:
#lang racket
(define placeholder-unique-prefix "#$#@")
(define (new-placeholder)
(gensym placeholder-unique-prefix))
(define (placeholder? x)
(and (symbol? x)
(string-prefix? (symbol->string x) placeholder-unique-prefix)))
(define placeholder1 (new-placeholder))
(define placeholder2 (new-placeholder))
(define cons1 (cons 'a placeholder1))
(define cons2 (cons 'b placeholder2))
(eq? (cdr cons1) placeholder1) => #t
(eq? (cdr cons2) placeholder1) => #f
(placeholder? (cdr cons1)) => #t
(placeholder? (cdr cons2)) => #t
我想到了一种方法。这可能是可行的,但它困扰我。
(struct unique [])
(define placeholder (unique))
(define (placeholder? x) (eq? x placeholder))
(define not-applicable (unique))
(define (not-applicable? x) (eq? x not-applicable))
(equal? placeholder not-applicable) ; => #f
困扰我的是它的工作方式非常微妙。它的工作原理是利用结构定义缺少#:transparent
这一事实。如果你使unique
透明,那么每个unique
都是equal?
给所有其他人,这意味着他们并不是真正独特的:
(struct unique [] #:transparent)
(define placeholder (unique))
(define not-applicable (unique))
(equal? placeholder not-applicable) ; => #t
如果可能的话,我希望代码的含义和有效性在检查时是显而易见的。