खोज…
आम ऑपरेटरों का उपयोग करके मूल्यों और कार्यों की रचना कैसे करें
ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग में एक सामान्य कार्य वस्तुओं (मूल्यों) की रचना करना है। कार्यात्मक प्रोग्रामिंग में मूल्यों के साथ-साथ कार्यों की रचना करना भी सामान्य कार्य है।
हम +
, -
, *
, /
और जैसे ऑपरेटरों का उपयोग करके अन्य प्रोग्रामिंग भाषाओं के अपने अनुभव से मूल्यों की रचना करने के लिए उपयोग किए जाते हैं।
मूल्य रचना
let x = 1 + 2 + 3 * 2
चूंकि कार्यात्मक प्रोग्रामिंग कार्यों के साथ-साथ मूल्यों को भी आश्चर्यचकित करता है, इसलिए यह आश्चर्य की बात नहीं है कि फ़ंक्शन रचना के लिए आम ऑपरेटर हैं जैसे >>
, <<
, |>
और <|
।
क्रिया रचना
// val f : int -> int
let f v = v + 1
// val g : int -> int
let g v = v * 2
// Different ways to compose f and g
// val h : int -> int
let h1 v = g (f v)
let h2 v = v |> f |> g // Forward piping of 'v'
let h3 v = g <| (f <| v) // Reverse piping of 'v' (because <| has left associcativity we need ())
let h4 = f >> g // Forward functional composition
let h5 = g << f // Reverse functional composition (closer to math notation of 'g o f')
F#
फॉरवर्ड पाइपिंग में रिवर्स पाइपिंग पर प्राथमिकता दी जाती है क्योंकि:
- टाइप इंफ़ेक्शन (आम तौर पर) बाएं से दाएं से बहती है इसलिए मूल्यों और कार्यों के साथ-साथ बाएं से दाएं प्रवाहित होना स्वाभाविक है
- क्योंकि
<|
और<<
सही<<
होनी चाहिए, लेकिनF#
वे सहयोगी हैं जो हमें सम्मिलित करने के लिए मजबूर करते हैं () - आगे और रिवर्स पाइपिंग को मिलाकर आम तौर पर काम नहीं किया जाता है क्योंकि उनके पास एक ही पूर्वता है।
मोनाड रचना
जैसा कि मोनाड्स (जैसे Option<'T>
या List<'T>
) आमतौर पर कार्यात्मक प्रोग्रामिंग में उपयोग किया जाता है, वहाँ भी आम हैं लेकिन कम ज्ञात संचालक जैसे मोनाड्स के साथ काम करने के लिए रचना करते हैं जैसे >>=
, >=>
, <|>
और <*>
<|>
<*>
।
let (>>=) t uf = Option.bind uf t
let (>=>) tf uf = fun v -> tf v >>= uf
// val oinc : int -> int option
let oinc v = Some (v + 1) // Increment v
// val ofloat : int -> float option
let ofloat v = Some (float v) // Map v to float
// Different ways to compose functions working with Option Monad
// val m : int option -> float option
let m1 v = Option.bind (fun v -> Some (float (v + 1))) v
let m2 v = v |> Option.bind oinc |> Option.bind ofloat
let m3 v = v >>= oinc >>= ofloat
let m4 = oinc >=> ofloat
// Other common operators are <|> (orElse) and <*> (andAlso)
// If 't' has Some value then return t otherwise return u
let (<|>) t u =
match t with
| Some _ -> t
| None -> u
// If 't' and 'u' has Some values then return Some (tv*uv) otherwise return None
let (<*>) t u =
match t, u with
| Some tv, Some tu -> Some (tv, tu)
| _ -> None
// val pickOne : 'a option -> 'a option -> 'a option
let pickOne t u v = t <|> u <|> v
// val combine : 'a option -> 'b option -> 'c option -> (('a*'b)*'c) option
let combine t u v = t <*> u <*> v
निष्कर्ष
नए फंक्शनल प्रोग्रामर फंक्शन कंपोजिशन का उपयोग करके ऑपरेटरों को अपारदर्शी और अस्पष्ट लग सकता है, लेकिन ऐसा इसलिए है क्योंकि इन ऑपरेटरों का अर्थ आमतौर पर ऑपरेटर के रूप में नहीं जाना जाता है जो मूल्यों पर काम करते हैं। हालाँकि, कुछ प्रशिक्षण के साथ |>
, >>
, >>=
और >=>
का उपयोग करना जितना स्वाभाविक हो जाता है +
, -
, *
और /
।
F # में लेटबाइंडिंग? ऑपरेटर
F#
जैसी एक सांख्यिकीय रूप से टाइप की गई भाषा में हम संकलन-समय पर अच्छी तरह से ज्ञात प्रकार के साथ काम करते हैं। हम टाइप प्रोवाइडरों का उपयोग करके एक सुरक्षित तरीके से बाहरी डेटा स्रोतों का उपभोग करते हैं।
हालांकि, कभी-कभी देर से बाध्यकारी (जैसे C#
में dynamic
) का उपयोग करने की आवश्यकता होती है। उदाहरण के लिए जब JSON
दस्तावेजों के साथ काम करना, जिसमें कोई अच्छी तरह से परिभाषित स्कीमा नहीं है।
देर से बाध्यकारी F#
साथ काम करना आसान बनाने के लिए गतिशील लुकअप ऑपरेटरों का समर्थन करता है ?
और ?<-
।
उदाहरण:
// (?) allows us to lookup values in a map like this: map?MyKey
let inline (?) m k = Map.tryFind k m
// (?<-) allows us to update values in a map like this: map?MyKey <- 123
let inline (?<-) m k v = Map.add k v m
let getAndUpdate (map : Map<string, int>) : int option*Map<string, int> =
let i = map?Hello // Equivalent to map |> Map.tryFind "Hello"
let m = map?Hello <- 3 // Equivalent to map |> Map.add "Hello" 3
i, m
यह पता चला है कि देर से बाध्यकारी के लिए F#
समर्थन सरल अभी तक लचीला है।