如何在 Racket 中将符号转换为数字?

How to convert a symbol into a number in Racket?

我正在尝试将“红色”变成 2,“白色”变成 9,“棕色”变成 1,等等。

我的代码是这样开始的:(define (sum-of-colours colour1 colour2 colour3 ...)

我希望用户将“红色”、“黄色”或“黑色”等符号输入颜色 1、颜色 2 等...,然后将所有相应的值相加。根据我目前的知识,我想不出一种方法可以直接将符号转换为数字。有人可以提示我该怎么做吗?非常感谢!

经典的 lispy 方法是使用 关联列表 将颜色符号与数字关联起来。关联列表是一种字典,它本身就是要关联的对列表。例如:

(define my-colors '((red 2)
                    (white 9)
                    (brown 1)))

现在可以使用 assoc 函数得到正确的一对:

scratch.rkt> (assoc 'red my-colors)
'(red 2)

可以通过在此结果上使用 second 来检索数字本身;但最好编写一个访问器函数,这样可以在不破坏使用颜色字典的代码的情况下更改字典的实现细节。此外,直接在 assoc 的结果上使用 second 可能会失败,因为字典中可能不存在输入的颜色符号。此定义returns #f 当找不到颜色符号时:

(define (get-color c)
  (let ((entry (assoc c my-colors)))
    (if entry
        (second entry)
        #f)))

在 Racket 中,你也可以为此使用散列 table(其他 lisps 也有散列 table):

(define my-color-table (hash 'red 2
                             'white 9
                             'brown 1))

现在,如果您重新定义 get-color 以使用新的字典表示,只要新定义保留接口,使用 get-color 的其他代码将继续工作:

(define (get-color c)
  (hash-ref my-color-table c #f))

hash-ref函数允许指定失败结果;这里当找不到密钥时,像以前一样返回 #f。这在 sum-colors 函数中可能很有用:

(define (sum-colors cs)
  (apply + (remove* '(#f)
                    (map get-color cs))))

注意 sum-colors 不关心颜色字典是如何实现的,只有 get-color 知道如何从颜色符号中检索颜色编号。这里,map 用于将输入的颜色符号列表映射到颜色编号列表。当未找到颜色符号时,该符号将映射到颜色编号列表中的 #fremove* 用于在使用 apply 对列表求和之前删除 #f 的所有实例。当然还有其他的写法,除了忽略输入中的未知颜色符号之外,您可能还需要一些其他的行为。

示例 REPL 交互:

scratch.rkt> (sum-colors '(red brown))
3
scratch.rkt> (sum-colors '(red white purple green))
11