Лучший синтаксис для перебора значений
От: 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<#)
Re[3]: Лучший синтаксис для перебора значений
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 06.04.06 04:24
Оценка: 1 (1) :))) :)
De-Bill,

DB>
DB>  (map 'vector #'* #(1 2 3 4 5) #(10 9 8 7 6)) ==> #(10 18 24 28 30)
DB>


DB>К сожалению, такого рода конструкции не выражаются хорошо на многих main-stream языках... а жаль...


Ещё можно предложить
http://foldl.com
http://foldr.com

quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re: Лучший синтаксис для перебора значений
От: Eugene Beschastnov Россия http://eugenius-nsk.livejournal.com/
Дата: 06.04.06 05:10
Оценка: 5 (1)
В Smalltalk используются следующие конструкции:

Перебор коллекции:

общий вид:
aCollection do: [ :element | "do something with element" ].

примеры:
aCollection do: [ :element | element blink ].
Посылает каждому элементу коллекции aCollection сообщение blink.

aCollection do: [ :element | anObject doSomethingWith: element ].
Посылает объекту anObject сообщение doSomethingWith: на каждый элемент коллекции aCollection. Параметром каждый раз передаётся текущий элемент коллекции.


Перебор по числам (реально требуется довольно редко):

общий вид:
aNumber1 to: aNumber2 do: [ :number | "do something with number" ].
или
(aNumber1 to: aNumber2) do: [ :number | "do something with number" ].
(с точки зрения поведения разницы нет)

пример:
1 to: 10 do: [ :i | anObject doSomethingWith: i ].



Перебор по числам с интервалом:

общий вид:
aNumber1 to: aNumber2 by: aNumber3 do: [ :number | "do something with number" ].
или
(aNumber1 to: aNumber2 by: aNumber3) do: [ :number | "do something with number" ].
(с точки зрения поведения разницы нет)

примеры:
1 to: 10 by: 3 do: [ :i | anObject doSomethingWith: i ].
выполнит
anObject doSomethingWith: 1.
anObject doSomethingWith: 4.
anObject doSomethingWith: 8.


1.4 to: 13.3 by: 4.7 do: [ :i | anObject doSomethingWith: i ].
выполнит
anObject doSomethingWith: 1.4.
anObject doSomethingWith: 6.1.
anObject doSomethingWith: 10.8.
--
Бесчастнов Евгений
Re[4]: Лучший синтаксис для перебора значений
От: Pavel Dvorkin Россия  
Дата: 06.04.06 05:25
Оценка: +2
Здравствуйте, IT, Вы писали:

IT>+1. Похоже, что именно поэтому так быстро прижился foreach в C#, гораздо чаще используется for в C++ по сравнению с while и в очень редких случаях применяется do while.


do while применяется так редко не поэтому, а потому что ситуации, когда необходимо выполнить тело цикла один раз обязательно, встречаются намного реже, чем ситуации, когда это не требуется.
for используеться чаще, чем while просто потому, что с for мы обычно ассоциируем последовательный перебор (0,1,2..) , а c while — произвольный итерационный процесс. Хотя это и неверно, но мы так подсознательно считаем. Есть у нас такие абстракции — for и while. А последовательный перебор встречается чаще.
With best regards
Pavel Dvorkin
Re: Лучший синтаксис для перебора значений
От: Pavel Dvorkin Россия  
Дата: 06.04.06 05:25
Оценка:
Здравствуйте, VladD2, Вы писали:

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


Да.. Есть еще проблемы на свете...

А проще всего было в Фортране

DO 100 I = 1,10

или с шагом

DO 100 I = 1,11,2


Только вот никому не советовали по ошибке вместо запятой ставить точку. Из-за этой точки в 60-е годы одна американская ракета при взлете самоуничтожилась (по крайней мере так говорят)
With best regards
Pavel Dvorkin
Re: Лучший синтаксис для перебора значений
От: Sinclair Россия https://github.com/evilguest/
Дата: 06.04.06 05:40
Оценка: 46 (5) :)
Здравствуйте, VladD2, Вы писали:
VD>В общем, приветствуются любые мысли.
Мысль такая:
public class Range : IEnumerable<int>
{
    private int _low;
    private int _high;
    public IEnumerator<int> GetEnumerator()
    {
        for (int i = _low; i <= _high; i++)
            yield return i;
    }

    #region Construction
    public Range(int low, int high)
    {
        _low = low;
        _high = high;
    }
    public static Range Indexes<T>(T[] array)
    {
        return new Range(0, array.Length - 1);
    }

    #endregion

    #region IEnumerable Members

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    #endregion
}

использование:
int[] a = new int[5];
foreach(int i in Range.Indexes(a)) // нет выбора между Length/Length-1
  Console.Write(i);

foreach(int i in new Range(0, 10))
  Console.Write(i);

Предполагается набор перегруженных конструкторов для указания step. Предполагается наличие свойства Reverse для обращения обхода. Предполагается наличие операций пересечения/объединения интервалов. Велком
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: Лучший синтаксис для перебора значений
От: Pavel Dvorkin Россия  
Дата: 06.04.06 05:48
Оценка: +1 -1
Здравствуйте, Sinclair, Вы писали:

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

VD>>В общем, приветствуются любые мысли.
S>Мысль такая:

<skipped>

М-да... Похоже, пора объявить конкурс на самую длинную реализацию цикла for...

Господа, а не кажется ли Вам, что для того, чтобы сравнивать нынешний программный продукт по числу LOC c тем, что писали 10 лет назад, надо для нынешнего продукта автоматически применять понижающий коэффициент, равный так примерно 10 ?

P.S. А вообще дискуссия начинает понемногу напоминать незавбвенную "Hello, World".
With best regards
Pavel Dvorkin
Re: Лучший синтаксис для перебора значений
От: vdimas Россия  
Дата: 06.04.06 05:57
Оценка:
Здравствуйте, VladD2, Вы писали:

Если использовать foreach, то надо подразумевать, что x итерирует по множеству, соответственно запись множества при использовании оператора цикла и при самостоятельном использовании должна быть одинакова, Ruby — как раз тому пример.

Если же мы просто определяем границы и правила итерации (шаг и выход за границы), то ИМХО, оператор for предпочтительней.

Это по самому ключевому слову было.

Далее.

Для первого случая, ИМХО, надо придумать операторы порождения потока, результат применения которых неплохо смотрелся бы как IEnumerator<> или IEnumerable<>.

Почему бы не взять "знакомые" конструкции с других языков (ruby, pascal)?

[1 .. 3]        // от 1-го до 3-х включительно
[1 .. 10; 2] // шаг 2

[0 .. 10, 20 .. 30; 5] = {0, 5, 10, 20, 25, 30}

public delegate T NextIndexGenerator<T>(T current); // позволить использовать формулу для вычисления следующего члена ряда 
                                                    // исходя из значения предыдущего

[1 .. 1024; @current*2] = {1, 2, 4, 8, ..., 1024}

[0.1 .. 0.9, Math.Sqrt] = {0.1, 0.316, ..., 0.8999 } // ряд, сходящщийся к 1.0 по формуле next = sqrt(current);



Несчет неудобства array.Length-1 ничего сказать не могу, лично мне безразлично. Если кому-то важно, то можно оппробовать разные формы записи для открытых и закрытых диапазонов. Я бы предложил так:
[0..array.Length),

но боюсь, случайная опечатка в парных скобочках будет пересекаться с семантикой, что не есть гут. Может быть будут еще идеи как указать открытый диапазон? А может быть ввести некое ключевое слово, типа before:
[1 .. before 1024; @current*4]


----------
Насчет же указания границ перебора для цикла for — все предложенные варианты интересны (хоть и записаны были как foreach). Действительно, надо взять несколько наиболее встречающихся случаев переборав цикла и заточить синтаксис под них.

Вот еще варианты:
for(i from 0 to 10 step 2) // закрытый диапазон слева и справа

for(i from 0 before 10 step 5) // открытый диапазон

Кстати, почему бы не сделать from 0 по умолчанию для before (самый востребованный сценарий использования)?

Совсем коротко выходит:
int[] arr = new int[10];

for(i before arr.Length) 
    arr[i]=i*i;
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Лучший синтаксис для перебора значений
От: Кодёнок  
Дата: 06.04.06 06:00
Оценка: 27 (1) +1
Здравствуйте, VladD2, Вы писали:

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


VD>foreach (i in 0..3) // выдает последовательность 0, 1, 2, 3

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

Есть такие мысли:

1. Использовать генератор xrange() (или range()) для открытых справа диапазонов. При этом ".." будет соответствовать закрытому интервалу, вроде closed_range()

2. for (int i = 0 while i < 10), for (int i = 0 while i <= 10 step 2). Но мне очень не нравится, что < можно спутать с <=, по сути это тот же Си-шный for.

3. Для перебора индексов использовать какой-нибудь генератор вроде IndexesOf из твоего примера и этим ограничиться.

4. Финт: for (int i = 0 to 10) для открытого сверху (0..9), for (int i = 1 upto 10) для закрытого (1..10). Перепутать трудно, визуально длина слов разная. Но с первого взгляда кажется непривычным. Собственно, сами слова "to" и "upto" можно исопльзовать вместо двух и трех точек для конструирования интервалов, не только в конструкции for.
Re[3]: Лучший синтаксис для перебора значений
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 06.04.06 06:01
Оценка: 23 (1) +2 -1 :)
Pavel Dvorkin,

PD>Господа, а не кажется ли Вам, что для того, чтобы сравнивать нынешний программный продукт по числу LOC c тем, что писали 10 лет назад, надо для нынешнего продукта автоматически применять понижающий коэффициент, равный так примерно 10 ?


Чаще всего величина библиотечного кода нас не волнует. Можно хоть на 1024 умножить, главное чтобы потом в своём файле иметь возможность писать
(+/ % #) list


вместо
int n = list.size();
double sum = 0;
for (int i = 0; i < n; i++)
    sum += list[i];
return sum/n;
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[4]: Лучший синтаксис для перебора значений
От: Кодёнок  
Дата: 06.04.06 06:08
Оценка: +1
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

LCR>Чаще всего величина библиотечного кода нас не волнует. Можно хоть на 1024 умножить, главное чтобы потом в своём файле иметь возможность писать

LCR>(+/ % #) list

LCR>вместо

LCR>int n = list.size();
LCR>double sum = 0;
LCR>for (int i = 0; i < n; i++)
LCR> sum += list[i];
LCR>return sum/n;

Отличная иллюстрация двух диких крайностей

Я предпочитаю золотую середину:

sum = reduce(float.__add__, list, 0.0)


В других языках reduce имеет имя fold или accumulate.
Re[5]: Лучший синтаксис для перебора значений
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 06.04.06 06:25
Оценка: +1 :)
Кодёнок,

Кё>Отличная иллюстрация двух диких крайностей


Кё>Я предпочитаю золотую середину:

Кё>
Кё>sum = reduce(float.__add__, list, 0.0)
Кё>

Я так полагаю, это Питончик? Да, там кстати считалось среднее
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[6]: Лучший синтаксис для перебора значений
От: Кодёнок  
Дата: 06.04.06 06:43
Оценка:
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

Кё>>Я предпочитаю золотую середину:

Кё>>sum = reduce(float.__add__, list, 0.0)
LCR>Я так полагаю, это Питончик? Да, там кстати считалось среднее

Совершенно верно, питон Но можно и другие языки:
return Nemerle.Collections.List.FoldLeft(lisT, 0, fun(a,b) {a+b}) / x.Length


Ну а насчет среднего — не намного сложнее, return reduce(float.__add__, lisT, 0.0)/len(lisT)

Кстати, а как в Nemerle сослаться на оператор + для класса, например, для целых? Пробовал System.Int32.op_Add и System.Int32.operator+, в документации не знаю где искать.
Re[5]: Лучший синтаксис для перебора значений
От: Kemsky  
Дата: 06.04.06 06:54
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>do while применяется так редко не поэтому, а потому что ситуации, когда необходимо выполнить тело цикла один раз обязательно, встречаются намного реже, чем ситуации, когда это не требуется.


Это зависит от того, как мыслит человек. Например, у меня большая часть циклов вообще полуторные: одна часть цикла должна выполняться на одну итерацию больше, чем другая. А чистые do и while, как вырожденные случаи, встречаются реже.
Re[3]: Лучший синтаксис для перебора значений
От: Kemsky  
Дата: 06.04.06 07:21
Оценка: -3 :))
Здравствуйте, VladD2, Вы писали:


VD>Понимаш ли в чем дело? С-шный for никто не отменяет. Но его гибкость выливается в ошибки и усложнение чтения кода когда он используется для простых вещей.


VD>Ведь если так мыслить, то даже самая приметивная программа станет архи-сложной.


VD>По этому за конструкцией "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. Разглядывать паттерны в накромождениях кода очень не просто.


VD>Посему код написанный в таком стиле плохо читается.


Эта сложность служит барьером от случайных людей. Можно избавить программистов от проблем на этом, весьма низком уровне. Однако, если человек не может научиться преодолевать подобные препядствия, то польза от него, как программиста, довольно сомнительна. Оперирование паттернами более высокого уровня, в действительности, намного сложнее. Если, конечно, речь не идёт о "Copy" и "Paste" фрагментов кода из документации и др. источников.
Re[2]: Лучший синтаксис для перебора значений
От: Sinclair Россия https://github.com/evilguest/
Дата: 06.04.06 07:35
Оценка: +1
Здравствуйте, vdimas, Вы писали:
V>Несчет неудобства array.Length-1 ничего сказать не могу, лично мне безразлично. Если кому-то важно, то можно оппробовать разные формы записи для открытых и закрытых диапазонов. Я бы предложил так:
V>
[0..array.Length),

Поскольку итерация в массиве — очень частая штука, имеет смысл сделать ее отдельной операцией. В дотнете уже придумано отличное решение — в большинстве случаев мне совсем не надо париться с индексом благодаря встроенному foreach:
int[] a = new int[] {1, 2, 3, 4};
int sum = 0;
foreach(int item in a)
  sum += item;

В тех редких случаях, когда мне все же нужен именно индекс, я бы предпочел вообще отказаться от манипуляций с Length. Оптимально было бы так:
int[] a = new int[] {1, 2, 3, 4};
int weightedSum = 0;
foreach(int i in a.Indexes)
  weightedSum += i*a[i];

V>но боюсь, случайная опечатка в парных скобочках будет пересекаться с семантикой, что не есть гут. Может быть будут еще идеи как указать открытый диапазон? А может быть ввести некое ключевое слово, типа before:
Мне кажется, сама проблема использования диапазонов в значительной мере надумана. Во-первых, диапазон настолько часто приделан к коллекции, что проще сделать нарошные операции извлечения диапазона напрямую, чем давать человеку возможность ошибиться при "двухстадийной" схеме — сначала вытаскиваем границы, а потом формируем из них диапазон.
Во-вторых, все эти скобочки экономят буквально одиночные символы, в ущерб понятности и безошибочности. По мне, так гораздо лучше ввести необходимые функции-конструкторы диапазонов:
Range(low, high) // для (1, 4) переберет 1, 2, 3, 4
ExclusiveRange(beforeLow, afterHigh) // для (1, 4) переберет (2, 3)
Since(low) // для (1) будет перебирать 1, 2, 3, ... до бесконечности
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Лучший синтаксис для перебора значений
От: ie Россия http://ziez.blogspot.com/
Дата: 06.04.06 07:53
Оценка: 24 (1)
Здравствуйте, VladD2, Вы писали:

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


foreach (i in (0, 4, 7)) // выдает последовательность 0, 4, 7
foreach (i in (0, 4..7+)) // выдает последовательность 0, 4, 5, 6, 7
foreach (i in (0, 4..7-, 12..14+)) // выдает последовательность 0, 4, 5, 6, 12, 13, 14


Но так Nemerle сделать не даст
Я в недавно в образовательных целях сделал такой макрос:
    macro @foreachIn (inexpr, body)
    syntax ("foreachIn", "(", inexpr, ")", body)
    {
        def intervalExecute(pat, intervalExpr, body)
        {
            match (intervalExpr)
            {
                | <[ $first .. $last ]> => 
                    <[
                        mutable i = $first;
                        def last = $last;
                        while (i <= last) 
                        {
                            def $pat = i;
                            $body;
                            i++;
                        }
                    ]>
                | <[ $single ]> => 
                    <[
                        def $pat = $single;
                        $body;
                    ]>
                | _ => throw Exception("foreachIn Usage: foreachIn(i[2..5, 7..10])");
            }
        }

        match (inexpr) 
        {
            | <[ $pat $[$single] ]>
            | <[ $pat [$single] ]> =>
                intervalExecute(pat, single, body)
            | <[ $pat $[..$list] ]>
            | <[ $pat [..$list] ]> =>
                {
                    def m(intervalExpr) { intervalExecute(pat, intervalExpr, body) }
                    mutable s = [];
                    foreach (i in list)
                        s =  m(i) :: s;
                    <[ { .. $(s.Reverse()) } ]>;
                }
            | _ => throw Exception("foreachIn Usage: foreachIn(i[2..5, 7..10])");
        }
    }

Использовать так:
    def p = 6;
    def q = 9;
    foreachIn (i[2..4, p..q, 11, 13..15])
        printf("%d\n", i);

Но так как это делалось исключительно в образовательных целях, о синтаксисе паттерна перебора сильно не задумывался.
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Превратим окружающую нас среду в воскресенье.
Re: Лучший синтаксис для перебора значений
От: igna Россия  
Дата: 06.04.06 07:53
Оценка: +1
Здравствуйте, VladD2, Вы писали:

VD>foreach (i in 0...3) // то есть добавляется третья точка.

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


А если так?:

foreach (i in 0..<3)
Re: Лучший синтаксис для перебора значений
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 06.04.06 08:00
Оценка: +1
Здравствуйте, VladD2, Вы писали:

VD>этот синтаксис хорош, но неудобен когда нужно перебрать значения индекса некой коллекции:

VD>
VD>foreach (i in 0..array.Length - 1) // не нравится этот "- 1"
VD>


Для полноты картины:
  for I := Low(A) to High(A) do;


Я для своих классов в которых нумерация начинается с нуля, ввожу еще одно поле Limit = Length — 1. В этом случае цикл:

  for I := 0 to A.Limit do;


Хорошая реализация в MATLAB. Там цикл имеет вид
  for i = A
    ...
  end


где i это переменная, а A это массив (рассматривается как одномерный). Поскольку массивы можно определить при помощи оператора ":", то Цикл от 1 до 10 может быть записан как

  for i = 1:10
    ...
  end


Цикл от 10 до 1 дожет быть записан как
  for i = 1:10:-1
    ...
  end


Распечатать все элементы массива можно просто
  for i = A
    print(i)
  end


Если при этом добавить для классов свойство Range, то получим
  for i = A.Range
    A(i) = 0.0
  end
Re: Лучший синтаксис для перебора значений
От: Undying Россия  
Дата: 06.04.06 08:00
Оценка:
Здравствуйте, VladD2, Вы писали:

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

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


И чем это лучше кода for (x = 0; x < 10; ++x)?

Почему так широко используется foreach? Потому что полностью соответствует задаче — "последовательно получить элементы коллекции". For задаче не соответствует, т.к. задача требует получения элементов, а не индексов и не содержит ни условия для отбора индексов, ни шага изменения индекса.

Ты же рассматриваешь другую задачу, а именно — "получить индексы в диапазоне от 0 до 10 с шагом 1". В чем здесь заключается несоответсвие for'а задаче? For работает именно с индексами, в нем задается диапазон и шаг, задавать еще что-то не надо. For для такой задачи по меньшей мере не хуже любой другой формы записи, соответственно не понятно стремление к его замене и тем более замене дублирующей.
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Re[7]: Лучший синтаксис для перебора значений
От: ie Россия http://ziez.blogspot.com/
Дата: 06.04.06 08:10
Оценка: 10 (1)
Здравствуйте, Кодёнок, Вы писали:

Кё>Кстати, а как в Nemerle сослаться на оператор + для класса, например, для целых? Пробовал System.Int32.op_Add и System.Int32.operator+, в документации не знаю где искать.


Должно быть Int32.op_Addition. По крайней мере компилиться, но во время выполнения падает, видимо баг (может уже поправили).
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Превратим окружающую нас среду в воскресенье.
Re[2]: Лучший синтаксис для перебора значений
От: igna Россия  
Дата: 06.04.06 08:10
Оценка: 43 (3) +2
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
Re[7]: Лучший синтаксис для перебора значений
От: Oyster Украина https://github.com/devoyster
Дата: 06.04.06 08:23
Оценка: 15 (1)
Здравствуйте, Кодёнок, Вы писали:

Кё>Кстати, а как в Nemerle сослаться на оператор + для класса, например, для целых? Пробовал System.Int32.op_Add и System.Int32.operator+, в документации не знаю где искать.


Всё проще
Автор: Vermicious Knid
Дата: 25.03.06
:

list.FoldLeft(0, _ + _) / x.Length
Re[2]: Лучший синтаксис для перебора значений
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 06.04.06 08:24
Оценка: 7 (1)
Здравствуйте, 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>


irb(main):013:0> 5.times { |i| puts "- #{i} -" }
- 0 -
- 1 -
- 2 -
- 3 -
- 4 -
=> 5
irb(main):014:0> (2..4).each { |i| puts "= #{i} =" }
= 2 =
= 3 =
= 4 =
=> 2..4
irb(main):015:0> (2...4).each { |i| puts "= #{i} =" }
= 2 =
= 3 =
=> 2...4
irb(main):016:0>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re: Лучший синтаксис для перебора значений
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 06.04.06 08:42
Оценка:
Здравствуйте, VladD2, Вы писали:

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


foreach, но так, чтобы сначала указывалась коллекция, а затем элемент. Т.е. как нибудь так (жирным выделены ключевые слова):
string[] strs = new {"a", "b", "c"};
on (strs each string str)
    Console.WriteLine(str);

Опционально можно так:
string[] strs = new {"a", "b", "c"};
on (strs each string str with index)
    Console.WriteLine(strs[index]);

Что же касается интервалов, степов и т.п., то тут я согласен с Синклером, для этого достаточно иметь набор соотв. итераторов.
... << RSDN@Home 1.2.0 alpha rev. 642>>
AVK Blog
Re: Лучший синтаксис для перебора значений
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 06.04.06 08:45
Оценка: 8 (1) +1
Здравствуйте, VladD2, Вы писали:

VD>В Руби для таких случаев используется синтаксис:

VD>
VD>foreach (i in 0...3) // то есть добавляется третья точка.
VD>

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

Это ты где в Ruby цикл foreach нашел?
В Ruby есть понятие Range, которое записывается либо с двумя точками (тогда это соответствует [a,b]), либо с тремя точками (что соответствует [a,b)).

Кроме того, если нужно перебрать все элементы контейнера, то используются методы each:
[1, 2, 3, 4].each { |item| ... }

Если нужно выполнить определенное количество циклов, то используется метод times:
10.times { |n| ... }

Если нужно перебрать значения от a до b, то можно использовать методы upto, downto или Range#each:
1.upto(10) { ... } # от 1 до 10.
10.downto(1) { ... } # от 10 до 1.
(1..10).each { ... } # от 1 до 10.
(1...10).each { ... } # от 1 до 9


Цикла foreach в Ruby нет. Есть for in, для которого важно, чтобы в итерируемом объекте был метод each:

Вы можете использовать for для итерации по любому объекту, который отвечает на метод each, например Array или Range:

for i in ['fee', 'fi', 'fo', 'fum']
  print i, " "
end
for i in 1..3
  print i, " "
end
for i in File.open("ordinal").find_all { |l| l =~ /d$/}
  print i.chomp, " "
end

выводит:
fee fi fo fum 1 2 3 second third


Как только ваш класс определяет соответствующий метод each, вы можете использовать цикл for для его обхода
class Periods
  def each
    yield "Classical"
    yield "Jazz"
    yield "Rock"
  end
end

periods = Periods.new
for genre in periods
  print genre, " "
end

выводит:
Classical Jazz Rock

Programming Ruby, глава Expressions


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[3]: Лучший синтаксис для перебора значений
От: adontz Грузия http://adontz.wordpress.com/
Дата: 06.04.06 09:14
Оценка: 9 (1) +1
Здравствуйте, igna, Вы писали:

I>
I>foreach (i in 0 .. 3) // 0, 1, 2, 3
I>

I>
I>foreach (i in 0 ..< 3) // 0, 1, 2
I>

I>
I>foreach (i in 0 <.. 3) // 1, 2, 3
I>

I>
I>foreach (i in 0 <..< 3) // 1, 2
I>


Тогда уже

foreach (0 = i = 3) // 0, 1, 2, 3

foreach (0 = i < 3) // 0, 1, 2

foreach (0 < i = 3) // 1, 2, 3

foreach (0 < i < 3) // 1, 2

что кажется уже предлагали
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[3]: Лучший синтаксис для перебора значений
От: kan_izh Великобритания  
Дата: 06.04.06 09:19
Оценка:
VladD2 wrote:

> _>Честно говоря, С++ синтаксис мне больше всего нравится, т.к. более

> гибок, позволяет перебирать не только целые числа в некоем интервале с
> шагом 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.

Нет, конечно. Просто рассматривается цикл как конструкция из 3 частей — начальное условие; условие окончания; операция
получения следующего элемента.
И не важно, что перебирается — индексы, родители, или диапозон, или ещё что...
Мне нравится единообразие при многообразии
for(int i=0; i<arguments.length; i+=2)
{
    map[arguments[i]] = arguments[i+1];
}
for(Node *parent = theNode; parent; parent = parent->getParent())
{
}
for(Range r(collection); r; ++r)
{
  cout << *r;
}
char *list[] = {"aaa", "bbb", "ccc", NULL};
for(char **elem = list; *elem; ++elem)
{
}

//Синтаксис типа этого будет совершенно не в тему. А преимущества какие?
foreach( int i=[0..arguments.length) )
{
   cout << arguments[i];
}
// Ещё можно оправдать такой синтаксис, тем, что выкидывается неиспользуемое здесь понятие "индекс"/"итератор", 
используется только "коллекция" и её "элемент коллекции".
foreach int arg(arguments)
{
   cout << arg;
}

В этом и заключается абстракция — в совершенно на первый взгляд различных конструкциях увидеть одинаковую сущность. А
придумывание красивого синтаксиса для какого-то частного случая — это процесс обратный абстрагированию, это
синтаксический сахар. Да, сложными абстракциями сложно пользоваться новичку, но это проходит.

Резюме. В перле приняли правильное решение — перебор элементов массива (без итераторов) foreach и универсальный сишный for.
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re: Лучший синтаксис для перебора значений
От: last_hardcoder  
Дата: 06.04.06 09:38
Оценка:
Здравствуйте, VladD2, Вы писали:

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


VD>Например, в С/С++ для этого используется императивный стиль:

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

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

VD>Во многих ЯП можно увидить синтаксис вроде:

VD>
VD>foreach (i in 0..3) // выдает последовательность 0, 1, 2, 3
VD>

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


Мне кажется, тут должно быть два паттерна: паттерн диапазона и паттерн перебора. Перебор применим как к диапазонам, так и к контейнерам. А диапазон можно использовать отдельно от перебора. Например создать контейнер, содержащий диапазоны.
Re[4]: Лучший синтаксис для перебора значений
От: igna Россия  
Дата: 06.04.06 09:41
Оценка:
Здравствуйте, adontz, Вы писали:

A>Тогда уже


A>foreach (0 = i < 3) // 0, 1, 2


Имелось ввиду так?:

foreach (0 <= i < 3) // 0, 1, 2


Согласен, foreach (0 <= i < 3) выглядит естественнее чем foreach (i in 0 ..< 3), но во-первых я предложил, как с минимальными изменениями снять конкретные нарекания вызванные конкретной конструкцией, а во-вторых кто-то возможно найдет, что

foreach (i in offset + delta * (m..n))

более понятен нежели

foreach (offset + delta * m <= i <= offset + delta * n)
Re[2]: Лучший синтаксис для перебора значений
От: Кодт Россия  
Дата: 06.04.06 09:41
Оценка: 1 (1) +1
> Почему бы не использовать традиционную математическую нотацию для inclusive/exclusive:

Используйте полуинтервалы [x1..x2) и будет щасте.
Это и С++ные указатели/итераторы за концом массива, и питоньи диапазоны.

#! python

for x in range(   3) : print x  # 0 1 2
for x in range(3, 7) : print x  #       3 4 5 6
for x in range(7,10) : print x  #               7 8 9
Posted via RSDN NNTP Server 2.0
Перекуём баги на фичи!
Re: Лучший синтаксис для перебора значений
От: z00n  
Дата: 06.04.06 10:31
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>
VD>foreach (i in 0..array.Length - 1) // не нравится этот "- 1"
VD>


-- Haskell

-- так:
take array.Length [0..]
-- или так:
[i | i <- [0..], i < array.Length]


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

Как в Python,Haskell etc. — совокупность генераторов и гардов, другими словами: List comprehension.
Re[2]: Лучший синтаксис для перебора значений
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 06.04.06 10:55
Оценка: 8 (1)
Здравствуйте, last_hardcoder, Вы писали:

_>Мне кажется, тут должно быть два паттерна: паттерн диапазона и паттерн перебора. Перебор применим как к диапазонам, так и к контейнерам. А диапазон можно использовать отдельно от перебора. Например создать контейнер, содержащий диапазоны.


Кстати. Вот в St есть #do: (типа foreach) и select: (фильрация коллекции). Наблюдательные программисты подметили, что иногда встречается патерн
типа (коллекция select: [ ...условие... ]) do: [ ...действие...]. То есть выбираем подмножество и его обрабатываем. Результат появление внутреннего итератора с фильтром типа коллекция select: [ ...условие... ] do: [ ...действие...]. От предідущего єтот вариант отличается не только отсутсвием кругліх скобок, но и отсутсвием промежуточной временной коллекции.

Что касается диапазона вообще (класс Interval в ST), то я видел, что бы он применялся только на низком уровне, при реализации самих методов do:, select: и пр.

Что касается исходного примера:

foreach (i in 0..array.Length - 1) // не нравится этот "- 1"


то в ST являются нормальным явлением методы коллекций first, last, allButFirst, allButLast, copyWithouFirst, copyWithouLast. Названия, вроде, говорят сами за себя.
http://www.smalltalk.ru | << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[2]: Лучший синтаксис для перебора значений
От: VladD2 Российская Империя www.nemerle.org
Дата: 06.04.06 11:48
Оценка: :)
Здравствуйте, Sinclair, Вы писали:

S>Мысль такая:

...

S>Предполагается набор перегруженных конструкторов для указания step. Предполагается наличие свойства Reverse для обращения обхода. Предполагается наличие операций пересечения/объединения интервалов. Велком


Сысль зравая и я даже дошел до ее аналога. Только уже в новом формате. Можно написать простенокий макрос который будет определять тип коллекции и формировать включающий дипазон (ее я озвучил здесь).
macro IndexesOf(collection) 
{ 
   // In real code one needs to do check type of collection and make specialized code 
   <[ $$[0..collection.Length - 1] ]> 
}
...
foreach (i in IndexesOf(myArray)) 
  ...


Более того товарищь Москаль сказал, что в Немерле в ближайшее время появятся расширяющие методы и расширяющие макросы. Это позволит писать так:
foreach (i in myarr.Indexes)
  ...


Причем реально код будет переписываться в тот самый for.

Так что ваша улыбочка, сэр, в конце сообщения ниуместна!
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: Лучший синтаксис для перебора значений
От: VladD2 Российская Империя www.nemerle.org
Дата: 06.04.06 11:48
Оценка: +1
Здравствуйте, Кодёнок, Вы писали:

Кё>Совершенно верно, питон Но можно и другие языки:

Кё>
Кё>return Nemerle.Collections.List.FoldLeft(lisT, 0, fun(a,b) {a+b}) / x.Length
Кё>


Можно проще:
lisT.FoldLeft(0, _ + _) . lisT.Length
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Лучший синтаксис для перебора значений
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 06.04.06 11:53
Оценка:
eao197,

E>5.times { |i| puts "- #{i} -" }


Здорово! Я теперь понял, откуда у меня такие фантазии
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[2]: Лучший синтаксис для перебора значений
От: VladD2 Российская Империя www.nemerle.org
Дата: 06.04.06 11:56
Оценка:
Здравствуйте, eao197, Вы писали:

E>Это ты где в Ruby цикл foreach нашел?


В Руби есть задание диапазонов с тремя точками (0...3). Об этом и шала речь.
Тебе же снова хочется обсудить вопрос не имеющий отношения к делу.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Лучший синтаксис для перебора значений
От: VladD2 Российская Империя www.nemerle.org
Дата: 06.04.06 11:56
Оценка:
Здравствуйте, z00n, Вы писали:

Z>Как в Python,Haskell etc. — совокупность генераторов и гардов, другими словами: List comprehension.


List comprehension перебор для такого случая. В общем-то диапазон и является простым случаем List comprehension, но все же городить нагромождения по этому поводу наверно не стоит.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Лучший синтаксис для перебора значений
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 06.04.06 12:02
Оценка:
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

LCR>
E>>5.times { |i| puts "- #{i} -" }
LCR>


LCR>Здорово! Я теперь понял, откуда у меня такие фантазии


Так ведь, с кем поведешься...

Кстати, если само значение счетчика не интересует, то можно писать просто:
5.times { puts "---" }


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[5]: Лучший синтаксис для перебора значений
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 06.04.06 12:14
Оценка:
Здравствуйте, eao197, Вы писали:

E>>>5.times { |i| puts "- #{i} -" }


E>Кстати, если само значение счетчика не интересует, то можно писать просто:

E>
E>5.times { puts "---" }
E>


Прикольно. Во-первых, в ST этот метод никогда не передаёт значение счетчика и для того, что бы его получить приходится писать 1 to: 5 do: [...]. Не то чтобы я этим часто пользовался, но когда изредка пишу какие-то тестики, то постоянно об этом забываю. Во-вторых, только сейчас заметил, что название метода в ST слегка неконсистентно — timesRepeat:. Почему Repeat если можно было сделать просто times:, или timesDo: на крайняк. История, блин.
http://www.smalltalk.ru | << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[3]: Лучший синтаксис для перебора значений
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 06.04.06 12:30
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>В Руби есть задание диапазонов с тремя точками (0...3). Об этом и шала речь.

VD>Тебе же снова хочется обсудить вопрос не имеющий отношения к делу.

Я хотел сказать, что в Ruby нет оператора foreach.
А так же то, что приведенная тобой для Ruby запись:
foreach (i in 0...3)

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

Поскольку для Ruby будет выдана последовательность 0, 1, 2 (без тройки). Т.е. твои два примера не эквивалентны.
Если же ты хочешь именно 0,1,2,3, то следует писать диапазон именно с двумя точками.

Так что я не пытаюсь увести разговор в сторону. а исправляю фактические ошибки. Относись к ним как опечаткам, которые заметил читатель.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[3]: Лучший синтаксис для перебора значений
От: igna Россия  
Дата: 06.04.06 12:31
Оценка:
Вместо того чтобы вводить в язык дополнительно три операции образования интервалов ..<, <.. и <..<, можно ввести постфиксные и префиксные унарные операции < и > (последнюю — для симметрии, как впрочем и в случае операций образования интервалов для симметрии следовало бы добавить также ..>, >.. и >..>).

Выражения <n и n> были бы сокращением для n-1, а >n и n< — для n+1.

Может быть тогда наши foreach-и логичнее было бы записать с пробелом между .. и <:

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


Но и предыдущий вариант
Автор: igna
Дата: 06.04.06
остался бы работоспособен.
Re[3]: Лучший синтаксис для перебора значений
От: Зверёк Харьковский  
Дата: 06.04.06 12:48
Оценка: +1
Здравствуйте, Sinclair, Вы писали:

S> В тех редких случаях, когда мне все же нужен именно индекс, я бы предпочел вообще отказаться от манипуляций с Length. Оптимально было бы так:

S>
S>int[] a = new int[] {1, 2, 3, 4};
S>int weightedSum = 0;
S>foreach(int i in a.Indexes)
S>  weightedSum += i*a[i];
S>


#как-то так, да
weightedSum = 0
a.each_with_index {|obj, i| weightedSum += i * obj}


Ruby, вестимо
FAQ — це мiй ай-кью!
Re[4]: Лучший синтаксис для перебора значений
От: VladD2 Российская Империя www.nemerle.org
Дата: 06.04.06 15:10
Оценка:
Здравствуйте, eao197, Вы писали:

E>Так что я не пытаюсь увести разговор в сторону. а исправляю фактические ошибки. Относись к ним как опечаткам, которые заметил читатель.


Нда. Исправляй дальше. Общаться с тобой по существу невозможно.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Лучший синтаксис для перебора значений
От: WoldemaR Россия  
Дата: 06.04.06 15:49
Оценка:
Здравствуйте, VladD2, Вы писали:

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



А зачем тебе это?

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

Кто-то думает что решить эту проблему можно препроцессором (R#) или шаблонами (boost).
А мне кажется, что тут помогут Code-snippetы, жаль что для с++ их ещё не сделали.

Плюсы от их применения огромны.
1) стандартизация кода через шаблонные решения.
2) скорость чтения кода от применения узнаваемых решений.
3) автоматическая переконвертация кода под другой стиль.

Короче через 5 лет программер будет писать в своём коде паттерн в полюбившемся ему виде,
а при сдаче проекта другому программеру или заказчику маленькая программка переправит всё в соответствии со вкусами заказчика.

так что можно не париться.
Re: Лучший синтаксис для перебора значений
От: IO Украина  
Дата: 07.04.06 08:04
Оценка: :)
Здравствуйте, VladD2, Вы писали:

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


перебор(x, [0, 10))
{
}

Re[3]: Лучший синтаксис для перебора значений
От: vdimas Россия  
Дата: 07.04.06 12:17
Оценка: +1
Здравствуйте, Sinclair, Вы писали:

S> В тех редких случаях, когда мне все же нужен именно индекс, я бы предпочел вообще отказаться от манипуляций с Length. Оптимально было бы так:

S>
S>int[] a = new int[] {1, 2, 3, 4};
S>int weightedSum = 0;
S>foreach(int i in a.Indexes)
S>  weightedSum += i*a[i];
S>


+1 за общую мысль, но мне не нравится реализация.

Один из частых случаев, когда нас интеерсует именно индекс — это заполнение значениями value-type массива.

Например:
struct SomeStruct { 
    public double a, b, c, d, e, f; 
}

...

SomeStruct[] s = new SomeStruct[100];
for(int i = 0; i<s.Length; i++)
    Fill(s[i]);
    
...

public void Fill(ref SomeStruct item) {}


Так вот, избавление от явного указания границ могло бы выглядеть так:
foreach(ref item in s)
    Fill(item);


Красота!

S>Мне кажется, сама проблема использования диапазонов в значительной мере надумана. Во-первых, диапазон настолько часто приделан к коллекции, что проще сделать нарошные операции извлечения диапазона напрямую, чем давать человеку возможность ошибиться при "двухстадийной" схеме — сначала вытаскиваем границы, а потом формируем из них диапазон.


Угу, но все же лучше обойтись вообще без явных вытаскиваний диапазонов.

S>Во-вторых, все эти скобочки экономят буквально одиночные символы, в ущерб понятности и безошибочности. По мне, так гораздо лучше ввести необходимые функции-конструкторы диапазонов:

S>Range(low, high) // для (1, 4) переберет 1, 2, 3, 4
S>ExclusiveRange(beforeLow, afterHigh) // для (1, 4) переберет (2, 3)
S>Since(low) // для (1) будет перебирать 1, 2, 3, ... до бесконечности

Похоже в Nemerle можно будет всякого такого прикрутить
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: Лучший синтаксис для перебора значений
От: vdimas Россия  
Дата: 07.04.06 12:17
Оценка:
Здравствуйте, adontz, Вы писали:

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


I>>
I>>foreach (i in 0 .. 3) // 0, 1, 2, 3
I>>

I>>
I>>foreach (i in 0 ..< 3) // 0, 1, 2
I>>

I>>
I>>foreach (i in 0 <.. 3) // 1, 2, 3
I>>

I>>
I>>foreach (i in 0 <..< 3) // 1, 2
I>>


A>Тогда уже


A>
A>foreach (0 = i = 3) // 0, 1, 2, 3
A>

A>
A>foreach (0 = i < 3) // 0, 1, 2
A>

A>
A>foreach (0 < i = 3) // 1, 2, 3
A>

A>
A>foreach (0 < i < 3) // 1, 2
A>

A>что кажется уже предлагали

В твоем варианте уместней ключевое слово for, а в их варианте — forech
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: Лучший синтаксис для перебора значений
От: vdimas Россия  
Дата: 07.04.06 12:17
Оценка:
Здравствуйте, Mystic, Вы писали:

Да, в MatLab удобнее всего на настоящий момент.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: Лучший синтаксис для перебора значений
От: VladD2 Российская Империя www.nemerle.org
Дата: 07.04.06 22:30
Оценка:
Здравствуйте, vdimas, Вы писали:

Цитиру по меньше, плиз.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Лучший синтаксис для перебора значений
От: DJ KARIES Россия  
Дата: 12.04.06 18:19
Оценка: +1
Здравствуйте, VladD2, Вы писали:

VD>В Паскале используется синтаксис:

VD>
VD>for i := 0 to 3 step 1 do
VD>

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

Step — это уже из бейсика.
В паскале нет указания шага в цикле.
http://dkdens.narod.ru http://giref.forthworks.com
Re: Лучший синтаксис для перебора значений
От: mogadanez Чехия  
Дата: 13.04.06 12:36
Оценка:
Здравствуйте, VladD2, Вы писали:

f(x)
{
....
}

foreach( array, f );
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Re[4]: Лучший синтаксис для перебора значений
От: gear nuke  
Дата: 14.04.06 06:47
Оценка:
Здравствуйте, kan_izh, Вы писали:

[]

_>Резюме. В перле приняли правильное решение — перебор элементов массива (без итераторов) foreach и универсальный сишный for.


из Programming Perl:

Ключевое слово foreach служит просто синонимом ключевого слова for, поэтому for и foreach можно использовать взаимозаменяемо и в зависимости от того, которое из них выглядит более удобочитаемым в конкретной ситуации.

People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re: Лучший синтаксис для перебора значений
От: _nn_ www.nemerleweb.com
Дата: 14.04.06 12:31
Оценка:
Здравствуйте, VladD2, Вы писали:

Вот идея без синтаксического оверхеда

Для чисел:
i@len // for (int i = 0; i < len; i++)
i@len@2 // for (int i = 0; i < len; i+=2)
i@@len // for (int i = 0; i <= len; i++)
i@(len+1) // for (int i = 0; i <= len; i++)


Для коллекций:
v@x // foreach(v in x)
 print v
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[5]: Лучший синтаксис для перебора значений
От: kan_izh Великобритания  
Дата: 14.04.06 13:42
Оценка:
gear nuke wrote:

> _>Резюме. В перле приняли правильное решение — перебор элементов массива

> (без итераторов) foreach и универсальный сишный for.
>
> из Programming Perl:
> Ключевое слово foreach служит просто *синонимом* ключевого слова for,
> поэтому for и foreach можно использовать взаимозаменяемо и в зависимости
> от того, которое из них выглядит более удобочитаемым в конкретной ситуации.
Я знаю, но какая лексема применяется — дело второе. Главное — две различные семантические конструкции:
for(var iter=init(); cond(iter); next(iter))
{
    use(*iter);
}
foreach var elem(collection)
{
    use(elem);
}

Просто в этом треде обсуждали как лучше перебирать числа от нуля до n — ну не требуется это в большинстве практических
задач, максимум в учебных целях, когда человек ещё не понимает абстракцию "итератор".
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[6]: Лучший синтаксис для перебора значений
От: gear nuke  
Дата: 14.04.06 15:27
Оценка:
Здравствуйте, kan_izh, Вы писали:

_>Я знаю


я не сомневался

_>но какая лексема применяется — дело второе.


Со вторым не соглашусь. В Perl чего только не понапихали, с этим There is more than one way to do it. Казалось бы, что мешает наделать ещё пару десятков этих вариантов for, не пожалели же лишнюю лексему-синоним. А сделали всего 2. Должен же быть в этом всём какой-то смысл (учитывая, что P — это practical)

_>Просто в этом треде обсуждали как лучше перебирать числа от нуля до n — ну не требуется это в большинстве практических

_>задач, максимум в учебных целях, когда человек ещё не понимает абстракцию "итератор".

Дык это как раз перебор всех элементов множества.
foreach(@a)


А точнее, вопрос был такой:

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


А что такое диапазон множества, как не другое множество (срез от первого) ?
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.