Лучший синтаксис для перебора значений
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.04.06 23:10
Оценка: :)
Хочется услышать мнение народа о том как бы он хотел видеть паттерн перебора значений из некоторого диапазона.

Например, в С/С++ для этого используется императивный стиль:
for (int i = 0; i < len; i++)

но этот синтаксис слишком громоздок и может приводить к случайным ошибкам (так как императивен).

Во многих ЯП можно увидить синтаксис вроде:
foreach (i in 0..3) // выдает последовательность 0, 1, 2, 3

этот синтаксис хорош, но неудобен когда нужно перебрать значения индекса некой коллекции:
foreach (i in 0..array.Length - 1) // не нравится этот "- 1"

В Руби для таких случаев используется синтаксис:
foreach (i in 0...3) // то есть добавляется третья точка.

Но это не интуитивно и легко путается с вариантом с двумя точками.

В Паскале используется синтаксис:
for i := 0 to 3 step 1 do

он тоже не удобен для перебора значений индексов из коллекций.

Вопрос в том как должен выглядить идеальный синтаксис перебора значений из диапазона на ваш взгляд.

Мне в голову прили следующие варианты:
foreach (x where 0 >= x < 10 step 1) // "step 1" необязательный параметр позволяющий задать шаг отличный от еденицы

Этот вариант позволяет регулировать включение верхней и нижней границы просто заменой знаков > и < на >= и <=.
и
foreach (x from 0 to x < 10)

Этот варинт вроде бы крайне локоничен, но сбивает, то что условие "x < 10" будет истенно и для "x = 0".

В общем, приветствуются любые мысли.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Лучший синтаксис для перебора значений
От: kan_izh Великобритания  
Дата: 05.04.06 23:28
Оценка:
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
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re: Лучший синтаксис для перебора значений
От: IT Россия linq2db.com
Дата: 06.04.06 00:09
Оценка: +5
Здравствуйте, VladD2, Вы писали:

VD>Мне в голову прили следующие варианты:

VD>
VD>foreach (x where 0 >= x < 10 step 1) // "step 1" необязательный параметр позволяющий задать шаг отличный от еденицы
VD>


foreach (x = 0 where x < 10 step 1) // "step 1" необязательный параметр позволяющий задать шаг отличный от еденицы

Только foreach и step 1 как-то не очень согласуются.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re: Лучший синтаксис для перебора значений
От: adontz Грузия http://adontz.wordpress.com/
Дата: 06.04.06 00:28
Оценка:
Здравствуйте, VladD2, Вы писали:

for (int i = 0; i < len; i++)

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) равнозначны
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[2]: Лучший синтаксис для перебора значений
От: VladD2 Российская Империя www.nemerle.org
Дата: 06.04.06 00:39
Оценка: 21 (1) +2
Здравствуйте, 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>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Лучший синтаксис для перебора значений
От: VladD2 Российская Империя www.nemerle.org
Дата: 06.04.06 00:42
Оценка:
Здравствуйте, adontz, Вы писали:

...

Нет разницы писать 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>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Лучший синтаксис для перебора значений
От: McSeem2 США http://www.antigrain.com
Дата: 06.04.06 00:43
Оценка: 15 (4) +3
Здравствуйте, 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
Я жертва цепи несчастных случайностей. Как и все мы.
Re[3]: Лучший синтаксис для перебора значений
От: adontz Грузия http://adontz.wordpress.com/
Дата: 06.04.06 00:59
Оценка: +1 :)
Здравствуйте, VladD2, Вы писали:

VD>Нет разницы писать i++ или ++i если возвращаемое значение выражения не используется.


Разница естьв скорости. Для int всё равно, а вообще говоря i++ медленее.

VD>Общепринято, что запись "0..3" и "i to 3" возвращает последовательность включающую 3 (т.е. 1, 2, 3).

VD>Менять семантику означает повергать кучу народа на мучения.

Где это общепринято? Запись с двумя точками я помню только в паскале, но для меня это "дела давно минувших дней, преданья старины глубокой"
Поверь, к удобной вещи, пусть даже и новой, люди привыкают быстро.
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[2]: Лучший синтаксис для перебора значений
От: adontz Грузия http://adontz.wordpress.com/
Дата: 06.04.06 01:00
Оценка:
Здравствуйте, McSeem2, Вы писали:

MS>Щас ересь скажу

MS>Почему бы не использовать традиционную математическую нотацию для inclusive/exclusive:

Я об этом подумал, но фигня выходит
(0..3)
[0..3)
(0..3]
[0..3]
в глазах рябит
A journey of a thousand miles must begin with a single step © Lau Tsu
Re: Лучший синтаксис для перебора значений
От: ansi  
Дата: 06.04.06 01:04
Оценка: +1
Здравствуйте, 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)
{
}
Re: Лучший синтаксис для перебора значений
От: c-smile Канада http://terrainformatica.com
Дата: 06.04.06 01:10
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Хочется услышать мнение народа о том как бы он хотел видеть паттерн перебора значений из некоторого диапазона.


А насколько часто используется этот "перебор значений из некоторого диапазона"

Чаще всего нужно перебрать значения в последовательности, это да.

Т.е. :

var arr = [3,4,5,6,7,8];

for( var n in arr ) {....}
for( var n in arr[2..4] ) {....}


(Это мой tiscript)
Re[3]: Лучший синтаксис для перебора значений
От: c-smile Канада http://terrainformatica.com
Дата: 06.04.06 01:14
Оценка:
Здравствуйте, adontz, Вы писали:

A>Здравствуйте, McSeem2, Вы писали:


MS>>Щас ересь скажу

MS>>Почему бы не использовать традиционную математическую нотацию для inclusive/exclusive:

A>Я об этом подумал, но фигня выходит

A>(0..3)
A>[0..3)
A>(0..3]
A>[0..3]
A>в глазах рябит

Парсить такое трудно если не невозможно вообще.

((a+b)(0..3))
Re[4]: Лучший синтаксис для перебора значений
От: adontz Грузия http://adontz.wordpress.com/
Дата: 06.04.06 01:19
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Парсить такое трудно если не невозможно вообще.

CS>((a+b)(0..3))

Это уже проблемы Влада Он просил удобный для человека синтакисис, а просто парсить — паскаль
A journey of a thousand miles must begin with a single step © Lau Tsu
Re: Лучший синтаксис для перебора значений
От: De-Bill  
Дата: 06.04.06 02:07
Оценка: +1
Лично мне нравятся такие конструкуции (Лисп):



(dolist (var list-form)
  body-form*)

(dotimes (var count-form)
  body-form*)
Re[3]: Лучший синтаксис для перебора значений
От: IT Россия linq2db.com
Дата: 06.04.06 02:09
Оценка: +1
Здравствуйте, VladD2, Вы писали:

VD>Мы (люди) думаем абстракциями.


+1. Похоже, что именно поэтому так быстро прижился foreach в C#, гораздо чаще используется for в C++ по сравнению с while и в очень редких случаях применяется do while.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[2]: Лучший синтаксис для перебора значений
От: De-Bill  
Дата: 06.04.06 02:18
Оценка: +2
На самом деле, в зависимости от ситуации удобнее пользоваться функциями второго порядка, например:
  (map 'vector #'* #(1 2 3 4 5) #(10 9 8 7 6)) ==> #(10 18 24 28 30)


или

  (reduce #'+ #(1 2 3 4 5 6 7 8 9 10)) ==> 55


К сожалению, такого рода конструкции не выражаются хорошо на многих main-stream языках... а жаль...
Re[4]: Лучший синтаксис для перебора значений
От: VladD2 Российская Империя www.nemerle.org
Дата: 06.04.06 02:26
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Парсить такое трудно если не невозможно вообще.


В Nemerle действительно невозможно. Он контролирует парность скобок еще до синтаксического анализа. Это позволяет встравивать в язык синтаксические расширения и DSL-и.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Лучший синтаксис для перебора значений
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 06.04.06 03:51
Оценка:
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 различных значений)


ещё непривычнее
action 5+i.10  // порождает список значений (action 5), (action 6), ..., (action 14)
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[2]: Лучший синтаксис для перебора значений
От: IT Россия linq2db.com
Дата: 06.04.06 04:03
Оценка:
Здравствуйте, 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>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[3]: Лучший синтаксис для перебора значений
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 06.04.06 04:17
Оценка:
IT,

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

диапазон явно не фигурирует.
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.