Я думаю, что ответ от kvb отвечает на большинство вопросов. Тем не менее, я думаю, что более точный ответ заключается в том, что диапазоны вычисляются лениво во время выполнения . Вот еще несколько подробностей о том, как работают диапазоны ...
Когда вы используете, например, 1 .. 10
где-то в вашем коде, это просто переводится в вызов некоторого метода. Вызов зависит от используемого контекста и числовых типов.
Для [ 1 .. 10 ]
или других выражений последовательности и цикла for
компилятор сгенерирует что-то вроде RangeInt32(1, 1, 10)
(дополнительным параметром является шаг).
Если у вас есть что-то вроде obj.[ 1 .. ]
и obj
- это какой-то объект, который поддерживает нарезку (например, тип матрицы), тогда он будет переведен в obj.GetSlice(Some(1), None)
(обратите внимание, что в этом случае верхняя / нижняя граница может отсутствовать).
Теперь довольно легко ответить на ваш вопрос - это вызов метода, который будет оцениваться во время выполнения. Однако важно отметить, что весь диапазон может не нуждаться в оценке! Например:
let nums = seq { 1 .. 10 } |> Seq.take 1
Выражение последовательности будет преобразовано в вызов RangeInt32
. Это просто вернет значение типа seq<int>
, которое вычисляется лениво. Вызов take 1
принимает только первый элемент, поэтому потребуется только первый номер из диапазона и будет оцениваться.
Я не думаю, что ваша собственная реализация диапазонов может отличаться от стандартной, однако вы можете предоставить свою реализацию в качестве члена объекта. Тогда вы можете написать myObj.[1 .. 10]
(и результат может быть любого типа, который вы хотите). Для этого вам понадобится метод экземпляра GetSlice
, более подробно обсуждаемый здесь .