2015-04-14 4 views
2
let makeIdGenerator startvalue = 
    let index : uint64 ref = ref startvalue 
    fun() -> 
     let result = !index 
     index := !index + 1UL 
     result 

Что мне нужно - это генератор для функции, которая имеет тип unit -> uint64, как показано выше.Есть ли более идиоматический способ генерации бесконечной последовательности uint64?

Приведенный выше код работает, но использует контрольную переменную для запоминания состояния генератора.

Пытается использовать бесконечную последовательность, как в Seq.initInfinite (fun i -> i), не работает, так как последовательность использует uint32 для своего состояния.

Кто-нибудь здесь знает способ сделать это даже без ссылочной переменной? Может быть, путем рекурсии и урожайности?

Заранее спасибо.

+0

Вероятно Я не правильно задаю вопрос, но что не так с 'Seq.initInfinite uint64' –

+0

@olodnad лямбда для генерации значения последовательности в индексе i вызывается с 32-битным параметром. Вы не можете создать 2^64 элемента последовательности с этим. Только 2^32. – BitTickler

+0

Если вам нужно использовать аннотацию типа лямбда-добавления в лямбда. Например: '(fun (i: uint64) -> i)' – Petr

ответ

4

Вы можете использовать Seq.unfold:

let makeIdGenerator (startvalue : uint64) = 
    Seq.unfold (fun i -> Some((i, i+1UL))) startvalue 
+0

Но его uint32 в вашем случае. Нужна uint64. Умм ... это тоже работает для uint64? – BitTickler

+0

@ user2225104 - Извините, я думал, что аргумент должен был быть 'uint32', см. Обновление. – Lee

+0

Принимает это как прохладно. Но одна часть проблемы все еще остается. Теперь мне нужно как-то сохранить состояние последовательности в коде приложения. – BitTickler

5

Стандартный метод функционального программирования, позволяющий избежать изменчивого состояния в цикле, состоит в том, чтобы передать его в параметр.

Если вы хотите бесконечная последовательность вы можете использовать выражение последовательности с yield для результата «первого» и yield! для рекурсивного вызова:

let genUint64() = 
    let rec genFrom n = 
     seq { 
      yield n 
      yield! genFrom (n+1UL) 
     } 
    genFrom 0UL 
+0

И тогда, как избежать необходимости возиться с '' Seq.Head'' и '' Seq.skip 1'' в коде, используя это? – BitTickler

+0

@ пользователь2225104 вы хотите какой-то узорmatching? Поскольку вы не должны делать это с помощью seqs - попробуйте использовать 'map',' filter', 'fold', ... вместо – Carsten

+0

Если вы на самом деле просто хотите использовать изменяемый генератор уникальных идентификаторов, таких как вы присутствуете в вопросе, тогда вы Не обязательно использовать последовательность в первую очередь, так как тогда вам нужно ее прокрутить или использовать мутацию в любом случае. –

Смежные вопросы