On Exercise (or entry?) 57, I'm just not understanding how the logic flows. The question is that this: given
(define teacupo
(lambda (x)
(conde
((= tea x ) #s)
((= cup x ) #s)
(else #u))))
where '=' is actually the triple-bar unify (?) operator. Running the following:
(run* (r)
(fresh (x y)
(conde
((teacupo x) (= #t y) #s)
((= #f x) (= #t y))
(else #u)
(= (cons x (cons y ())) r)))
the book gives the answer:
((tea #t) (cup #t) (#f #t))
I would have thought that the answer would have been:
(((tea cup) #t) (#f #t))
My reasoning being that the 'x' in (teacupo x) should have its conde go through all of its solutions first, and unify to the list of all of its solutions. But it appears that teacupo only gives up one of its solutions at a time. It confuses me because my interpretation of conde is that, using the rule it gives, is that you should go through the lines of conde, and after a line succeeds, pretend that it failed, refresh the variables and find the next line that succeeds. Given the way that the solution works, it seems like the conde in that code goes back to a successful line, then forcing the teacupo conde to fail and give up the next possible value. Again, I would have thought that the teacupo solution would give up all of its conde solutions in a list, and then move on in the outer conde call. Can anyone provide me guidance as to why it works as provided in the book and not in the way I reasoned?
My reasoning being that the 'x' in (teacupo x) should have its conde
go through all of its solutions first, and unify to the list of all of
its solutions.
The variable x is unified to one value at a time.
The form (run* (x) <goals>) collects values for x which fulfill the goals.
> (run* (x)
(teacupo x))
'(tea cup)
In
(conde
((teacupo x) (== #t y))
((== #f x) (== #t y)))
there is two ways to succeed: either the goal (teacupo x) is met and x is one of tea or cup -- or -- the goals (== #f x) is met, and x is (unified to) #f.
In short run* runs through the possible possible value for x one at time collecting those values that meets all goals. This means that x is unified to one value at a time.
A simpler example:
> (run* (x)
(fresh (y)
(== y 10)
(conde
[(== x 1) (== y 10)]
[(== x 2) (== y 20)]
[(== x 3) (== y 10)])))
'(1 3)
Full code for those who want to try the snippets in DrRacket:
#lang racket
(require minikanren)
(define-syntax succeed (syntax-id-rules () [_ (fresh (t) (== t t))]))
(run* (x)
(fresh (y)
(== y 10)
(conde
[(== x 1) (== y 10)]
[(== x 2) (== y 20)]
[(== x 3) (== y 10)])))
(define teacupo
(lambda (x)
(fresh (result)
(conde
((== 'tea x ) succeed)
((== 'cup x ) succeed)))))
(run* (x)
(teacupo x))
(run* (r)
(fresh (x y)
(conde
((teacupo x) (== #t y))
((== #f x) (== #t y)))
(== (cons x (cons y '())) r)))
(teacupo x) means "succeed twice: once with x unified with tea, and the second time with x unified with cup". Then,
(conde
((teacupo x) (= #t y) #s)
((= #f x) (= #t y)) ; you had a typo here
(else #u)
means,
for each solution produced by (teacupo x), also unify y with #t and succeed; and also
for each solution produced by (= #f x), also unify y with #t and succeed; and also
produce no more solutions
So each x in (tea cup) is paired up with y in (#t), and also x in (#f) is paired up with y in (#t), to form r; and then r is reported, i.e. collected into the final result list of solutions, giving ( (tea #t) (cup #t) (#f #t) ).
"it appears that teacupo only gives up one of its solutions at a time."
yes, this is exactly right, conceptually.
"after a line succeeds, pretend that it failed, refresh the variables and find the next line that succeeds."
yes, but each line can succeed a multiple number of times, if the conditional (or a subsequent goal) succeeds a multiple number of times.
"it seems like the conde in that code goes back to a successful line, then forcing the teacupo conde to fail and give up the next possible value."
it actually prepares to produce them in advance (but as a stream, not as a list), and then each is processed separately, fed through the whole chain of subsequent steps until either the last step is reached successfully, or the chain is broken, cut short by an #u or by an otherwise failed goal. So the next one is tried when the processing of a previous one has finished.
In pseudocode:
for each x in (tea cup):
for each y in (#t): ; does _not_ introduce separate scope for `y`;
collect (x y) ; `x` and `y` belong to the same logical scope
for each x in (#f): ; so if `x` is used in the nested `for` too,
for each y in (#t): ; its new value must be compatible with the
collect (x y) ; one known in the outer `for`, or else
for each _ in (): ; it will be rejected (x can't be two different
collect (x y) ; things at the same time)
As to why does it work this way, I can point you to another answer of mine, which might be of help (though it doesn't use Scheme syntax).
Using it, as an illustration, we can write your test as a Haskell code which is actually functionally equivalent to the book's code I think (in this specific case, of course),
data Val = Fresh | B Bool | S String | L [Val] deriving Show
type Store = [(String,Val)]
teacupo x = unify x (S "tea") &&: true -- ((= tea x ) #s)
||: unify x (S "cup") &&: true -- ((= cup x ) #s)
||: false -- (else #u)
run = [[("r", Fresh)]] -- (run* (r) ......
>>: (\s -> [ s ++: [("x", Fresh), ("y", Fresh)] ]) -- (fresh (x,y)
>>: -- (conde
( teacupo "x" &&: unify "y" (B True)
&&: true -- ((teacupo x) (= #t y) #s)
||: unify "x" (B False) &&: unify "y" (B True) -- ((= #f x) (= #t y))
||: false -- (else #u)
)
&&: project ["x", "y"] (unify "r" . L) -- (= r (list x y))
>>:
reporting ["r"] -- ...... )
reporting names store = [[a | a#(n,_) <- store, elem n names]]
with bare minimum implementation, just enough to make the above code work,
project vars kont store =
kont [val | var <- vars, (Just val) <- [lookup var store]] store
unify :: String -> Val -> Store -> [Store]
unify sym val store =
let
(Just v) = (lookup sym store)
in
case (val_unify v val) of
Just newval -> [replace_val sym newval store] -- [updated store], if unifies
Nothing -> [] -- couldn't unify - reject it
val_unify v Fresh = Just v -- barely working,
val_unify Fresh v = Just v -- initial
val_unify (B v) (B u) | v == u = Just (B v) -- implementation
| otherwise = Nothing
val_unify (S v) (S u) | v == u = Just (S v)
| otherwise = Nothing
val_unify _ _ = Nothing
replace_val s n ((a,b):c) | s == a = (a,n) : c
| otherwise = (a,b) : replace_val s n c
producing the output
*Main> run
[[("r", L [S "tea",B True])], [("r", L [S "cup",B True])], [("r", L [B False,B True])]]
And if we change the second line in the translated conde expression to
||: unify "x" (B False) &&: unify "x" (B True) -- ((= #f x) (= #t x))
we indeed get only two results,
*Main> run
[[("r", L [S "tea",B True])], [("r", L [S "cup",B True])]]
Related
I'm currently learning Clojure and am stuck with list comprehension.
;; https://stackoverflow.com/a/7625207/4110233
(defn gen-primes "Generates an infinite, lazy sequence of prime numbers"
[]
(letfn [(reinsert [table x prime]
(update-in table [(+ prime x)] conj prime))
(primes-step [table d]
(if-let [factors (get table d)]
(recur (reduce #(reinsert %1 d %2) (dissoc table d) factors)
(inc d))
(lazy-seq (cons d (primes-step (assoc table (* d d) (list d))
(inc d))))))]
(primes-step {} 2)))
(defn prime-factors-not-working [x]
(for [y (gen-primes)
:when (= (mod x y) 0)
:while (< y (Math/sqrt x))]
y))
(defn prime-factors-working [x]
(for [y (gen-primes)
:while (< y (Math/sqrt x))
:when (= (mod x y) 0)]
y))
(prime-factors-working 100)
;; ↪ (2 5)
(prime-factors-not-working 100)
;; Goes into infinite loop
(gen-primes) is a lazy sequence of prime numbers. The only difference between the working and not-working sequences is the order of the modifiers while and when. Why does the not-working implementation go into an infinite loop?
The not working variant expands conceptually (but not factually) into this:
(loop [ys (gen-primes)
result []]
(if (seq ys)
(let [y (first ys)]
(if (= (mod x (first ys)) 0) ;; Can be replaced with `(zero? (mod x y))` BTW.
(if (< y (Math/sqrt x))
(recur (next ys) (conj result y))
result)
(recur (next ys) result)))
result))
As you can see, if (mod x (first ys)) is not 0, it will go to the next number - without checking for that <, going forever.
When you exchange :when and :while, the checks in the pseudo-expansion above are also swapped - stopping the iteration once y reaches the square root of x.
the macro expansion of for is sensitive to the order in which you put :when and :while. macroexpanding gives slightly different code.
you can go very far in clojure without relying on complicated macros beyond defn, for is not very common, and this isn't a usecase where it is clearly advantagous over map->filter->take
good expansion: line 28:
(when (< y (Math/sqrt x)) ; XXX
(if (= (mod x y) 0) ; XXX
(do
(chunk-append b__86695 y)
(recur (unchecked-inc i__86694)))
(recur (unchecked-inc i__86694))))
bad expansion: line 28:
(if (= (mod x y) 0) ; XXX
(when (< y (Math/sqrt x)) ; XXX
(do
(chunk-append b__86666 y)
(recur (unchecked-inc i__86665))))
(recur (unchecked-inc i__86665)))
you can learn about the implementation of the for macro by going to it's source code (your editor should have a way for navigating to defs of symbols)
https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L4654
there is nothing about clojure that requires it's macros to write code in the way you think they should, though in this case it may be a bug in for, it's hard to tell. some use cases may want to be able to when while and when are written.
since this is about learning, and macros are pretty much magic unless you see the code they write out, i think the best way to learn is to figure out how to view the expanded macro forms in your code. this is generally how macros are debugged.
link to topic on macro expansion
how is a macro expanded in clojure?
documentation for expanding macros in cider (emacs clojure editor)
https://docs.cider.mx/cider/debugging/macroexpansion.html
i try to realize what this expiration, and don't get it.
( lambda (a b) (lambda (x y) (if b (+ x y a) (-x y a)))
i think,
a is a number, and b is #t or #f,
on the if statement we ask if b is true, if yes return first expression(sum 3 numbers), else the second(Subtract 3 numbers)
what i need to write on Racket to run this?
i try
(define question( lambda (a b) (lambda (x y) (if b (+ x y a) (-x y a)))))
and than
(question 5 #f)
and nothing not going well in this language.
This is not a complete answer as I don't want to do your homework for you.
First of all formatting and indenting your code is going to help you in any programming language. You almost certainly have access to an editor which will do this. Below I've done this.
So, OK, what does a form like (λ (...) ...) denote? Well, its a function which takes some arguments (the first ellipsis) and returns the value of the last form in its body (the second ellipsis), or the only form in its body in a purely functional language.
So, what does:
(λ (a b)
(λ (x y)
...))
Denote? It's a function of two arguments, and it returns something: what is the thing it returns? Well, it's a form which looks like (λ (...) ...): you know what those forms mean already.
And finally we can fill out the last ellipsis (after correcting an error: (-x ...) is not the same as (- x ...)):
(λ (a b)
(λ (x y)
(if b
(+ x y a)
(- x y a))))
So now, how would you call this, and how would you make it do something interesting (like actually adding or subtracting some things)?
(lambda (a b) (lambda (x y) (if b (+ x y a) (- x y a))))
is a function that takes two arguments (that's what (lambda (a b) ...) says).
You can use the substitution method to discover what it produces.
Apply it to 5 and #f:
((lambda (a b) (lambda (x y) (if b (+ x y a) (- x y a)))) 5 #f)
[Replace a with 5 and b with #f in the body]:
(lambda (x y) (if #f (+ x y 5) (- x y 5)))
And this is a function that takes two numbers and produces a new number.
(Note that the #f and the 5 became fixed by the application of the outer lambda.)
It's easier to use the function if we name it (interactions from DrRacket):
> (define question (lambda (a b) (lambda (x y) (if b (+ x y a) (- x y a)))))
> (question 5 #f)
#<procedure>
which is as expected, based on the reasoning above.
Let's name this function as well:
> (define answer (question 5 #f))
and use it:
> (answer 3 4)
-6
or we could use it unnamed:
> ((question 5 #f) 3 4)
-6
or you could do it all inline, but that's a horrible unreadable mess:
> (((lambda (a b) (lambda (x y) (if b (+ x y a) (- x y a)))) 5 #f) 3 4)
-6
How do I return a function using conditionals in scheme? What I want to do is to return the product of 2 numbers (when r = 0), or the sum (when r=1) or the difference (when r=2) or 0 (otherwise) depending on the value of r.
What I tried is below, but the return value is always 0. How do I fix that?
(define (f r)( lambda (x y)
(cond (equal? r 0)
((* x y))
( (equal? r 1)
( (+ x y)))
( (equal? r 2))
( (- x y))
(else
0 ))))
(( f 0) 2 3)
I would expect 6, but I get 0. Thanks in advance.
cond works like this:
(cond (test-expr then-body)
(test-expr2 then-body2)
(else then-body3))
The test-exprs are tested one by one, and the first test-expr that returns a non-false value causes its corresponding then-body to be executed. The last value in the executed then-body is the value of the whole cond.
To know why you got 0 (and not 6), look carefully at your first cond clause: (cond (equal? r 0) ...). equal? is the test-expr, and since equal? itself is not false, its then-body is executed (i.e. r and 0 are executed). Since 0 is the last value in the then-body, 0 is the value of the whole cond. That's why you got 0.
Note that nearly all lines in your cond have parentheses that have been incorrectly placed. Here's a fixed version:
(define (f r)
(lambda (x y)
(cond ((equal? r 0) ; <- Parentheses fixed.
(* x y)) ; <- Parentheses fixed.
((equal? r 1) ; <- Parentheses fixed.
(+ x y)) ; <- Parentheses fixed.
((equal? r 2) ; <- Parentheses fixed.
(- x y)) ; <- Parentheses fixed.
(else 0))))
Here's an arguably better way to define the same function:
(define (f r)
(cond ((= r 0) *)
((= r 1) +)
((= r 2) -)
(else (lambda _ 0))))
For example:
((f 0) 2 3)
;; '(f 0)' returns '*', so this reduces to: (* 2 3)
;; Answer:
6
This version is technically better as it is not restricted to taking only two arguments. For example, you can now do this: ((f 1) 1 2 3 4 5 6) (reduces to (+ 1 2 3 4 5 6)).
The cond expression in your code has some syntax errors:
There are brackets missing in each condition
You must not surround a procedure application with double brackets, this is a mistake: ((* x y))
Notice that you require to return an arithmetic procedure and, for example, we can simply return + which is similar to returning (lambda (x y) (+ x y)) (except that it'll work for more than two parameters, but that's a win!).
Bear in mind that in Racket the solution can be written in a more concise way: for example, by using case to simplify the conditions and const for the last case, when we want to return a procedure that returns 0 no matter what are the parameters. Here's how:
(define (f r)
(case r
((0) *)
((1) +)
((2) -)
(else (const 0))))
It works as expected, by returning a procedure that you can apply to the given arguments:
((f 0) 6 7)
=> 42
((f 3) 2 3)
=> 0
I was just beginning to feel I had a vague understanding of the use of lambda in racket and scheme when I came across the following 'alternate' definitions for cons and car in SICP
(define (cons x y)
(lambda (m) (m x y)))
(define (car z)
(z (lambda (p q) p)))
(define (cdr z)
(z (lambda (p q) q)))
For the life of me I just cannot parse them.
Can anybody explain how to parse or expand these in a way that makes sense for total neophytes?
This is an interesting way to represent data: as functions. Notice that this
definition of cons returns a lambda which closes over the parameters x
and y, capturing their values inside. Also notice that the returned lambda
receives a function m as a parameter:
;creates a closure that "remembers' 2 values
(define (cons x y) (lambda (m) (m x y)))
;recieves a cons holding 2 values, returning the 0th value
(define (car z) (z (lambda (p q) p)))
;recieves a cons holding 2 values, returning the 1st value
(define (cdr z) (z (lambda (p q) q)))
In the above code z is a closure, the same that was created by cons, and in
the body of the procedure we're passing it another lambda as parameter,
remember m? it's just that! the function that it was expecting.
Understanding the above, it's easy to see how car and cdr work; let's
dissect how car, cdr is evaluated by the interpreter one step at a time:
; lets say we started with a closure `cons`, passed in to `car`
(car (cons 1 2))
; the definition of `cons` is substituted in to `(cons 1 2)` resulting in:
(car (lambda (m) (m 1 2)))
; substitute `car` with its definition
((lambda (m) (m 1 2)) (lambda (p q) p))
; replace `m` with the passed parameter
((lambda (p q) p) 1 2)
; bind 1 to `p` and 2 to `q`, return p
1
To summarize: cons creates a closure that "remembers' two values, car
receives that closure and passes it along a function that acts as a selector for
the zeroth value, and cdr acts as a selector for the 1st value. The key
point to understand here is that lambda acts as a
closure.
How cool is this? we only need functions to store and retrieve arbitrary data!
Nested Compositions of car & cdr are defined up to 4 deep in most LISPs. example:
(define caddr (lambda (x) (car (cdr (cdr x)))))
In my view, the definitive trick is reading the definitions from the end to the beginning, because in all three of them the free variables are always those that can be found in the lambda within the body (m, p and q). Here is an attempt to translate the code to English, from the end (bottom-right) to the beginning (top-left):
(define (cons x y)
(lambda (m) (m x y))
Whatever m is, and we suspect it is a function because it appears right next to a (, it must be applied over both x and y: this is the definition of consing x and y.
(define (car z)
(z (lambda (p q) q)))
Whatever p and q are, when something called z is applied, and z is something that accepts functions as its input, then the first one of p and q is selected: this is the definition of car.
For an example of "something that accepts functions as its input", we just need to look back to the definition of cons. So, this means car accepts cons as its input.
(car (cons 1 2)) ; looks indeed familiar and reassuring
(car (cons 1 (cons 2 '()))) ; is equivalent
(car '(1 2)) ; is also equivalent
(car z)
; if the previous two are equivalent, then z := '(1 2)
The last line means: a list is "something that accepts a function as its input".
Don't let your head spin at that moment! The list will only accept functions that can work on list elements, anyway. And this is the case precisely because we have re-defined cons the way that we have.
I think the main point from this exercise is "computation is bringing operations and data together, and it doesn't matter in which order you bring them together".
This should be easy to understand with the combinatory notation (implicitly translated to Scheme as currying functions, f x y = z ==> (define f (λ (x) (λ (y) z)))):
cons x y m = m x y
car z = z _K ; _K p q = p
cdr z = z (_K _I) ; _I x = x _K _I p q = _I q = q
so we get
car (cons x y) = cons x y _K = _K x y = x
cdr (cons x y) = cons x y (_K _I) = _K _I x y = _I y = y
so the definitions do what we expect. Easy.
In English, the cons x y value is a function that says "if you'll give me a function of two arguments I'll call it with the two arguments I hold. Let it decide what to do with them, then!".
In other words, it expects a "continuation" function, and calls it with the two arguments used in its (the "pair") creation.
I am newbie to Scheme programming and trying to define a var in if condition. For example, I have:
(if (< x y) (define x y) ) ;(GOAL: if x < y, than x=y..)
But I got the error:
let: bad syntax (not an identifier and expression for a binding) in:...
Any ideas how to resolve this, would be greatly appreciated.
p.s. Sorry for my English
Unlike imperative languages you should refrain not use define or set! to update variables where you can avoid it. In some circumstances it's needed, like in generators.
Since you don't have a full code example where you'd like to do this I cannot see what obvious solution is to be used.
The way to store intermediate values if by let or recursion:
;; within the let block x shadows the original x
;; with the smalles of the outer x and y
(let ((x (if (< x y) x y)))
(do-something x))
You can do several intermediates by let*
(let* ((tmp (+ x y))
(tmp2 (* tmp y))) ; tmp is bound here
(do-something-with tmp2)); or tmp and tmp2
You you can use recursion, where you update cur and lst in th innner procedure by recursion:
(define (mmin x . xs)
(define (min-aux cur lst)
(cond ((null? lst) cur)
((<= cur (car lst)) (min-aux cur (cdr lst)))
(else (min-aux (car lst) (cdr lst)))))
(min-aux x xs)) ; start recursion
It is an error to define something that is already defined so thats why I defined
If you need to do this top level you can:
(define min_xy (if (< x y) x y))
min_xy. To alter a binding destructively (get it to reference another value) you can use set!
(set! x (+ x 1)) ; increases x
You'll alter the most local definition and it's an error if it doesnæt already exist. This can be used for creating generators:
(define (generator start alter-proc)
(lambda () ; returns a procedure taking 0 arguments
(let ((old start)) ; temporary store what start points to
(set! start (alter-proc start)) ; change what the local start points to
old))) ; return the old value
(define counter (generator 1 (lambda (x) (+ x 1))))
(counter) ; ==> 1
(counter) ; ==> 2
(define doubler (generator 1 (lambda (x) (* x 2))))
(doubler) ; ==> 1
(doubler) ; ==> 2
(doubler) ; ==> 4
Using define is wrong; you are not defining a function here. There are two solutions:
(if (< x y) (set! x y) (void)) ; if x < y set x = y; else do nothing
Or
(set! x (if (< x y) y x)) ; sets x to y if (x<y) is true; else sets x to x