В процессе реализации аналогичного кода(пузырьковая сортировка)
на языках зиг, питон, раст
и т.п.
обратил внимание, что отсутствие конструкции FOR i := 0 TO N — 1 DO (* something do *) END
усложняет понимание и разработку алгоритма, так в зиг забыл обнулить счетчик вложенного цикла(for отсутствует как класс).
Тоже самое касается множественных return из функции.
Все таки ЯП и синтаксис(!) чертовски важны.
Согласны?
Здравствуйте, Разраб, Вы писали:
Р>Тоже самое касается множественных return из функции. Р>Все таки ЯП и синтаксис(!) чертовски важны. Р>Согласны?
Важны некоторые возможности. Начнем с того, что большинство программистов пишут код сортировки и подобное сильно реже одного раза в год, больнинство вообще в практической работы не писали ни разу (я модифицированные сортировки, отличные от стандартной — писал, правда реюзал стандартную один черт).
А вот for со счетчиком по большому счету именно в языке не нужен нафик. Однако в хорошем языке должна быть возможность подобную конструкцию реализовать в библиотеках, и это будет выглядить органично. Объясню даже почему — в цикле со счетчиком очень легко ошибиться на 1, и чаще всего на практике требуется именно for each. Также цикл со счетчиком прекрасно заменяется с for each по индексам чего то там, здесь не ошибешься. Такой for each еще хорошь тем, что его можно легко распараллелить допустим по ядрам процессора вообще без непрягов и практически без доп кода, for each сам по себе позволяет все делать параллельно в большинстве случаев.
Ну и если уж приспичило именно for со счетчиком, я вообще не понимаю сложности создать функцию, в которой в качестве аргумента передается начальное числовое значение, функция изменения этого значения, функция сравнения с условием а также функция, которая зависит от счетчика. При этом за счет параметрического полиморфизма можно создать до фига функция с одним именем, но разными аргументами, например в одном случае будет как я сказал, в другом случае вторым аргументом будет просто конечное число и итерироваться мы будем по одному, а третьим функция от этого аргумента. Можно еще вариант со step создать и все такое. for со счетчиком ну совершенно избыточная конструкция для современного языка программирования, которая требуется крайне редко на практике. А именно в языке программирования по хорошему нужны в основном часто используемые практичные конструкции, все маловажное либо в стандартные библиотеки, а совсем не важное и специфичное пусть сам пользователь пишет при желании.
Здравствуйте, Разраб, Вы писали:
Р>В процессе реализации аналогичного кода(пузырьковая сортировка) Р>на языках зиг, питон, раст Р>и т.п. Р>обратил внимание, что отсутствие конструкции FOR i := 0 TO N — 1 DO (* something do *) END Р>усложняет понимание
ээм
Здравствуйте, Разраб, Вы писали:
Р>range это функция?
то есть питончик даже на базовом уровне не того
Р>непрозрачно, ихмо
с таким уровнем неудивительно
Здравствуйте, GarryIV, Вы писали:
GIV>Здравствуйте, Разраб, Вы писали:
Р>>range это функция? GIV>то есть питончик даже на базовом уровне не того
так функция ли что?
я вот оберон тоже не знаю
но когда смотрю
FOR i:=2 TO 6 DO
Out.Ln;
END;
или
for i = 2 to 6 do
printfn "%d" i
даже не задумываюсь Р>>непрозрачно, ихмо GIV>с таким уровнем неудивительно >>> range
<class 'range'>
s = 0
for i in range(1,1000_000_001):
s = s + i
print(s)
т.е. вот этот класс вместо банального инкремента, творит какую-то неведомую магию?
Иначе почему выполнялось 3 минуты вместо 4 секунд(аналогичный скрипт на F#)
Здравствуйте, GarryIV, Вы писали:
Р>>непрозрачно, ихмо GIV>с таким уровнем неудивительно
А вот это немножко контринтуитивно, что в конструкции range(2,6) итерации включают 2, но не включают 6. С другой стороны, если бы включали, была бы путаница в длине последовательности 4 или 5. Также может сбивать с толку использование индексов, хотя их вроде придумали наоборот для удобства и питон как бы считается мощным языком для манипуляций с векторами, матрицами, списками подобным образом.
a = [x for x in range(2,5)] # a = [2,3,4]print(a[-1]) # 4print(a[:-1]) # [2,3]print(a[::]) # [2,3,4]
Питонисты к этому привыкают, но я например до сих пор несколько напрягаюсь в подобных местах, особенно в чужом коде. Учитывая, что например, все эти двоеточия, запятые и -1 ведут себя слегка по разному "просто в питоне", в numpy и в torch. И встретив какое-нибудь
a = x[:,0,:]
Вот так сходу скажешь, что эта конструкция делает? Без подсказки про размерности.
Здравствуйте, elmal, Вы писали:
E>А вот for со счетчиком по большому счету именно в языке не нужен нафик.
Интересно, а как ты без индекса будешь интегрироваться по нескольким массивам одновременно. Вполне частый случай, когда обрабатывается константный массив объектов, для которого вычисляются признаки/характеристики, складываемые в другой массив, той же длины. И после этого получаем два массива, по которым надо пройти параллельно или просто ссылаться по индексу на другой.
Если говорить про вычисления типа алгебры, то там такая ситуация вообще на каждом шагу.
Здравствуйте, Nuzhny, Вы писали:
N>Интересно, а как ты без индекса будешь интегрироваться по нескольким массивам одновременно.
Элементарно. Итерироваться не по счетчику, а по for each индекса массива. Сильно надежнее получается, и не нужно думать о всяких прибавлениях или вычитаниях единицы.
Р>print(s) Р>[/python] Р>т.е. вот этот класс вместо банального инкремента, творит какую-то неведомую магию? Р>Иначе почему выполнялось 3 минуты вместо 4 секунд(аналогичный скрипт на F#)
Потому что питон интерпретатор, аналогичный код (вместо 0..=1000_000_000 подставляется std::ops::Range)
fn main() {
let mut s: usize = 0;
for i in 0..=1000_000_000 {
s += i
}
println!("{}", s);
}
на rust вообще всегда 0 показывает времени, так как оптимизируется до подстановки результата, в C++ с range весьма вероятно также будет.
Здравствуйте, Nuzhny, Вы писали:
N>Интересно, а как ты без индекса будешь интегрироваться по нескольким массивам одновременно.
Ну для нескольких массивов функциональщики всякие zip и т. п. придумали, это не проблема.
Индексы реально нужны только если нужен (почти) произвольный доступ, например как во всяких фильтрах для графики (например окружение точки в двухмерном массиве).
Здравствуйте, elmal, Вы писали:
N>>Интересно, а как ты без индекса будешь интегрироваться по нескольким массивам одновременно. E>Элементарно. Итерироваться не по счетчику, а по for each индекса массива. Сильно надежнее получается, и не нужно думать о всяких прибавлениях или вычитаниях единицы.
Индекс массива — это что такое? Если как в Питоне с enumerate, то так себе по удобству.
Через 1 он может? Через 2? Не до конца массива, а до len-1? Попутно удалять элементы из массива?
Здравствуйте, FR, Вы писали:
FR>Ну для нескольких массивов функциональщики всякие zip и т. п. придумали, это не проблема. FR>Индексы реально нужны только если нужен (почти) произвольный доступ, например как во всяких фильтрах для графики (например окружение точки в двухмерном массиве).
Это тоже. CUDA/OpenCL — там в принципе всё исключительно на индексах
Здравствуйте, FR, Вы писали: FR>Индексы реально нужны только если нужен (почти) произвольный доступ, например как во всяких фильтрах для графики (например окружение точки в двухмерном массиве).
Окружение точки в двухмерном массиве нужно делать аккуратно, т.к. легко вылететь куда не надо.
На развитых платформах можно делать рантайм-оптимизации безопасным образом: https://githib.com/evilguest/linq2d
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Nuzhny, Вы писали:
N>Индекс массива — это что такое? Если как в Питоне с enumerate, то так себе по удобству.
Примерно так. В других языках это можно допустим через array.WithIndex или еще как, когда при итерации будет пара индекс значение, а можно что то вроде indexes, когда для массива из трех элементов будет сгенерировано 0, 1, 2, и по нима фигачить уже for each. N>Через 1 он может? Через 2? Не до конца массива, а до len-1? Попутно удалять элементы из массива?
Через 1 это уже достаточно редкий случай. Как и не до len-1. И тут никакой проблемы не составит это все сделать через цикл while с внешним мутирующимся счетчиком или даже через функцию, которая делает все то, что делает цикл for со счетчиком.
Здравствуйте, Nuzhny, Вы писали:
N>Это тоже. CUDA/OpenCL — там в принципе всё исключительно на индексах
Вот только там ни хрена не цикл for с индексом. Индексы тупо приходят извне, ибо вся обработка идет параллельно.
Здравствуйте, elmal, Вы писали:
E>Примерно так. В других языках это можно допустим через array.WithIndex или еще как, когда при итерации будет пара индекс значение, а можно что то вроде indexes, когда для массива из трех элементов будет сгенерировано 0, 1, 2, и по нима фигачить уже for each.
То есть при проходе по картинке размером, скажем, 20 Мп нам сгенерируют индекс размером 20 млн элементов? Хм, оптимальненько.
E>Через 1 это уже достаточно редкий случай. Как и не до len-1. И тут никакой проблемы не составит это все сделать через цикл while с внешним мутирующимся счетчиком или даже через функцию, которая делает все то, что делает цикл for со счетчиком.
Здравствуйте, Nuzhny, Вы писали:
N>То есть при проходе по картинке размером, скажем, 20 Мп нам сгенерируют индекс размером 20 млн элементов? Хм, оптимальненько.
Там кроме языка есть еще и оптимизатор. Который поймет что там требуется и не будет ни черта генерировать в памяти, а тупо сделает цикл или даже что поэффективнее, например SIMD операции.