首先,为了测试,我们将定义一个readword
从列表中返回连续单词的过程。(在这种情况下,它只是一个数字列表,但这并不重要。)您已经拥有其中一个,但我们需要一个来使其余代码工作。这使用了一个赋值 ( set!
),但这不是您真正需要编写的代码;这只是为了使这个答案的其余部分起作用。
(define words (list 1 2 3 4 5 6))
(define (readword)
(cond
((null? words) words)
(else (let ((word (car words)))
(set! words (cdr words))
word))))
> (readword)
1
> (readword)
2
现在我们可以定义创建、使用 填充readword
并返回哈希表的主函数。 insert-words
有一个内部辅助函数,假设已经读取了两个单词,因此它只需要读取下一个单词。当没有更多单词要读取时,我们的readword
函数返回,所以我们的辅助函数在返回时停止并简单地返回。否则,返回一个单词,我们可以使用as 在哈希表中添加一个条目。之后,我们再次调用辅助函数,但使用and作为前两个单词,需要第三个单词。()
readword
()
ngrams
readword
hash-set!
(hash-set! ngrams (list w1 w2) w3)
w2
w3
(define (insert-words)
(define (insert-helper ngrams w1 w2)
(let ((w3 (readword)))
(cond
((null? w3) ngrams)
(else
(hash-set! ngrams (list w1 w2) w3)
(insert-helper ngrams w2 w3)))))
(insert-helper (make-hash) (readword) (readword)))
> (insert-words)
'#hash(((1 2) . 3) ((3 4) . 5) ((4 5) . 6) ((2 3) . 4))
这种带有执行迭代的辅助函数的模式非常常见,以至于 Scheme 和 Racket 都支持一种名为 let的东西。使用命名的 let,如下所示。我使用了 name loop
,因为这本质上是一个循环,但特定的名称并不重要。
(define (insert-words)
(let loop ((ngrams (make-hash))
(w1 (readword))
(w2 (readword)))
(let ((w3 (readword)))
(cond
((null? w3) ngrams)
(else
(hash-set! ngrams (list w1 w2) w3)
(loop ngrams w2 w3))))))