spec: multiple values — values/call-with-values/let-values/define-values
25 tests pass on both JS and OCaml hosts. Uses dict marker
{:_values true :_list [...]} for 0/2+ values; 1 value passes
through directly. step-sf-define extended to desugar shorthand
(define (name params) body) forms on both hosts.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
172
spec/tests/test-values.sx
Normal file
172
spec/tests/test-values.sx
Normal file
@@ -0,0 +1,172 @@
|
||||
(defsuite
|
||||
"multiple-values"
|
||||
(deftest
|
||||
"values single returns value directly"
|
||||
(do
|
||||
(assert= 42 (values 42))
|
||||
(assert= "hi" (values "hi"))
|
||||
(assert= nil (values nil))))
|
||||
(deftest
|
||||
"values multiple returns marker dict"
|
||||
(do
|
||||
(let
|
||||
((v (values 1 2 3)))
|
||||
(assert (dict? v))
|
||||
(assert= true (get v :_values false))
|
||||
(assert-equal (list 1 2 3) (get v :_list)))))
|
||||
(deftest
|
||||
"call-with-values basic two values"
|
||||
(do
|
||||
(assert=
|
||||
3
|
||||
(call-with-values
|
||||
(fn () (values 1 2))
|
||||
(fn (a b) (+ a b))))))
|
||||
(deftest
|
||||
"call-with-values three values"
|
||||
(do
|
||||
(assert=
|
||||
6
|
||||
(call-with-values
|
||||
(fn () (values 1 2 3))
|
||||
(fn (a b c) (+ a b c))))))
|
||||
(deftest
|
||||
"call-with-values single value passthrough"
|
||||
(do
|
||||
(assert= 10 (call-with-values (fn () 10) (fn (x) x)))))
|
||||
(deftest
|
||||
"call-with-values passes non-values result as single arg"
|
||||
(do (assert= "hello" (call-with-values (fn () "hello") (fn (x) x)))))
|
||||
(deftest
|
||||
"call-with-values with string concat"
|
||||
(do
|
||||
(assert=
|
||||
"ab"
|
||||
(call-with-values (fn () (values "a" "b")) (fn (a b) (str a b))))))
|
||||
(deftest
|
||||
"let-values basic two bindings"
|
||||
(do
|
||||
(let-values
|
||||
(((a b) (values 10 20)))
|
||||
(assert= 10 a)
|
||||
(assert= 20 b))))
|
||||
(deftest
|
||||
"let-values computes with bindings"
|
||||
(do
|
||||
(let-values
|
||||
(((x y) (values 3 4)))
|
||||
(assert= 7 (+ x y)))))
|
||||
(deftest
|
||||
"let-values three values"
|
||||
(do
|
||||
(let-values
|
||||
(((a b c) (values 1 2 3)))
|
||||
(assert= 6 (+ a b c)))))
|
||||
(deftest
|
||||
"let-values single value binding"
|
||||
(do (let-values (((x) (values 42))) (assert= 42 x))))
|
||||
(deftest
|
||||
"let-values multiple binding clauses"
|
||||
(do
|
||||
(let-values
|
||||
(((a b) (values 1 2))
|
||||
((c d) (values 3 4)))
|
||||
(assert= 10 (+ a b c d)))))
|
||||
(deftest
|
||||
"let-values body is multiple expressions"
|
||||
(do
|
||||
(let-values
|
||||
(((a b) (values 5 6)))
|
||||
(define sum (+ a b))
|
||||
(assert= 11 sum))))
|
||||
(deftest
|
||||
"let-values with no bindings evals body"
|
||||
(do (let-values () (assert= 99 99))))
|
||||
(deftest
|
||||
"define-values binds multiple names"
|
||||
(do
|
||||
(define-values (x y) (values 7 8))
|
||||
(assert= 7 x)
|
||||
(assert= 8 y)))
|
||||
(deftest
|
||||
"define-values three names"
|
||||
(do
|
||||
(define-values (a b c) (values 10 20 30))
|
||||
(assert= 10 a)
|
||||
(assert= 20 b)
|
||||
(assert= 30 c)))
|
||||
(deftest
|
||||
"define-values single name"
|
||||
(do (define-values (n) (values 42)) (assert= 42 n)))
|
||||
(deftest
|
||||
"define-values used in computation"
|
||||
(do
|
||||
(define-values (w h) (values 6 7))
|
||||
(assert= 42 (* w h))))
|
||||
(deftest
|
||||
"values in let binding"
|
||||
(do
|
||||
(let
|
||||
((v (values 100 200)))
|
||||
(assert= true (get v :_values false))
|
||||
(assert= 100 (first (get v :_list))))))
|
||||
(deftest
|
||||
"call-with-values with swap"
|
||||
(do
|
||||
(define (swap a b) (values b a))
|
||||
(assert=
|
||||
5
|
||||
(call-with-values
|
||||
(fn () (swap 3 5))
|
||||
(fn (first-val second-val) first-val)))))
|
||||
(deftest
|
||||
"let-values from function returning values"
|
||||
(do
|
||||
(define (min-max a b) (values (min a b) (max a b)))
|
||||
(let-values
|
||||
(((lo hi) (min-max 7 3)))
|
||||
(assert= 3 lo)
|
||||
(assert= 7 hi))))
|
||||
(deftest
|
||||
"nested let-values"
|
||||
(do
|
||||
(let-values
|
||||
(((a b) (values 1 2)))
|
||||
(let-values
|
||||
(((c d) (values 3 4)))
|
||||
(assert= 10 (+ a b c d))))))
|
||||
(deftest
|
||||
"call-with-values chained"
|
||||
(do
|
||||
(define
|
||||
result
|
||||
(call-with-values
|
||||
(fn
|
||||
()
|
||||
(call-with-values
|
||||
(fn () (values 4 6))
|
||||
(fn (a b) (* a b))))
|
||||
(fn (x) x)))
|
||||
(assert= 24 result)))
|
||||
(deftest
|
||||
"values zero args produces dict"
|
||||
(do
|
||||
(let
|
||||
((v (values)))
|
||||
(assert (dict? v))
|
||||
(assert (get v :_values false))
|
||||
(assert-equal (list) (get v :_list)))))
|
||||
(deftest
|
||||
"let-values strings"
|
||||
(do
|
||||
(let-values
|
||||
(((first-name last-name) (values "Alice" "Smith")))
|
||||
(assert= "Alice Smith" (str first-name " " last-name)))))
|
||||
(deftest
|
||||
"define-values with list values"
|
||||
(do
|
||||
(define-values
|
||||
(head tail)
|
||||
(values 1 (list 2 3 4)))
|
||||
(assert= 1 head)
|
||||
(assert-equal (list 2 3 4) tail))))
|
||||
Reference in New Issue
Block a user