作为用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)
答案 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)
如果你将它分割成线条,对的分组就一样清晰,但没有额外的括号和圆点。
第一种方式更传统,看起来像一个经典的关联列表。我发现自己更喜欢第二种风格。