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.
Related
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 am making a console Lisp survival game and I am trying to add a function where until a = b, show "." every second. Then, when a = b, set a "hurt" variable to true, and if/when that variable is true, subtract "health" by 1 until the "use-medkit" function is invoked by the user and the "hurt" variable is set false and you exit both loops.
The problem I am having is when I am prompted to use the "use-medkit" function and I type it in, it doesn't evaluate anything that I input and keeps subtracting 1 from "health". How can I call a user-inputted function while a loop is running?
Here is my code:
(setq a (random 11)) ; Random from 0 - 10
(setq b (random 11)) ; ^^^^^^^^^^^^^^^^^^
(setq hurt 0)
(setq repair 0)
(setq health 999)
(defun use-medkit ()
(setq repair 1))
(defun get-hurt ()
(loop
(progn
(setq a (random 11))
(setq b (random 11))
(progn
(princ ".")
(sleep 1)))
(if (eq a b) (progn
(setq hurt 1)
(when (eq hurt 1) (progn
(format t "~%You are hurt!~%You will lose 1 hp every 10 seconds~%~%Type use-medkit to stop the bleeding~%")
(loop
(progn
(- 1 health)
(sleep 10))
;(format t "health: ~A~%" health)
(when (eq repair 1) (progn
(return "You stopped the bleeding") (setq hurt 0) (setq repair 0))))))))))
So a program can’t do two things at once. In particular if you’re busy printing dots, sleeping and subtracting 1 from 999 then you won’t pause to see if there’s another command coming.
Unfortunately solving this problem is hard. The nicest solution in a terminal would probably use something like ncurses. Additionally there is no standard way to control input buffering. In lieu of that, here is a simple way you can do a bit of concurrency and some prompts. You might want to use a proper async library instead.
(defun maybe-read (input-stream recording-stream)
(when (listen input-stream)
(let ((char (read-char input-stream)))
(if (char= char #\Newline)
t
(progn (write-char char recording-stream) (maybe-read))))))
(defun make-partial-reader (input-stream)
(list input-stream (make-string-output-stream)))
(defun partial-read (reader)
(when (apply #'maybe-read reader)
(get-output-stream-string (second reader))))
(defun how-long-until (time)
(let ((gap
(/ (- time (get-internal-run-time)) internal-time-units-per-second)))
(cond ((< gap 0) (values 0 :late))
((<= gap 0.001) (values 0 :now))
(T (values (- gap 0.001) :soon)))))
(defun sleep-until (time)
(multiple-value-bind (span type)
(how-long-until time)
(when (> span 60) (warn “long wait!”)
(case type
(:late nil)
(:now t)
(:soon
(sleep span)
(unless (sleep-until time) (warn “poor timekeeping”))
t))))
(defmacro with-prompt-and-scheduler ((schedule) (line &optional (input *standard-input*)) &body handle-line-input)
(let ((reader (gensym)) (insched (gensym)))
`(let ((,reader (make-partial-reader ,input) (,insched)))
(flet ((,schedule (in fun &aux (at (+ (get-internal-run-time) (* in internal-time-units-per-second))))
(if (null ,insched) (push (cons at fun) schedule)
(loop for s on ,insched
for ((at2) . y) = s
if (< at at2)
do (psetf (car s) (cons at fun)
(cdr s) (cons (car s) (cdr s)))
(finish-loop)
unless y do (setf (cdr s) (acons at fun nil)) (finish-loop)))))
(loop
(if ,insched
(let ((,insched (pop ,insched)))
(when (sleep-until (car ,insched))
(let ((,line (partial-read ,reader)))
(when ,line ,#handle-line-input)))
(funcall (cdr ,insched)))
(let ((,line (concatenate 'string (get-output-stream-string (second ,reader)) (read-line (first ,reader)))))
,#handle-line))))))))
And then you could use it like:
(let ((count 0))
(with-prompt-and-scheduler (schedule) (line)
(let ((n (read-from-string line)))
(when (realp n)
(schedule n (let ((x (incf count))) (lambda () (format t "Ding ~a ~a~%" x count) (finish-output))))))))
And after running that input 10, then on the next line 5. If you do that quickly you’ll get:
Ding 2 2
Ding 1 2
With the first line appearing after 5 seconds and the second after 10. If you are slow you should get:
Ding 1 1
Ding 2 2
With the first line coming 10 seconds after you enter 10 and the second line coming 5 seconds after you enter 5.
Hopefully this can give you an idea of how to make a program seem to do two things at once.
I am going through a practice exam for my programming languages course. One of the problems states:
Define a function named function+ that “adds” two functions together and returns this composition. For example:
((function+ cube double) 3)
should evaluate to 216, assuming reasonable implementations of the functions cube and double.
I am not sure how to approach this problem. I believe you are supposed to use the functionality of lambdas, but I am not entirely sure.
If you need a procedure which allows you two compose to unary procedures (procedure with only 1 parameter), you'll smack yourself in the head after seeing how simple the implementation is
(define (function+ f g)
(λ (x) (f (g x))))
(define (cube x)
(* x x x))
(define (double x)
(+ x x))
((function+ cube double) 3)
;=> 216
Basically if you need to do that you just do (x (y args ...)) so if you need to have a procedure that takes two arguments proc1 and proc2 returns a lambda that takes any number of arguments. You just use apply to give proc1 arguments as a list and pass the result to proc2. It would look something like this:
(define (compose-two proc2 proc1)
(lambda args
...))
The general compose is slightly more complicated as it takes any number of arguments:
#!r6rs
(import (rnrs))
(define my-compose
(let* ((apply-1
(lambda (proc value)
(proc value)))
(gen
(lambda (procs)
(let ((initial (car procs))
(additional (cdr procs)))
(lambda args
(fold-left apply-1
(apply initial args)
additional))))))
(lambda procs
(cond ((null? procs) values)
((null? (cdr procs)) (car procs))
(else (gen (reverse procs)))))))
(define (add1 x) (+ x 1))
((my-compose) 1) ;==> 1
((my-compose +) 1 2 3) ; ==> 6
((my-compose sqrt add1 +) 9 15) ; ==> 5
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))))))
I'm working on a function that takes in a list of structures and then using that list of structures produces a function that processes a list of symbols into a number. Each structure is made up of a symbol, that will be in the second list consumed, and a number. This function produced has to turn the list of symbols into a number by assigning each symbol a value based on the previous structures. Using abstract list functions btw.
Example: ((function (list (make-value 'value1 10) (make-value 'value2 20)))
(list 'value1 'value2 'nothing 'value1)) would produced 40.
Heres my code but it only works for specific cases.
(define (function lst)
(lambda (x) (foldr + 0 (map (lambda (x)
(cond
[(equal? x (value-name(first lst)))(value-value (first lst))]
[else (value-value (second lst))]))
(filter (lambda (x) (member? x (map value-name lst)))x)))))
Looks like a homework. Basic shape of your solution is ok. I think the reason you have a problem here is that there is no decomposition in your code so it's easy to get lost in parentheses.
Let's start with your idea of fold-ing with + over list of integers as a last step of computation.
For this subtask you have:
1) a list of (name, value) pairs
2) a list of names
and you need to get a list of values. Write a separate function which does exactly that and use it. Like this
(define (function lst)
(lambda (x) (foldr +
0
(to-values x lst)))
(define (to-values names names-to-values)
(map (lambda (name)
(to-value name names-to-values))))
(define (to-value n ns-to-vs)
...)
Here we map over the names with another little function. It will lookup the n value in ns-to-vs and return it or 0 if there is no one.
There are two approaches for solving the problem with foldr, it'd be interesting to study and understand both of them. The first one, attempted in the question, is to first produce a list with all the values and let foldr take care of adding them. It can be implemented in a simpler way like this:
(define (function lst)
(lambda (x)
(foldr +
0
(map (lambda (e)
(cond ((assoc e lst) => value-value)
(else 0)))
x))))
Alternatively: maybe using foldr is overkill, applying + is simpler:
(define (function lst)
(lambda (x)
(apply +
(map (lambda (e)
(cond ((assoc e lst) => value-value)
(else 0)))
x))))
In the second approach we take the input list "as is" and let foldr's lambda perform the addition logic. This is more efficient than the first approach using foldr, because there's no need to create an intermediate list - the one generated by map in the first version:
(define (function lst)
(lambda (x)
(foldr (lambda (e a)
(cond ((assoc e lst) => (lambda (p) (+ a (value-value p))))
(else a)))
0
x)))
In both approaches I'm using assoc for finding the element in the list; it's easy to implement as a helper function if you're not allowed to use it or if it doesn't work for the values created with make-value: assoc takes a list of name-value pairs and returns the first pair with the given name. The => syntax of cond passes the pair returned by assoc to a lambda's parameter and executes it.
And because you're using Racket, there's a bit of syntactic sugar that can be used for returning a function from another function, try this equivalent code, for simplicity's sake:
(define ((function lst) x)
(foldr +
0
(map (lambda (e)
(cond ((assoc e lst) => value-value)
(else 0)))
x)))
Or this:
(define ((function lst) x)
(foldr (lambda (e a)
(cond ((assoc e lst) => (lambda (p) (+ a (value-value p))))
(else a)))
0
x))
Anyway, the result is as expected:
((function (list (make-value 'value1 10) (make-value 'value2 20)))
(list 'value1 'value2 'nothing 'value1))
=> 40