2016-09-02 6 views
5

Warum sind unter read_rest_of_csv Klammern erforderlich?Warum sind Klammern für diese F # -Funktion erforderlich?

let read_rest_of_csv() = 
     csv_data.Add(csv_fileH.ReadFields()) |> ignore 
     not csv_fileH.EndOfData 

    while read_rest_of_csv() do ignore None 

Ohne die Klammern wird die Schleife nicht beendet.

open System 
open System.Threading 
open System.Collections.Generic 
open System.Linq 
open System.Text 
open System.Threading.Tasks 
open System.IO 
open Microsoft.VisualBasic.FileIO 

[<EntryPoint>] 
let main argv = 
    let csv_fileH = new TextFieldParser("test1.csv") 
    csv_fileH.TextFieldType = FieldType.Delimited |> ignore 
    let x = csv_fileH.SetDelimiters(",") 
    let csv_data = new List<string[]>() 

    let eod = csv_fileH.EndOfData 
    if not eod then 
     let column_headings = csv_fileH.ReadFields() 
     csv_data.Add(column_headings) |> ignore 

     let read_rest_of_csv = 
      csv_data.Add(csv_fileH.ReadFields()) |> ignore 
      not csv_fileH.EndOfData 

     while read_rest_of_csv do ignore None 

    0 

Ich entschuldige mich, dass ich mich nicht erinnern kann, wo ich das gesehen habe. Ich denke, es war in SO. Es ist ein schönes Beispiel.

Könnte das sein, dass ich ohne Parens ein Funktionsobjekt habe?

Ich komme in der Tat nicht nur von einem C, C++ und C# Hintergrund, sondern auch eine Zwischen Clojure Hintergrund. In meinem Fall mit der F # -Syntax könnte das Lesen meines Haskell-Handbuchs etwas mehr hilfreich gewesen sein, weil die Syntax ähnlich aussieht.

Antwort

18

Es scheint, dass Leute aus C-Familiensprachen (C#, Java, C, C++, JavaScript) Probleme haben, die Verwendung von Klammern in F # zu verstehen. Ich hatte sicherlich, und es dauerte einige Jahre zu lernen, wie die Dinge funktionieren.

Kurz gesagt, ist der einfachste Baustein in F # ein Wert. Werte können let -gebunden sein:

let foo = bar 

Dies bedeutet, dass foo ein Wert ist, der gleich sein bar passiert.

Funktionen sind auch Werte:

// 'a -> 'a * 'a 
let f = fun x -> x, x 

Hier f ist eine Funktion, die sowohl einen gewissen Wert (x) und gibt ein Tupel nimmt mit x als das erste und das zweite Element.

Das ist ein bisschen umständlich ist zu schreiben, so dass es eine Abkürzung für die:

// 'a -> 'a * 'a 
let f x = x, x 

Hinweis, dass es keine Klammern in diesem Ausdrücken.

Manchmal müssen Sie den Vorrang von Operatoren anpassen. Genau wie in Mathe ist 1 + 2 * 3 (was 1 + (2 * 3) entspricht) nicht dasselbe wie (1 + 2) * 3. In F # verwenden Sie auch Klammern, um Vorrang zu überschreiben. So

// 'a -> string * 'a 
let f x = someOtherFunction x, x 

nicht die gleiche ist wie

// x:'a -> string 
let f x = someOtherFunction (x, x) 

(in diesem Fall ist someOtherFunction eine Funktion, die eine string zurückgibt.)

Beachten Sie, dass die Klammern bezeichnen keine Funktion Anruf; Sie sind nur da, um die Reihenfolge der Auswertung zu kontrollieren.

Manchmal möchten Sie eine Funktion definieren, die keine Eingabe benötigt. Sie können jedoch nicht es wie folgt definieren:

let f = whatever 

da, dass es ein Wert machen würde, die let -bound zu whatever sofort ist. Stattdessen können Sie der Funktion einen Wert des integrierten Typs unit annehmen lassen. Dieser Typ hat nur einen einzigen Wert, der geschrieben wird ():

let f() = whatever 

Dies bedeutet, dass f ist eine Funktion, die Muster seinem Eingang gegen den einzigen bekannten Wert von unit einstimmt. Wenn Sie f mit () aufrufen, wird der Ausdruck whatever ausgewertet und zurückgegeben.

+0

Sie haben einen guten Punkt über die Programmierung der Menschen auf F # gemacht. Also fügte ich dem OP noch etwas hinzu, um meinen Hintergrund anzuzeigen. Der Teil, an den ich mich gewöhnen muss, sind Dinge wie unit,() und diese Bindungen. – octopusgrabbus

5

Ohne die Klammern wird der Inhalt einmal und nie wieder ausgeführt. read_rest_of_csv hat eine Art von bool: Sie sagen im Grunde while true do ignore None.

Die Klammern zeigen an, dass read_rest_of_csv den Typ unit -> bool hat. Bei jedem Aufruf wird eine Zeile gelesen und der Cursor bewegt. Ansonsten wird es das nur einmal tun.

+0

Könnte ich Klammern anstelle von Parens verwendet haben? – octopusgrabbus

+0

Für "Klammern", lesen Sie "Klammern". Ich bearbeite meine Antwort (nicht mit den Kindern, ich habe Angst). –

+0

Dank RobLyndon – octopusgrabbus

3

Die Antwort auf Ihre Frage ist, dass:

let read_rest_of_csv = 
    csv_data.Add(csv_fileH.ReadFields()) |> ignore 
    not csv_fileH.EndOfData 

keine Funktion überhaupt ist. Dies ist kein Unterschied zu:

> let i = 1;; 

val i : int = 1 

Dies deklariert eine Bindung mit einem ganzzahligen Wert. Wenn Sie eine Bindung mit einem Funktionswert erklären wollen, die keine Parameter annimmt, sieht das wie folgt aus:

> let i() = 1;; 

val i : unit -> int 

Genau die gleiche Argumentation read_rest_of_csv gilt. Ohne die Klammer deklarieren Sie eine Bindung mit dem Typ bool. Mit den Klammern deklarieren Sie eine Bindung mit dem Typ unit->bool, d. H. Eine Bindung mit einem Funktionswert, wobei die Funktion keine Eingaben annimmt und einen bool-Wert zurückgibt.

Verwandte Themen