Следующий код взят из листинга Стильный F# 6: создание элегантного функционального кода для .NET 6 9-13:
let randomByte =
let r = System.Random()
fun () ->
r.Next(0, 255) |> byte
// E.g. A3-52-31-D2-90-E6-6F-45-1C-3F-F2-9B-7F-58-34-44-
for _ in 0..15 do
printf "%X-" (randomByte())
printfn ""
Автор заявляет: «Хотя мы вызываем randomByte() несколько раз, создается только один экземпляр System.Random()».
Я понимаю, что randomByte возвращает функцию, которая не создает экземпляр System.Random(), но мне кажется, что несколько экземпляров System.Random() все равно будут создаваться каждый раз через цикл for-do.
Я был бы признателен за объяснение того, как в этом случае не создаются несколько экземпляров System.Random().
Ключевым моментом является то, что randomByte
— это не функция. Это значение с некоторой сложной логикой инициализации. Например, я мог бы написать:
let x = 5
Или я мог бы написать:
let x =
let fourtyTwo = 42
let thirtySeven = 37
fourtyTwo - thirtySeven
И это будет эквивалентно. Оба объявляют значение с именем x
и равным 5
. Надеюсь, вы видите, что выражение fourtyTwo - thirtySeven
оценивается только один раз, а не каждый раз, когда кто-то получает значение x
.
Так что это работает и с randomByte
: это значение с нетривиальной логикой инициализации. Во время инициализации этого значения сначала создается экземпляр System.Random
, а затем создается анонимная функция, которая закрывается для этого экземпляра, и эта анонимная функция становится значением randomByte
.