Как Юлия интерпретирует 10:1?
Я эмигрант с долгое время сосредоточиться на R, где :
Оператор (двоеточие) создает целочисленные последовательности от первого до второго аргумента:
1:10
# [1] 1 2 3 4 5 6 7 8 9 10
10:1
# [1] 10 9 8 7 6 5 4 3 2 1
Заметив, что в Джулии это работает одинаково, я столкнулся с ошибкой:
1:10 .== 10:1
DimensionMismatch ("массивы не могут быть переданы в общий размер")
Так как:
10:1
Выходы
10:9
Я озадачен тем, как это могло произойти. Кажется вполне естественным, не нужно использовать 10:-1:1
- почему Джулия подумала 10:9
была правильная интерпретация 10:1
?
2 ответа
Джулия не R. Есть другие языки, которые имеют схожую интерпретацию синтаксиса двоеточия как Джулия. MATLAB лечит 10:1
в качестве пустого массива и синтаксиса среза Python (хотя и отличается в других отношениях) также обрабатывает индексирование с 10:1
как пустой выбор. Юлия выбирает нормализовать пустые целочисленные диапазоны так, чтобы разница между стартом и стопом всегда была -1
так становится 10:9
,
Так что я не думаю, что есть однозначно очевидная интерпретация 10:1
, Однако, на мой взгляд, есть несколько очень убедительных аргументов в пользу интерпретации Юлии:
Пустой диапазон
10:9
используется для представления местоположения между индексами 9 и 10 в некоторых API.Диапазоны являются основной конструкцией в Юлии и
for x in 1:10
абсолютно и однозначно должно быть так же быстро, как эквивалентный цикл C. Потому что синтаксисx:y
всегда увеличивая на единицу (и никогда не отрицая), Джулия (и LLVM) может использовать эту константу при компиляции для циклов, чтобы обеспечить дальнейшую оптимизацию. Делая это не постоянным --- или хуже, динамическое переключение междуUnitRange
а такжеStepRange
в зависимости от значений конечных точек эта оптимизация может помешать или будет нестабильной.Лично я нахожу интерпретацию R такой же удивительной, как и интерпретацию Джулии. Я бы сказал, что нужно четко указать, что вы хотите сделать шаг
-1
выгодно как в удобочитаемости, так и в предотвращении ошибок. Но я признаю, что мой опыт работы с предыдущими языками такой же предвзятый, как и ваш.
В Юлии мы предполагаем a:b
строит диапазон с размером шага 1, так10:1
является UnitRange
который должен быть пустым диапазоном. поскольку a:a-1
также пустой диапазон, это эквивалентно a:b
где b<a
Пожалуйста, посмотрите на исходный код здесь.
julia> dump(10:1)
UnitRange{Int64}
start: Int64 10
stop: Int64 9
julia> dump(10:-1:1)
StepRange{Int64,Int64}
start: Int64 10
step: Int64 -1
stop: Int64 1
Вот 10:-1:1
это StepRange
с размером шага -1, что, я думаю, является более точным и естественным для представления идеи "10 к 1".