【问题标题】:What is supposed to happen when a procedure's argument is given multiple values when it expects one value only?当一个过程的参数只需要一个值而被赋予多个值时,应该发生什么?
【发布时间】:2022-01-08 03:13:25
【问题描述】:

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

【问题讨论】:

    标签: scheme


    【解决方案1】:

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

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

    将它的所有参数传递给它的延续......

    一个序列中所有非最终表达式的延续 表达式,例如lambdabeginletlet*letrecletrec*let-valueslet*-valuescasecond 表格, 通常取任意数量的值。

    除了这些和call-with-values 创建的延续, let-valueslet*-values延续隐式接受 单个值,例如 的延续和 过程调用的 或中的 表达式 条件,只取一个值。通过的效果 未定义此类延续的不适当数量的值。

    R7RS 在 6.10 中有类似的语言:

    未指定向未以其中一种方式创建的延续传递任何值或多个值的效果。

    (+ (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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-13
      • 2017-09-04
      • 1970-01-01
      • 1970-01-01
      • 2012-11-08
      相关资源
      最近更新 更多