为什么这些都打印相同的东西?

Flo*_*ofk 1 lisp clisp common-lisp

我真的好奇为什么使用"删除"实际上并没有从列表中删除,如果我在一个变量中声明它,但是我有另一个变量可以使用它并且它变得非常混乱,他是我的代码;

    ;;;;Pig latin
(defun pig-latin ()
    (let ((word (read-line)))
        (setf ind-characters (loop for char across word
            collect char))    
        (setf first-char (car ind-characters))
        (setf reversed-word (reverse ind-characters));flips the 
        (remove (last reversed-word) reversed-word)
        (print reversed-word)))
Run Code Online (Sandbox Code Playgroud)

我得到的输出是:

(#\d #\r #\o #\w)
(#\d #\r #\o #\w)
Run Code Online (Sandbox Code Playgroud)

我原本期望#\ w从输出的第二部分中删除,但除非我在变量中声明它,否则它不会.如何处理单个数据并删除/添加我需要的内容而不声明很多变量?

Jos*_*lor 7

(我以为之前会问过这个问题,Stack Overflow肯定有相关的东西,但我找不到合适的副本.)

问题是删除返回一个新列表; 它不会修改现有列表.HyperSpec条目中的相关部分用于删除(强调添加):

remove,remove-if,remove-if-not返回与具有相同元素的序列相同类型的序列,除了已经删除了由start和end限定并满足测试的子序列中的那些序列.这是一种非破坏性的操作.如果需要删除任何元素,结果将是一个副本.删除的结果可以与序列共享; 如果不需要删除元素,则结果可能与输入序列相同.

这意味着您需要使用remove返回的值.例如,您可以将其返回,将其绑定到变量,或将其分配给变量:

(defun remove-1 (list)
  (remove 1 list))  ; return the result

(let ((list-without-ones (remove 1 list)))  ; bind the result
  ...)

(setf list (remove 1 list)) ; update a variable
Run Code Online (Sandbox Code Playgroud)

请注意,该语言还包括删除功能,该功能可能具有破坏性.但请注意,这并不能消除保存结果的需要.这意味着可以修改列表结构.但是,您仍然需要保存结果,因为旧列表中第一个的cons单元可能不是新列表中第一个的cons单元.有关此内容的更多信息,请参阅:


值得注意的是,许多Common Lisp函数都在序列上运行,而不仅仅是列表.序列包括向量,其中字符串是子类型.例如,(反向"单词")将返回"卓尔".同样,您可以在序列上使用position-if.这意味着可以通过以下方式完成简单的猪拉丁功能:

(defun vowelp (char)
  (position char "aeiou" :test 'char-equal))

(defun pig-latin (word)
  (let ((i (position-if 'vowelp word))) ; position of first vowel
    (if (null i) word                   ; if no vowels, return word
      (concatenate 'string              ; else, concatenate parts:
                   (subseq word i)      ; * "ord"
                   (subseq word 0 i)    ; * "w"
                   "ay"))))             ; * "ay"
Run Code Online (Sandbox Code Playgroud)