This question already has answers here:
Why does an elisp local variable keep its value in this case?
(3 answers)
Why does this function return a different value every time?
(4 answers)
Closed 5 years ago.
I just stumbled across this phenomenon while trying to implement a simple function that is counting the number of letters in a list.
This is the code:
(defun countit (liste)
(let* ((*dict* '((a 0)(b 0) (c 0) (d 0) (e 0) (f 0) (g 0) (h 0) (i 0)
(j 0) (k 0) (l 0) (m 0) (n 0) (o 0) (p 0) (q 0)(r 0)
(s 0) (t 0) (u 0) (v 0) (w 0) (x 0) (y 0) (z 0))))
(dolist (i liste *dict*)
(incf (second (assoc i *dict*))))))
Interestingly if I run this functon several times the *dict* keeps the numbers from the last call.
So running (countit '(a a)) and then again (countit '(a a)) yields (a 4) as a result which I don't quite get why because I'm defining a local environment with let for every function call, right?
Can someone explain to me why this is happening and how I can do it better without changing it too much?
Related
Hi I'm a beginner in Common Lisp. I want to check if two variables are integers. If both n and m are integers I want to it to return - if it is negative, 0 if it is zero, + if it is positive and NIL if it is not an integer for both n and m. I figured out how to do this with one variable but I can't seem to figure out how to do it with two variables. Thanks.
This is the code that takes a numeric argument and returns - if it is negative, 0 if it is zero, + if it is positive and NIL if its not an integer:
(defun sign (n)
(if(typep n 'integer)
(cond ((< n 0) '-)
((= n 0) 0)
((> n 0) '+))))
The output for each case is:
CL-USER> (sign 3)
+
CL-USER> (sign -3)
-
CL-USER> (sign 0)
0
CL-USER> (sign 3.3)
NIL
This is the code I have for checking two variables which I want it to check if n and m are integers and if n and m are positive, negative or a zero:
(defun sign (n m)
(if (and (typep n 'integer) (typep m 'integer))
(cond (and ((< n 0) '-) ((< m 0) '-))
(and ((= n 0) 0) ((= m 0) 0))
(and ((> n 0) '+) ((> m 0) '+)) ))))
Remember basic Lisp syntax. Function calls and some basic expressions are written as
(operator argument-0 argument-1 ... argument-n)
Right?
open parenthesis, operator, argument-0 argument-1 ... argument-n, closing parenthesis.
Now if we have (< n 0) and (< m 0) how would an AND expressions look like?
(and (< n 0) (< m 0))
But you write:
and ((< n 0) '-) ((< m 0) '-)
You have these mistakes:
no parentheses around the AND expression.
extra parenthesis around the argument expressions.
'- mixed into the argument expressions.
Now COND expects:
(COND (testa1 forma0 forma1 ... forman)
(testb1 formb1 formb1 ... formbn)
...
(testm1 formm0 formm1 ... formmn))
So instead of
(defun sign (n m)
(if (and (typep n 'integer) (typep m 'integer))
(cond (and ((< n 0) '-) ((< m 0) '-))
(and ((= n 0) 0) ((= m 0) 0))
(and ((> n 0) '+) ((> m 0) '+)))))
Btw, there was an extra parenthesis at the end.
We write:
(defun sign (n m)
(if (and (typep n 'integer) (typep m 'integer))
(cond ((and (< n 0) (< m 0)) '-)
.... )))
It's also possible to use predicates like integerp, minusp, zerop and plusp.
You can use the already functioning and tested sign definition - which is typical for the way, lispers program. The first naive solution would be:
(defun sign-for-two (n m)
(when (eql (sign n) (sign m))
(sign n))
;; (if (condition) return-value NIL)
;; is equivalent to
;; (when (condition) return-value)
Note, in common lisp it is important,
which equality test you choose:
;; only symbols - for object identity eq
;; symbols or numbers - for object identity eql
;; (in most tests the default)
;; eql for each component? also in lists equal
;; equal not only lists but also
;; arrays (vectors, strings), structures, hash-tables
;; however case-insensitive in case of strings
;; equalp
;; mathematical number equality =
;; specifically characters char=
;; case-sensitive string equality string=
In our case, eql is sufficient.
;; to avoid `(sign n)` to be evaluated twice,
;; you could store it using `let`
;; and call from then on the stored value
;; (which is less costly).
(defun sign-for-two (n m)
(let ((x (sign n)))
(when (eql x (sign m))
x)))
Or create an equality tester (default test function: #'eql)
which returns the equally tested value
and if not equal, NIL:
(defun equality-value (x y &key (test #'eql))
(when (funcall test z y) z)))
;; and apply this general solution to our case:
(defun sign-for-two (n m)
(equality-value (sign n) (sign m)))
and you can apply the equality-value function
in future for functions where you want to
return the value when tested as "equal"
and you can give the function via :test whatever equality
function other than eql is suitable for that case, like
(equality-value string1 string2 :test #'string=)
It looks like you have the right approach and just got lost in the parentheses. Each of your cond cases looks like
(and ((< n 0) '-) ((< m 0) '-))
I think you meant
((and (< n 0) (< m 0)) '-)
and the same thing for the other two cases.
Another compact way to write sign is to use the standard function signum which
returns one of -1, 0, or 1 according to whether number is negative,
zero, or positive
The code could look like:
(defun sign (n)
(when (integerp n)
(case (signum n)
(-1 '-)
(0 0)
(1 '+))))
I need to write procedure for calculation of weighted sum in follow functionality:
((weighted-sum 1) 5)
5
((weighted-sum 1/2 1/2) 3 1)
2
etc..
So far I did only how to get parameters for procedure:
(define (weighted-sum x . xn) (cons x xs))
(weighted-sum 2 3)
> '(2 3)
How to get ((weighted-sum 2 3) X X) parameters?
Thank you.
Your question doesn't have one easy answer. It sounds like you're supposed to write a function that accepts a sequence of weights, and returns a function that accepts a sequence of weights, and sums the products of the weights and the sums (by the way, stating this yourself would have been really helpful...).
1) Is this your design, or someone else's? I would not design this function this way.
2) You can write functions that return functions in a bunch of different ways. E.g.:
;; these all do the same thing.
;; they all have the type (number -> (number -> number))
(define a (lambda (x) (lambda (y) (+ x y))))
(define ((a x) y) (+ x y))
(define (a x)
(define (b y) (+ x y))
b)
So weighted-sum takes a variable number of values as parameters (let's call them ws) , and returns a new procedures that, in its turn, takes a variable number of parameters (vs) and does the calculation.
In racket, the for/fold construct comes in handy:
(define (weighted-sum . ws)
(lambda vs
(for/fold ((res 0)) ((i (in-list ws))
(j (in-list vs)))
(+ res (* i j)))))
or even
(define ((weighted-sum . ws) . vs)
(for/fold ((res 0)) ((i (in-list ws))
(j (in-list vs)))
(+ res (* i j))))
Alternatively, using a more classic foldl returning a named inner procedure:
(define (weighted-sum . ws)
(define (sub . vs)
(foldl
(lambda (i j res) (+ res (* i j)))
0
ws
vs))
sub)
For any of those:
> ((weighted-sum 1) 5)
5
> ((weighted-sum 1/2 1/2) 3 1)
2
This procedure takes a non-negative integer n and creates a list of all lists of n 0's or 1's in the specific order required for a truth table. I am just trying to understand how the map portion of the procedure works. I am particularly confused as to how append, map, and the recursive call to all-lists are working together in the second argument of the if. Any help would be greatly greatly appreciated!
(define all-lists
(lambda (n)
(if (= n 0)
'(())
(append (map (lambda (k) (cons 0 k)) (all-lists (- n 1)))
(map (lambda (k) (cons 1 k)) (all-lists (- n 1)))
))))
The best strategy to understand a recursive function is to try it with the case sligthly more complex than the terminal one. So, let's try it with n=1.
In this case, the function becomes:
(append (map (lambda (k) (cons 0 k)) (all-lists 0))
(map (lambda (k) (cons 1 k)) (all-lists 0))
that is:
(append (map (lambda (k) (cons 0 k)) '(()))
(map (lambda (k) (cons 1 k)) '(())))
So, the first map applies the function (lambda (k) (cons 0 k)) to all the elements of the list '(())), which has only an element, '(), producing '((0)) (the list containing an element obtained by the cons of 0 and the empty list), and in the same way the second map produces '((1)).
These lists are appended together yielding the list '((0) (1)), in other words, the list of all the lists of length 1 with all the possible combinations of 0 and 1.
In the case of n=2, the recursive case is applied to '((0) (1)): so the first map puts a 0 before all the elements, obtaining '((0 0) (0 1)), while the second map produces '((1 0) (1 1)). If you append together these two lists, you obtain '((0 0) (0 1) (1 0) (1 1)), which is the list of all the possible combinations, of length 2, of 0 and 1.
And so on, and so on...
Actually, the function is not well defined, since it calculates unnecessarily the value of (all-lists (- n 1)) two times at each recursion, so doubling its work, which is already exponential. So it could be made much more efficient by computing that value only once, for instance in the following way:
(define all-lists
(lambda (n)
(if (= n 0)
'(())
(let ((a (all-lists (- n 1))))
(append (map (lambda (k) (cons 0 k)) a)
(map (lambda (k) (cons 1 k)) a))))))
Separating statements along with 'println' can help understand what is happening:
(define (all-lists n)
(if (= n 0)
'(())
(let* ((a (all-lists (- n 1)))
(ol1 (map (λ (k) (cons 0 k)) a))
(ol2 (map (λ (k) (cons 1 k)) a))
(ol (append ol1 ol2)))
(println "---------")
(println ol1)
(println ol2)
(println ol)
ol)))
(all-lists 3)
Output:
"---------"
'((0))
'((1))
'((0) (1))
"---------"
'((0 0) (0 1))
'((1 0) (1 1))
'((0 0) (0 1) (1 0) (1 1))
"---------"
'((0 0 0) (0 0 1) (0 1 0) (0 1 1))
'((1 0 0) (1 0 1) (1 1 0) (1 1 1))
'((0 0 0) (0 0 1) (0 1 0) (0 1 1) (1 0 0) (1 0 1) (1 1 0) (1 1 1))
'((0 0 0) (0 0 1) (0 1 0) (0 1 1) (1 0 0) (1 0 1) (1 1 0) (1 1 1))
One can clearly see how outlists (ol1, ol2 and combined ol) are changing at each step.
For class, I have to write a function that takes positive integer n and returns the sum of n’s odd digits in scheme. So far, I have my base case such that if n equals 0 then 0. But I am not sure on how to continue.
(define sumOddDigits
(lambda (n)
(if (= n 0)
0
Test cases:
(sumOddDigits 0) → 0
(sumOddDigits 4) → 0
(sumOddDigits 3) → 3
(sumOddDigits 1984) → 10
You could do it efficiently using one functional loop:
(define (sumOddDigits n)
(let loop ([n n])
(cond [(zero? n) 0]
[else
(let-values ([(q r) (quotient/remainder n 10)])
(+ (if (odd? r) r 0)
(loop q)))])))
One can get list of digits using following function which uses 'named let':
(define (getDigits n)
(let loop ((ol '()) ; start with an empty outlist
(n n))
(let-values (((q r) (quotient/remainder n 10)))
(if (= q 0) (cons r ol)
(loop (cons r ol) q)))))
Then one can apply a filter using odd? function to get all odd elements of list- and then apply 'apply' function with '+' to add all those elements:
(apply + (filter
(lambda(x)
(odd? x))
digitList))
Together following can be the full function:
(define (addOddDigits N)
(define (getDigits n)
(let loop ((ol '())
(n n))
(let-values (((q r) (quotient/remainder n 10)))
(if (= q 0) (cons r ol)
(loop (cons r ol) q)))))
(define digitList (getDigits N))
(println digitList)
(apply + (filter
(lambda(x)
(odd? x))
digitList)))
Testing:
(addOddDigits 156)
Output:
'(1 5 6)
6
Your basecase is if n < 10. Because you are then on the last digit.
You then need to check if it's odd, and if so return it. Else, return the addition qualifier(0).
If n > 10, you remainder off the first digit, then test it for odd.
If odd, then add it to a recursive call, sending in the quotient of 10(shaves off the digit you just added).
Else, you recursively call add-odds with the quotient of 10, without adding the current digit.
Here it is in a recursive form(Scheme LOVES recursion) :
(define add-odds
(lambda (n)
(if(< n 10)
(if(= (remainder n 2) 1)
n
0)
(if(= (remainder (remainder n 10) 2) 1)
(+ (remainder n 10) (add-odds (quotient n 10)))
(add-odds(quotient n 10))))))
First get a (reversed) list of digits with simple recursive implementation:
(define (list-digits n)
(if (zero? n) '()
(let-values ([(q r) (quotient/remainder n 10)])
(cons r (list-digits q)))))
then filter the odd ones and sum them:
(define (sum-of-odd-digits n)
(apply + (filter odd? (list-digits n))))
Note: (list-digits 0) returns '() but it is ok for later usage.
More accurate list-digits iterative implementation (produce list of digits in right order):
(define (list-digits n)
(define (iter n acc)
(if (zero? n) acc
(let-values ([(q r) (quotient/remainder n 10)])
(iter q (cons r acc)))))
(iter n '()))
This question already has answers here:
Recursive euclidean distance
(2 answers)
Closed 7 years ago.
I am to write a recursive function to find the euclidean distance given 2 list that is assumed to be of equal size always. The 2 list represents the vectors.
So below is my code but am missing the final step which is to square root the whole result after the last recursive call. Can I do so without introducing any variables?
(defun distance (l1 l2)
(if (null l1)
0
(+ (expt (- (first l1) (first l2)) 2)
(distance (rest l1) (rest l2)))))
EDIT: I tried the answers from the suggested page and I get an error while testing it.
It says The variable SQ-EUCLIDEAN-DISTANCE is unbound.
(defun sq-euclidean-distance-rec (p q)
(if (null p)
0
(+ (expt (- (first p) (first q)) 2)
(sq-euclidean-distance-rec (rest p) (rest q)))))
(defun euclidean-distance-rec (p q) (sqrt sq-euclidean-distance p q))
func distance(l1, l2):
if l1 == null || l2 == null
return 0
else
return sqrt((l1.first - l2.first) * (l1.first - l2.first) + distance(rest(l1), rest(l2)))