3.1.1 值的声明和作用域

来源:互联网 发布:湛庐文化 知乎 编辑:程序博客网 时间:2024/04/27 19:11

3.1.1 值的声明和作用域

 

我们已经知道,可以使用 let 关键字声明不可变值。但尚未讨论值的范围域(scope),不过很容易用一个具体的示例来解释。清单 3.1 非常简单,但是,在这四行代码的后面到底隐藏了多少奥秘,我想你也一定会很惊讶。

 

清单 3.1 值的作用域 (F#)

 

let number = 42    [1]

printfn "%d" number

let message = "Answer: " +number.ToString()    [2]

printfn "%s" message

 

清单 3.1 非常简单:它声明了两个值,第二个值[2]是由第一个值[1]计算出来的;然后,将它们输出到控制台。这里,我们着重想说的是值的作用域,即值可以被访问的代码区域。可以预料,值 number 在第一行声明了以后就可以访问;而值 message 只在最后一行才可以访问。可以看一下代码,并验证我们使用的值,都在作用域内,因此,代码是正确的。

这段代码还说明了另外一件事。清单 3.1 中的示例看上去很像 C# 代码,[看出相同不难,但能看出不同,就难了。]但要了解 F# 不同的处理代码方式才是重要的。在第二章(2.2.4 节),尝试在 C# 中只用表达式来写代码时,涉及过这个主题。我们知道,如果想让每个有效 F# 代码都成为表达式,值绑定必须特别处理。确实,如果用 C# 写代码,实现与清单 3.1 同样的功能,编译器会四个语句看作一个序列。我们现在来看看 F# 是如何理解这段代码的。为了演示,我们在语法上做了些小改动(见清单 3.2)。

 

清单 3.2 有显式作用域的 let 绑定(F#)

 

let number = 42 in

(                               |

printfn "%d" number;   [2]      |

let message =                  |       |

"Answer: " + number.ToString() in  |  [1]  |

(                             |       |  [3]

printfn "%s" message           |       |

)                             |       |

)                                |

 

清单 3.2 最明显的变化是布局,还有一点值得关注的是引入了关键字 in,出现在每个 let 绑定后。如果我们要关闭默认语法,即空白是有意义的1,那么,添加关键字 in 就是必须的;另一个变化是,跟在let 绑定后的代码块都括在括号中。这样做是可选的,但它更接近 F# 编译器对我们所写代码的理解。有趣的是,清单 3.2 中的代码仍然是有效 F# 代码,且与前面的代码功能完全相同。有时,我们可能希望代码更明确,使用关键字 in 和额外的括号,把想要处理的表达式括起来。

清单 3.2 中更明显的变化,是 let 绑定把值赋给符号,指定在表达式内可以使用这个符号。第一个 let 绑定声明了符号 number 表示 42,用于跟在 in 关键字后面用括号括起来的表达式中[1],整个 let 绑定就当成是一个表达式,它返回内部表达式的值。例如,定义值 message 的 let 绑定[3]是返回 printfn结果的表达式,这个函数的返回类型是 unit,因此,整个表达式的结果也是 unit。

 

注意

 

单独一行代码以let 开始、以 in 结束,不可能是有效的表达式,因为它缺少 let 绑定的主体。因此,必须为主体指定一些表达式。

 

再一个有趣的事情是表达式顺序。表达式[2]在表达式[3]之前,如你所见,我们在个表达式之间加了分号。分号是 F# 的顺序运算符(sequencing operator),它指定分号前面的表达式计算应先计算,后面的后计算。在这个示例中,[2]应该在[3]之前计算。在顺序运算符前面的表达式还应该返回 unit,否则返回值也会丢失。

 

注意

 

使用轻量级语法,就不必使用分号,只要分行就行了。编译器通过缩进代码找到哪些行是表达式,并自动在行尾处插入分号。

 

到目前为止,我们还是只看到声明普通值的普通let 绑定,但是,同样的let  绑定还能用于声明函数和嵌套绑定,下一节将学习。

-----------------

1 默认设置是有时也称为轻量级语法(lightweightsyntax)。F# 还支持兼容 OCaml 的语法,它更严谨,如我们在这个示例中使用的。本书的后面我们不会使用,如果你想尝试使用这种语法,在F# 源文件的开头添加#light "off" 指令,就可以打开。

0 0
原创粉丝点击