Lisp void-variable error when evaluating function - lisp

I'm trying to learn Lisp (elisp, actually), and I tried writing the following function as an exercise Project Euler Problem 2
(defun sumfib (n fn1 fn2 sum)
"Calculate Fibonacci numbers up to 4,000,000 and sum all the even ones"
(if (< 4000000 (+ fn1 fn2))
sum
(if (equal n 3)
(sumfib 1 (+ fn1 fn2) fn1 (+ sum (+fn1 fn2)))
(sumfib (+ n 1) (+ fn1 fn2) fn1 sum)))
When I evaluate it I get the following error:
Debugger entered--Lisp error: (void-variable fn1)
(+ fn1 fn2)
(< 4000000 (+ fn1 fn2))
...
Why wouldn't it recognize fn1? If I try to put (+ fn1 fn2) before the 'if' it doesn't complain about it there, so why the error here?
Also, I realize the function may not actually be correct, but for now I'm not worried about the logic - I'll figure that out later. For now, I'm only interested in understanding this error.

You need an extra close parenthesis at the end of your function.
You need a space in the first clause of the second if: (+fn1 fn2) should be (+ fn1 fn2). ELisp otherwise reads it as passing fn2 to a function named +fn1.
Couple of other style issues:
A cond is a lot easier to read than nested ifs, especially using ELisp indentation style.
= is the normal predicate used for comparing numbers, not equal. Although equal will work, it looks funny to the reader. (At least it does in all the other Lisps I know, I could be wrong because I don't know ELisp as well.)
Here's how I'd restructure the function.
(defun sumfib (n fn1 fn2 sum)
"Calculate Fibonacci numbers up to 4,000,000 and sum all the even ones"
(cond
((< 4000000 (+ fn1 fn2)) sum)
((= n 3) (sumfib 1 (+ fn1 fn2) fn1 (+ sum (+ fn1 fn2))))
(t (sumfib (1+ n) (+ fn1 fn2) fn1 sum))))
I ran it, and it returns an answer, but I don't know if it's right according to the project euler specification.

Not sure if this solves your problem (I don't have an elisp interpreter handy), but you're missing a right paren. There should be one at the end of the first 'if' statement, after 'sum'.
(if (< 4000000 (+ fn1 fn2))
sum)
instead of:
(if (< 4000000 (+ fn1 fn2))
sum
I also think there might be some other issues in there.

Related

a function called A-SUM that calculates Σpi=ni, where n≥0,p≥0. Below are examples of what A-SUM returns considering different arguments

CL-USER> (a-sum 0 3)
->> 6
I wrote this program :
(defun a-sum (x y)
(if (and (> x -1) (> y -1))
(do ((i 0 (1+ i))
(sum 0)
(num x))
((equal i (+ (- y x) 1)))
(setq sum (+ sum num))
(setq num (+ num 1))
sum)
(print " NOPE")))
put if I run it in the terminal it returns nil and not the answer stated above;
can someone help with the problem so it returns the value then Boolean.
DO,DO* Syntax
The entry for DO,DO* says that the syntax is as follows:
do ({var | (var [init-form [step-form]])}*)
(end-test-form result-form*)
declaration*
{tag | statement}*
The body is used as a list of statements and no intermediate value in this body is used as the result form of the do form. Instead, the do form evaluates as the last expression in result-form*, which defaults to nil.
(do ((i 0 (1+ i))
(sum 0)
(num x))
((equal i (+ (- y x) 1))
;;; RESULT FORMS HERE
)
(setq sum (+ sum num)) ;; (*)
(setq num (+ num 1)) ;; (*)
sum ;; (*)
)
All the expressions marked commented (*) above are used for side-effects only: the result of their evaluation is unused and discarded.
Problem statement
It is not clear to me what Σpi=ni means, and your code does not seem to compute something that could be expressed as that mathematical expression.
One red flag for example is that if (+ (- y x) 1) is negative (i.e. if y < x-1, for example y=1,x=3), then your loop never terminates because i, which is positive or null, will never be equal to the other term which is negative.
I would try to rewrite the problem statement more clearly, and maybe try first a recursive version of your algorithm (whichever is easier to express).
Remarks
Please indent/format your code.
Instead of adding setq statements in the body, try to see if you can define them in the iteration clauses of the loop (since I'm not sure what you are trying to achieve, the following example is only a rewrite of your code):
(do ((i 0 (1+ i))
(sum 0 (+ sum num)
(num x (1+ num))
(... sum))
Consider what value(s) a function returns. It's the value of the last form evaluated. In your case, that appears to be a do or maybe a setq or print (It's difficult to read as it's formatted now, and I don't have question edit privileges).
In short, the form that's returning the value for the function looks to be one evaluated for side-effects instead of returning a value.

if: Bad syntax error (Scheme programming)

(define generalized-triangular
(lambda (input n)
(if (= n 1)
1
(+ (input n) (generalized-triangular (- n 1))))))
This program is designed to take a number and a function as inputs and do the following..
f(1) + f(2) + f(3)+ … + f(N).
An example input would be:
(generalized-triangular square 3)
The Error message:
if: bad syntax;
has 4 parts after keyword in: (if (= n 1) 1 (+ (input n) (generalized-triangular (- n 1))) input)
The error is quite explicit - an if form can only have two parts after the condition - the consequent (if the condition is true) and the alternative (if the condition is false). Perhaps you meant this?
(if (= n 1)
1
(+ (input n) (generalized-triangular input (- n 1))))
I moved the input from the original code, it was in the wrong place, as the call to generalized-triangular expects two arguments, in the right order.
For the record: if you need to execute more than one expression in either the consequent or the alternative (which is not the case for your question, but it's useful to know about it), then you must pack them in a begin, for example:
(if <condition> ; condition
(begin ; consequent
<expression1>
<expression2>)
(begin ; alternative
<expression3>
<expression4>))
Alternatively, you could use a cond, which has an implicit begin:
(cond (<condition> ; condition
<expression1> ; consequent
<expression2>)
(else ; alternative
<expression3>
<expression4>))
Literal answer
The code you posted in your question is fine:
(define generalized-triangular
(lambda (input n)
(if (= n 1)
1
(+ (input n) (generalized-triangular (- n 1))))))
The error message in your question would be for something like this code:
(define generalized-triangular
(lambda (input n)
(if (= n 1)
1
(+ (input n) (generalized-triangular (- n 1)))
input)))
The problem is input. if is of the form (if <cond> <then> <else>). Not counting if itself, it has 3 parts. The code above supplies 4.
Real answer
Two tips:
Use DrRacket to write your code, and let it help you with the indenting. I couldn't make any sense of your original code. (Even after someone edited it for you, the indentation was a bit wonky making it still difficult to parse mentally.)
I don't know about your class, but for "real" Racket code I'd recommend using cond instead of if. Racket has an informal style guide that recommends this, too.
here's the tail-recursive
(define (generalized-triangular f n-max)
(let loop ((n 1) (sum 0))
(if (> n n-max)
0
(loop (+ n 1) (+ sum (f n))))))
Since you're using the racket tag, I assume the implementation of generalized-triangular is not required to use only standard Scheme. In that case, a very concise and efficient version (that doesn't use if at all) can be written with the racket language:
(define (generalized-triangular f n)
(for/sum ([i n]) (f (+ i 1))))
There are two things necessary to understand beyond standard Scheme to understand this definition that you can easily look up in the Racket Reference: how for/sum works and how a non-negative integer behaves when used as a sequence.

From Google Common Lisp Style Guide: "Avoid modifying local variables, try rebinding instead" meaning?

Google Common Lisp Style Guide say Avoid modifying local variables, try rebinding instead
What does it mean? What does rebinding mean in that sentence?
It means that you should create new variables instead of changing the value of old ones. For example, let's take the following code:
(defun foo (x)
(when (minusp x)
(setq x (- x)))
do something with x)
Instead, one should create a new binding and use that one instead:
(defun foo (x)
(let ((xabs (if (minusp x)
(- x)
x)))
do something with xabs)
The reason for this is that you will always know what a variable contains, since it will never change. If you want the new value, simply use the variable that holds that new value.
Now you might ask why this is so important? Well, some people have a stronger preference for this than others. Especially people who prefer to emphasise the functional aspect of Lisp will advocate this style. However, regardless of preference, it can be very useful to always be able to rely on the fact that variables doesn't change. Here's an example where this can be important:
(defun foo (x)
(let ((function #'(lambda () (format t "the value of x is ~a~%" x))))
(when (minusp x)
(setq x (- x)))
(other-function x)
function))
Then, the return value of FOO is a function that when called with print the value of x. But, the value will be that of x later in the function, the absolute value. This can be very surprising if the function is large and complicated.
I don't know Common Lisp well enough to answer with how to do this in Common Lisp, so I'm using Scheme for my example below. Suppose you're writing a function to return the factorial of a number. Here's a "modify local variables" approach to that function (you'll have to define your own while macro, but it's not hard):
(define (factorial n)
(define result 1)
(while (> n 0)
(set! result (* result n))
(set! n (- n 1)))
result)
Here's a "rebind local variables" approach to that function:
(define (factorial n)
(let loop ((n n)
(result 1))
(if (zero? n)
result
(loop (- n 1) (* result n)))))
In this case, loop is called with new values to rebind with each time. The same function can be written using the do macro (which, by the way, also uses rebinding, not modifying, at least in Scheme):
(define (factorial n)
(do ((n n (- n 1))
(result 1 (* result n)))
((zero? n) result)))

Scheme/Racket: do loop order of evaluation

The following procedure is valid in both scheme r6rs and Racket:
;; create a list of all the numbers from 1 to n
(define (make-nums n)
(do [(x n (- x 1)) (lst (list) (cons x lst))]
((= x 0)
lst)))
I've tested it for both r6rs and Racket and it does work properly, but I only know that for sure for DrRacket.
My question is if it is guaranteed that the step expressions ((- x 1) and (cons x lst) in this case) will be evaluated in order. If it's not guaranteed, then my procedure isn't very stable.
I didn't see anything specifying this in the standards for either language, but I'm asking here because when I tested it was evaulated in order.
They're generally not guaranteed to be evaluated in order, but the result will still be the same. This is because there are no side-effects here -- the loop doesn't change x or lst, it just rebinds them to new values, so the order in which the two step expressions are evaluated is irrelevant.
To see this, start with a cleaner-looking version of your code:
(define (make-nums n)
(do ([x n (- x 1)] [lst null (cons x lst)])
[(zero? x) lst]))
translate to a named-let:
(define (make-nums n)
(let loop ([x n] [lst null])
(if (zero? x)
lst
(loop (- x 1) (cons x lst)))))
and further translate that to a helper function (which is what a named-let really is):
(define (make-nums n)
(define (loop x lst)
(if (zero? x)
lst
(loop (- x 1) (cons x lst))))
(loop n null))
It should be clear now that the order of evaluating the two expressions in the recursive loop call doesn't make it do anything different.
Finally, note that in Racket evaluation is guaranteed to be left-to-right. This matters when there are side-effects -- Racket prefers a predictable behavior, whereas others object to it, claiming that this leads people to code that implicitly relies on this. A common small example that shows the difference is:
(list (read-line) (read-line))
which in Racket is guaranteed to return a list of the first line read, and then the second. Other implementations might return the two lines in a different order.

Is it correct to use the backtick / comma idiom inside a (loop ...)?

I have some code which collects points (consed integers) from a loop which looks something like this:
(loop
for x from 1 to 100
for y from 100 downto 1
collect `(,x . ,y))
My question is, is it correct to use `(,x . ,y) in this situation?
Edit: This sample is not about generating a table of 100x100 items, the code here just illustrate the use of two loop variables and the consing of their values. I have edited the loop to make this clear. The actual loop I use depends on several other functions (and is part of one itself) so it made more sense to replace the calls with literal integers and to pull the loop out of the function.
It would be much 'better' to just do (cons x y).
But to answer the question, there is nothing wrong with doing that :) (except making it a tad slower).
I think the answer here is resource utilization (following from This post)
for example in clisp:
[1]> (time
(progn
(loop
for x from 1 to 100000
for y from 1 to 100000 do
collect (cons x y))
()))
WARNING: LOOP: missing forms after DO: permitted by CLtL2, forbidden by ANSI
CL.
Real time: 0.469 sec.
Run time: 0.468 sec.
Space: 1609084 Bytes
GC: 1, GC time: 0.015 sec.
NIL
[2]> (time
(progn
(loop
for x from 1 to 100000
for y from 1 to 100000 do
collect `(,x . ,y)) ;`
()))
WARNING: LOOP: missing forms after DO: permitted by CLtL2, forbidden by ANSI
CL.
Real time: 0.969 sec.
Run time: 0.969 sec.
Space: 10409084 Bytes
GC: 15, GC time: 0.172 sec.
NIL
[3]>
dsm: there are a couple of odd things about your code here. Note that
(loop for x from 1 to 100000
for y from 1 to 100000 do
collect `(,x . ,y))
is equivalent to:
(loop for x from 1 to 100
collecting (cons x x))
which probably isn't quite what you intended. Note three things: First, the way you've written it, x and y have the same role. You probably meant to nest loops. Second, your do after the y is incorrect, as there is not lisp form following it. Thirdly, you're right that you could use the backtick approach here but it makes your code harder to read and not idiomatic for no gain, so best avoided.
Guessing at what you actually intended, you might do something like this (using loop):
(loop for x from 1 to 100 appending
(loop for y from 1 to 100 collecting (cons x y)))
If you don't like the loop macro (like Kyle), you can use another iteration construct like
(let ((list nil))
(dotimes (n 100) ;; 0 based count, you will have to add 1 to get 1 .. 100
(dotimes (m 100)
(push (cons n m) list)))
(nreverse list))
If you find yourself doing this sort of thing a lot, you should probably write a more general function for crossing lists, then pass it these lists of integers
If you really have a problem with iteration, not just loop, you can do this sort of thing recursively (but note, this isn't scheme, your implementation may not guaranteed TCO). The function "genint" shown by Kyle here is a variant of a common (but not standard) function iota. However, appending to the list is a bad idea. An equivalent implementation like this:
(defun iota (n &optional (start 0))
(let ((end (+ n start)))
(labels ((next (n)
(when (< n end)
(cons n (next (1+ n))))))
(next start))))
should be much more efficient, but still is not a tail call. Note I've set this up for the more usual 0-based, but given you an optional parameter to start at 1 or any other integer. Of course the above can be written something like:
(defun iota (n &optional (start 0))
(loop repeat n
for i from start collecting i))
Which has the advantage of not blowing the stack for large arguments. If your implementation supports tail call elimination, you can also avoid the recursion running out of place by doing something like this:
(defun iota (n &optional (start 0))
(labels ((next (i list)
(if (>= i (+ n start))
nil
(next (1+ i) (cons i list)))))
(next start nil)))
Hope that helps!
Why not just
(cons x y)
By the way, I tried to run your code in CLISP and it didn't work as expected. Since I'm not a big fan of the loop macro here's how you might accomplish the same thing recursively:
(defun genint (stop)
(if (= stop 1) '(1)
(append (genint (- stop 1)) (list stop))))
(defun genpairs (x y)
(let ((row (mapcar #'(lambda (y)
(cons x y))
(genint y))))
(if (= x 0) row
(append (genpairs (- x 1) y)
row))))
(genpairs 100 100)