当一个过程的参数被赋予多个值而它只期望一个值时应该发生什么?
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
(+ (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
, andcond
forms, usually take an arbitrary number of values.Except for these and the continuations created by
call-with-values
,let-values
, andlet*-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