I'm really curious why using "remove" isn't actually removing from the list, it would if I declared it in a variable, but then I have another variable to work with and it all becomes very messy, he is my code;
;;;;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)))
The output I get is:
(#\d #\r #\o #\w)
(#\d #\r #\o #\w)
I would have expected the #\w to be removed from the second part of the output but it doesn't unless I declare it in a variable. How do I just work with a single piece of data and remove/add what I need to it without declaring a lot of variables?
(I thought this would have been asked before, and there are certainly relevant things on Stack Overflow, but I didn't find a suitable duplicate.)
The issue is that remove returns a new list; it doesn't modify the existing list. The relevant portion from the HyperSpec entry for remove (emphasis added):
remove, remove-if, remove-if-not return a sequence of the same type as sequence that has the same elements except that those in the subsequence bounded by start and end and satisfying the test have been removed. This is a non-destructive operation. If any elements need to be removed, the result will be a copy. The result of remove may share with sequence; the result may be identical to the input sequence if no elements need to be removed.
This means that you need to use the value returned by remove. E.g., you could return it, bind it to a variable, or assign it to a variable:
(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
Note that the language also includes a delete function, which can be destructive. Note, though, that this doesn't eliminate the need to save the result. It means that the list structure may be modified. You still need to save the result, though, because the cons cell that was the first in the old list might not be the cons cell that's the first in the new list. For more about this, see, for instance:
It's also worth noting that many Common Lisp functions operate on sequences, not just lists. Sequences include vectors, of which strings are a subtype. E.g., (reverse "word") will return "drow". Similarly, you can use position-if on sequences. This means that a simple pig latin function can be done with something like this:
(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"