首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >F#检查算术作用域

F#检查算术作用域
EN

Stack Overflow用户
提问于 2010-02-16 15:20:54
回答 2查看 1.3K关注 0票数 21

通过打开Checked模块,F#允许使用已检查的算术,该模块重新定义了要检查的标准运算符,例如:

代码语言:javascript
复制
open Checked
let x = 1 + System.Int32.MaxValue // overflow

将导致算术溢出异常。

但是,如果我想在小范围内使用校验算法,比如C#允许使用关键字checked怎么办

代码语言:javascript
复制
int x = 1 + int.MaxValue;             // ok
int y = checked { 1 + int.MaxValue }; // overflow

如何通过打开Checked模块来控制运算符重新定义的范围,或者使其尽可能小?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-02-16 15:36:47

您始终可以定义单独的运算符,或使用阴影,或使用括号来创建临时阴影的内部作用域:

代码语言:javascript
复制
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

票数 21
EN

Stack Overflow用户

发布于 2010-02-16 22:47:57

这里有一个复杂(但可能很有趣)的替代方案。如果你正在写一些严肃的东西,那么你可能应该使用Brians的建议之一,但出于好奇,我想知道是否有可能编写F#计算表达式来实现这一点。您可以声明一个表示int的类型,该类型只能与选中的操作一起使用:

代码语言:javascript
复制
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,因为操作类型完全是非标准的):

代码语言:javascript
复制
type CheckedBuilder() = 
  member x.Bind(v, f) = f (Ch v)      
  member x.Return(Ch v) = v
let checked = new CheckedBuilder()  

当你调用‘checked’时,它会自动将给定的整数值包装成一个整数,该整数应该与绑定操作一起使用,因此其余的代码将使用声明为成员的选中的+*运算符。你最终会得到类似这样的结果:

代码语言:javascript
复制
checked { let! a = 10000 
          let! b = a * 10000 
          let! c = b * 21 
          let! d = c + 47483648 // !
          return d }

这会抛出异常,因为它会在标记的行上溢出。如果更改数字,它将返回一个int值(因为Return成员从Checked类型中展开数值)。这是一个有点疯狂的技巧:-)但我想这可能会很有趣!

(注意,checked是一个保留供将来使用的关键字,因此您可能更喜欢选择其他名称)

票数 19
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2271198

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档