二、名称空间(namespace)

名称空间,将一组逻辑上相关的类型、模块放在一起,主要是为了解决名称冲突的问题,同时也便于更好的理解程序结构。F#的名称空间概念及定义与C#基本相似。

1、定义名称空间

在F#中定义名称空间,使用关键字namespace。

namespace FSharpLearning

名称空间声明的位置应在源文件的开头,除注释、部分指令外,namespace声明前不能有语句或表达式。

名称空间的作用域为定义开始到文件结束,除非遇到下一个名称空间的定义。在F#中一个源代码文件中可以定义多个名称空间。名称空间没有嵌套的概念,对F#来说,名称空间只是为了给名称空间下的元素定义一个完全限定名称而已。

C#可以在一个名称空间中嵌套定义名称空间,而F#不支持这种定义方式。

//在C#中定义嵌套名称空间的伪码

namespace N1

{

namespace N2

{

public class Test{}

}

}

这在c#中定义了一个N1.N2的名称空间。

不过F#支持使用.号分隔(与C#一致),表示一种逻辑上的层次关系,值得说明的是,对于编译器来说名称空间只是为了生成长名称(long name)而已,并没有真正的层次关系。

namespace FSharpLearning.StringExtensions

名称空间的作用域中只能定义类型、模块、异常(使用exception关键字定义的特殊联合类型,编译器会生成继承于System.Exception的类),不能定义值,所以在名称空间中不能出现let绑定,表达式。上一篇博客中讲到了在模块中是可以定义let绑定,函数,表达式。

名称空间可以使用open关键字打开。在F#中,open的使用与c#的using也有不同。在c#中using语句后跟的名称空间必须是全名称,但在F#中不仅支持这种写法,还有另一种使用方法。

open FSharpLearning

open StringExtensions(*open FSharpLearning.StringExtensions*)

在F#中虽然没有嵌套定义名称空间的语法,但却能使用open打开逻辑上嵌套的名称空间。

现在我来回答上一篇博客中留下来的问题。

由于使用了open关键字,使用未限定名访问,所以出现了同名的标识,F#会以最后一个open打开的名称空间及模块的名称,同名的会隐藏。后者隐藏前者。你当然可以使用完全限定名来访问隐藏的名称,其次你也可能使用别名的方式访问。

#light

module sw=System.Windows.Forms

module se=FSharpLearning.StringExtensions

open se

let s="Test".Link

sw.MessageBox.Show("good")|>ignore

2、定义名称空间下的子模块

上一篇博客中只讲到了顶级模块的定义,未讲到子模块的定义。F#子模块的定义仍然使用module。

#light

namespace FSharpLearning

module DateTimeExtensions =

open Math

type System.DateTime with

member x.ToNumber =

BigNum.of_bigint << BigInt.FromInt64 <| x.Ticks

你注意到不同了吗?子模块的定义于顶级模块不同在于,子模块的名称后面接着一个等号(=)。

module submodulename =begin

(*模块中可以定义子模块、类型、函数、值*)

end

begin end在#light指令下可以省略。

子模块与顶级模块从概念上来讲,子模块是指嵌套在模块之下的模块。顶级模块在一个名称空间下只可以定义一个,并且必须是名称空间下第一条语句。

子模块却可以定义多个。一个名称空间下可以定义多个子模块。

3、名称空间、模块之间的区别

名称空间主要用于组织逻辑上相关的类型。而模块主要用于定义对一个类型相关的行为。

名称空间就是为一组相关的类型定义一个完全限定名称,一是从逻辑上表示相关,二是为了解决名称冲突

模块则是为了模块化代码。在函数式语言中,通常把对某一个类型的操作放入到一个模块中,主要为了表示逻辑上依附于某一个类型,也部分解决名称冲突

从语义上来讲名称空间与模块没有什么不同,都是为了解决名称冲突与模块化编程而引入的语法。历史上来看,名称空间是后引入的,模块早于名称空间出现。

三、再议F#如何编译及确定入口点

上一篇博客讲过F#编译器依据传递给他的源代码文件名顺序依次编译、连接,以及编译为可执行文件时,以传递给他的最后一个文件名为入口点。

然后知道这一些仍然不够,很模糊,也并不完全正确。下面我用C#概念来描述一下规则

F#在编译的过程中,与源代码文件有很大关系。根据每一个源代码文件,F#会生成一个程序集访问级别的静态类(internal static),为便于描述,我把这个静态类称为内部静态类。每一个模块生成一个静态类。为了初始化这些静态类,F#会为每个静态类生成一个静态构造函数。内部静态类会初始化整个源代码文件中所有的静态成员。换句话如果一个源代码文件中有多个模块,那么这些模块都会被初始化。

F#以传递他的最后一个文件名作为程序入口点,会生成一个_main的方法。这是生成可执行文件默认的规则。显然生成dll,就没有入口点的说法,也就不会生成这个_main方法了。

不过F#还允许你指定入口方法。

#light

[<EntryPoint>] 
let test (a:string[]) =

printfn "Hello world"

System.Console.ReadKey(true) |>ignore

使用EntryPointAttribute属性指定一个方法为程序入口点,这种定义方法与C#很相似。不过,这个函数必须位于你传递给编译器最后一个文件中,且必须位于文件的最后。

对于可执行文件来说,程序执行时,入口点所在的源代码文件(编译器为我们生成的内部静态类)会首先加载,如果这个内部静态类引用了其他源代码文件,那么就会加载那个引用的源代码文件的内部静态类,如果引用的是类型,会加载相关类型,如果是模块,则会执行模块的静态构造函数,这种方式称为按需加载原则。对于dll,由于没有入口点,所以程序集加载时不会强制执行静态初始化,只会发生在调用时,当引用某个类型或模块时,相应的类型或模块所在的源代码文件的内部静态类静态构造器会被执行。

四、总结:

1、名称空间、模块的命名应以大写字母开头。

2、对于模块不要使用open,但使用可选类型扩展的模块除外,可选类型扩展的模块应使用类型名加上Extensions。

名称空间下主要包含类型及模块,类型和模块都有很好的封装能力,因此大多数情况下不会发生名称冲突的问题。而使用open打开了模块,就增大了名称冲突,并且也会为阅读代码造成影响,前面说过模块主要是为封装某一类型的行为或某一组逻辑上相同的行为,从某种意义上说,是模拟OO中的类的职责。F#库的List,Map,Seq这些模块如果使用open打开,就会造成阅读上的困难,也会造成名称隐藏。

但可选类型扩展则可以使用open打开。

type System.DateTime with

member x.ToNumber =

BigNum.of_bigint << BigInt.FromInt64 <| x.Ticks

可选类型扩展,与C#3.0的扩展方法相似,可以扩展某一类型的功能。可选类型扩展,必须定义在模块中,且扩展的类型名必须使用完全限定名称。

3、源代码文件名要使用字母开头。

4、不要轻易使用open的未限定名称方法,这很难看出完整的名称空间。

5、顶级模块不与命名空间一同使用,命名空间与子模块一起使用。

6、不要把不相关的模块放到一个源代码文件中,即使是同一个名称空间下的一组相关的模块

F#在生成内部静态类时是以源代码文件为单位的,不管调用了哪个模块中的值、类型、函数,任何一个在这个源代码文件中定义的模块,都会被静态初始化。

下一篇:F#学习之路(4) 基本类型

转载于:https://www.cnblogs.com/lvxuwen/archive/2008/08/17/1269948.html

F#学习之路(3) 如何组织程序(下)相关推荐

  1. F#学习之路(2) 深刻理解函数(上)

    函数在函数式编程语言中是一等公民,是函数式语言中最重要的基本组成元素,也是其名称的由来. F# 中的函数之如C#中的类,是组织程序结构的最基本单元.是命令式编程语言中函数或OO编程语言中方法的超集.超 ...

  2. C++学习之路 | PTA乙级—— 1026 程序运行时间(精简)

    1026 程序运行时间 (15 分) 要获得一个 C 语言程序的运行时间,常用的方法是调用头文件 time.h,其中提供了 clock() 函数,可以捕捉从程序开始运行到 clock() 被调用时所耗 ...

  3. python可视化双向箭头_python学习之路--可视化利器matplotlib(下)

    上一期我们介绍了matplotlib作图的基本思维,也对相关参数以及一些简单的图表进行示例演示,今天继续用matplotlib绘制一些既实用又有趣的图表.另外还有朋友问到能不能介绍一下pyechart ...

  4. Python学习之路【第一篇】-Python简介和基础入门

    1.Python简介 1.1 Python是什么 相信混迹IT界的很多朋友都知道,Python是近年来最火的一个热点,没有之一.从性质上来讲它和我们熟知的C.java.php等没有什么本质的区别,也是 ...

  5. 学计算机之路写一篇作文,学习之路作文

    学习之路作文 在日常生活或是工作学习中,大家对作文都再熟悉不过了吧,作文是由文字组成,经过人的思想考虑,通过语言组织来表达一个主题意义的文体.你知道作文怎样写才规范吗?下面是小编整理的学习之路作文,供 ...

  6. 微信小程序学习之路(一)

    微信小程序学习之路(一) 1.前言 2.准备工作 (1).IDE的选择 (2).微信小程序的文件说明 (3)开发者用户注册 3.编写 (1).新建项目 (2).代码的编写 3.代码的发布以及审核 1. ...

  7. 一个程序员的Java和C++学习之路(整理)

    转载:http://blog.csdn.net/ajian005/article/details/8003655 Java学习之路 一直有这么个想法,列一下我个人认为在学习和使用Java过程中可以推荐 ...

  8. 【转】一个程序员的Java和C++学习之路(整理)

    经典编程书籍大全:  http://blog.jobbole.com/106093/  https://github.com/jobbole/awesome-programming-books Jav ...

  9. 一个程序员的Java和C++学习之路

    转载自:http://blog.csdn.net/ajian005/article/details/8003655 经典编程书籍大全: http://blog.jobbole.com/106093/ ...

最新文章

  1. 周志华教授发表首届国际学习与推理联合大会IJCLR开场Keynote:探索从纯学习到学习+推理的AI...
  2. Python模块制作
  3. ggplot2设置坐标轴范围_Matplotlib入门-2-坐标轴axis/axes设置
  4. buildroot output子目录
  5. ubuntu下的能安装的百度网盘的资源最新网址
  6. php 字符串混合分割并存入数组
  7. java绘制图形_Java绘制图形
  8. J - X and Beasts
  9. 从数据库查询数据并输出到前台页面
  10. 税控数据接口之XML接口导入
  11. JVM 内存分析工具MAT
  12. 非华为电脑安装华为电脑管家,实现与手机平板的多屏协同
  13. vue 组件自己调用自己
  14. (端到端多尺度去雾算法)FAMED-Net: A Fast and Accurate Multi-scale End-to-end Dehazing Network
  15. android本地视频 投屏,小米投屏神器
  16. UVa 220 黑白棋 算法竞赛入门经典 习题4-3
  17. 人工神经网络连接权重的优化与调整
  18. 【白皮书】用于过程工业的PROFINET
  19. 中文编程,最精致的python访客登记系统实例项目,微信机器人不再只当人工智障---08
  20. 使用python3.7中的scrapy框架,爬取起点小说

热门文章

  1. ORACLE 表空间SQL
  2. c# mysql 文件存储_c# 如何实现保存文件到数据库
  3. mos管工作原理_筋膜枪原理与筋膜枪方案,和筋膜枪烧mos管原理。推荐使用mos管 AP15G04NF...
  4. java1234小峰推荐书籍_java1234 webservice 第2 课 cfx实现
  5. vscode运行conda出现 “无法加载文件C:\Users\WindowsPowerShell\profile.ps1,因为在此系统上禁止运行脚本” 的错误
  6. springboot 跨域配置cors
  7. Struts2中jsp page=xxx.action/jsp失效
  8. 优秀!22岁读博士,26岁当教授,因为太优秀反而没人敢追?
  9. 13 个 Python 新手练级项目
  10. 入门 | 32 个常用 Python 实现