F # Adventure (III): imperative programming (II)

Source: Internet
Author: User

Control Flow)

In the article functional programming (medium), we have a preliminary understanding of the F # control process in the functional programming paradigm, that is, the structure composed of IF, Elif, then, else, and so on. In the imperative programming paradigm, F # provides more control process support, including if, while, and.

The main difference between the if structure in the imperative programming paradigm and the corresponding structure in functional programming is that for an if branch, the called function is of the unit type (that is, no return value ), else branch is not required:

F# Code
if System.DateTime.Now.DayOfWeek = System.DayOfWeek.Thursday then
  print_endline "Thursday play list: lazy afternoon"

Here, the print_endline function is of the string-> int type. Although else branch is not required, you can add it if needed, but else branch must also be of the unit type.

F# Code
if System.DateTime.Now.DayOfWeek = System.DayOfWeek.Thursday then
  print_endline "Thursday play list: lazy afternoon"
else
  print_endline "Alt play list: pop music"

At this point, no matter whether the branch of the IF structure returns the value, we have a way to represent it, so it is consistent with the if structure of C.

In C #, if there are more than one statement in a branch, curly brackets are required. In F #, the statements contained in the branch are represented by indentation.

For Loop is a common structure in imperative programming. If you have experience in C # Or VB. NET, it is easy to understand:

F# Code
let sentence = [| "To "; "live "; "is "; "to "; "function." |]
for index = 0 to Array.length sentence - 1 do
  System.Console.Write sentence.[index]

In C #, whether the for loop is executed depends on the result of the bool expression in the middle. Here, it depends on whether the local value index is within the specified range and the initial value is smaller than the end value. F # provides another for loop structure:

F# Code
let whitePollution = [| "This term refers to "; "pollution caused by ";
  "litter of used plastic bags, "; "polystyrene cups, ";
  "food containers and paper." |]

for index = Array.length whitePollution - 1 downto 0 do
  System.Console.Write whitePollution.[index]

The index value changes in descending order.

The while loop is also relatively simple, similar to C #. Let's look at an example:

F # code
// Geozhou
Let pressurecontinent = Ref ["this phrase's pronunciation is ";
"Similar to" Asia "in Chinese,"; "but it means ";
"A continent of pressure."]

while (List.nonempty !pressureContinent) do
  System.Console.Write(List.hd !pressureContinent);
  pressureContinent := List.tl !pressureContinent

Loop derivation (loops over comprehensions)

You can use the for loop to enumerate a set. This method is similar to the foreach structure in C. The following example enumerate a string array.

F# Code
let words = [| "Red"; "Lorry"; "Yellow"; "Lorry" |]
for word in words do
  print_endline word

Call static methods and properties in the. NET class library

Imperative programming in F # has an extremely useful feature. It can call class libraries written in any. NET language, including the Bcl itself. However, when calling a class library compiled by F # and compiled by other languages
The written class libraries are different because the F # class library has additional metadata, such as whether a method accepts a tuples or whether its parameters can be colized. These metadata is dedicated to F #.
Microsoft. fsharp. Reflection
API generation is largely due to the metadata, which is used for interaction between the metadata of F # And. net.

The static or basic syntax of the call class is the same as that of the instance method and attribute. Brackets must be used to call methods in a non-F # class library (spaces are usually available in F ). Methods in non-F # class libraries cannot
The method itself is not a value because it cannot be passed as a parameter. Following these rules, the method for calling a non-F # class library becomes straightforward and simple. Let's take a look at how to use static attributes and methods:

F# Code
#light
open System.IO
if File.Exists("test.txt") then
  print_endline "test.txt is present"
else
  print_endline "test.txt does not exist"

The exists method is a static method of the file class. The usage here is similar to that in C # Or VB. NET. However, the Code style here is not similar to the functional programming style. We can make a simple package of the. NET class library method:

F# Code
let exists filePath = File.Exists(filePath)
let files = ["test1.txt"; "test2.txt"; "test3.txt"]
let results = List.map exists files
print_any results

The code function above is to check the files in the list one by one to see if they exist. The exists function encapsulates the exist method, so that it can be called in the functional programming style.

If the. NET method you call has many parameters, you may forget the purpose of a parameter. In vs, you can view the parameter information (shortcut: Ctrl + k, p ). In F #, we can also use the named parameter (named argumengs ):

F# Code
open System.IO
let file = File.Open(path = "test.txt",
          mode = FileMode.Append,
          access = FileAccess.Write,
          share = FileShare.None)

print_any file.Length
file.Close()

Use objects and instance members in the. NET class library

In addition to static members of the class, we can also create an instance of the class and use its members (fields, attributes, events, and methods ):

F# Code
#light
open System.IO
let file = new FileInfo("notExisting.txt")
if not file.Exists then
  using(file.CreateText()) (fun stream ->
    stream.WriteLine("hello, f#"))
  file.Attributes <- FileAttributes.ReadOnly

print_endline file.FullName

This code references the namespace, creates an instance of the fileinfo class, checks whether the file exists, (if not,) creates the file, writes the text, sets the attribute value, and is familiar with C # Or
Are you familiar with VB. NET? The instance created here is similar to the record type. The referenced object itself (File) cannot be modified, but its content can be modified.
(Attributes attribute ). The "<-" operator is used to set the attribute value. Using is actually an operator used to clear resources (compare the using statements in C ).

Consider the example above. The two steps in the middle are to create an instance and set attributes. This is what we often do:

C# Code
Person person = new Person(1);
person.Name = "Steve";
person.BirthOn = DateTime.Now;

F # can also simplify the above process:

F# Code
open System.IO
let fileName = "test.txt"
let file =
  if File.Exists(fileName) then
    Some(new FileInfo(fileName, Attributes = FileAttributes.ReadOnly))
  else
    None

Use the indexer In the. NET class library)

Indexer is an important concept in. net. It makes a collection class look like an array. It is essentially a special attribute named item. Based on the above two points, F # provides two methods to access the indexer.

F# Code
#light
open System.Collections.Generic
let stringList =
  let temp = new ResizeArray<string>() in
  temp.AddRange([|"one"; "two"; "three"|]);
  temp

let itemOne = stringList.Item(0)
let itemTwo = stringList.[1]
printfn "%s %s" itemOne itemTwo

The first is access by attribute, and the second is access by array.

Note: the code in the above example is very simple, but shows a common mode in F. When creating a stringlist, instantiate it, call its instance Member (addrange) to set the status, and return the result.

Use the event in the. NET class library)

For developers of Windows Forms and web forms, I am afraid I do not know the meaning of the event? We can attach functions to events, such as button click events. These additional functions are sometimes called event handlers ).

Adding a processor function to an event is also easy. Each event exposes the add method. Because the event is defined in a non-F # class library, the add method must contain parentheses. In F #, anonymous functions can be used as processor functions.

The following example uses the Timer class and its elapsed event:

F # code-timer elapsed event
# Light
Open System. Timers
Module WF = system. Windows. Forms
Let timer =
Let temp = new timer ()
Temp. Integer <-1000.0
Temp. enabled <-true
Let messageno = ref 0
Temp. elapsed. Add (fun _->
Let messages = ["bet"; "this"; "gets ";
"Really"; "annoying"; "very"; "quickly";]
WF. MessageBox. Show (list. nth messages! Messageno) |> ignore
Messageno: = (! Messageno + 1) % (list. Length messages ))
Temp

print_endline "Whack the return to finish!"
read_line() |> ignore
timer.Enabled <- false

The removehandler method can be used to append the event processor and, of course, remove the event processor. The removehandler method accepts a delegate value.
The value encapsulates methods in. net so that they can be passed between methods like values. However, before removehandler is used, add the event processor with addhandler instead of ADD.
Method.

 

Apply pattern matching to. Net Type

Pattern Matching allows us to perform different operations on different values. In addition, F # allows matching of. Net types, which requires :? Operator.

F# Code
#light
let simpleList = [box 1; box 2.0; box "three"]

let recognizeType (item : obj) =
  match item with
  | :? System.Int32 -> print_endline "An integer"
  | :? System.Double -> print_endline "A double"
  | :? System.String -> print_endline "A string"
  | _ -> print_endline "Unkown type"

We cannot list all. Net types. The last row is used to match all other types. Naturally, when matching a type, we not only want to know the type but also the current value. You can do this:

F# Code
#light
let simpleList = [box 1; box 2.0; box "three"]
let recognizeType (item : obj) =
  match item with
  | :? System.Int32 as x -> printfn "An integer: %i" x
  | :? System.Double as x -> printfn "A double: %f" x
  | :? System.String as x -> printfn "A string: %s" x
  | x -> printfn "An object: %A" x

In the previous article, we learned the basic usage of exception handling, and the technology here is also available in exception handling, because we often capture exceptions based on types.

F# Code
let now = System.DateTime.Now
System.Console.WriteLine(now)
try
  if now.Second % 3 = 0 then
    raise (new System.Exception())
  else
    raise (new System.ApplicationException())
with
| :? System.ApplicationException ->
  print_endline "A second that was not a multiple of 3"
| _ ->
  print_endline "A second that was a multiple 3"

|> Operator (pipe-forward operator)

When applying the. NET class library, the "|>" operator is useful because it can help the compiler correctly export the type of function parameters. Its definition is simple:

F# Code
let (|>) x f = f x

Type information:

Tips
'a -> ('a -> 'b) -> 'b

It can be understood that the type of X is 'a, function f accepts a parameter of 'A', And the return type is 'B, the result of the operator is the value obtained after X is passed to F. In addition to "transferring" the parameter, "|>" is more important to help the compiler derive the type:

F# Code
open System
let dateList = [ new DateTime(1999, 9, 18);
  new DateTime(2000, 9, 19);
  new DateTime(2001, 9, 20) ]

List.iter (fun d -> print_int d.Year) dateList

In this case, the compiler reports an error because it cannot deduce the D type (this makes me feel a bit strange, the ITER function type is (a'-> unit)->
A' list->
Unit, which can deduce the type of datelist, but cannot obtain the type of D ). When "|>" is used, it is okay, because we explicitly tell the compiler the type of D:

F# Code
dateList |> List.iter (fun d -> print_int d.Year)

Let's take a look at the second example to understand how things are going:

F# Code
type fsDate = { year : int; month : int; day : int }
let fsDateList =
  [ { year = 1999; month = 12; day = 31 }
   { year = 2000; month = 12; day = 31 }
   { year = 2001; month = 12; day = 31 } ]

List.iter (fun d -> print_int d.year) fsDateList
fsDateList |> List.iter (fun d -> print_int d.year)

This Code does not produce compilation errors. Although it looks similar to the previous example, the main difference is that fsdate is the custom type in F #, datetime is not the class in F # class library.
Type. We can conclude that both the external. Net Type and F # type can be used, and the automatic type derivation of F # is best for F # type.

F# Code
let methods = System.AppDomain.CurrentDomain.GetAssemblies()
      |> List.of_array
      |> List.map (fun assm -> assm.GetTypes())
      |> Array.concat
      |> List.of_array
      |> List.map (fun t -> t.GetMethods())
      |> Array.concat

print_any methods

The "|>" operator can also be used to concatenate multiple function calls. Each function call sends the return value to the next function.

Summary

The scenery on this site is almost as elegant as it is, and the core part of imperative programming is also introduced. With the knowledge of functional and imperative programming, we should be confident to solve most of the problems. With F #, we can select the appropriate programming paradigm, instead of a specific one. Next, we will see the third main programming paradigm-object-oriented programming.

Note: The code in this article is written in F #1.9.4.17, and may not be compiled in F # CTP 1.9.6.0.

Refer:

Foundations of F # by Robert Pickering

Expert F # by Don Syme, Adam granicz, Antonio cisternino

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.