F#基础教程 范围

  在一个程序里,你可以在有效的范围里使用一个标识符。范围是一个相当简单的概念,重要的是要有很好的理解。如果尝试在标识符范围外使用它,你会得到一个编译错误。所有的标识符,不论是值(Values)或函数(Functions),其范围从其定义,直到其出现部分(空格缩进部分)的结束。在顶层的标识符(即标识符的定义没有被函数或值包含),其范围从它的定义直到源代码的结束有效。一旦一个顶层标识符被分配一个值(value)(或功能(function)),这个值就不能更改或重新定义。

  在函数中定义的标识符与顶层标识符稍有不同,它们可以使用let关键字重新定义。这意味着,在F#里不必保留标识符用于保留中间值。为了演示,下面是一个F#实现的数学题,这里需要计算大量的中间值,而发明每一个名称将是程序员不必要的负担。这点比Haskell灵活多了。

#light
let mathsPuzzle() =
  print_string "输入你出生的在一月中的天数 "
  let input = read_int ()
  let x = input * 4     // 乘以4
  let x = x + 13        //  加13
  let x = x * 25        //  乘以25
  let x = x - 200       //  减200
  print_string "输入你出生月份 "
  let input = read_int ()
  let x = x + input

  let x = x * 2        // 乘以2
  let x = x - 40       // 减40
  let x = x * 50       // 乘以50
  print_string "输入出生年份的最后两位数字 "
  let input = read_int ()
  let x = x + input
  let x = x - 10500     // 最后减去10500
  printf "Date of birth (ddmmyy): %i" x
mathsPuzzle()


执行结果:
输入你出生的在一月中的天数:23
输入你出生的月份数:5
输入出生年份的最后两位数字:78
出生日期(DDMMYY):230578


  我要指出,这不是不断改变一个标识符的值,因为你重新定义了标识符,给予它新的含义。你也可以改变标识符的类型,但要注意类型安全。

  下面的例子代码将涉及类型安全,因为在第三行,你改变x的值由一个整形到字符串,并在第四行尝试与一个整数相加。F#的类型系统会阻止你执行操作,返回一个编译错误。

#light
let changeType () =
  let x = 1          // 定义 x 为一个整数
  let x = "change me"    // 重新定义 x 为一个字符串
  let x = x + 1       // 试图将字符串和一个整数相加
  print_string x

执行结果:
prog.fs(55,13): error: FS0001: 这个表达式的类型是
int
但是这里用类型
string
试图相加

  如果重新定义标识符,其旧值将被隐藏,直到新值的范围结束,标识符才恢复其旧值。简单说重新定义并未丢弃原来的定义,只是在其范围内屏蔽了旧的定义。下面将给出一个示例。

#light
let printMessages() =
  // 定义消息并打印
  let message = "Important"
  printfn "%s" message;
  // 定义一个内部功能,重新定义消息的值
  let innerFun () =
    let message = "Very Important"
    printfn "%s" message
  // 执行内容函数
  innerFun ()
  // 最后再打印消息
  printfn "%s" message
printMessages()

执行结果:
Important
Very Important
Important

  innerFun ()是一个内部函数,使用用内部函数是一种常见和优秀的方法,你会看到它的使用贯穿全书。有时它们也被称为闭包和lambda表达式,虽然这两个词有更具体的含义。

posted @ 2011-11-22 16:39  银河系漫游指南  阅读(430)  评论(0编辑  收藏  举报