@@ -252,6 +252,43 @@ module AVal =
252252 let res = mapping.Invoke ( va, vb)
253253 inner <- ValueSome ( struct ( va, vb, res))
254254 res.GetValue token
255+
256+ /// Aval for binding three values in 'parallel'
257+ type Bind3Val < 'T1 , 'T2 , 'T3 , 'T4 >( mapping : 'T1 -> 'T2 -> 'T3 -> aval < 'T4 >, value1 : aval < 'T1 >, value2 : aval < 'T2 >, value3 : aval < 'T3 >) =
258+ inherit AbstractVal< 'T4>()
259+
260+ let mapping = OptimizedClosures.FSharpFunc< 'T1, 'T2, 'T3, aval< 'T4>>. Adapt( mapping)
261+ let mutable inner : ValueOption < struct ( 'T1 * 'T2 * 'T3 * aval < 'T4 >) > = ValueNone
262+ let mutable inputDirty = 1
263+
264+ override x.InputChangedObject ( _ , o ) =
265+ if Object.ReferenceEquals( o, value1) || Object.ReferenceEquals( o, value2) || Object.ReferenceEquals( o, value3) then
266+ inputDirty <- 1
267+
268+ override x.Compute ( token : AdaptiveToken ) =
269+ let va = value1.GetValue token
270+ let vb = value2.GetValue token
271+ let vc = value3.GetValue token
272+ #if FABLE_ COMPILER
273+ let inputDirty = let v = inputDirty in inputDirty <- 0 ; v <> 0
274+ #else
275+ let inputDirty = System.Threading.Interlocked.Exchange(& inputDirty, 0 ) <> 0
276+ #endif
277+
278+ match inner with
279+ | ValueNone ->
280+ let res = mapping.Invoke ( va, vb, vc)
281+ inner <- ValueSome ( struct ( va, vb, vc, res))
282+ res.GetValue token
283+
284+ | ValueSome( struct ( oa, ob, oc, res)) when not inputDirty || ( cheapEqual oa va && cheapEqual ob vb && cheapEqual oc vc) ->
285+ res.GetValue token
286+
287+ | ValueSome( struct (_, _, _, old)) ->
288+ old.Outputs.Remove x |> ignore
289+ let res = mapping.Invoke ( va, vb, vc)
290+ inner <- ValueSome ( struct ( va, vb, vc, res))
291+ res.GetValue token
255292
256293 /// Aval for custom computations
257294 type CustomVal < 'T >( compute : AdaptiveToken -> 'T ) =
@@ -337,5 +374,23 @@ module AVal =
337374 else
338375 Bind2Val< 'T1, 'T2, 'T3>( mapping, value1, value2) :> aval<_>
339376
377+ let bind3 ( mapping : 'T1 -> 'T2 -> 'T3 -> aval < 'T4 >) ( value1 : aval < 'T1 >) ( value2 : aval < 'T2 >) ( value3 : aval < 'T3 >) =
378+ if value1.IsConstant && value2.IsConstant && value3.IsConstant then
379+ mapping ( force value1) ( force value2) ( force value3)
380+
381+ elif value1.IsConstant then
382+ let a = force value1
383+ bind2 ( fun b c -> mapping a b c) value2 value3
384+
385+ elif value2.IsConstant then
386+ let b = force value2
387+ bind2 ( fun a c -> mapping a b c) value1 value3
388+
389+ elif value3.IsConstant then
390+ let c = force value3
391+ bind2 ( fun a b -> mapping a b c) value1 value2
392+ else
393+ Bind3Val< 'T1, 'T2, 'T3, 'T4>( mapping, value1, value2, value3) :> aval<_>
394+
340395 let custom ( compute : AdaptiveToken -> 'T ) =
341396 CustomVal compute :> aval<_>
0 commit comments