How do I do anything with multiple return values in racket? - 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.

Related

Find max in lisp

I am trying to do Recursive method to find max value in list.
Can anyone explain where I made the mistake on this code and how to approach it next time.
(defun f3 (i)
(setq x (cond (> (car (I)) (cdr (car (I))))
(f3 (cdr (I)))))
)
(f3 '(33 11 44 2) )
also I tried this following method and didn't work:
(defun f3 (i)
(cond ((null I )nil )
(setq x (car (i))
(f3(cdr (i)))
(return-from max x)
)
Thanks a lot for any help. I am coming from java if that helps.
If you're working in Common Lisp, then you do this:
(defun max-item (list)
(loop for item in list
maximizing item))
That's it. The maximizing item clause of loop determines the highest item value seen, and implicitly establishes that as the result value of loop when it terminates.
Note that if list is empty, then this returns nil. If you want some other behavior, you have to work that in:
(if list
(loop for item in list
maximizing item))
(... handle empty here ...))
If the number of elements in the list is known to be small, below your Lisp implementation's limit on the number of arguments that can be passed to a function, you can simply apply the list to the max function:
(defun max-item (list)
(apply #'max list))
If list is empty, then max is misused: it requires one or more arguments. An error condition will likely be signaled. If that doesn't work in your situation, you need to add code to supply the desired behavior.
If the list is expected to be large, so that this approach is to be avoided, you can use reduce, treating max as a binary function:
(defun max-item (list)
(reduce #'max list))
Same remarks regarding empty list. These expressions are so small, many programmers will avoid writing a function and just use them directly.
Regarding recursion, you wouldn't use recursion to solve this problem in production code, only as a homework exercise for learning about recursion.
You are trying to compute the maximum value of a list, so please name your function maximum and your parameter list, not f3 or i. You can't name the function max without having to consider how to avoid shadowing the standard max function, so it is best for now to ignore package issues and use a different name.
There is a corner case to consider when the list is empty, as there is no meaningful value to return. You have to decide if you return nil or signal an error, for example.
The skeleton is thus:
(defun maximum (list)
(if (null list)
...
...))
Notice how closing parentheses are never preceded by spaces (or newlines), and opening parentheses are never followed by spaces (or newlines). Please note also that indentation increases with the current depth . This is the basic rules for Lisp formatting, please try following them for other developers.
(setq x <value>)
You are assigning an unknown place x, you should instead bind a fresh variable if you want to have a temporary variable, something like:
(let ((x <value>))
<body>)
With the above expression, x is bound to <value> inside <body> (one or more expressions), and only there.
(car (i))
Unlike in Java, parentheses are not used to group expressions for readability or to force some evaluation order, in Lisp they enclose compound forms. Here above, in a normal evaluation context (not a macro or binding), (i) means call function i, and this function is unrelated to your local variable i (just like in Java, where you can write int f = f(2) with f denoting both a variable and a method).
If you want to take the car of i, write (car i).
You seem to be using cond as some kind of if:
(cond (<test> <then>) <else>) ;; WRONG
You can have an if as follows:
(if <test> <then> <else>)
For example:
(if (> u v) u v) ;; evaluates to either `u` or `v`, whichever is greater
The cond syntax is a bit more complex but you don't need it yet.
You cannot return-from a block that was undeclared, you probably renamed the function to f3 without renaming that part, or copied that from somewhere else, but in any case return-from is only needed when you have a bigger function and probably a lot more side-effects. Here the computation can be written in a more functionnal way. There is an implicit return in Lisp-like languages, unlike Java, for example below the last (but also single) expression in add evaluates to the function's return value:
(defun add-3 (x)
(+ x 3))
Start with smaller examples and test often, fix any error the compiler or interpreter prints before trying to do more complex things. Also, have a look at the available online resources to learn more about the language: https://common-lisp.net/documentation
Although the other answers are right: you definitely need to learn more CL syntax and you probably would not solve this problem recursively in idiomatic CL (whatever 'idiomatic CL' is), here's how to actually do it, because thinking about how to solve these problems recursively is useful.
First of all let's write a function max/2 which returns the maximum of two numbers. This is pretty easy:
(defun max/2 (a b)
(if (> a b) a b))
Now the trick is this: assume you have some idea of what the maximum of a list of numbers is: call this guess m. Then:
if the list is empty, the maximum is m;
otherwise the list has a first element, so pick a new m which is the maximum of the first element of the list and the current m, and recurse on the rest of the list.
So, we can write this function, which I'll call max/carrying (because it 'carries' the m):
(defun max/carrying (m list)
(if (null list)
m
(max/carrying (max/2 (first list) m)
(rest list))))
And this is now almost all we need. The trick is then to write a little shim around max/carrying which bootstraps it:
to compute the maximum of a list:
if the list is empty it has no maximum, and this is an error;
otherwise the result is max/carrying of the first element of the list and the rest of the list.
I won't write that, but it's pretty easy (to signal an error, the function you want is error).

Why andmap returns #t in this case?

I am using Racket and Dr. Racket.
There is built-in function called andmap.
The built-in version of andmap works this way:
> (andmap positive? '(1 2 3))
#t
Function number usually works as:
(number? 3)
> #t
(number? '())
>#f
I do not get why this happens:
(andmap number? '())
> #t
I think the result should be false.
The documentation says:
*If the lsts are empty, then #t is returned.*
Why on earth would that make sense? I do not see it. I am curious about the design choices of languages, specially new ones, like Racket.
The reason (andmap pred '()) returns #t is exactly the same reason (and) returns #t… but that’s perhaps not the most useful explanation, is it? The real answer is that #t is the identity for logical AND, just like 0 is the additive identity and 1 is the multiplicative identity:
> (+)
0
> (*)
1
> (and)
#t
> (or)
#f
The idea here is that the identity will not change the output when combined with any given input. For example, just like (+ 0 x) is always x and (* 1 x) is always x, (and #t x) is always x and (or #f x) is always x. This is a useful property to have, since it cooperates well with the idiomatic way to sum a list in Scheme, (apply + lst):
> (apply + '(1 2 3))
6
> (apply + '())
0
Similarly, (apply * lst) can be used instead of a separate product function. The and and or operators cannot be used with apply, since they are short-circuiting and are thus implemented as macros instead of functions, but andmap and ormap implement that functionality instead.
If that argument doesn’t seem satisfying enough to you, you can also think about these things in their plain English definitions to come to the same conclusion. What does the andmap operation mean? Well, it asks a question: “Do all of the elements in this list satisfy a predicate?” On an empty list, the answer will always be yes, given that you cannot possibly produce a counterexample to that claim.
In contrast, ormap is the dual: “Does at least one of the elements in this list satisfy a predicate?” The answer will always be no, since it’s impossible to produce any element at all, so producing one that satisfies a predicate is surely impossible.

Questions on case

I tried to create an example for cond and case and came up with a simple implementation of the fizz buzz problem (see Wikipedia for details).
My initial version is:
(defun is-fizz-buzz (n)
(cond ((and (zerop (mod n 3)) (zerop (mod n 5))) 'fizz-buzz)
((zerop (mod n 3)) 'fizz)
((zerop (mod n 5)) 'buzz)
(t n)))
(defun fizz-buzz (n)
(princ (case (is-fizz-buzz n)
('fizz "Fizz!")
('buzz "Buzz!")
('fizz-buzz "Fizz-Buzz!")
(otherwise n))))
Now, #RainerJoswig pointed out to me that my case is wrong. I was quite surprised, as it had worked as it should, but as he's way more experienced with Lisp than I am, he's most probably right (and in fact, he is).
I tried to read and understand http://clhs.lisp.se/Body/m_case_.htm, but now I'm left with more questions than answers. As I didn't want to discuss things in 140 characters and as it may be helpful for other Lisp beginners, I thought to publish my questions here.
Basically, the syntax of case is described as
case keyform {normal-clause}* [otherwise-clause] => result*
keyform is easy: It's a form that is evaluated to get the key that is being tested. For sure
(is-fizz-buzz n)
is a form and it returns a symbol, hence everything looks fine. Additionally, as I learned from Land of Lisp, case internally works with eq, and as eq is used to compare symbols, this should be fine as well.
Now, the normal-clause: This is defined as
(keys form*)
form* again is simple, it's just a number of forms, basically with an implicit progn. For keys, it tells me that this is a designator for a list of objects. Phew. Here my questions begin…
This document tells me that a designator is:
an object that denotes another object.
Hm. As case is working with eq, I would have expected that I need to give a symbol here. And why is keys a designator for a list of objects, not for a single one? May I have multiple symbols that I can compare against in a single branch? I guess the problem here comes down to not really understanding what is meant by a designator, but maybe someone can help me and push me into the right direction. How would you explain what a designator is in Lisp?
Then, I started playing around with the code, and I noticed that if I remove the ' character, things still work. The code
(defun fizz-buzz (n)
(princ (case (is-fizz-buzz n)
(fizz "Fizz!")
(buzz "Buzz!")
(fizz-buzz "Fizz-Buzz!")
(otherwise n))))
produces the very same result as the code above. Why is this? I would not even have expected this to be executable at all, as (fizz "Fizz!") to me looks like a function call of fizz, which doesn't exist. Why does this work?
And then, the final question is, when I run
(case 'quote ('foo 1) ('bar 2))
it returns 1 (which does not seem to be logical, I would have expected nil). If I change this to
(case 'quote ('foo 1) ('bar 2) (otherwise 3))
it still returns 1, not 3 as I now would have expected. From the documentation I don't get why my otherwise-clause obviously does not what it should do.
Any hints why these two cases behave like they do?
CASE use EQL not EQ. EQL is in most cases the default comparison. Thus case works for identity, numbers and characters.
The keyforms are NOT evaluated. Thus it makes no sense to quote objects. Quoting means stopping evaluation. But there is no evaluation -> no quote.
The keyform is either a single item, or a list of items
(case foo
(bar 'it-is-bar)
((1 2) 'one-or-two)
(1 'one))
((apple banana orange) 'either-apple-banana-or-orange)))
It also means that one the left side are constants, no variables. bar above is the symbol bar, not the variable bar.
Problem:
(case 'quote
('foo 'foo-or-quote))
because it really is
(case 'quote
((quote foo) 'foo-or-quote))
Okay, I was able to figure out some of the problems by myself, primarily by reading this question and the according answers. This explains to me why my otherwise-clause didn't work, and it also explains why
(case 'quote ('foo 1) ('bar 2))
is being evaluated the way it is. So I guess that my fizz-buzz function at least should be:
(defun fizz-buzz (n)
(princ (case (is-fizz-buzz n)
(fizz "Fizz!")
(buzz "Buzz!")
(fizz-buzz "Fizz-Buzz!")
(otherwise n))))
UPDATE
Okay, now after having re-read the aforementioned question and answers multiple times, I think I finally got what is meant by a list of objects, and hence my code should be:
(defun fizz-buzz (n)
(princ (case (is-fizz-buzz n)
((fizz) "Fizz!")
((buzz) "Buzz!")
((fizz-buzz) "Fizz-Buzz!")
(otherwise n))))
For keys, it tells me that this is a designator for a list of
objects. Phew. Here my questions begin…
This document
tells me that a designator is:
an object that denotes another object.
Hm. As case is working with eq, I would have expected that I need
to give a symbol here. And why is keys a designator for a list
of objects, not for a single one? May I have multiple symbols that I
can compare against in a single branch? I guess the problem here comes
down to not really understanding what is meant by a designator, but
maybe someone can help me and push me into the right direction. How
would you explain what a designator is in Lisp?
I originally posted this as a comment, but I think this might stand as a sufficient answer, if it's the core problem in the question, so I'm adding it as an answer.
The text you need is in the HyperSpec. 1.4.1.5 Designators notes
The specific nature of the object denoted by a "<> designator"
or a "designator for a <>" can be found in the Glossary entry
for "<> designator."
The glossary entry for list designator is what you need:
list designator n. a designator for a list of objects; that is,
an object that denotes a list and that is one of: a non-nil atom
(denoting a singleton list whose element is that non-nil atom) or a proper list (denoting itself).
Thus the symbol fizz (a non-nil atom) and the list (fizz) both designate the list (fizz), the list (quote fizz) (often abbreviated as 'fizz) designates itself, etc.
Once you've learned about list designators,they're a very handy concept to use in you own code. Just document that you accept a list designator, and then convert with (if (listp x) x (list x)), and you're in business. It's very helpful, and you'll find more uses for it than you expect. E.g., I used it just the other day in an answer to How to group any consecutive numbers or items of a given series.

What would the consequences be of allowing special forms to be treated as normal values?

I discovered that special forms can not be passed as arguments or saved in variables, both in Clojure:
user=> (defn my-func
[op]
(op 1 2 3))
#'user/my-func
user=> (my-func +)
6
user=> (my-func if)
java.lang.Exception: Unable to resolve symbol: if in this context (NO_SOURCE_FILE:5)
user=> (def my-if if)
java.lang.Exception: Unable to resolve symbol: if in this context (NO_SOURCE_FILE:9)
and in Racket/Scheme:
> (define (my-func op)
(op 1 2 3))
> (my-func +)
6
> (my-func if)
if: bad syntax in: if
> (define my-if if)
*if: bad syntax in: if
That's cool, I'm fine with that, I know that I can just write a function to wrap a special form and then pass that function.
But I'd like to know why Lisps have this restriction, and what negative consequences allowing this would have. Are they any major dialects that do allow that?
It makes evaluation more complicated and compilation hard.
If you have a form (a b c), then you need to resolve at runtime the value of a and then apply it somehow to the forms b and c.
The simpler model of a few limited number of special forms and otherwise strict evaluation is then gone.
See also: FEXPR
Special forms are not functions: functions take values as arguments, whereas special forms take forms. For example, look at your example of if:
(if 1 2 3)
Okay, that's easy, since 2 and 3 are already values. But what about this?
(define (modadd a b n)
(if (zero? n) #f (modulo (+ a b) n)))
In this case, the if is actually receiving the #f and (modulo (+ a b) n) as forms, not as values. And this is important! (modulo x n) will fail if n is 0: that is why it's left unevaluated until we know that n is not 0.
The trouble with being able to pass special forms as first-class objects is that higher-order functions cannot call those objects using predictable semantics: is it a function object, so that you're passing in values, or is it a special form, so that you're passing in forms? This gets to be a huge mess.
Yes, you can write a wrapper function, like my modadd, that encapsulates if. However, there is no way you can just reimplement if as a function, while still preserving the only-evaluate-one-of-the-branches behaviour.

Which is better?: (reduce + ...) or (apply + ...)?

Should I use
(apply + (filter prime? (range 1 20)))
or
(reduce + (filter prime? (range 1 20)))
Edit: This is the source for prime in clojure from optimizing toolkit.
(defn prime? [n]
(cond
(or (= n 2) (= n 3)) true
(or (divisible? n 2) (< n 2)) false
:else
(let [sqrt-n (Math/sqrt n)]
(loop [i 3]
(cond
(divisible? n i) false
(< sqrt-n i) true
:else (recur (+ i 2)))))))
If you are asking in terms of performance, the reduce is better by a little:
(time (dotimes [_ 1e6] (apply + (filter even? (range 1 20)))))
"Elapsed time: 9059.251 msecs"
nil
(time (dotimes [_ 1e6] (reduce + (filter even? (range 1 20)))))
"Elapsed time: 8420.323 msecs"
nil
About 7% difference in this case, but YMMV depending on the machine.
You haven't provided your source for the prime? function, so I have substituted even? as the predicate. Keep in mind that your runtime may be dominated by prime?, in which case the choice between reduce and apply matters even less.
If you are asking which is more "lispy" then I would say that the reduce implementation is preferrable, as what you are doing is a reduce/fold in the functional programming sense.
I would think that reduce would be preferable when it is available, because apply uses the list as arguments to the function, but when you have a large number -- say, a million -- elements in the list, you will construct a function call with a million arguments! That might cause some problems with some implementations of Lisp.
(reduce op ...) is the norm and (apply op ...) the exception (notably for str and concat).
I would expect apply to realize a lazy list which could be ugly, and you never want to assume your list is not lazy, 'cause you could suddenly find yourself getting smacked with massive memory useage.
Reduce is going to grab them 1 by one and roll the results together into a single whole, never taking the whole list in at once.
i am going to play devil's advocate and argue for apply.
reduce is clojure's take on fold (more exactly foldl), the left-fold, and is usually defined with an initial element, because a fold operation has two parts:
an initial (or "zero") value
an operation for combining two values
so to find the sum of a set of numbers the natural way to use + is as (fold + 0 values) or, in clojure, (reduce + 0 values).
this explicitly shows the result for an empty list, which is important because it is not obvious to me that + returns 0 in this case - after all, + is a binary operator (all that fold needs or assumes).
now, in practice, it turns out that clojure's + is defined as more than a binary operator. it will take many or, even, zero values. cool. but if we're using this "extra" information it's friendly to signal that to the reader. (apply + values) does this - it says "i am using + in a strange way, as more than a binary operator". and that helps people (me, at least) understand the code.
[it's interesting to ask why apply feels clearer. and i think it's partly that you are saying to the reader: "look, + was designed to accept multiple values (that's what apply is used for), and so the language implementation will include the case of zero values." that implicit argument is not present with reduce applied to a single list.]
alternatively, (reduce + 0 values) is also fine. but (reduce + values) triggers an instinctive reaction in me: "huh, does + provide a zero?".
and if you disagree, then please, before you downvote or post a reply, are you sure about what (reduce * values) will return for an empty list?
I agree with Andrew Cooke. But I would like to add that since it already knows how to work and handle multiple arguments, we are essentially re-telling the '+' operator how to work by using it in the 'reduce', in my opinion.
Also, if I told you do to add a bunch of numbers together, you would probably use the '+' operator by itself, and not use 'reduce' at all.
(+ 1 2 3 etc...)
'apply' is just saying, I want to do the same thing, but use what's inside this list for the arguments. There is no extra reasoning required and you are using it as if the numbers didn't exist in a list to begin with, like you would if you were writing it out yourself.
(Reduce is so heavily used that using/reasoning about it in this case isn't a big deal at all, I think either way is fine, but personally prefer apply)