क्या हो रहा है यह समझने के हित में मैंने Event.map, Event.merge और Choice पर स्रोत कोड देखा।
type Choice<'T1,'T2> =
| Choice1Of2 of 'T1
| Choice2Of2 of 'T2
[<CompiledName("Map")>]
let map f (w: IEvent<'Delegate,'T>) =
let ev = new Event<_>()
w.Add(fun x -> ev.Trigger(f x));
ev.Publish
[<CompiledName("Merge")>]
let merge (w1: IEvent<'Del1,'T>) (w2: IEvent<'Del2,'T>) =
let ev = new Event<_>()
w1.Add(fun x -> ev.Trigger(x));
w2.Add(fun x -> ev.Trigger(x));
ev.Publish
इसका मतलब है कि हमारा समाधान 3 नई घटनाएं बना रहा है।
async {
let merged = Event.merge
(f.KeyDown |> Event.map Choice1Of2)
(f.MouseMove |> Event.map Choice2Of2)
let! move = Async.AwaitEvent merged
}
हम इस लाइब्रेरी कोड का कसकर युग्मित संस्करण बनाकर इसे एक ईवेंट में कम कर सकते हैं।
type EventChoice<'T1, 'T2> =
| EventChoice1Of2 of 'T1
| EventChoice2Of2 of 'T2
with
static member CreateChoice (w1: IEvent<_,'T1>) (w2: IEvent<_,'T2>) =
let ev = new Event<_>()
w1.Add(fun x -> ev.Trigger(EventChoice1Of2 x))
w2.Add(fun x -> ev.Trigger(EventChoice2Of2 x))
ev.Publish
और यहां हमारा नया कोड है।
async {
let merged = EventChoice.CreateChoice form.MouseMove form.KeyDown
let! move = Async.AwaitEvent merged
}
सावधान रहें! जब आप 'AwaitEvent' और' let! 'के साथ' Event.xyz' combinators का उपयोग करके बनाई गई घटनाओं का उपयोग करते हैं, तो आप एक मेमोरी लीक बना सकते हैं (जब आप लूप में प्रतीक्षा करते हैं)। यदि आप एसिंक्रोनस वर्कफ़्लोज़ के साथ संयोजक जोड़ना चाहते हैं तो आपको ** हमेशा 'ईवेंट' के बजाय 'अवलोकन योग्य' मॉड्यूल का उपयोग करना चाहिए। अधिक जानकारी के लिए मेरा उत्तर देखें ... –