How to convert cond statements that produces a boolean value into an expression involving only not, and and or - boolean

I am learning about racket/scheme and came across an online resource that said, if a function written using a cond gives true or false, it can be rewritten using only not, and, and or. I have worked out some simple examples where I was able to to convert cond statements into a statement only involving not and and or. My question is if there is a way that the logic can be "seen" right away when converting between these two types of statements. I understand that it is not always practical to convert every cond statement into a combination of not's and's and or's but I am interested in learning about the logic behind the process of converting.
Thanks in advance.
(If something about the question does not make sense, leave a comment and I will try clarifying what I want to understand)

All conditional expressions (and not only those evaluating to true/false) can be rewritten using only boolean combinators. This is because of how logical operators are evaluated in Scheme/Racket. For instance, logically (and a b) would be true if both a and b are true, and otherwise false. But in Racket, the result of (and a b) is b if both a and b are truthy, and otherwise false. That is, evaluation proceeds to the right until either the last argument or a falsy value is encountered. At that point, evaluation stops and that value (which could be a boolean but needn't be) is returned. It's because and and or don't simply produce boolean output that they can be used to stand in for conditional expressions.
E.g.
(if #t 'hello 'bye) ;=> hello
(or (and #t 'hello) 'bye) ;=> hello
(if #f 'hello 'bye) ;=> bye
(or (and #f 'hello) 'bye) ;=> bye
(cond [#f 'hello]
[#f 'bye]
[#t 'aloha]) ;=> aloha
(or (and #f 'hello)
(and #f 'bye)
(and #t 'aloha)) ;=> aloha
But you wouldn't usually want to use them that way since they're hard to read. As a general guideline, use if and cond in most cases, rather than elementary boolean operators. If you only care about taking action on a positive or negative result of the conditional, then you could use when or unless. If you do care about handling both positive and negative results, but one of them is a boolean result such as this example:
(if (positive? n)
#t
(even? n))
... then this would be a case where a boolean operator would be preferable, like so:
(or (positive? n) (even? n))
If both arms of the if conditional are boolean values, like this:
(if (> n 3)
#t
#f)
... then just replace the entire conditional expression with the condition itself:
(> n 3)
Otherwise, stick to if and cond.

Once you convert a cond to nested ifs, you can always turn it into and or and not like this:
(if A B C) --> (or (and A B) (and (not A) C))
However, if you do this blindly, you will get a much more complicated expression than what you could get, so I would add a couple more transformations you can use:
(if A B #f) --> (and A B)
(if A B #t) --> (or (not A) B)
(if A #f C) --> (and (not A) C)
(if A #t C) --> (or A C)
(note: that or above might return a different truthy-value other than #t, making it technically different but equivalent-when-used-as-a-boolean)
Another thing I should note is that sometimes you can transform a multi-branch cond into and or not without transforming into ifs first. For example a 3-branch cond:
(cond [A B]
[C D]
[else E])
-->
(or (and A B)
(and (not A) C D)
(and (not A) (not C) E))
Or a 4-branch cond:
(cond [A B]
[C D]
[E F]
[else G])
-->
(or (and A B)
(and (not A) C D)
(and (not A) (not C) E F)
(and (not A) (not C) (not E) G))
Each and corresponds to a cond-branch, and each cond-branch's and has nots in it for every previous condition, in addition to its own condition.
A more generic rule you can apply:
for i from 1 through n,
(cond [Q_i A_i]
...
[else E])
-->
on each i, for j from 1 through i-1,
(or (and (not Q_j) ... Q_i A_i)
...
(and (not Q_i) ... E)

First of all, you need to desugar cond language into a sequence of if-then-else sequences, which is trivial.
After that, you can rewrite if conditionals into boolean operators. You can look into a manual of propositional logic to learn this. Or look here.
Btw. It is forbidden to paste your homework on stack overflow.

Related

Is there a way to get a macro to do an extra evaluation before returning its result?

I’m trying to get get my macro to do an extra evaluation of its result before returning it. Can this be done without eval?
I'm trying to solve the problem in exercise 4 below:
Define a macro nth-expr that takes an integer n and an arbitrary number of expressions, evaluates the nth expression and returns its value. This exercise is easy to solve, if you assume that the first argument is a literal integer.
4. As exercise 3, but assume that the first argument is an expression to be evaluated.
It's easy to get the macro to pick the right expression:
(defmacro nth-expr% (n &rest es)
`(nth ,n ',es))
CL-USER> (defvar i 1)
I
CL-USER> (nth-expr% (1+ i) (+ 2 3) (- 4 3) (+ 3 1))
(+ 3 1)
The expression (+ 3 1) is the one we want, but we want the macro to evaluate it to 4 before returning it.
It can of course be done with eval:
(defmacro nth-expr%% (n &rest es)
`(eval (nth ,n ',es)))
CL-USER> (nth-expr%% (1+ i) (+ 2 3) (- 4 3) (+ 3 1))
4
But is there another way?
It feels like the solution should be to put the body of nth-expr% in a helper macro and have the top level macro only contain an unquoted call to this helper:
(defmacro helper (n es)
`(nth ,n ',es))
(defmacro nth-expr (n &rest es) ; doesn't work!
(helper n es))
The idea is that the call to helper would return (+ 3 1), and this would then be the expansion of the call to nth-expr, which at run-time would evaluate to 4. It blows up, of course, because N and ES get treated like literals.
That's not that easy.
Using eval is not good, since eval does not evaluate the code in the local lexical environment.
Remember, if we allow an expression to be evaluated to determine the number of another expression to execute, then we don't know this number at macro expansion time - since the expression could be based on a value that needs to be computed - for example based on some variable:
(nth-expression
foo
(bar)
(baz))
So we might want to think about code which does that:
(case foo
(0 (bar))
(1 (baz)))
CASE is evaluating foo and then uses the result to find a clause which has the same value in its head. The consequent forms of that clause then will be evaluated.
Now we need to write code which expands the former into the latter.
This would be a very simple version:
(defmacro nth-expression (n-form &body expressions)
`(case ,n-form
,#(loop for e in expressions
and i from 0
collect `(,i ,e))))
Question: what might be drawbacks of using CASE like that?
Knuto: Rainer Joswig may be asking you to think about how the case statement works. Namely, that after evaluating the keyform (ie, the first argument), it will be compared sequentially to the key in each clause until a match is found. The comparisons could be time consuming if there are many clauses. You can discover this by carefully reading the entry for case in the Hyperspec (as he more than once has insisted I do):
The keyform or keyplace is evaluated to produce the test-key. Each of
the normal-clauses is then considered in turn.
Also note that constructing many case clauses will add to the time to expand and compile the macro at compile time.
Regarding your use of eval in nth-expr%%, you can still achieve the effect of an eval by switching to apply:
(defmacro nth-expr%% (n &rest es)
`(let ((ne (nth ,n ',es)))
(apply (car ne) (cdr ne))))
But see Plugging the Leaks at http://www.gigamonkeys.com/book/macros-defining-your-own.html about a more robust treatment.
In general, a more efficient way to process the expressions is as a simple vector, rather than a list. (The problem statement does not rule out a vector representation.) While nth and case involve searching through the expressions one-by-one, a function like aref or svref can directly index into it. Assuming a vector of expressions is passed to the macro along with an index, perhaps first requiring (coerce expressions 'simple-vector) if a list, then the result can be computed in constant time no matter how many expressions there are:
(defmacro nth-expr%%% (n es)
`(let ((ne (svref ',es ,n)))
(apply (car ne) (cdr ne))))
so that now
(defvar i 1)
(nth-expr%%% (1+ i) #((+ 2 3) (- 4 3) (+ 3 1))) -> 4

car and quote in Lisp

I am currently studying about Lisp but I still don't get quote.
Why use quote in Lisp?
And I got a problem here which is hard to understand to me.
(car (car '((a b) c d)))
The above gives A.
But I don't know why the result is A because there is no quote first car after.
quote is an operator; its meaning only kicks in when it is the head of a Lisp expression which is evaluated. The syntax 'X stands for (quote X): the Lisp reader translates a prefix apostrophe, followed by any syntactic unit X denoting one object, into the syntax (quote X). The quote expression, when evaluated, returns the syntax X itself as the value, rather than the value of the syntax. For instance (quote (+ 1 2)) returns the three element list (+ 1 2), rather than the value of the expression (+ 1 2) which is 3. quote effectively reflects a piece of the program's list-based syntax back into the running program as a value.
In the expression:
(car (car '((a b) c d)))
we simply have a nested function application to a value:
(car (car value))
This value is the result of a quote expression, and so the value is the object ((a b) c d). This object started out as a piece of syntax wrapped inside quote, but is now a run-time value being passed to the car function. The inner car produces the first element of the list, returning (a b). This (a b) value is passed to the outer car, which retrieves the a.
Lisp provides quote because it is a homoiconic language. The principal data structures manipulated in that language have a printed notation, and that printed notation is used to write programs also. Thus programs are understood to be made out of a data structure. In this kind of language, suppose you want to be able to use any data structure as a literal. Of course, that creates confusion because the data uses the same notation as the code, and some data structures look like valid syntax. You need an operator which you can wrap around a piece of syntax to say, "this is literal data; do not evaluate this as an expression, but just the data that it looks like".
This is exactly the same like when we use English to talk about English. We have to use quotes—at least when we write this talk down. A sentence like:
A penny saved is a penny earned is a good old proverb.
is badly written. Of course we understand what it means because our brains are good at dealing with ambiguity and mistakes, but it appears to be saying that a penny is a proverb. We need quotes:
"A penny saved is a penny earned" is a good old proverb.
See? The quote says that this sentence is not a relative clause of my sentence; it's text that my sentence is talking about (which happens to be in the same language that I'm using to talk about it). This is why the Lisp operator is called quote: it's related to this type of quoting.
Why use quote
Think of the quote as an indication that it's data and not to be thought of as code:
(cons 1 2) ; ==> (1 . 2) (a cons with car as 1 and cdr as 2)
'(cons 1 2) ; ==> (cons 1 2) (a list with the symbol cons and the numbers 1 and 2)
You see in the first that is not quoted it's executed and the result is the result of the cons function. In the second you could say quote is executed and it evaluates soley to it's argument. Note that 'x is just an abbrevation for (quote x) and both thus evaluate to x while without quote it would evaluate to the value bound to the variable x.
Nested functions
When you nest functions like (car (car '((a b) c d)))) you'll se why you need to quote since all arguments in functions are evaluated. Thus before the outer car can be applied it needs to evaluate it's argument (car '((a b) c d))) and before the inner car can do it's job it needs to evaluate it's argument '((a b) c d)). We know that '((a b) c d)) becomes ((a b) c d)) and car of this is (a b). The outer car then works on (a b) and thus a is the result. If you would have put the quote like this (car '(car ((a b) c d)))) then the innser car is just a symbol in the data structure and not a function. car evaluates its argument to be (car ((a b) c d))) and car of that is the symbol car.
'((a b) c d)) ; ==> ((a b) c d))
(car '((a b) c d)) ; ==> (a b)
(car (car '((a b) c d))) ; ==> a
'(car ((a b) c d)) ; ==> (car ((a b) c d))
(car '(car ((a b) c d))) ; ==> car
Also know that if you put quotes inside quoted data, like ''x only the outer quote is taken off and the rest is data. The result is (quote x) or 'x depending on the display settings but since it's already data quote here is just a symbol. (car ''x) ; ==> quote (symbol)

Where's foldl1 and foldr1 in Racket?

Racket has only foldl and foldr, which require initial value. Haskell in addition has foldl1 and foldr1, which instead of applying a function on the initial value and the first element, applies to first and second element. Currently i implemented them as:
(define (foldl1 f xs)
(foldl f (first xs) (rest xs)))
Is there a better way?
There is a better way, just (require srfi/1) and use reduce and reduce-right. :-D
What you are describing looks like reduce in CL. Your procedure looks ok except it would fail if the list is empty.
Be aware that first and rest are not the same as car and cdr since they only work on proper lists. eg.
(first '(a b c d e . f))
;;==>
;;first: contract violation
;; expected: (and/c list? (not/c empty?))
;; given: '(a b c d e . f)
Now. For racket to signal here it must have traversed the whole list to make sure it ends with null and since it didn't it signaled an error. I did a small test and found out that sorting a 2 million list used 32% more time with first/rest.

How do I do anything with multiple return values in racket?

It seems like in order to use multiple return values in Racket, I have to either use define-values or collect them into a list with (call-with-values (thunk (values-expr)) list). In the latter case, why would someone to choose to return multiple values instead of a list, if just have to collect them into a list anyway? Additionally, both of these are very wordy and awkward to work into most code. I feel like I must be misunderstanding something very basic about multiple-return-values. For that matter, how do I write a procedure accepting multiple return values?
Although I may be missing some of the Scheme history and other nuances, I'll give you my practical answer.
First, one rule of thumb is if you need to return more than 2 or 3 values, don't use multiple values and don't use a list. Use a struct. That will usually be easier to read and maintain.
Racket's match forms make it much easier to destructure a list return value -- as easy as define-values:
(define (f)
(list 1 2))
(match-define (list a b) (f))
(do-something-with a b)
;; or
(match (f)
[(list a b) (do-something-with a b)])
If you have some other function, g, that takes a (list/c a b), and you want to compose it with f, it's simpler if f returns a list. It's also simpler if both use a two-element struct. Whereas call-with-values is kind of an awkward hot mess, I think.
Allowing multiple return value is an elegant idea, because it makes return values symmetric with arguments. Using multiple values is also faster than lists or structs (in the current implementation of Racket, although it could work otherwise).
However when readability is a higher priority than performance, then in modern Racket it can be more practical to use a list or a struct, IMHO. Having said that I do use multiple values for one-off private helper functions.
Finally, there's a long, interesting discussion on the Racket mailing list.
Racket doc gives us the quintessential example why, in disguise:
> (let-values ([(q r) (quotient/remainder 10 3)])
(if (zero? r)
q
"3 does *not* divide 10 evenly"))
"3 does *not* divide 10 evenly"
We get two values directly, and use them separately in a computation that follows.
update: In Common Lisp, with its decidedly practical, down-to-the-metal, non-functional approach (where they concern themselves with each extra cons cell allocation), it makes much more sense, especially as it allows one to call such procedures in a "normal" way as well, automatically ignoring the "extra" results, kind of like
(let ([q (quotient/remainder 10 3)])
(list q))
But in Racket this is invalid code. So yeah, it looks like an extraneous feature, better to be avoided altogether.
Using list as the consumer defeats the purpose of multiple values so in that case you could just have used lists to begin with. Multiple values is actually a way of optimization.
Semanticly returning a list and several values are similar, but where you return many values in a list effort goes into creation of cons cells to make the list and destructuring accessors to get the values at the other end. In many cases however, you wouldn't notice the difference in performance.
With multiple values the values are on the stack and (call-with-values (lambda () ... (values x y z)) (lambda (x y z) ...) only checks the number to see if it's correct.. If it's ok you just apply the next procedure since the stack has it's arguments all set from the previous call.
You can make syntactic sugar around this and some popular ones are let-values and SRFI-8 receive is a slightly simpler one. Both uses call-with-values as primitive.
values is handy because it
checks that the number of elements returned is correct
destructures
For example, using
(define (out a b) (printf "a=~a b=~a\n" a b))
then
(let ((lst (list 1 2 3)))
(let ((a (first lst)) (b (second lst))) ; destructure
(out a b)))
will work even though lst has 3 elements, but
(let-values (((a b) (values 1 2 3)))
(out a b))
will not.
If you want the same control and destructuring with a list, you can however use match:
(let ((lst (list 1 2)))
(match lst ((list a b) (out a b))))
Note that he creation of the structure, e.g. (list 1 2) vs (values 1 2) is equivalent.

Scheme - my gcd() always returns zero

I just start to learn Scheme today.
I wrote a function gcd(), but it always returns 0.
(define (gcd a b)
(cond (= b 0)
(a)
(else ((gcd b (modulo a b))))
)
)
Why I am wrong?
This should fix the problems:
(define (gcd a b)
(cond [(= b 0) a]
[else (gcd b (modulo a b))]))
You were incorrectly surrounding some expressions between parenthesis, and some parenthesis were missing from the cond expression.
Notice that in Scheme, when you surround something in parenthesis, say (a) you're telling the interpreter: a is a procedure with no arguments and I want to call it, and this was not the case in here, a is just a number.
Also, for readability's sake, it's a good idea to use [] instead of () to separate each of the conditions in a cond expression, as shown in my code above - but don't forget them, they're mandatory and in your code you forgot them in the first condition.
Other people have described what your mistake is and what you should do.
It is also instructive to consider how your code is actually run and why it produces the output you see. Because of your missing parentheses, the first case for your cond is (= b 0). The first thing (=) is taken as the condition. Everything in Scheme except #f is true, so this is always true. Since it is true, this case is evaluated. Specifically, the rest of the things in the parentheses is taken as (possible multiple) expressions to evaluate, as an implicit begin. So basically it evaluates (begin b 0). The result is the result of the last expression, 0.