оцениваются диапазоны F # во время компиляции или во время выполнения - PullRequest
1 голос
/ 21 сентября 2010

операторы (..) и (.. ..) в F # в какой-то момент развернуты, это операция компиляции или операция во время выполнения?

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

Ответы [ 2 ]

3 голосов
/ 22 сентября 2010

Я думаю, что ответ от 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, более подробно обсуждаемый здесь .

3 голосов
/ 21 сентября 2010

Время выполнения. F # будет очень редко запускать ваш код как часть компиляции - единственный случай, о котором я могу подумать, это код в NumericLiteralX модулях. Кроме того, в коде, как это:

let f n = [1 .. n]

верхняя граница даже не известна во время компиляции. Конечно, возможно, что в качестве детали реализации компилятор F # явно развернет определения, где обе границы являются статически известными значениями известного типа (например, int), но семантически это всегда должно быть таким же, как если бы это было сделано во время выполнения.

Относительно вашего второго вопроса, быстрее чем?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...