Lisp: How to obtain the final loop value? - lisp

(defun index-iteration (n)
(let ((x 0))
(loop for j from 0 to n while (< x n) do
(setf x (max-index-for-iteration j)))))
I have the following lisp code, at the end of the loop I want to return the value j. I have investigated:
collect but that returns a list of values with the value I want (the last j at the end)
finally but it didn't work.
return but it ends the loop early

You need to combine finally and return like this:
(loop ...
finally (return (1- j)))
Please note the unfortunate use
of 1- which is due to the
fact that the finally clause is executed after the termination
clause (while in your case) transfers control there.
IOW, it requires the knowledge about how the termination clause is handled.
You can stay within the loop domain (without the extra let) like
this:
(loop for j from 0 to n
for ret = j
do ...
finally (return ret))
You could also use the maximize clause:
(loop for j from 0 to n ...
maximize j)
but this relies on the knowledge that the final value of j was the maximum one.
PS. Note also that you do not need the while clause in your loop.

It seems like you might want something like this, but I am unsure:
(defun index-iteration (n)
(loop :for j :from 0 :to n
:for x := (max-index-for-iteration j)
:while (<= x n)
:finally (return (1- j))))
There are several things that make this smell like off-by-one: the to, the <=, and in your question code the fact that x is always 0 during the first iteration (what should happen for n = 0?). Maybe show a bit more context, e. g. max-index-for-iteration, or what you want to achieve, for a better answer.

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.

Questions about using recursive functions in lisp

I'm a beginner at lisp. I'm grateful that stackoverflow helped me a lot.
First, I want to express the recursive function using the lisp function.
There is no compilation error, but I want to check if the code I wrote is grammatically correct.
Below is the C code I wrote.
void queens(int i)
{
int j;
if (promising(i))
{
if (i == n)
{
//print all col list
return
}
else
{
for (j = 1; j <= n; j++)
{
col[i + 1] = j;
queens(i + 1);
}
}
}
}
Below is the lisp code.
(defvar n 4)
(defvar col (list 0 0 0 0 0 ))
(defun queens(i)
(let ((j 1))
(if (promising i)
(if (= i n) (print col)
(loop while (<= j n) do (setf (nth (+ 1 i ) col) j)
( queens (+ 1 i ) )
(incf j)))
)
))
First, you (still) need to fix the indentation, alignment, and general style. This is not merely to annoy you, but because it actually makes things clearer, and easier to debug. For example, if you do not indent properly, it becomes hard to see where each expression ends, and this is even worse when using complex macros such as loop. Your code, properly formatted but without any other modification, should be:
(defun queens (i)
(let ((j 1))
(if (promising i)
(if (= i n)
(print col)
(loop while (<= j n)
do (setf (nth (+ 1 i) col) j)
(queens (+ 1 i))
(incf j))))))
The closing parenthesis is placed right after the last form of the expression, without line break, without whitespace.
The opening parenthesis is also right before the first element of the form, without whitespace, but should be detached from what comes before, unless it is another parenthesis (so (defun queen (i) ...) is correct, while ( defun queens(i)) breaks two of the rules).
When using an if construct, either you write it all on a single line (the condition, the "then" form and the "else" form), or you have to insert line breaks after each of them. Otherwise, it is unclear when the "then" form ends and when the "else" starts.
When defining special variables with defvar, name them with '*' around their names, as in (defvar *n* 4) and (defvar *col* (list ...)).
Another style considerations, which helps with problems related to nesting: use when and unless instead of if if you are only interested in one of the two branches. This makes intent clear, and can also simplify the syntax in case of complex branches.
Now, for the code:
If you want to use loop, use the basic for constructs. Instead of writing
(loop while (< j n) do ... (incf j))
use
(loop for j from <start> to <end> do ...)
You can also use upto, below ... if you want subtly different termination conditions.
When you do this, you do not need to introduce a binding for j using let, it will be introduced by the loop.
If you want to modify a list, use a vector instead. Instead of defining col as (list ...), simply use (vector ...) or the make-array function. Afterwards, use elt or aref to access individual elements instead of nth which only works for lists. A version of the code which assumes that all the previous remarks have been taken into account:
(defun queens (i)
(when (promising i)
(if (= i n)
(print *col*)
(loop for j from 1 to *n*
do (setf (aref *col* (1+ i)) j)
(queens (1+ i))))))
Without knowing what promising does and what queens is supposed to do, it is hard to give more insight, but the algorithm is weird nonetheless. For example, in a given call to (queens i), the lexically apparent setf will only ever modify the i+1-th cell of col, setting it to a new j at each iteration. As far as I can tell, this simply results in (aref col (1+ i)) being set to n at the end of the loop. It also seems that you do not use the value recursively returned by queens (which is to be expected: your C function returns nothing !), and that you do not really do any check involving col, so a recursive solution seems weird, there is (seemingly) no relation between (queens i) and the (queens (1+ i)) that it calls n times in a loop !
If the above paragraph is irrelevant because promising also heavily modifies col: stop doing C-in-Lisp and stop modifying things all around the place. Don't rely on state, mutation, global variables & the like, when you can avoid it. It is easy to define recursive solution, to pass lists as arguments, to return several values ... and so it is generally unnecessary to use multiple functions, each of them calling the other ones, recursively modifying the shared global state. That's a mess and can't be debugged.

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).

Sum numbers that are positive which is less than n

(defun sum (n)
(if (n<0) 0 n-1) ;; if n<0, add 0. Else add the next smallest.
(sum (n-1)))
So far I come out with something like this but I am not sure how do I declare a variable to store the sum that I would like to return.
Note that you are implementing 1+2+...+m for m = n-1, which admits a simple formula:
(lambda (n)
;; You could inject n-1 on the formula to get n.(n-1)/2
;; (like in Vatine's answer), but here I just decrement
;; the input to show how to modify the local variable
;; and reuse the formula linked above to sum up-to m.
(decf n)
(if (minusp n)
0
(/ (* n (1+ n)) 2)))
An iterative version would work too, there is no need go recursive when doing simple loops:
(lambda (n) (loop :for x :below n :sum x))
Regarding your code:
Space matters1: n<0 is read as a symbol of name "N<0" (upcased by default). The same goes for n-1 which is a symbol named "N-1".
(n<0) will attempt to run the function named n<0. The same goes for (n-1).
Comparison: you can use (minusp n) or (< n 0).
Decrement: you can use (1- n) or (- n 1).
If what you wrote was correctly written, like this:
(defun sum (n)
(if (< n 0) 0 (- n 1))
(sum (- n 1)))
... there would still be issues:
You expect your (n-1) to actually decrement n but here the if only compute a value without doing side-effects.
You unconditionally call (sum (n-1)), which means: infinite recursion. The value returned by the preceding if is always ignored.
1: For details, look at constituent and terminating characters: 2.1.4 Character Syntax Types
Edit: zerop > minusp to check for negative numbers, fixed to fit OPs question
Was some time ago I used Lisp but if I recall right the last evaluation gets returned. A recursive solution to your problem would look like this:
(defun sum (n)
(if (<= n 0) 0 ;;if n is less or equal than 0 return 0
(+ (- n 1) (sum (- n 1))))) ;; else add (n-1) to sum of (n-1)
In Lisp, all comparator functions are just that, functions, so it needs to be (< n 0) and (- n 1) (or, more succinct, (1- n)).
You don't need to keep an intermediate value, you can simply add things up as you go. However, this is complicated by the fact that you are summing to "less than n", not "to n", so you need to use a helper function, if you want to do this recursively.
Even better, if you peruse the standard (easily available on-line, as the Common Lisp HyperSpec, you will sooner or later come across the chapter on iteration, where the loop facility does everything you want.
So if I needed to do this, I would do one of:
(defun my-sum (n)
(/ (* n (1- n)) 2))
or
(defun my-sum (n)
(loop for i below n
sum i))
If I absolutely needed to make it recursive, I would use something like:
(defun my-sum (n)
(labels ((sum-inner (i)
(if (< i 1)
0
(+ i (sum-inner (1- i))))))
(sum-inner (1- n))))
This is (almost) identical to defining a global function called sum-inner, which may be preferable for debugging purposes. However, since it is very unlikely that sum-inner would have any other use, I made it local.

How to find sum of n number using clojure for loop macro?

I'm using a for-loop macro in clojure:
(defmacro for-loop [[sym initial check-exp post-exp] & steps]
`(loop [~sym ~initial]
(if ~check-exp
(do
~#steps
(recur ~post-exp)))))
I want to write a simple function to find the sum of n numbers like:
for(int i=1; i<n; i++)
sum=sum+i;
How can I do this in clojure using the for-loop macro?
First of all, there is no need to use a macro here. Second, your use of do with the final call to recur will prevent the macro from ever returning a value other than nil as discussed in Lee's answer. That you should use when instead of if when you're not really providing an else case is only a slight matter, but hints at a possible better solution: Use the else case to return the result. For this to work you need to introduce an accumulator into the equation.
(defmacro for-loop [[sym initial result initial-result check-exp post-exp] & steps]
`(loop [~sym ~initial
~result ~initial-result]
(if ~check-exp
(do
~#steps
(recur ~#post-exp))
~result)))
This is still pretty ugly, but allows you to solve your summing task like this, actually not requiring any intermediate steps:
(for-loop [i 0 r 0 (< i n) ((inc i) (+ r i))] nil)
If you macro-expand this, it's easier to see that is going on:
(pprint (macroexpand-1 '(for-loop [i 0 r 0 (< i n) ((inc i) (+ r i))] nil)))
==> (clojure.core/loop [i 0 r 0]
(if (< i n)
(do nil
(recur (inc i) (+ r i)))
r))
It would be nice if one would not have to explicitly name and use the accumulator but just use the results from the steps, but as the steps will likely need to refer to any intermediate values build up so far as in this example, there is no way around it.
(def sum (atom 0))
(def n 100)
(for-loop [i 0 (< i n) (inc i)] (swap! sum #(+ % i)))