F # อย่างชัดเจนตรงกับไวยากรณ์ของฟังก์ชัน


90

ขออภัยเกี่ยวกับชื่อเรื่องที่คลุมเครือ แต่ส่วนหนึ่งของคำถามนี้เรียกว่ารูปแบบไวยากรณ์ทั้งสองนี้:

let foo1 x = 
    match x with
    | 1 -> "one"
    | _ -> "not one"

let foo2 = function 
    | 1 -> "one" 
    | _ -> "not one"

อีกส่วนหนึ่งคือความแตกต่างระหว่างทั้งสองและเมื่อใดที่ฉันต้องการใช้อย่างใดอย่างหนึ่ง

คำตอบ:


58

เวอร์ชันที่ตรงกันเรียกว่า "นิพจน์การจับคู่รูปแบบ" เวอร์ชันของฟังก์ชันเรียกว่า "ฟังก์ชันการจับคู่รูปแบบ" พบได้ในส่วน 6.6.4 ของข้อมูลจำเพาะ

การใช้อย่างใดอย่างหนึ่งเป็นเรื่องของสไตล์ ฉันชอบใช้เวอร์ชันฟังก์ชันเมื่อฉันต้องการกำหนดฟังก์ชันที่เป็นเพียงคำสั่งที่ตรงกันเท่านั้น


ขอขอบคุณ. แม้ว่าการเขียนโปรแกรมเชิงฟังก์ชันโดยใช้ F # กล่าวว่าการใช้คำสำคัญของฟังก์ชันระบุว่าเป็นฟังก์ชันการจับคู่รูปแบบคำตอบนี้และ OP ชี้แจงช่วงเวลาที่สมองติดขัด
octopusgrabbus

ดูเหมือนว่าลิงก์จะเสีย
MattMS

84

Pro สำหรับไวยากรณ์ที่สองคือเมื่อใช้ในแลมบ์ดามันอาจจะสั้นกว่าและอ่านได้

List.map (fun x -> match x with | 1 -> "one" | _ -> "not one") [0;1;2;3;1]

เทียบกับ

List.map (function 1 -> "one" | _ -> "not one") [0;1;2;3;1]

23

เวอร์ชันของฟังก์ชันเป็นคำสั่งสั้น ๆ สำหรับไวยากรณ์การจับคู่แบบเต็มในกรณีพิเศษที่คำสั่งที่ตรงกันคือฟังก์ชันทั้งหมดและฟังก์ชันมีเพียงอาร์กิวเมนต์เดียว (สิ่งที่รวมเป็นหนึ่ง) หากคุณต้องการมีสองอาร์กิวเมนต์คุณต้องใช้ไวยากรณ์การจับคู่แบบเต็ม * คุณสามารถดูสิ่งนี้ได้ในประเภทของสองฟังก์ชันต่อไปนี้

//val match_test : string -> string -> string
let match_test x y = match x, y with
                        | "A", _ -> "Hello A"
                        | _, "B" -> "Hello B"
                        | _ -> "Hello ??"

//val function_test : string * string -> string                   
let function_test = function
                        | "A", _ -> "Hello A"
                        | _, "B" -> "Hello B"
                        | _ -> "Hello ??"

ดังที่คุณเห็นเวอร์ชันการจับคู่ใช้อาร์กิวเมนต์แยกกันสองอาร์กิวเมนต์ในขณะที่เวอร์ชันของฟังก์ชันใช้อาร์กิวเมนต์ tupled เดียว ฉันใช้เวอร์ชันของฟังก์ชันสำหรับฟังก์ชันอาร์กิวเมนต์เดียวส่วนใหญ่เนื่องจากฉันพบว่าไวยากรณ์ของฟังก์ชันดูสะอาดกว่า

* หากคุณต้องการจริงๆคุณสามารถรับเวอร์ชันฟังก์ชันเพื่อให้มีลายเซ็นประเภทที่ถูกต้อง แต่ในความคิดของฉันดูน่าเกลียดมาก - ดูตัวอย่างด้านล่าง

//val function_match_equivalent : string -> string -> string
let function_match_equivalent x y = (x, y) |> function
                                                | "A", _ -> "Hello A"
                                                | _, "B" -> "Hello B"
                                                | _ -> "Hello ??"

12

พวกเขาทำสิ่งเดียวกันในกรณีของคุณ - functionคำหลักจะทำหน้าที่เหมือนการรวมกันของfunคำหลัก (เพื่อสร้างแลมด้าที่ไม่ระบุตัวตน) ตามด้วยmatchคำหลัก

ในทางเทคนิคทั้งสองนี้เหมือนกันโดยมีการเพิ่มfun:

let foo1 = fun x ->
    match x with
    | 1 -> "one"
    | _ -> "not one"

let foo2 = function
    | 1 -> "one"
    | _ -> "not one"

1
มันไม่ได้เป็นวิธีอื่นจริง ๆ - กล่าวfunคือมีการกำหนดทางเทคนิคในแง่ของfunction | _ -> ...?
Pavel Minaev

1
การจะมีความเฉพาะเจาะจงfun x y -> ...จะfun x -> fun y -> ...แล้วจะเป็นfun x -> ... function | x -> ...มันเป็นเหตุผลที่คุณสามารถทำได้ในการจับคู่แบบfun- fun (x::xs) -> ...เช่น
Pavel Minaev

10

เพื่อความสมบูรณ์ฉันไปที่หน้า 321 ของExpert FSharp :

"หมายเหตุรายการ 12-2 ใช้รูปแบบนิพจน์function pattern-rules -> expressionซึ่งเทียบเท่า(fun x -> match x with pattern-rules -> expression)และสะดวกเป็นพิเศษในการกำหนดฟังก์ชันที่ทำงานโดยตรงกับสหภาพแรงงานที่เลือกปฏิบัติ"


6

ฟังก์ชันอนุญาตให้ใช้อาร์กิวเมนต์เดียวเท่านั้น แต่อนุญาตให้จับคู่รูปแบบได้ในขณะที่ความสนุกสนานเป็นวิธีที่กว้างและยืดหยุ่นกว่าในการกำหนดฟังก์ชัน ดูที่นี่: http://caml.inria.fr/pub/docs/manual-ocaml/expr.html


ทำไมคุณพูดเพียง 1 อาร์กิวเมนต์แทนที่จะเป็นอาร์กิวเมนต์สุดท้ายเท่านั้น เป็นไปได้ที่จะมีอาร์กิวเมนต์มากกว่า 1 รายการและใช้ "ฟังก์ชัน" นี่เป็นการตีความฟังก์ชันลำดับที่สูงขึ้นหรือไม่
symbiont

4

ไวยากรณ์ทั้งสองเทียบเท่ากัน โปรแกรมเมอร์ส่วนใหญ่เลือกอย่างใดอย่างหนึ่งแล้วใช้อย่างสม่ำเสมอ

ไวยากรณ์แรกยังคงอ่านได้ง่ายขึ้นเมื่อฟังก์ชันยอมรับหลายอาร์กิวเมนต์ก่อนเริ่มทำงาน


2

นี่เป็นคำถามเก่า แต่ฉันจะทุ่ม $ 0.02

โดยทั่วไปแล้วฉันชอบที่ดีกว่า matchเวอร์ชันเนื่องจากฉันมาจากโลก Python ซึ่ง "Explicit ดีกว่าโดยปริยาย"

แน่นอนว่าหากต้องการข้อมูลประเภทเกี่ยวกับพารามิเตอร์ functionไม่สามารถใช้เวอร์ชันนี้ได้

OTOH ฉันชอบอาร์กิวเมนต์ที่สร้างขึ้นStringerดังนั้นฉันจะเริ่มใช้functionใน lambdas แบบธรรมดา

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.