1. Trang chủ
  2. » Công Nghệ Thông Tin

Foundations of F#.Net phần 5 potx

32 319 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 32
Dung lượng 332,82 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

The typical way to create asignature file is to generate it from the module source and then go through and erase any val-ues and functions that you want to be private.. InVisual Studio,

Trang 1

module GColl = System.Collections.Generic

let l = new GColl.List<int>()

Signature Files

Signature files are a way of making function and value definitions private to a module You’ve

already seen the syntax for the definition of a signature file in Chapter 2 It is the source thatthe compiler generates when using the –i switch Any definitions that appear in a signaturefile are public and can be accessed by anyone using the module Any that are not in the signa-ture file are private and can be used only inside the module itself The typical way to create asignature file is to generate it from the module source and then go through and erase any val-ues and functions that you want to be private

The signature file name must be the same as the name of the module with which it ispaired It must have the extension fsi or mli You must specify the signature file to the com-piler On the command line, you must give it directly before the source file for its module InVisual Studio, the signature file must appear before the source file in Solution Explorer.For example, if you have the following in the file Lib.fs:

val funkyFunction : string -> string

and would use the command line like this:

in this section and execution order in the next

Values and types within a module cannot be seen from another module unless the ule they’re in appears on the command line before the module that refers to them This isprobably easier to understand with an example Suppose you have a source file, ModuleOne.fs,containing the following:

mod-C H A P T E R 6 n O R G A N I Z I N G, A N N OTAT I N G, A N D Q U OT I N G C O D E

116

7575Ch06.qxp 4/27/07 1:11 PM Page 116

Trang 2

module ModuleOne

let text = "some text"

and another module, ModuleTwo.fs, containing the following:

#light

module ModuleTwo

print_endline ModuleOne.text

These two modules can be compiled successfully with the following:

fsc ModuleOne.fs ModuleTwo.fs -o ModuleScope.exe

But the following command:

fsc ModuleTwo.fs ModuleOne.fs -o ModuleScope.exe

would result in this error message:

ModuleTwo.fs(3,17): error: FS0039: The namespace or module 'ModuleOne' is not

Roughly speaking, execution in F# starts at the top of a module and works its way down to

the bottom Any values that are functions are calculated, and any top-level statements are

executed So, the following:

module ModuleOne

print_endline "This is the first line"

print_endline "This is the second"

let file =

let temp = new System.IO.FileInfo("test.txt") inPrintf.printf "File exists: %b\r\n" temp.Exists;

tempwill give the following result:

Trang 3

This is the first line

This is the second

File exists: false

This is all pretty much as you might expect When a source file is compiled into an bly, none of the code in it will execute until a value from it is used by a currently executingfunction Then, when the first value in the file is touched, all the let expressions and top-levelstatements in the module will execute in their lexical order When a program is split over morethan one module, the last module passed to the compiler is special All the items in this mod-ule will execute, and the other items will behave as they were in an assembly Items in othermodules will execute only when a value from that module is used by the module currentlyexecuting Suppose you create a program with two modules

print_endline "This is the first line"

print_endline "This is the second"

If this is compiled with the following:

fsc ModuleOne.fs ModuleTwo.fs -o ModuleExecution.exe

this will give the following result:

This is the first line

This is the second

This might not be what you expected, but it is important to remember that since ModuleOnewas not the last module passed to the compiler, nothing in it will execute until a value from it isused by a function currently executing In this case, no value from ModuleOne is ever used, so itnever executes Taking this into account, you can fix your program so it behaves more as youexpect

Trang 4

Here is ModuleTwo.fs:

module ModuleTwo

print_endline "This is the first line"

print_endline "This is the second"

let funct() =

Printf.printf "%i" ModuleOne.n

funct()

If this is compiled with the following:

fsc ModuleOne.fs ModuleTwo.fs -o ModuleExecution.exe

it will give the following result:

This is the first line

This is the second

This is the third and final

1

However, using this sort of trick to get the results you want is not recommended It is erally best only to use statements at the top level in the last module passed to the compiler In

gen-fact, the typical form of an F# program is to have one statement at the top level at the bottom

of the last module that is passed to the compiler

Optional Compilation

Optional compilation is a technique where the compiler can ignore various bits of text from a

source file Most programming languages support some kind of optional compilation It can

be handy, for example, if you want to build a library that supports both NET 1.1 and 2.0 and

want to include extra values and types that take advantage of the new features of version 2.0

However, you should use the technique sparingly and with great caution, because it can

quickly make code difficult to understand and maintain

In F# optional compilation is supported by the compiler switch define FLAG and thecommand #if FLAG in a source file

The following example shows how to define two different versions of a function, one forwhen the code is compiled for NET 2.0 and the other for all other versions of NET:

Trang 5

let getArray() = CompatArray.of_array [|1; 2; 3|]

#endif

This example assumes that the compiler switch define FRAMEWORK_AT_LEAST_2_0 isdefined when the code is being compiled for NET 2.0 Chapter 13 gives more on the differ-ences between NET 1.0, 1.1, and 2.0 and covers compiler options

Comments

F# provides two kinds of comments Multiline comments start with a left parenthesis and an

asterisk and end with an asterisk and a right parenthesis For example:

(* this is a comment *)

or

(* this

is acomment

Doc comments allow comments to be extracted from the source file in the form of XML or HTML.

This is useful because it allows programmers to browse code comments without having to browsethe source This is convenient for the vendors of APIs because it allows them to provide documen-tation about the code without having to provide the source itself, and it is just more convenient to

be able to browse the docs without having to open the source In addition, the documentation isstored alongside the source where it has more chance of being updated when code changes.Doc comments start with three slashes instead of two They can be associated only withtop-level values or type definitions and are associated with the value or type they appearimmediately before The following code associates the comment this is an explanation withthe value myString:

#light

/// this is an explanation

let myString = "this is a string"

To extract doc comments into an XML file, you use the –doc compiler switch If this ple were saved in a source file, prog.fs, the following command:

exam-fsc -doc doc.xml Prog.fs

C H A P T E R 6 n O R G A N I Z I N G, A N N OTAT I N G, A N D Q U OT I N G C O D E

120

7575Ch06.qxp 4/27/07 1:11 PM Page 120

Trang 6

would produce the following XML:

You can then process the XML using various tools, such as NDoc (ndoc.sourceforge.net),

to transform it into a number of more readable formats The compiler also supports the direct

generation of HTML from doc comments Although this is less flexible than XML, it can

pro-duce usable documentation with less effort It can also propro-duce better results, under some

circumstances, because notations such as generics and union types are not always well

sup-ported by documentation generation tools I cover the compiler switches that generate HTML

in “Useful Command-Line Switches” in Chapter 12

In F# there is no need to explicitly add any XML tags; for example, the <summary> and

</summary> tags were added automatically I find this useful because it saves a lot of typing and

avoids wasted space in the source file; however, you can take control and write out the XML

tags themselves if you want The following is a doc comment where the tags have been

explic-itly written out:

Trang 7

be included in the resulting XML or HTML if the compiler is given a signature file for it.

Custom Attributes

Custom attributes add information to your code that will be compiled into an assembly andstored alongside your values and types This information can then be read programmaticallyvia reflection or by the runtime itself

Attributes can be associated with types, members of types, and top-level values They canalso be associated with do statements An attribute is specified in brackets, with the attributename in angle brackets For example:

C H A P T E R 6 n O R G A N I Z I N G, A N N OTAT I N G, A N D Q U OT I N G C O D E

122

7575Ch06.qxp 4/27/07 1:11 PM Page 122

Trang 8

So far, we’ve used attributes only with values, but using them with type or type members

is just as straightforward The following example marks a type and all its members as obsolete:

because the libraries that provide the graphical components use unmanaged (not compiled

by the CLR) code under the covers The easiest way to do this is by using the STAThread

attrib-ute This must modify the first do statement in the last file passed to the compiler, that is, the

first statement that will execute when the program runs For example:

Trang 9

n Note The dokeyword is usually required only when not using the #lightmode; however, it is alsorequired when applying an attribute to a group of statements.

Once attributes have been added to types and values, it’s possible to use reflection to find which values and types are marked with which attributes This is usually done with theIsDefined or GetCustomAttributes methods of the System.Reflection.MemberInfo class,meaning they are available on most objects used for reflection including System.Type Thenext example shows how to look for all types that are marked with the Obsolete attribute:

m.IsDefined((type System.ObsoleteAttribute), true))

Now that you’ve seen how you can use attributes and reflection to examine code, let’s look

at a similar but more powerful technique for analyzing compiled code, called quotation.

Quoted Code

Quotations are a way of telling the compiler, “Don’t generate code for this section of the source

file; turn it into a data structure, an expression tree, instead.” This expression tree can then be

interpreted in a number of ways, transformed or optimized, compiled into another language,

or even just ignored

Quotations come in two types, raw and typed, the difference being that typed quotationscarry static type information whereas raw quotations do not Both carry runtime type annota-tions Typed quotations are designed for use in client programs, so usually you will want to use

C H A P T E R 6 n O R G A N I Z I N G, A N N OTAT I N G, A N D Q U OT I N G C O D E

124

7575Ch06.qxp 4/27/07 1:11 PM Page 124

Trang 10

typed quotations These are the only quotations covered in this section Raw quotations are

designed for implementing libraries based on quotations; these will generally be

automati-cally typed quotations before they are consumed

To quote an expression, place it between guillemets (also called French quotes), « » To

ensure the compiler recognizes these characters, you must save your file as UTF-8 Visual

Studio users can do this with File äAdvanced Save If you have some objection to using

UTF-8, you can use an ASCII alternative: <@ @> Both ways of quoting an expression are

essentially just an operator defined in a module, so you need to open the module Microsoft

FSharp.Quotations.Typed to be able to use them The next example uses a quotation and

prints it:

#light

open Microsoft.FSharp.Quotations.Typed

let quotedInt = « 1 »

printf "%A\r\n" quotedInt

The result is as follows:

printf "%A\r\n" asciiQuotedInt

The result is as follows:

printf "%A\r\n" quotedId

The result is as follows:

<@ Prog.n @>

Trang 11

Next we’ll quote a function applied to a value Notice that since we are quoting two items,the result of this quotation is split into two parts The first part represents the function, andthe second represents the value to which it is applied.

#light

open Microsoft.FSharp.Quotations.Typed

let inc x = x + 1

let quotedFun = « inc 1 »

printf "%A\r\n" quotedFun

The result is as follows:

printf "%A\r\n" quotedOp

The result is as follows:

<@ Microsoft.FSharp.Operators.op_Addition (Int32 1) (Int32 1) @>

The next example quotes an anonymous function:

#light

open Microsoft.FSharp.Quotations.Typed

let quotedAnonFun = « fun x -> x + 1 »

printf "%A\r\n" quotedAnonFun

The result is as follows:

C H A P T E R 6 n O R G A N I Z I N G, A N N OTAT I N G, A N D Q U OT I N G C O D E

126

7575Ch06.qxp 4/27/07 1:11 PM Page 126

Trang 12

function, interpretInt, that queries the expression passed to it to see whether it is an integer.

If it is, it prints the value of that integer; otherwise, it prints the string "not an int"

#light

open Microsoft.FSharp.Quotations

open Microsoft.FSharp.Quotations.Typed

let interpretInt exp =

let uexp = to_raw exp inmatch uexp with

In this chapter, you saw how to organize code in F# You also saw how to comment, annotate,

and quote code, but you just scratched the surface of both annotation and quoting

This concludes the tour of the F# core language The rest of the book will focus on how touse F#, from working with relational databases to creating user interfaces, after you look at the

F# core libraries in the next chapter

Trang 14

The F# Libraries

Although F# can use all the classes available in the NET BCL, it also ships with its own set of

libraries

The F# libraries are split into two, FSLib.dll, which is also referred to as the native F# library

or just FSLib, and MLLib.dll, which is sometimes referred to as the ML compatibility library or

MLLib FSLib contains everything that the F# compiler really needs to work; for example, it

con-tains the Tuple class that is used when you use a tuple MLLib is a set of libraries for doing

common programming tasks partially based on the libraries that ship with OCaml

The objective of this chapter is not to completely document every nuance of every F#

library type and function It is to give you an overview of what the modules can do, with a

par-ticular focus on features that aren’t readily available in the BCL The F# online documentation

(http://research.microsoft.com/fsharp/manual/namespaces.html) is the place to find

detailed documentation about each function

There is some crossover between the functionality provided by the F# libraries and the.NET BCL Programmers often ask when should they use functions from the F# library and

when should they use the classes and methods available in the NET BCL Both have their

advantages and disadvantages, and a good rule of thumb is to prefer what is in FSLib over the

classes available in the NET Framework BCL and prefer what is available in the NET

Frame-work BCL over MLLib

Libraries Overview

The following sections list all the modules that are contained in FSLib and MLLib; the

mod-ules covered in this chapter are highlighted in bold

129

C H A P T E R 7

n n n

Trang 15

The Native F# Library FSLib.dll

These are the modules in FSLib:

• Microsoft.FSharp

• Idioms

• Reflection

• Microsoft.FSharp.Collections

• ComparisonIdentity • HashIdentity • IEnumerable

• LanguagePrimitives • Operators • OptimizedClosures

• UInt8

• Microsoft.FSharp.Math

C H A P T E R 7 n T H E F # L I B R A R I E S

130

7575Ch07.qxp 4/27/07 1:03 PM Page 130

Trang 16

The ML Compatibility Library MLLib.dll

These are the modules in MLLib:

Ngày đăng: 05/08/2014, 10:21

TỪ KHÓA LIÊN QUAN