Syntax Error in Lisp Loop for defining variables in a loop - lisp

I am a beginner student who is learning Lisp. I want to turn the loop to the i value using k using the loop statement, but the following error appears. I think I wrote the parentheses correctly, but I don't know why this error occurs.
LOOP: illegal syntax near (SETQ K (1+ K)) in
(LOOP WHILE (< K I) (SETQ K (1+ K)))
Below is my code.
(DEFUN promising (i)
(setq k 1)
(loop while (< k i) (setq k (1+ k)))
(return-from promising 1)
)
promising(2)

I see several small things:
The loop syntax is not 100% correct, you missed a do keyword
(loop while (< k i) do (setq k (1+ k)))
^^
do keyword is missing!
The syntax for the function call promising(2) is also incorrect
(promising 2)
The return-from thing is unusual
The first reason is that the return value is always 1, in your case, you probably want to return k.
(DEFUN promising (i)
(setq k 1)
(loop while (< k i) (setq k (1+ k)))
(return-from promising 1))
^
Always return 1
The second reason is you don't need a return-from, the last value of a defun form will be given to the function caller.
(DEFUN promising (i)
(setq k 1)
(loop while (< k i) do (setq k (1+ k)))
k)
^
The last value will be returned to the function caller
The k variable should be defined locally and not use a global definition
The final code could be something like this:
(defun promising (i)
(let ((k 1))
(loop while (< k i) do (setq k (1+ k)))
;; return value
k))
(promising 2)
This should return:
2

Related

Questions about replacing while and if statements with lisp

I want to change the code below to Lisp code, but I keep getting errors in grammar. How do I fix the if statement?
int promising(int i)
{
int k = 1;
while (k < i)
{
if (col[i] == col[k] || abs(col[i] - col[k]) == abs(i - k))
return 0;
k++;
}
return 1;
}
Below is the one I changed to the Lisp code.
(setq col (list 0 0 0 0))
(DEFUN promising (i)
(let ((k 1)) ; k =1
(loop while (< k i)
do((if (or ( = (nth i col) (nth k col))
(= ( abs((setq a (- (nth i col) (nth k col)))))
( abs((setq b (- i k ))))))
(return-from promising 0)))
do (setq k (1+ k)))
(return-from promising 1))
)
It is difficult for me to flexibly change the complicated condition of the if statement to the lisp code.
You are doing "C-in-Lisp". Trying to directly translate C (or for that matter, C++/Java/C#/Python ...) programs into Lisp will often lead to poor code, and you should be better off trying to understand how those problems are sovled in Lisp.
That being said:
You should not use (setq col <whatever>) at the toplevel. Global variables are introduced using defvar or defparameter and their name is of the form *variable-name* to distinguish them from other variables. This is because they have different scoping rules, and behave differently (i.e. they are not equivalent to other languages' global variables). In particular, using setq with a variable that has not been declared with defvar or defparameter is undefined behaviour, and most implementations will allow it, but they will then create this global variable. You generally don't want that. To sum up: either use (defvar *col* (list 0 0 ...)) if you need this really is a global variable, or simply use (let ((col (list 0 ...))) <more-code>) where you need it.
loop is a complicated construct. This is, in itself, another mini-language that you have to learn on top of Lisp. In particular, if all you ever want to do is "loop with some variable between some bounds and increment it by some value at each step", use
(loop for k from 1 do ...) ;; this introduces a local variable k, incremented by 1 at each step, with no upper bound
(loop for k from 1 to 10 do ...) ;; same, but only loop until k reaches 10
(loop for k from 1 to 10 by 3 do ...) same, but increments k by 3 at each step
Other constructs are available. Read this section of Practical Common Lisp for a good introduction, and the relevant CLHS section for a technical description and documentation.
Please follow conventions for whitespace this makes it much easier to read. For example, never place a parenthesis alone on its line (e.g. your very last parenthesis), and ( abs((setq b (- i k )))) should really be written (abs ((setq b (- i k)))) (ignoring the fact that this is incorrect, see below ...). As far as style is concerned, you also need to fix the indentation, and don't write DEFUN is uppercase, it is unnecessary and looks weird.
You cannot place extra parenthensis just to group things together, parenthesis have semantic meaning. In particular, in most cases, calling a function or using pretty much any special operator is done by (<operator-name> <first-arg> <second-arg> ... ). You almost never have 2 consecutive opening parenthesis.
Why are you using (setq a ...) and (setq b ...) in your loop ? Neither a nor b is ever declared or used anywhere else.
If you want to access specific elements of a list, don't use a list, use a vector. In particular, several calls to the nth function is often the sign that you really should have been using a vector.
A correct version of your code, using a few loop facilities, and still assuming that col is a list (which is should not be) although there would be other loop constructs making this even clearer ...
(defun promising (i)
(loop for k from 1 below i
for col-k = (nth k col)
do (when (or (= (nth i col) (nth k col))
(= (abs (- (nth i col) (nth k col)))
(abs (- i k))))
(return-from promising 0)))
1)
Note that this code is incredibly inefficient and this is why I suggested not to translate directly from C to Lisp. In particular, although you traverse a list (you access the k-th element at the k-th step), your code calls nth at each step instead of traversing the list ! You also compute (nth i col) at each step, which is already useless in C (it is constant so doesn't need to be recomputed at every step), but is catastrophic here. This should really be:
(defun promising (i)
(let ((col-i (nth i col)))
(loop for k from 1 below i
for col-k in (cdr col) ;; you start from the index 1, not 0
do (when (or (= col-i col-k)
(= (abs (- col-i col-k))
(abs (- i k))))
(return-from promising 0))))
1)
There are several mistakes in the code.
Incorrect function calls
(DEFUN promising (i)
(let ((k 1)) ; k =1
(loop while (< k i)
do((if (or ( = (nth i col) (nth k col))
;; ^^
;; Incorrect
)
And also here:
(setq col (list 0 0 0 0))
(DEFUN promising (i)
(let ((k 1)) ; k =1
(loop while (< k i)
do((if (or ( = (nth i col) (nth k col))
(= ( abs((setq a (- (nth i col) (nth k col)))))
;; ^^
;; Incorrect
( abs((setq b (- i k ))))))
;; ^^
;; Incorrect
(return-from promising 0)))
do (setq k (1+ k)))
(return-from promising 1))
)
The loop macro have 2 do keywords
(setq col (list 0 0 0 0))
(DEFUN promising (i)
(let ((k 1)) ; k =1
(loop while (< k i)
do((if (or ( = (nth i col) (nth k col))
;; ^^
;; First do
(= ( abs((setq a (- (nth i col) (nth k col)))))
( abs((setq b (- i k ))))))
(return-from promising 0)))
do (setq k (1+ k)))
;; ^^
;; Second do
(return-from promising 1))
)
return-from is used several times
return-from is usually not present in Common Lisp code, this is pretty much like C goto, something developers try to avoid.
Incoherent setq defining a and b (probably old code)
(setq col (list 0 0 0 0))
(DEFUN promising (i)
(let ((k 1)) ; k =1
(loop while (< k i)
do((if (or ( = (nth i col) (nth k col))
(= ( abs((setq a (- (nth i col) (nth k col)))))\
;; ^^^^^^
;; ??
( abs((setq b (- i k ))))))
;; ^^^^^^
;; ??
Weird incrementation scheme
(setq k (1+ k))
While being correct, Common Lisp programmers will simply use the increment function:
(incf k)
Final code
The code you might looking for should be close to that one:
(defun promising (i)
(let ((k 1))
(loop while (< k i) do
(if (or (= (nth i col) (nth k col))
(= (abs (- (nth i col) (nth k col)))
(abs (- i k ))))
(return-from promising 0))
(incf k))
;; return value
k))
Please note that the code is not equivalent to the C version, because the data structure is completely different. In the C version, the access to the data will be very fast O(1). The Common Lisp version will be slow if you have a large number of elements O(n). You can be fast with Common Lisp if you replace your list by an array/vector.

LISP : SYSTEM::READ-EVAL-PRINT: variable I has no value

I made a simple test function trying to assign j a value of i by calling (test j 10).
I am getting SYSTEM::READ-EVAL-PRINT: variable J has no value.
(DEFUN test (j i)
(LET ((j i))
(print j)
)
)
I'm unsure if you are aware that the variable j in the let and j defined in the parameters of test are two completely different variables. As a true refactoring would be to rename them so that it is clear, here is your code with that ambiguity removed:
(defun test (pj pi)
(let ((lj pi))
(print lj)))
This is exactly the same code since the new binding in the let effectively makes the old variable with that same name inaccessible for the duration of the let. The warning will be about pj since it is still unused in the function and thus you should consider removing it:
(defun test (pi)
(let ((lj pi))
(print lj)))
Usually having a parameter that is not used is a bug so CL nags about such things. However sometimes you make higher order functions that use functions you pass values. eg.
(defun map-assoc (fn lst)
(loop :for n :from 0
:for (k . v) :in lst
:collect (funcall fn k v n lst)))
Now imagine you want to make a list of just the keys.
(defun assoq-keys (lst)
(map-assoc (lambda (k v n lst)
(declare (ignore v n lst))
k)
lst))
(assoq-keys '((I . 1) (II . 2) (III . 3) (IV . 4) (V . 5)))
; ==> (I II III IV V)
The declare statement will supress the error that the other variables passed will not be used, but you must include them as that is the contract made by the map-assoc function. For a function that takes their values or perhaps swaps other there are other variables you will be using so passing the values is a good generalization.
I think you're misunderstanding how the arguments work. Your test function, in its current form, takes two arguments: j and i. You seem to only use i, so there's no reason to pass a second one. Consider
(defun test (i)
(let ((j i))
(print j)))
Then call it simply as (test 10).

N-Queen Lisp (1- n) mean?

(defun queens (n &optional (m n))
(if (zerop n)
(list nil)
(loop for solution in (queens (1- n) m) ;; <=== what does the (1- n) mean?
nconc (loop for new-col from 1 to m
when (loop for row from 1 to n
for col in solution
always (/= new-col col (+ col row) (- col row)))
collect (cons new-col solution)))))
(defun print-solution (solution)
(loop for queen-col in solution
do (loop for col from 1 to (length solution)
do (write-char (if (= col queen-col) #\Q #\.)))
(terpri))
(terpri))
(defun print-queens (n)
(mapc #'print-solution (queens n)))
hi, can anyone explain to me this N-Queen algo why is there a (1- n)? what does the "1-" part and &optional syntax?
thank you,
1- is a function that subtracts one from its parameter.
&optional states that optional parameters will follow. Usually the default value is nil, but if you specify it as a list - i.e. (m n) then the parameter defaults to the second value in the list (in this case m defaults to n if a second parameter is not passed).

What is wrong with the following Common Lisp macro using gensym?

Learning Common Lisp (using GNU CLISP 2.43) .. so might be a noob mistake. Example is the 'print prime numbers between x and y'
(defun is-prime (n)
(if (< n 2) (return-from is-prime NIL))
(do ((i 2 (1+ i)))
((= i n) T)
(if (= (mod n i) 0)
(return NIL))))
(defun next-prime-after (n)
(do ((i (1+ n) (1+ i)))
((is-prime i) i)))
(defmacro do-primes-v2 ((var start end) &body body)
`(do ((,var (if (is-prime ,start)
,start
(next-prime-after ,start))
(next-prime-after ,var)))
((> ,var ,end))
,#body))
(defmacro do-primes-v3 ((var start end) &body body)
(let ((loop-start (gensym))
(loop-end (gensym)))
`(do ((,loop-start ,start)
(,loop-end ,end)
(,var (if (is-prime ,loop-start)
,loop-start
(next-prime-after ,loop-start))
(next-prime-after ,var)))
((> ,var ,loop-end))
,#body )))
do-primes-v2 works perfectly.
[13]> (do-primes-v2 (p 10 25) (format t "~d " p))
11 13 17 19 23
Next I tried using gensym to avoid naming clashes in macro expansion - do-primes-v3. However I'm stuck with a
*** - EVAL: variable #:G3498 has no value
Tried using macro-expand to see if i could spot the mistake but I can't.
[16]> (macroexpand-1 `(do-primes-v3 (p 10 25) (format t "~d " p)))
(DO
((#:G3502 10) (#:G3503 25)
(P (IF (IS-PRIME #:G3502) #:G3502 (NEXT-PRIME-AFTER #:G3502))
(NEXT-PRIME-AFTER P)))
((> P #:G3503)) (FORMAT T "~d " P)) ;
Use DO* instead of DO.
DO Initializes the bindings in a scope where they are not yet visible. DO* initializes the bindings in a scope where they are visible.
In this particular case var needs to reference the other binding loop-start.
You don't actually need the gensym here for avoiding variable capture, because you do not introduce any variables that would be "local to the macro". When you macroexpand your do-primes-v2, you will see that no variable is introduced that didn't exist outside of the macro.
You do need it for a different thing, though: avoiding multiple evaluation.
If you call the macro like this:
(do-primes-v2 (p (* x 2) (* y 3))
(format "~a~%" p))
it expands to
(do ((p (if (is-prime (* x 2))
(* x 2)
(next-prime-after (* x 2))
(next-prime-after p)))
((> p (* y 3))
(format "~a~%" p))
At best, this is inefficient, because those multiplications are done multiple times. However, if you use a function with side effects as inputs, like setf or incf, this can be a big problem.
Either move the binding of your loop-start and loop-end to an enclosing LET block or use DO*. The reason is that all loop variables in DO are bound "in parallel", so for the first binding, the (expanded) loop-start variable does not yet have a binding.
I know this doesn't really answer your question, but I do think it is relevant. In my experience, the type of macro you are attempting to write is a very common one. One problem I have with the way you have approached the problem is that it doesn't handle another common use case: functional composition.
I don't have the time to highlight some of the difficulties you will probably encounter using your macro, I will however highlight that, had you built your prime iterator geared towards functional composition, your macro turns out to be extremely simple, avoiding your question altogether.
Note: I have slightly modified some of your functions.
(defun is-prime (n)
(cond
((< n 2)
nil)
((= n 2)
t)
((evenp n)
nil)
(t
(do ((i 2 (1+ i)))
((= i n) t)
(when (or (= (mod n i) 0))
(return nil))))))
(defun next-prime (n)
(do ((i n (1+ i)))
((is-prime i) i)))
(defun prime-iterator (start-at)
(let ((current start-at))
(lambda ()
(let ((next-prime (next-prime current)))
(setf current (1+ next-prime))
next-prime))))
(defun map-primes/iterator (fn iterator end)
(do ((i (funcall iterator) (funcall iterator)))
((>= i end) nil)
(funcall fn i)))
(defun map-primes (fn start end)
(let ((iterator (prime-iterator start)))
(map-primes/iterator fn iterator end)))
(defmacro do-primes ((var start end) &body body)
`(map-primes #'(lambda (,var)
,#body)
,start ,end))
I too recommend that you look at Series. The generator pattern is also a very common occurrence in lisp programs. You may also want to look at Alexandria, in particular the function ALEXANDRIA:COMPOSE to see what cool stuff you can do with functional composition.
I suggest avoiding DO/DO* and macros altogether and instead going for Series (an implementation of which can be found on series.sourceforge.net).
If that's too complex then consider just generating a list of primes with recursion or a generator (for on-demand generation).

How do I memoize a recursive function in Lisp?

I'm a Lisp beginner. I'm trying to memoize a recursive function for calculating the number of terms in a Collatz sequence (for problem 14 in Project Euler). My code as of yet is:
(defun collatz-steps (n)
(if (= 1 n) 0
(if (evenp n)
(1+ (collatz-steps (/ n 2)))
(1+ (collatz-steps (1+ (* 3 n)))))))
(defun p14 ()
(defvar m-collatz-steps (memoize #'collatz-steps))
(let
((maxsteps (funcall m-collatz-steps 2))
(n 2)
(steps))
(loop for i from 1 to 1000000
do
(setq steps (funcall m-collatz-steps i))
(cond
((> steps maxsteps)
(setq maxsteps steps)
(setq n i))
(t ())))
n))
(defun memoize (fn)
(let ((cache (make-hash-table :test #'equal)))
#'(lambda (&rest args)
(multiple-value-bind
(result exists)
(gethash args cache)
(if exists
result
(setf (gethash args cache)
(apply fn args)))))))
The memoize function is the same as the one given in the On Lisp book.
This code doesn't actually give any speedup compared to the non-memoized version. I believe it's due to the recursive calls calling the non-memoized version of the function, which sort of defeats the purpose. In that case, what is the correct way to do the memoization here? Is there any way to have all calls to the original function call the memoized version itself, removing the need for the special m-collatz-steps symbol?
EDIT: Corrected the code to have
(defvar m-collatz-steps (memoize #'collatz-steps))
which is what I had in my code.
Before the edit I had erroneously put:
(defvar collatz-steps (memoize #'collatz-steps))
Seeing that error gave me another idea, and I tried using this last defvar itself and changing the recursive calls to
(1+ (funcall collatz-steps (/ n 2)))
(1+ (funcall collatz-steps (1+ (* 3 n))))
This does seem to perform the memoization (speedup from about 60 seconds to 1.5 seconds), but requires changing the original function. Is there a cleaner solution which doesn't involve changing the original function?
I assume you're using Common-Lisp, which has separate namespaces for variable and function names. In order to memoize the function named by a symbol, you need to change its function binding, through the accessor `fdefinition':
(setf (fdefinition 'collatz-steps) (memoize #'collatz-steps))
(defun p14 ()
(let ((mx 0) (my 0))
(loop for x from 1 to 1000000
for y = (collatz-steps x)
when (< my y) do (setf my y mx x))
mx))
Here is a memoize function that rebinds the symbol function:
(defun memoize-function (function-name)
(setf (symbol-function function-name)
(let ((cache (make-hash-table :test #'equal)))
#'(lambda (&rest args)
(multiple-value-bind
(result exists)
(gethash args cache)
(if exists
result
(setf (gethash args cache)
(apply fn args)))))))
You would then do something like this:
(defun collatz-steps (n)
(if (= 1 n) 0
(if (evenp n)
(1+ (collatz-steps (/ n 2)))
(1+ (collatz-steps (1+ (* 3 n)))))))
(memoize-function 'collatz-steps)
I'll leave it up to you to make an unmemoize-function.
something like this:
(setf collatz-steps (memoize lambda (n)
(if (= 1 n) 0
(if (evenp n)
(1+ (collatz-steps (/ n 2)))
(1+ (collatz-steps (1+ (* 3 n))))))))
IOW: your original (non-memoized) function is anonymous, and you only give a name to the result of memoizing it.
Note a few things:
(defun foo (bar)
... (foo 3) ...)
Above is a function that has a call to itself.
In Common Lisp the file compiler can assume that FOO does not change. It will NOT call an updated FOO later. If you change the function binding of FOO, then the call of the original function will still go to the old function.
So memoizing a self recursive function will NOT work in the general case. Especially not if you are using a good compiler.
You can work around it to go always through the symbol for example: (funcall 'foo 3)
(DEFVAR ...) is a top-level form. Don't use it inside functions. If you have declared a variable, set it with SETQ or SETF later.
For your problem, I'd just use a hash table to store the intermediate results.
Changing the "original" function is necessary, because, as you say, there's no other way for the recursive call(s) to be updated to call the memoized version.
Fortunately, the way lisp works is to find the function by name each time it needs to be called. This means that it is sufficient to replace the function binding with the memoized version of the function, so that recursive calls will automatically look up and reenter through the memoization.
huaiyuan's code shows the key step:
(setf (fdefinition 'collatz-steps) (memoize #'collatz-steps))
This trick also works in Perl. In a language like C, however, a memoized version of a function must be coded separately.
Some lisp implementations provide a system called "advice", which provides a standardized structure for replacing functions with enhanced versions of themselves. In addition to functional upgrades like memoization, this can be extremely useful in debugging by inserting debug prints (or completely stopping and giving a continuable prompt) without modifying the original code.
This function is exactly the one Peter Norvig gives as an example of a function that seems like a good candidate for memoization, but which is not.
See figure 3 (the function 'Hailstone') of his original paper on memoization ("Using Automatic Memoization as a Software Engineering Tool in Real-World AI Systems").
So I'm guessing, even if you get the mechanics of memoization working, it won't really speed it up in this case.
A while ago I wrote a little memoization routine for Scheme that used a chain of closures to keep track of the memoized state:
(define (memoize op)
(letrec ((get (lambda (key) (list #f)))
(set (lambda (key item)
(let ((old-get get))
(set! get (lambda (new-key)
(if (equal? key new-key) (cons #t item)
(old-get new-key))))))))
(lambda args
(let ((ans (get args)))
(if (car ans) (cdr ans)
(let ((new-ans (apply op args)))
(set args new-ans)
new-ans))))))
This needs to be used like so:
(define fib (memoize (lambda (x)
(if (< x 2) x
(+ (fib (- x 1)) (fib (- x 2)))))))
I'm sure that this can be ported to your favorite lexically scoped Lisp flavor with ease.
I'd probably do something like:
(let ((memo (make-hash-table :test #'equal)))
(defun collatz-steps (n)
(or (gethash n memo)
(setf (gethash n memo)
(cond ((= n 1) 0)
((oddp n) (1+ (collatz-steps (+ 1 n n n))))
(t (1+ (collatz-steps (/ n 2)))))))))
It's not Nice and Functional, but, then, it's not much hassle and it does work. Downside is that you don't get a handy unmemoized version to test with and clearing the cache is bordering on "very difficult".