So, the Racket (6.5) documentation says you can bind several ids at once:
(for ([(i j) #hash(("a" . 1) ("b" . 20))])
(display (list i j)))
Bu-u-ut I can't figure out / find an example of how to do this with manually constructed data:
(define a '(1 2 3 4 5))
(define b '(10 20 30 40 50))
(for ([(i j) (map list a b)])
(display (list i j)))
explodes with
result arity mismatch;
expected number of values not received
expected: 2
received: 1
from:
in: local-binding form
values...:
What am I missing?
This
(for ([(i j) #hash(("a" . 1) ("b" . 20))])
(display (list i j)))
is short for
(for ([(i j) (in-hash #hash(("a" . 1) ("b" . 20)))])
(display (list i j)))
Now in-hash
returns two values at a time, so (i j)
will be bound to the two values.
On the other hand, this:
(for ([(i j) (map list a b)])
(display (list i j)))
is short for
(for ([(i j) (in-list (map list a b))])
(display (list i j)))
and in-list
will return one element at a time (in you example
the element is a list). Since there are two names in (i j)
and not just one, an error is signaled.
Follow Toxaris' advice in in-parallel
.
UPDATE
The following helper make-values-sequence
shows
how to create a custom sequence, that repeatedly
produces more than one value.
#lang racket
(define (make-values-sequence xss)
; xss is a list of (list x ...)
(make-do-sequence (λ ()
(values (λ (xss) (apply values (first xss))) ; pos->element
rest ; next-position
xss ; initial pos
(λ (xss) (not (empty? xss))) ; continue-with-pos?
#f ; not used
#f)))) ; not used]
(for/list ([(i j) (make-values-sequence '((1 2) (4 5) (5 6)))])
(+ i j))
Output:
'(3 9 11)
In this example, you can use separate clauses to bind i
and j
:
(for ([i (list 1 2 3 4 5)]
[j (list 10 20 30 40 50)])
(display (list i j)))
More generally, you can use in-parallel
to create a single sequence of multiple values from multiple sequences of single values:
(for ([(i j) (in-parallel (list 1 2 3 4 5)
(list 10 20 30 40 50))])
(display (list i j)))
Both solutions print (1 10)(2 20)(3 30)(4 40)(5 50)
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With