@mark.piffer has joined the channel
:raising_hand:
Welcome @mark.piffer :grinning:
Here’s a checklist to make things easier when asking for help, in order: 1. It is ok to just ask the question - permission is not required. 2. What is the task? 3. How far have you come? 4. What exactly are you struggling with? 5. What approaches have you tried to solve it? Encouragement: you can get better - keep practicing and keep asking questions :heart:
Which is the correct way to let
or define
(i.e. bind names to) the first n values of a list? I tried to recurse with a values
but this is obviously the wrong approach (define (values-rec n lst)
(if (= n 1) (values lst)
(values (first lst) (values-rec (- n 1) (rest lst)))))
Usage hould have been (values-rec 3 '("a" "b" "c" "d" "e"")
-> "a" "b" '("c" "d" "e")
For (define-values ...)
of course, I forgot
If you have a list of values, say, '(1 2 3)
and want to compute (f 1 2 3)
you can use apply
as in (apply f '(1 2 3))
. In this case, you want to compute (values 1 2 3)
, so you can use (apply values '(1 2 3))
.
Where ’(1 2 3) needs to be a list of the first n elements of lst.
I would probably look at split-at to split the list, and then define-values with apply values on the head; or, use match-define with a pattern for your specific n (maybe a macro could generate part of it?)
I’m having a conceptual problem in understanding what values
is actually returning
it is not a list, that much I do understand
Normally an expressions evaluates to a single value: > (+ 1 2) 3
Some computations naturally have two results.
yes, I read that in the Racket Reference
For example: > (split-at ’(a b c d) 2) needs to return both (a b) and (c d).
but what is the type of a two-value result?
You can think of two values as an implicit tuple.
If you think of the computation in term of a stack, (values 10 11) simply pushes two values to the stack.
In (define-values (a b) (values 10 11)) the identifiers are bound to the two top values on the stack.
how do functions consume these sstacked arguments?
only via the bound names?
Most contexts expect to receive only one value. So for example (+ (values 10 11) 3) gives an error.
You know about define-values
and let-values
but besides them call-with-values
is the most imported way of using multiple values.
> (https://docs.racket-lang.org/reference/values.html#%28def._%28%28quote._~23~25kernel%29._call-with-values%29%29\|call-with-values (https://docs.racket-lang.org/reference/lambda.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._lambda%29%29\|lambda () (https://docs.racket-lang.org/reference/values.html#%28def._%28%28quote._~23~25kernel%29._values%29%29\|values 1 2)) https://docs.racket-lang.org/reference/generic-numbers.html#%28def._%28%28quote._~23~25kernel%29._%2B%29%29\|+) 3
ah ok! That was the missing piece. Interesting.
thank you
I don’t think multiple return values are unique to Scheme/Racket, but most programming languages don’t have them. Most other languages use tuples instead.
I believe compose
can also be an alternative to call-with-values
. I think ((compose list split-at) '(a b c d) 2)
will give a first-class list instead of two values.
just tried it and it does :)
Also, let-values
, define-values
, etc. are handy. <file:///Users/badkins/sync/github/racket/racket/doc/reference/values.html#%28def.%28%28quote.~23~25kernel%29._values%29%29|See here>
Conversely, compose1
forces a single value, which can be useful