Вы можете эмулировать короткое замыкание с ленивыми значениями и активными паттернами:
//not sure why function Lazy.force is recognized in VS but not in FSI
//need to use member Force()
let (|Force|) (l:Lazy<_>) =
l.Force()
let encodeValue x y = function ...
match (encodeValue left value), lazy(encodeValue right value) with
| (true, encoded), _ -> (true, encoded + "1")
| _ , Force(true, encoded) -> (true, encoded + "0")
| (false, _) , Force(false, _) -> (false, "")
| _ -> failwith "Error"
Lazy
значения рассчитываются 0 или 1 раз: если вы никогда не наберете Force()
для них, они никогда не будут рассчитаны. При первом вызове Force()
они рассчитываются, а результат сохраняется при каждом следующем вызове Force()
.
(|Force|)
вот полный активный шаблон, действительно полезная функция, которая позволяет вам реализовывать собственные структуры сопоставления шаблонов.
Обратите внимание, что @Brian указал, что вам нужно использовать _
в положении отложенного значения, где возможно короткое замыкание. Если (true, encoded)
соответствует, тогда ленивый, дорогой расчет никогда не будет принудительным. Тогда для каждого другого случая при множественных совпадениях с использованием активного шаблона (|Force|)
будет использоваться только результат первого инцидента.
Обновление
@ Дэниел указал, что F # уже имеет активный шаблон, который делает именно то, что (|Force|)
делает: http://msdn.microsoft.com/en-us/library/ee340223.aspx