Lisp的问题,并构造出令人生厌的东西 [英] problems with lisp and do construct with itterating

查看:47
本文介绍了Lisp的问题,并构造出令人生厌的东西的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,我遇到了这个问题.我生成的代码不是遍历每个单词,而是遍历整个传递的参数.我正在使用do循环将信息传递到哈希表中.

Firstly, I am having this problem. The code I generated isn't iterating thru each word, but instead thru the entire passed argument. I am using a do loop to pass information into a hash table.

(defun set_isa (partOfSpeech &rest words)

(do ((wordVar words))
((null wordVar) nil) 

(putp partOfSpeech word-dict wordVar)
(setf wordVar (cdr wordVar))))

通过使用跟踪,我得到了这个结果

With this I am getting this as a result using trace

(set_isa 'Verb 'Talk 'Run 'jump )

1. Trace: (SET_ISA 'VERB 'TALK 'RUN 'JUMP)
1. Trace: SET_ISA ==> NIL
NIL

当我调用哈希表时,它只会添加最后一个传递的参数

And when I call the hashtable, it only adds the last passed argument

#S(HASH-TABLE :TEST FASTHASH-EQL (VERB . (JUMP)))

推荐答案

因此,了解此处发生情况的方法是对您的代码进行注释,以便它告诉您它在做什么.这似乎是一种古老的调试方法,但是在像CL这样的动态对话语言中,这是一种非常好的方法.这是函数的一个版本,它使用更常规的名称表示事物,还使用常规的indetration以及用于缺少代码的存根以使其全部可运行.

So, the way to understand what is going on here is to annotate your code so it tells you what it's doing. This may seem an antique way of debugging, but in a dynamic, conversational language like CL it's a really good approach. Here is a version of your function using more conventional names for things, and also using conventional indetnation, together with stubs for your missing code to make it all runnable.

(defvar *word-dict* nil)

(defun set-isa (part-of-speech &rest words)
  (do ((wtail words))
      ((null wtail) nil) 
    (putp part-of-speech *word-dict* wtail)
    (setf wtail (cdr wtail))))

(defun putp (part-of-speech dict thing)
  (format *debug-io* "~&putp: ~A ~A ~A~%" part-of-speech dict thing))

因此这现在是可运行的,并且 putp 将打印得到的内容作为参数.

So this is now runnable, and putp will print what it gets as arguments.

 > (set-isa 'verb 'talk 'run 'jump )
putp: verb nil (talk run jump)
putp: verb nil (run jump)
putp: verb nil (jump)
nil

因此,即使没有这里实际上是错误的代码(几乎可以肯定是 putp ),您也可以找出问题所在: putp replaces 任何值及其参数存储在哈希表中.因此,最终出现在表中的唯一值是最后一个.因此,我们需要修复此问题,稍后再做.

So even without having the code which is actually buggy here, which is almost certainly putp, you can work out what the problem is: putp replaces whatever value is stored in the hash table with its argument. So the only value that ends up in the table is the last one. So we need to fix that, which I'll do later.

但是实际上这不是唯一的问题.

But in fact that's not the only problem.

首先,您以一种非常奇怪的方式使用 do . do 的语法明确允许初始化和stepping 形式,因此您实际上应该使用stepping形式,而不是在正文中使用它.

First of all you're using do in a very odd way. The syntax of do explicitly allows initialisation and stepping forms, so you should actually use the stepping form rather than doing it in the body.

(defun set-isa (part-of-speech &rest words)
  (do ((wtail words (rest wtail)))
      ((null wtail) nil) 
    (putp part-of-speech *word-dict* wtail)))

其次,您要在列表的所有尾部上调用 putp :您可能只想在单个单词上调用它.您可以通过简单地将其传递给每条尾巴的汽车来做到这一点,但是正如Martin Buchmann在另一个答案中指出的那样,您可能会寻找一种在列表元素上进行迭代的语言构造.其中有很多,并且 dolist 是其中之一:

Secondly you're calling putp on all the tails of your list: you probably want to be calling it on just the individual words. You could do this by simply passing it the car of each tail, but as Martin Buchmann points out in the other answer you might instead look for a construct in the language which iterates over the elements of a list. And there are plenty of these, and dolist is one of them:

(defun set-isa (part-of-speech &rest words)
  (dolist (word words)
    (putp part-of-speech *word-dict* word)))

现在

(set-isa 'verb 'talk 'run 'jump )
putp: verb nil talk
putp: verb nil run
putp: verb nil jump
nil

请注意,调用 putp 的方式与以前的版本不兼容:现在是按单词而不是列表的尾部调用.

Note the way putp is called is not compatible with the previous version: it's now called on the words, not the tails of the list.

最后,让我们编写一个有效的 putp 版本.我将首先编写一个非常幼稚的版本:

So finally, let's write a version of putp that works. I'll first write a very naive version:

(defvar *word-dict* (make-hash-table))

(defun putp (part-of-speech dict thing)
  (let ((entries (gethash part-of-speech dict '())))
    (setf (gethash part-of-speech dict) (cons thing entries))))

这有效,但不是很好:

> (gethash 'verb *word-dict* '())
nil
nil

> (set-isa 'verb 'talk 'run 'jump )
nil

> (gethash 'verb *word-dict* '())
(jump run talk)
t

> (set-isa 'verb 'talk 'run 'jump )
nil

> (gethash 'verb *word-dict* '())
(jump run talk jump run talk)
t

这样就可以了,只要您只运行一次即可.好吧,我们可以做得更好:

So that's OK, so long as you only run it once. Well, we can do better than this:

  • 我们可以使用一种更惯用的方式将新事物推送到哈希表中存储的列表中;
  • 我们可以避免重复输入的事情,同时也更加惯用.

像这样:

(defun putp (part-of-speech dict thing)
  (pushnew thing (gethash part-of-speech dict)))

所以,现在:

 > (gethash 'verb *word-dict* '())
nil
nil

> (set-isa 'verb 'talk 'run 'jump )
nil

> (gethash 'verb *word-dict* '())
(jump run talk)
t

> (set-isa 'verb 'talk 'run 'jump )
nil

> (gethash 'verb *word-dict* '())
(jump run talk)

这好得多.您可以查找 push pushnew 来查看它们的作用.

This is much better. You can look up push, and pushnew to see what they do.

这篇关于Lisp的问题,并构造出令人生厌的东西的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆