球拍:在hasheq错误中找不到键值

时间:2012-11-03 10:10:34

标签: hashtable racket

作为用Racket编写的servlet的一部分,我想创建一个函数,将请求绑定(以hasheq-table的形式,字符串作为键和值)转换为SQL表行(再次写为hasheq-表,字符串作为键,sql类型作为值)。这一切似乎按预期工作,直到有问题的函数收到两个哈希表,此时它失败并出现以下错误:

请求绑定是:

'#hasheq(("lastname" . "Smith")
         ("firstname" . "John")
          ("birthdate" . "1900-10-25"))

列类型是

'#hasheq(("lastname" . "character varying")
         ("firstname" . "character varying")
         ("birthdate" . "date"))

错误消息是:

Servlet (@ /<... servlet URL ...>) exception:
hash-ref: no value found for key
  key: "lastname"

奇怪的是,如果将这些哈希表与相关代码片段一起粘贴到DrRacket提示符,它就会运行而不会产生错误

The value "Smith" needs to be converted to type "character varying"
The value "John" needs to be converted to type "character varying"
The value "1900-10-25" needs to be converted to type "date"

我做错了什么?任何帮助是极大的赞赏!这是代码:

#lang racket

(define bindings-hash
  '#hasheq(("lastname" . "Smith")
           ("firstname" . "John")
           ("birthdate" . "1900-10-25")))

(define types-hash
  '#hasheq(("lastname" . "character varying")
           ("firstname" . "character varying")
           ("birthdate" . "date")))

(define (test)
  (eprintf "The request bindings are \n~v\n" bindings-hash)
  (eprintf "The column types are \n~v\n" types-hash)
  (for ([(this-key this-value) (in-hash bindings-hash)])
    (eprintf "The value ~v needs to be converted to type ~v\n"
             this-value
         (hash-ref types-hash this-key))))

(test)

3 个答案:

答案 0 :(得分:4)

使用字符串时使用hash-equal。符号保证与eq?一起使用,但必须将字符串与equal?进行比较。

问题是(eq? "foo" "foo")的结果未定义。

答案 1 :(得分:3)

这是一个实际的答案 - 问题的另一部分:为什么它将代码粘贴到DrRacket中的REPL?

字符串文字"lastname"的多次使用被“拦截”为内存中的相同Racket对象。因此,它们是eq?

(eq? "lastname" "lastname")
=> #t

但是在真正的servlet程序中,哈希中的字符串值来自内存中的两个不同的Racket对象,即使它们碰巧具有相同的值。例如,让我们通过"lastname"构造一个值为(string-append "last" "name")的字符串。如果我们将那个与字符串文字"lastname"进行比较,那么他们 eq?

(eq? "lastname" (string-append "last" "name"))
=> #f

它们在内存中不是同一个对象,所以它们不是 eq?。两个不同的对象具有相同的值,因此它们 equal?

答案 2 :(得分:2)

[这只是对@soegaard发布的优秀答案的评论。我将它作为“答案”发布,只是为了获得合适的多行代码格式。]

要制作使用equal?比较密钥的哈希,您可以使用

#hash([key0 . value0]
      [key1 . value1])

你也可以通过说

来创建完全相同的东西
(hash key0 value0
      key1 value1)

如果你将它分割成线条,对的分组就一样清晰,但没有额外的括号和圆点。

第一种方式更传统,看起来像一个经典的关联列表。我发现自己更喜欢第二种风格。