Temporary edits global variable [duplicate] - lisp

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
LISP - Global variable keep their old value after reinitialization
I'm currently doing some coursework with Lisp (using Common Lisp) and have nowhere else to turn with this problem I'm having.
It's tricky to explain but here goes..
The situation:
I've got two global variables, p1 & p2, which are polynomial expressions. My task is to create a polynomial calculator, which is going well so far.
I keep my polynomial elements in a specific format: 3x^2 == ((x 2) 3), and I've created two functions which recursively run through both lists of polynomial elements.
If I wanted to add together 3x^2 and 2x^2, the answer would be 5x^2 (or "((x 2) (3+2))").
I have a third list, the result, which is appended to whenever an element is calculated/can't be calculated.
The problem:
With two elements I can add together, I create a temporary variable to be added to the result. However, the global variable is changed despite what I do.
I've tried let, lambda, various functions, etc. I've been stuck for a couple of days now and would greatly appreciate any help you could give me :)
Here's a small example of what I mean:
(setf p1 '((x 2) 2))
;2x^2
(setf p2 '((x 2) 3))
;3x^2
(if (equal (first p1) (first p2))
(progn
(setf temp p1)
(setf (second temp) (+ (second p1) (second p2)))
(append-to-result temp)
(print p1)
(print temp)))
Output:
((x 2) 5)
((x 2) 5)

When you do:
(setf temp p1)
you are not_making a copy of the list structure that p1 refers to. Both variables now refer to the same cons cells. Then when you do:
(setf (second temp) ...)
you're modifying that list structure, which both variables still refer to. Change to:
(setf temp (copy-tree p1))

Related

Defining a "minimum" function to return the minimum of a list using another function that returns the smaller of two numbers

(defun *smaller* (x y)
( if (> x y) y
x))
(defun *minimum* (lst)
(do ((numbers lst (cdr numbers))
(result (car numbers) (*smaller* result (car numbers))))
((null numbers) result)))
LISP says that variable "numbers" in "minimum" function is an unbound one although I think I've bound it to "lst". What am I missing?
Do binds in parallel. The expression for the initial value of result is (cdr numbers), and numbers is unbound there. Do* would work here.
Another approach to this problem is to try and think about it inductively.
an empty list has no minimum;
if the list is not empty, its first element is a candidate minimum:
if the rest of the list is empty it's the answer
else the candidate minumum is the smaller of the current candidate and the first element of the list, and carry on through the rest of the list.
This translates very naturally into Lisp:
(defun smaller (x y)
(if (< x y) x y))
(defun running-minimum (candidate tail)
(if (null tail)
candidate
(running-minimum (smaller candidate (first tail)) (rest tail))))
(defun minimum (list)
(when (null list)
(error "?")) ;ed is the standard text editor
(running-minimum (first list) (rest list)))
Notes
For good, if now mostly historical, reasons, CL makes no guarantees that code like this will be turned into an iterative process. Many implementations do so, but a conforming implementation need not, and even implementation which do so may not always do so, for instance in interpreted code or code compiled for ease of debugging. So a minimum function like the above is not really very idiomatic CL, and is certainly not completely safe if the code is meant to be portable.
However that is not my goal in this answer: one of the important things that you should get from learning lisp, in my opinion, is the ability to think inductively about solving problems. In other words to think about a class of problems which can be solved by starting from a simple base case and then steps which get from some general case closer to the base case, and then expressing this in code. This is a very different approach to programming than the approach which is natural in more imperative languages, and once you understand it it's a very powerful way of thinking.
As someone whose first serious language was FORTRAN (in the days when that was the correct way of writing its name even!) I think that this inductive approach is very important, and it's that which I wanted to get across here.
(defun smaller (x y)
"returns the smaller number"
(if (> x y)
y
x))
(defun minimum (list)
"returns the smallest number of a list"
(do* ((numbers list (rest numbers))
(result
(first numbers)
(if numbers
(smaller result (first numbers))
result)))
((null numbers) result)))
First of all, as pointed above, you should use do* instead of do, in order to bind the variables sequentially.
Second, you are testing (null numbers) to end the loop. However, when only one element is left to process, numbers is not nil but then it becomes (cdr numbers) which is nil. This nil value is what is being passed to *smaller* as second argument, and that's why you get the error message. To avoid this, you should test for (null (cdr numbers)) instead:
(defun *smaller* (x y)
( if (> x y) y
x))
(defun *minimum* (lst)
(do* ((numbers lst (cdr numbers))
(result (car numbers) (*smaller* result (car numbers))))
((null (cdr numbers)) result)))
This exits the loop when there is only one item left in the list.

setf seems to change both its arguments when they are given by aref

In Lisp, I've defined an array a and then let b be equal to a. I now want to redefine an entry of b to be equal to a different entry in a, like this:
(setf a (make-array '(2 2) :initial-contents '((1 2) (3 4))))
(setf b a)
(setf (aref b 0 0) (aref a 0 1))
So now, b will be #2A((2 2) (3 4)), which is all well and good. But what puzzles me is that a is also now #2A((2 2) (3 4)).
My question is this: why has applying setf to an entry of b changed a as well? I can get around this by introducing an intermediate variable with (setf x (aref a 0 1)) and then applying (setf (aref b 0 0) x), but this seems like a strange workaround to me.
Your (setf b a) in the second line does what is sometimes called a shallow copy in other languages. That is, b does not become an independent copy of the array a, but rather becomes just another name for the exact same array. As a result, when you modify b, you are modifying a as well.
If you want b to be a true, independent copy ("deep copy") of the array, then you'll need to allocate a new array and copy the elements of a into it. One way to do this is for 1-dimensional arrays is with the copy-seq function. For fancier arrays you might also look at this question about how to copy 2d arrays which talks about some available libraries and approaches.

a `let' binding is not available for subsequent `let' bindings?

I learn Emacs Lisp, because I want to customize my editor and to be clear I am little bit stuck with how Dynamic binding works.
Here is example:
(setq y 2)
(let ((y 1)
(z y))
(list y z))
==> (1 2)
As a result I get back => (1 2)
Please could some one explain what actually going on. I tried to explain it for my self using concept of frames where each frame create local binding, but it seems like here it works in different way.
Why it doesn't take closest value of 'y' in the nearest frame?
If could describe in details what is going here, I will be so happy.
Thanks in advance. Nick.
In emacs lisp (as in many lisps), the values that will be bound in let are computed in parallel, in the environment "outside" the let.
As an example, the following is (approximately) equivalent:
(let ((a b)
(b a))
...)
=>
(funcall (lambda (a b) ...) b a)
If you want to bind things in sequence, you should use let*, which does what you expected let to do.
Your example seems to be taken straight from the Emacs Lisp Reference. If you scroll down to let*, you'll get the explanation:
This special form is like let, but it binds each variable right after
computing its local value, before computing the local value for the
next variable. Therefore, an expression in bindings can refer to the
preceding symbols bound in this let* form. Compare the following
example with the example above for let:
(setq y 2)
⇒ 2
(let* ((y 1)
(z y)) ; Use the just-established value of y.
(list y z))
⇒ (1 1)
The problem is solved if You use let* which allows You to use the let-mentioned vars:
(setq y 2)
(let* ((y 1)
(z y))
(list y z))
==> (1 1)
The value of y you are setting in the let us only in effect in the BODY of the let, it is not yet in effect yet when you set z in the same let statement.

Problems with Nth in common lisp

I'm trying to write a function that can calculate GPA. Now I can do limited calculation(only 3 ),but I stuck on how to calculate more , without using loop or recursion (that's the requirement of subject) how to expend nth function? like: (nth n) ,if so ,is that mean i need to write a lambda expression? As an newbie, I maynot describe the question clearly, really need some help..
Glist is grade points Clist is credit hours.
GPA=( gradepoint *credithour + gradepoint *credithour) / ( the sum of credithour) like: (3*1+3*2+4*1)/(1+2+1)
here is my code:
(defun gpa (Glist Clist)
(format t "~3,2f~%"
(/
(+(nth 0 (mapcar #' * Glist Clist))
(nth 1 (mapcar #' * Glist Clist))
(nth 2 (mapcar #' * Glist Clist)))
(+ (nth 0 Clist)
(nth 1 Clist)
(nth 2 Clist))
);end "/"
);end "format"
(values) );end
EDIT
This seems like a good opportunity to emphasize some common (little c) Lisp ideas, so I fleshed out my answer to illustrate.
As mentioned in another answer, you could use a sum function that operates on lists (of numbers):
(defun sum (nums)
(reduce #'+ nums))
The dot product is the multiplicative sum of two (equal-length) vectors:
(defun dot-product (x y)
(sum (mapcar #'* x y)))
The function gpa is a simple combination of the two:
(defun gpa (grades credits)
(/ (dot-product grades credits) (sum credits)))
The example from the question results in the answer we expect (minus being formatted as a float):
(gpa '(3 3 4) '(1 2 1))
> 13/4
There are a few things worth mentioning from this example:
You should learn about map, reduce, and their variants and relatives. These functions are very important to Lisp and are very useful for operating on lists. map* functions generally map sequences to a sequence, and reduce usually transforms a sequence into to a single value (you can however use forms like (reduce #'cons '(1 2 3))).
This is a good example of the "bottom-up" approach to programming; by programming simple functions like sum that are often useful, you make it easy to write dot-product on top of it. Now the gpa function is a simple, readable function built on top of the other two. These are all one-liners, and all are easily readable to anyone who has a basic knowledge of CL. This is in contrast to the methodology usually applied to OOP.
There is no repetition of code. Sure, sum is used more than once, but only where it makes sense. You can do very little more to abstract the notion of a sum of the elements of a list. It's more natural in Scheme to write functions with functions, and that's a whole different topic. This is a simple example, but no two functions are doing the same thing.
If you're using nth to traverse a list, you're doing it wrong. In this case, you might want to write a summing function:
(defun sum (items)
(reduce #'+ items))

Conditional anaphoric collection best practices?

I trying to iterate through a sequence, conditionally perform an operation on each element and then collect it (but only if it matched the criteria). Here is a simplified example that works, I just want to know if this is proper or best practice in lisp:
(loop for n in '(1 2 3 4 5)
when (when (equal (mod n 2) 0) n )
collect it)
yields
(2 4)
This works, it just looks funny to me and not so much of the when-when but because I feel like I am having to rig the condition to return what I want. I get that the anaphoric it works on the evaluation of the when but this just seems a little artificial to me. Am I missing something? I have only been a lisper for a few weeks.
Edit: Actually, I am somewhat confused when I tried to apply this. What I really want to do is this:
(loop for n in '(1 2 3 4 5)
when (when (equal (mod n 2) 0) n)
collect it
do (format t "~A" it))
but the second it seems to become unbound... how do I do this?
I don't see why you need anaphor here.
(loop for n in '(1 2 3 4 5)
when (evenp n)
collect n and
do (format t "~A" n))
Delete the keyword AND if you want the FORMAT unconditionally.