通过打开Checked
模块,F#允许使用已检查的算术,该模块重新定义了要检查的标准运算符,例如:
open Checked
let x = 1 + System.Int32.MaxValue // overflow
将导致算术溢出异常。
但是,如果我想在小范围内使用校验算法,比如C#允许使用关键字checked
怎么办
int x = 1 + int.MaxValue; // ok
int y = checked { 1 + int.MaxValue }; // overflow
如何通过打开Checked
模块来控制运算符重新定义的范围,或者使其尽可能小?
发布于 2010-02-16 15:36:47
您始终可以定义单独的运算符,或使用阴影,或使用括号来创建临时阴影的内部作用域:
let f() =
// define a separate operator
let (+.) x y = Checked.(+) x y
try
let x = 1 +. System.Int32.MaxValue
printfn "ran ok"
with e ->
printfn "exception"
try
let x = 1 + System.Int32.MaxValue
printfn "ran ok"
with e ->
printfn "exception"
// shadow (+)
let (+) x y = Checked.(+) x y
try
let x = 1 + System.Int32.MaxValue
printfn "ran ok"
with e ->
printfn "exception"
// shadow it back again
let (+) x y = Operators.(+) x y
try
let x = 1 + System.Int32.MaxValue
printfn "ran ok"
with e ->
printfn "exception"
// use parens to create a scope
(
// shadow inside
let (+) x y = Checked.(+) x y
try
let x = 1 + System.Int32.MaxValue
printfn "ran ok"
with e ->
printfn "exception"
)
// shadowing scope expires
try
let x = 1 + System.Int32.MaxValue
printfn "ran ok"
with e ->
printfn "exception"
f()
// output:
// exception
// ran ok
// exception
// ran ok
// exception
// ran ok
最后,另请参阅--checked+
编译器选项:
http://msdn.microsoft.com/en-us/library/dd233171(VS.100).aspx
发布于 2010-02-16 22:47:57
这里有一个复杂(但可能很有趣)的替代方案。如果你正在写一些严肃的东西,那么你可能应该使用Brians的建议之一,但出于好奇,我想知道是否有可能编写F#计算表达式来实现这一点。您可以声明一个表示int
的类型,该类型只能与选中的操作一起使用:
type CheckedInt = Ch of int with
static member (+) (Ch a, Ch b) = Checked.(+) a b
static member (*) (Ch a, Ch b) = Checked.(*) a b
static member (+) (Ch a, b) = Checked.(+) a b
static member (*) (Ch a, b) = Checked.(*) a b
然后,您可以定义一个计算表达式构建器(这根本不是真正的monad,因为操作类型完全是非标准的):
type CheckedBuilder() =
member x.Bind(v, f) = f (Ch v)
member x.Return(Ch v) = v
let checked = new CheckedBuilder()
当你调用‘checked
’时,它会自动将给定的整数值包装成一个整数,该整数应该与绑定操作一起使用,因此其余的代码将使用声明为成员的选中的+
和*
运算符。你最终会得到类似这样的结果:
checked { let! a = 10000
let! b = a * 10000
let! c = b * 21
let! d = c + 47483648 // !
return d }
这会抛出异常,因为它会在标记的行上溢出。如果更改数字,它将返回一个int
值(因为Return
成员从Checked
类型中展开数值)。这是一个有点疯狂的技巧:-)但我想这可能会很有趣!
(注意,checked
是一个保留供将来使用的关键字,因此您可能更喜欢选择其他名称)
https://stackoverflow.com/questions/2271198
复制相似问题