I'm trying to write a function to determine whether a word is palindrome or not. I make this but it always returns "Is not a palindrome". I don't know what is happening.
(defun palindromo (X)
(setq i 0)
(setq j (- (length X) 1))
(setq bandera 0)
(loop while (< j i)
do
(when (char= (char X i) (char X j))
(+ i 1)
(- j 1)
(setq bandera 1))
(unless (char/= (char X i) (char X j))
(setq bandera 0)
)
)
(cond
((equal 0 bandera) (write "Is not a palindrome"))
((equal 1 bandera) (write "Is a palindrome"))
)
)
How can I fix this?
Your loop termination test is while (< j i)
, but you previously set i
and j
to respectively the index of the first and last character. That means that (<= i j)
. You never execute the body of the loop, and bandera
is never modified from its initial value, 0.
But suppose you fix your test so that it becomes (< i j)
, then your loop becomes an infinite loop, because you never mutates either i
nor j
in the body of your loop. The two expressions (+ i 1)
and (- j 1)
only computes the next indices, but do not change existing bindings. You would have to use setq
, just as you did above.
By the way, you cannot introduce variables with setq
: it is undefined what happens when trying to set a variable that is not defined. You can introduce global variables with defvar
, defparameter
, and local variables with, among others, let
, let*
and the loop keyword with
.
I assume your Common Lisp implementation implicitly defined global variables when you executed or compiled (setq i 0)
and other assignments. But this is far from ideal since now your function depends on the global state and is not reentrant. If you called palindromo
from different threads, all global variables would be modified concurrently, which would give incorrect results. Better use local variables.
Do not use 0
and 1
for your flag, Lisp uses nil
as false and everything else as true for its boolean operators.
In the loop body, you first write:
(when (char= (char X i) (char X j)) ...)
Then you write:
(unless (char/= (char X i) (char X j)) ...)
Both test the same thing, and the second one involves a double-negation (unless not equal), which is hard to read.
You generally do not want to print things from utility functions. You should probably only return a boolean result.
The name of X
is a little bit unclear, I'd would have used string
.
Try to use the conventional way of formatting your Lisp code. It helps to use an editor which auto-indents your code (e.g. Emacs). Also, do not leave dangling parentheses on their own lines.
(defun palindromep (string)
(loop with max = (1- (length string))
for i from 0
for j downfrom max
while (< i j)
always (char= (char string i)
(char string j))))
p
to palindrome
by convention, because it is a predicate.with max = ...
in the loop defines a loop variable which holds the index of the last character (or -1 if string
is empty).i
is a loop variable which increments, starting from 0j
is a loop variable which decrements, starting from maxwhile
is a termination testalways
evaluates a form at each execution of the loop, and check whether it is always true (non-nil).