NetRoc
http://www.DbgTech.net
F#和很多语言不同,它不一定具有明确的程序入口点,如C语言的main函数。在单源文件程序中,代码是从头至尾执行的。在多源文件程序中,代码需要被组织为模块或者命名空间这样的单位。
模块
默认情况下,F# 将所有代码都放置在匿名模块(anonymous module)中。模块的命名为首字母大写的源文件名。因此,如果在文件file1.fs中有一个名为value1的值,那么可以通过File1.value1来引用它。
创建模块
代码中可以在源文件开始处使用module关键字来明确指定模块名。在module定义之后的所有值、函数或类型定义都属于该模块。如:
module Alpha
//在模块外部使用Alpha.x来引用下面的值:
let x = 1
模块嵌套
单个源文件中可以包含嵌套的模块。被嵌套的模块应该使用module关键字后跟一个等号来声明。嵌套模块必须比上层模块缩进对齐。如:
module Utilities
module ConversionUtils =
// Utilities.ConversionUtils.intToString
let intToString (x : int) = x.ToString()
module ConvertBase =
// Utilities.ConversionUtils.ConvertBase.convertToHex
let convertToHex x = sprintf "%x" x
// Utilities.ConversionUtils.ConvertBase.convertToOct
let convertToOct x = sprintf "%o" x
module DataTypes =
// Utilities.DataTypes.Point
type Point = Point of float * float * float
命名空间
除了模块之外还可以使用命名空间来组织代码。命名空间和模块的唯一区别在于,命名空间中不能包含值,只能包含类型定义。另外,命名空间不能像模块一样嵌套,而只需要直接在同一个源文件中定义多个命名空间。下面的例子在两个命名空间中定义了一些类型:
namespace PlayingCards
// PlayingCard.Suit
type Suit =
| Spade
| Club
| Diamond
| Heart
// PlayingCards.PlayingCard
type PlayingCard =
| Ace of Suit
| King of Suit
| Queen of Suit
| Jack of Suit
| ValueCard of int * Suit
namespace PlayingCards.Poker
// PlayingCards.Poker.PokerPlayer
type PokerPlayer = { Name : string; Money : int; Position : int }
在F#中部推荐同时使用命名空间和模块。模块主要用于快速进行原型定义和快速浏览解决方案。而命名空间主要用于使用面向对象设计的较大型的项目。
程序的启动
F#中程序是从最后一个源文件的顶部开始执行的。假如现在有包含下面代码的单文件项目:
// Program.fs
let numbers = [1 .. 10]
let square x = x * x
let squaredNumbers = List.map square numbers
printfn "SquaredNumbers = %A" squaredNumbers
open System
printfn "(press any key to continue)"
Console.ReadKey(true)
在VS 2010中再添加一个新的空F#源文件。这时,最后一个文件是新添加的空文件,因此如果此时按F5运行程序时,不会执行任何代码。
这一点需要特别注意,否则程序的执行可能会对初学者造成混乱。可以说F#这个设计真的是非常之奇怪,不但没有任何好处,还会让人非常之不爽。。。。。。。。。
更正式的做法是使用[<EntryPoint>]属性来定义一个main函数。main函数需要满足以下几个要求:
如果要明确指定main函数,那么上面那个程序应该改写为:
// Program.fs
open System
[<EntryPoint>]
let main (args : string[]) =
let numbers = [1 .. 10]
let square x = x * x
let squaredNumbers = List.map square numbers
printfn "SquaredNumbers = %A" squaredNumbers
printfn "(press any key to continue)")
Console.ReadKey(True) |> ignore
// Return 0
0