VladD2 wrote:
> Хочется услышать мнение народа о том как бы он хотел видеть паттерн > перебора значений из некоторого диапазона. > > Например, в С/С++ для этого используется императивный стиль: > > for (int i = 0; i < len; i++) > > > но этот синтаксис слишком громоздок и может приводить к случайным > ошибкам (так как императивен). > > Во многих ЯП можно увидить синтаксис вроде: > > foreach (i in 0..3) // выдает последовательность 0, 1, 2, 3
Честно говоря, С++ синтаксис мне больше всего нравится, т.к. более гибок, позволяет перебирать не только целые числа в
некоем интервале с шагом 1, но фактически что угодно и как угодно. А простой перебор чисел от A до B на практике редко
встречается (по крайней мере в моей практике). Я обычно перебираю коллекции, родительские элементы, рекордсеты, и
прочее, числа встречаются довольно редко.
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
VD>но этот синтаксис слишком громоздок и может приводить к случайным ошибкам (так как императивен).
Я тебя ещё больше напугаю В си++ пишут так
for (int i = 0; i < len; ++i)
VD>В общем, приветствуются любые мысли.
Как показывает практика идея о том что элемент обозначающий конец это следующий после последнего — очень здравая. В твоём контексте
foreach (int i in 0..3) выдаёт 0 1 2
foreach (int i in 0..array.Length) перебирает все элементы массива
либо
foreach (int i in 0 to 3) выдаёт 0 1 2
foreach (int i in 0 to array.Length) перебирает все элементы массива
либо
foreach (int i in 0 upto 3) выдаёт 0 1 2
foreach (int i in 0 downto 3) выдаёт 2 1 0 мелочь, а приятно
foreach (int i in 0 upto array.Length) перебирает все элементы массива
foreach (int i in 0 downto array.Length) перебирает все элементы массива в обратном порядке
причём foreach (int i in 0 upto 3) и foreach (int i in 3 downto 0) равнозначны
Здравствуйте, kan_izh, Вы писали:
_>Честно говоря, С++ синтаксис мне больше всего нравится, т.к. более гибок, позволяет перебирать не только целые числа в некоем интервале с шагом 1, но фактически что угодно и как угодно.
Понимаш ли в чем дело? С-шный for никто не отменяет. Но его гибкость выливается в ошибки и усложнение чтения кода когда он используется для простых вещей.
Мы (люди) думаем абстракциями. Когда ты пишешь:
for (int i = 0; i < array.Length; i++)
array[i] = f(array[i]);
ты реально думашь не так:
1. Объявить перменную целого типа.
2. Инициализировать ее нулем который является нижней границей массива.
3. Выполнять условие цикла пока переменная не превысит значения длинны массива.
4. На каждой итерации увеличить индекс на один.
5. Вынуть значение по индексу находящемуся в ячейке с номером заданным в переменной i.
6. Применить к значению функцию f().
7. Поместить значение преобразования по индексу находящемуся в ячейке с номером заданным в переменной i.
Ведь если так мыслить, то даже самая приметивная программа станет архи-сложной.
По этому за конструкцией "for (int i = 0; i < array.Length; i++)" ты улавливашь некий паттерн. В данном случае "перебрать все индексы массива array". Но этот паттерн тебе приходится угадывать. А тут есть две проблемы. 1. Ты можешь не врено принять за этот паттерн просто похожую конструкцию, например, "for (int i = 0; i <= array.Length; i++)" или "for (int i = 0; i < array.Length; i--)". 2. Разглядывать паттерны в накромождениях кода очень не просто.
Посему код написанный в таком стиле плохо читается.
Чем более внятно будет выражен паттерн, тем проще будет читать код, и тем сложнее будет ошибиться в его написании или понимании. Сравни приведенный выше фракмент с:
foraech (i in IndexesOf(array))
array[i] = f(array[i]);
или темболее с:
ConvertElements(array, f);
_> А простой перебор чисел от A до B на практике редко встречается (по крайней мере в моей практике).
Тогд посчитай сколько у тебя в программе встречается вот таких вот for-ов. Думаю — уйма.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Нет разницы писать i++ или ++i если возвращаемое значение выражения не используется. Так что пишут так как больше нравится. Я лично предпочитаю i++.
A>Как показывает практика идея о том что элемент обозначающий конец это следующий после последнего — очень здравая. В твоём контексте
A>
A>foreach (int i in 0..3) выдаёт 0 1 2
A>foreach (int i in 0..array.Length) перебирает все элементы массива
A>foreach (int i in 0 to 3) выдаёт 0 1 2
A>foreach (int i in 0 to array.Length) перебирает все элементы массива
A>
Общепринято, что запись "0..3" и "i to 3" возвращает последовательность включающую 3 (т.е. 1, 2, 3).
Менять семантику означает повергать кучу народа на мучения.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Хочется услышать мнение народа о том как бы он хотел видеть паттерн перебора значений из некоторого диапазона. VD>В общем, приветствуются любые мысли.
Щас ересь скажу
Почему бы не использовать традиционную математическую нотацию для inclusive/exclusive:
foreach(i in [0,3]) // 0,1,2,3
foreach(i in [0,3[) // 0,1,2
foreach(i in ]0,3]) // 1,2,3
foreach(i in ]0,3[) // 1,2
Только вот непосредственно "[]" уже заняты и будут конфликтовать, следовательно надо придумать какие-нибудь другие "крокозяблы". Но это может все испортить.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Здравствуйте, VladD2, Вы писали:
VD>Нет разницы писать i++ или ++i если возвращаемое значение выражения не используется.
Разница естьв скорости. Для int всё равно, а вообще говоря i++ медленее.
VD>Общепринято, что запись "0..3" и "i to 3" возвращает последовательность включающую 3 (т.е. 1, 2, 3). VD>Менять семантику означает повергать кучу народа на мучения.
Где это общепринято? Запись с двумя точками я помню только в паскале, но для меня это "дела давно минувших дней, преданья старины глубокой"
Поверь, к удобной вещи, пусть даже и новой, люди привыкают быстро.
Здравствуйте, VladD2, Вы писали:
VD>Хочется услышать мнение народа о том как бы он хотел видеть паттерн перебора значений из некоторого диапазона. VD>В общем, приветствуются любые мысли.
foreach (x in array)
{
}
foreach (i in [0, array.Length); ++i) // i = 0..(array.Length-1)
{
}
foreach (i in [1, array.Length]; ++i) // i = 1..array.Length
{
}
foreach (0 <= i < array.Length; ++i) // i = 0..(array.Length-1)
{
}
Здравствуйте, adontz, Вы писали:
A>Здравствуйте, McSeem2, Вы писали:
MS>>Щас ересь скажу MS>>Почему бы не использовать традиционную математическую нотацию для inclusive/exclusive:
A>Я об этом подумал, но фигня выходит A>(0..3) A>[0..3) A>(0..3] A>[0..3] A>в глазах рябит
Здравствуйте, VladD2, Вы писали:
VD>Мы (люди) думаем абстракциями.
+1. Похоже, что именно поэтому так быстро прижился foreach в C#, гораздо чаще используется for в C++ по сравнению с while и в очень редких случаях применяется do while.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, c-smile, Вы писали:
CS>Парсить такое трудно если не невозможно вообще.
В Nemerle действительно невозможно. Он контролирует парность скобок еще до синтаксического анализа. Это позволяет встравивать в язык синтаксические расширения и DSL-и.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VladD2,
VD>Хочется услышать мнение народа о том как бы он хотел видеть паттерн перебора значений из некоторого диапазона.
VD>В общем, приветствуются любые мысли.
Хм. Будет немного непривычно:
12.times { say 'hello' } // _1 принимает значения от 0 до 11
(2..16).times { say 'hello '_1 } // _1 принимает значения от 2 до 16
(10+.5).times { say 'hello '_1 } // _1 принимает значения от 5 до 14 (то есть 10 различных значений)
Здравствуйте, Lazy Cjow Rhrr, Вы писали:
LCR>Хм. Будет немного непривычно: LCR>
LCR>12.times { say 'hello' } // _1 принимает значения от 0 до 11
LCR>(2..16).times { say 'hello '_1 } // _1 принимает значения от 2 до 16
LCR>(10+.5).times { say 'hello '_1 } // _1 принимает значения от 5 до 14 (то есть 10 различных значений)
LCR>
(2..16) (x) { say 'hello 'x } // _1 принимает значения от 2 до 16
(10+.5) (y) { say 'hello 'y } // _1 принимает значения от 5 до 14 (то есть 10 различных значений)
?
Т.е. фактически задание диапазона параметра вызываемого метода.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
IT>(2..16) (x) { say 'hello 'x } // _1 принимает значения от 2 до 16
IT>(10+.5) (y) { say 'hello 'y } // _1 принимает значения от 5 до 14 (то есть 10 различных значений)
?
Ну можно и так. Могу ещё предложить задавать диапазон в гварде:
(x, y)~(#10, 0..9): {say 'hello 'x','y}
Однако по-прежнему тот вариант с i.10 мне нравится больше.
IT>Т.е. фактически задание диапазона параметра вызываемого метода.
Да. Хотя вот здесь
LCR>>12.times { say 'hello' } // _1 принимает значения от 0 до 11