当一个过程的参数被赋予多个值而它只期望一个值时应该发生什么?

What is supposed to happen when a procedure's argument is given multiple values when it expects one value only?

(+ (values 1) (values 2))returns 3(+ 1 (values 2 3)) 应该 return 是什么?在 R7RS-small 中,当只需要一个值时,是否会自动忽略 (values ...) 中的第二个值?在Guile 3.0.7中,(+ 1 (values 2 3)) returns 3,但在MIT Scheme 11.2和Chibi 0.10.0中报错。

(+ (values 1) (values 2))就可以了,结果应该是3。但在 values 表达式中不需要的值不会被自动忽略;事实上 (+ 1 (values 2 3)) 的行为在 R6RS 和 R7RS 方案中均未指定。

来自 R6RS 11.15 values 的条目[强调我的]:

Delivers all of its arguments to its continuation....

The continuations of all non-final expressions within a sequence of expressions, such as in lambda, begin, let, let*, letrec, letrec*, let-values, let*-values, case, and cond forms, usually take an arbitrary number of values.

Except for these and the continuations created by call-with-values, let-values, and let*-values, continuations implicitly accepting a single value, such as the continuations of <operator> and <operand>s of procedure calls or the <test> expressions in conditionals, take exactly one value. The effect of passing an inappropriate number of values to such a continuation is undefined.

R7RS 在 6.10 中有类似的语言:

The effect of passing no values or more than one value to continuations that were not created in one of these ways is unspecified.

(+ (values 1) (values 2)) 没问题的原因是过程调用中操作数的延续只取一个值。 (values 1)(values 2) 分别为其各自的延续提供了一个值。

call-with-values 用于将多个值的生产者与使用这些值的过程连接起来。 call-with-values 的第一个参数应该是一个不带参数并产生要使用的值的过程。第二个参数应该是一个过程,它接受第一个过程产生的值的数量:

> (call-with-values (lambda () (values 2 3))
    (lambda (x y) (+ 1 x y)))
6

请注意,上述 call-with-values 的使用要求消费者接受生产者产生的值的数量,因为 Scheme 要求实现在过程不接受传递给它的参数数量时引发错误:

> (call-with-values (lambda () (values 2 3 4))
    (lambda (x y) (+ 1 x y)))

Exception: incorrect argument count in call (call-with-values (lambda () (values 2 3 4)) (lambda (x y) (+ 1 x y)))

如果需要忽略额外的参数,则必须针对该目标设计使用者。这里的消费者被设计为忽略除第一个参数之外的所有参数:

> (call-with-values (lambda () (values 2 3 4))
    (lambda (x . xs) (+ 1 x)))
3