Luk*_*les 12 scheme types contracts racket
我一直在阅读球拍指南中的合同.
该->i构造允许在函数的输入/输出上放置任意约束.
例如,我可以使用一个unzip函数来获取对列表并返回两个列表.使用契约,我可以确认列表中的每个元素都是一对,并且外部列表具有相应的元素.
球拍指南提示这是合同有用的时候.但似乎在函数本身内做得更好.如果遇到非配对,我可能会抛出错误,这会检查列表中的内容.通过具有正确的功能自动检查输出.
什么是通过比简单类型更复杂的契约以某种方式改进代码的具体示例?
Ale*_*ing 13
正如您所描述的那样,几乎任何可以执行的检查都可以在->i函数本身内执行,但是再次,合同执行的任何检查都可以在函数本身内执行.将信息编码到合同中提供了一些优点.
->i当合同需要在提供给函数的参数中指定依赖关系时,这些是最明显的.例如,我有一个集合库,其中包含一个subsequence函数.它需要三个参数,一个序列,一个起始索引和一个结束索引.这是我用来保护它的合同:
(->i ([seq sequence?]
[start exact-nonnegative-integer?]
[end (start) (and/c exact-nonnegative-integer? (>=/c start))])
[result sequence?])
Run Code Online (Sandbox Code Playgroud)
这允许我明确指定结束索引必须大于或等于起始索引,并且我不必担心在我的函数中检查该不变量.当我违反此合同时,我收到一条错误消息:
> (subsequence '() 2 1)
subsequence: contract violation
expected: (and/c exact-nonnegative-integer? (>=/c 2))
given: 1
which isn't: (>=/c 2)
Run Code Online (Sandbox Code Playgroud)
它也可用于确保更复杂的不变量.我还定义了自己的map函数,它与Racket的内置函数一样map,支持可变数量的参数.提供的过程map必须接受与提供的序列相同数量的参数.我使用以下合同map:
(->i ([proc (seqs) (and/c (procedure-arity-includes/c (length seqs))
(unconstrained-domain-> any/c))])
#:rest [seqs (non-empty-listof sequence?)]
[result sequence?])
Run Code Online (Sandbox Code Playgroud)
这份合同确保了两件事.首先,proc如上所述,参数必须接受与序列相同数量的参数.此外,它还要求该函数始终返回单个值,因为Racket函数可以返回多个值.
这些不变量在函数体内更难检查,因为特别是对于第二个不变量,它们必须被延迟,直到应用函数本身.每次调用函数时都必须检查它.另一方面,合同包装功能并自动处理.
您是否始终希望将函数的每个单不变量编码为合约?可能不是.但是如果你想要那种额外的控制水平,那就->i可以了.
| 归档时间: |
|
| 查看次数: |
171 次 |
| 最近记录: |