does anybody know how can I create a function in Scheme that takes no arguments and everytime I call it returns 0 or 1, depending on how many times it's been called? For example, the 1st time returns 1, the 2nd 0, the 3rd 1, etc.
I suppose I have to use a local variable inside the function, but I don't know exactly how, so that it changes value everytime I call it.
You didn't say how you are calling your function. Did you define some named function as the lambda you return with you make-flip function? I guess this is "making closures 101" but it's the first time I've done to my recollection. Anyway, I tried this way and it seemed to work:
(define (make-flipper)
(let ((flip 0))
(lambda ()
(set! flip (if (= flip 0) 1 0))
flip)))
(define doit (make-flipper))
(doit)
(doit)
(doit)
--results in 1, then 0, then 1. I guess you could change the value in the let if you want it to start with 0.
Your code doesn't work because you're overusing parentheses, which makes your code try to call "procedures" that aren't procedures.
Your code,
(define (make-flip)
(let ((x 1))
(lambda ()
((set! x (- 1 x))
(if (= x 0) (1) (0))))))
attempts the procedure calls (0) and (1), and it also tries to "call" the result of the sequence
(set! x (- 1 x))
(if (= x 0) (1) (0)))
(Scheme never ignores any parentheses the way some other languages do.)
If you fix those,
(define (make-flip)
(let ((x 1))
(lambda ()
(set! x (- 1 x))
(if (= x 0) 1 0))))
it works.
The conditional isn't necessary though, you can also say
(define (make-flip)
(let ((x 0))
(lambda ()
(set! x (- 1 x))
x)))
and get the same result.
If you only need one procedure of this kind, you can also do as follows:
(define flip
(let ((x 1))
(lambda ()
(begin0
x
(set! x (- 1 x))))))
Testing:
> (flip)
1
> (flip)
0
> (flip)
1
> (flip)
0
Related
You can notice the v in the lambda in the function body, where is the v coming from, what it is based on?
(define (cached-assoc xs n)
(letrec ([memo (make-vector n #f)]
[acc 0]
[f (lambda(x)
(let ([ans (vector-assoc x memo)])
(if ans
(cdr ans)
(let ([new-ans (assoc x xs)])
(begin
(vector-set! memo acc (cons x new-ans))
(set! acc (if (= (+ acc 1)) 0 (+ acc 1)))
new-ans)))))])
(lambda (v) (f v))))
The whole expression is returning a lambda as a result, and in that lambda there's a formal parameter named v. It doesn't have a value yet, you'll need to call the lambda to bind a value to v and produce a result (assuming the code is working):
((letrec ([memo (make-vector n #f)] ; notice the extra opening `(`, we want to call the returned lambda
[acc 0]
[f (lambda(x)
(let ([ans (vector-assoc x memo)])
(if ans
(cdr ans)
(let ([new-ans (assoc x xs)])
(begin
(vector-set! memo acc (cons x new-ans))
(set! acc (if (= (+ acc 1)) 0 (+ acc 1)))
new-ans)))))])
(lambda (v) (f v)))
10) ; <- the value 10 gets bound to `v`
However, your code isn't right. You are referring to variables named n and xs, but they are not defined anywhere and need a value of their own. The procedure vector-assoc doesn't exist. Also, the lambda at the end is redundant, you could simply return f, there's no need to wrap it in an additional lambda. Finally: you should define the whole expression with a name, it'll make it easier to call it.
I won't go into more details because first you need to fix the function and make it work, and is not clear at all what you want to do - but that should be a separate question.
I asked a similar question before, I just want to make sure I understand the idea, in the -lambda(x)- line 4, what is the x, where it is coming from?
(define (cached-assoc xs n)
(letrec ([memo (make-vector n #f)]
[acc 0]
[f (lambda(x)
(let ([ans (vector-assoc x memo)])
(if ans
(cdr ans)
(let ([new-ans (assoc x xs)])
(begin
(vector-set! memo acc (cons x new-ans))
(set! acc (if (= (+ acc 1)) 0 (+ acc 1)))
new-ans)))))])
f))
Your cached-assoc procedure returns f, a function which has x as an unbound parameter. It doesn’t have a value yet, the value will be whatever you pass to it when you finally invoke it:
((cached-assoc xs n) 10)
In the above example x will be bound to 10, and xs and n will be whatever you defined for them before calling cached-assoc. I believe the source of the confusion is the fact that cached-assoc is returning a lambda, once you understand this it'll be clear.
I'm new to lisp, trying to understand how lisp works, and I don't know how exactly to work with a local variable inside a large function.
here I have a little exc that I send a number to a function and if it is divisible by 3, 5 and 7 I must return a list of (by3by5by7), if only by 7, return (by7) and so on....
here is my code:
(defun checknum(n)
let* (resultt '() ) (
if(not(and(plusp n ) (integerp n))) (cons nil resultt) (progn
(if (zerop (mod n 7)) (cons 'by7 resultt) (cons nil resultt))
(if (zerop (mod n 5)) (cons 'by5 resultt) (cons nil resultt))
(if (zerop (mod n 3)) (cons 'by3 resultt) (cons nil resultt) )) ))
but if i send 21 for ex, I only get nil, instead of (by3by7) I guess the local variable is not affected by my if statements and I don't know how to do it...
(cons x y) creates a new cons cell and disposes of the result. To change the value of a variable you need to use setq, setf, push or the like, for example:
(defun checknum (n)
(let ((resultt nil))
(when (and (plusp n) (integerp n))
(when (zerop (mod n 7)) (push 'by7 resultt))
(when (zerop (mod n 5)) (push 'by5 resultt))
(when (zerop (mod n 3)) (push 'by3 resultt)))
resultt))
or perhaps, more elegantly using an internal function to factor out the repetition:
(defun checknum (n)
(when (and (plusp n) (integerp n))
(labels ((sub (d nsym res)
(if (zerop (mod n d))
(cons nsym res)
res)))
(sub 7 'by7
(sub 5 'by5
(sub 3 'by3 nil)))))
Testing:
CL-USER> (checknum 12)
(BY3)
CL-USER> (checknum 15)
(BY3 BY5)
CL-USER> (checknum 105)
(BY3 BY5 BY7)
CL-USER> (checknum 21)
(BY3 BY7)
Most lisp forms/functions don't modify their arguments. The ones that do will be explicitly documented as doing so. See adjoin and pushnew, for instance, or remove and delete.
To the point of 'trying to understand how lisp works', writing the same function in various different ways helped me a lot, so you might want to think about how you can write your function without modifying a variable at all, and why and when you would want to / not want to use destructive modifications.
Something like the below makes two passes, and will be too slow if there are a large quantity of numbers you need to check, but doesn't destructively modify anything.
(defun checknum (n)
(remove nil
(mapcar #'(lambda (m sym)
(when (zerop (mod n m)) sym))
'(7 5 3)
'(by7 by5 by3))))
The above approach can be written to not require two passes, etc.
How do I assign anonymous functions to local variables in either cl, emacs lisp or clojure?
I've tried the following with no success.
(let ((y (lambda (x) (* x x)) )) (y 2))
and
((lambda (x) 10) (lambda (y) (* y y)))
In CL, you could use flet or labels.
(defun do-stuff (n)
(flet ((double (x) (* 2 x)))
(double n)))
(do-stuff 123) ;; = 246
As Chris points out, since double is not recursive, we should use flet, as the difference between the two is that labels can handle recursive functions.
Check out docs for info on labels, or this question for the difference between labels and flet.
I'm trying to find the first missing key in a hash table, that should contain keys [1 ... N], using Scheme.
So far, I have the following code:
(define (find-missing n ht)
(define c 1)
(let forVertices ()
(cond (not (hash-has-key? ht c))
(c)
)
(set! c (+ c 1))
(when (>= n c) (forVertices))
)
)
When I execute the function to test it, nothing is returned. What am I doing wrong?
You have a couple of problems with the parentheses, and the else case is missing. This should fix the mistakes:
(define (find-missing n ht)
(define c 1)
(let forVertices ()
(cond ((not (hash-has-key? ht c))
c)
(else
(set! c (+ c 1))
(when (>= n c)
(forVertices))))))
… But you should be aware that the way you wrote the procedure is not idiomatic, at all. In general, in Scheme you should avoid mutating state (the set! operation), you can write an equivalent procedure by correctly setting up the recursion and passing the right parameters. Also, it's a good idea to return something whenever the recursion exits (for instance: #f), otherwise your procedure will return #<void> if there are no keys missing. Here, this is what I mean:
(define (find-missing n ht)
(let forVertices ((c 1))
(cond ((> c n) #f)
((not (hash-has-key? ht c)) c)
(else (forVertices (+ c 1))))))