Розробка ідеального діапазону в прямому сенсі


10

Я думав над тим, як би я пішов про розробку "ідеального" літералу діапазону, якби я займався дизайном мови. Для вас, хто не знає, знаєте літерал діапазону у висловлюванні, що представляє діапазон значень, наприклад 1-4. Вони найчастіше використовуються для циклів / foreach

Здається, є кілька питань, які слід враховувати

  • Підтримка інклюзивного та ексклюзивного діапазонів, позначення +1 або -1 до кінцевих точок, здається, трохи нечітке та помилкове.

  • Підтримка крокових дій, тому ви можете створити діапазон парних чи непарних чисел, наприклад

  • Читання, слід легко зрозуміти, що описує літерал діапазону

  • Однозначно, воно повинно бути абсолютно однозначним, що описує літерал діапазону

  • За замовчуванням, мабуть, має бути від включення до виключного, оскільки саме це використовується в більшості випадків для циклічного перегляду масивів тощо.

У будь-якому разі, я бачив один приклад діапазону літералу - Ruby, який має форму 1..3 для ексклюзивного (в кінці) діапазону і 1 ... 3 включно (в кінці). Ви також можете зробити 1..10.степ (5). Після ретельного розгляду я виявив, однак, кілька речей, які мені не сподобалися в такому підході (з моїх обмежених знань про рубін)

  1. Ви можете описати інклюзивне та ексклюзивне лише для кінця. Описуючи більшість сценаріїв, це здається трохи непослідовним.

  2. Варіюється лише додатковим. видається рецептом, коли важко зрозуміти, включено чи ексклюзивно асортимент. Я не знаю про вас, але пункти, як правило, стають чимось розмитим :)

  3. Додавання методу, як позначення для діапазонів, схоже, змішує поняття буквального з поняттям класу, яке здається трохи непослідовним (навіть якщо діапазони збираються до класу)

У будь-якому разі, після роздуму над різними альтернативами. Я придумав це

  • [5..1] 5,4,3,2,1
  • [1..5 [ 1,2,3,4
  • ] 1..5] 2,3,4,5
  • [ 0..5..20] 0,5,10,15,20

і так далі. Мені це подобається, тому що [зазвичай позначає набір, і це щось вписується в це, навіть якщо це на відміну від набору буде впорядковано.

Одне, що мене трохи турбує, хоча робить ексклюзивні / включні індикатори обов'язковими чи ні, тобто, якщо ви пишете всього 1..5, типовим буде 1,2,3,4, оскільки це найпоширеніший випадок з масивами тощо . Це легше і читабельніше, але менш конкретно, і якщо вам довелося писати [1..5 [ви дізнаєтесь рано про те, як вони працюють.

То як ви думаєте, чи я висвітлював більшість баз, щось переглядав? Ви зробите [] обов'язковим? Ви б по-різному проектували літерали діапазону в мові програмування?

Кандидати

  • стиль дужки: [0..10 [ , з кроком: [0..5..20 [
  • позначення інтервалу: [0..10) з кроком: [0..5..20)
  • вигук для ексклюзиву. 0 ..! 10, з кроком: 0..5 ..! 20
    • з різним кроком. 0 ..! 20, 5
    • однак це зробило б за замовчуванням * 0..10 ' включно-включно
  • багатослівно: [0 до! 20 на 5]

Треба сказати, що моє улюблене в естетичному відношенні дорівнює 0 ..! 10 і 0..5 ..! 20 , я просто бажаю, щоб за замовчуванням 0..10 до включно-ексклюзивного було б більш логічним


2
1,5,10,15,20Проміжок 4, 5, 5, 5 ?!
Пітер Тейлор

oops :) виправлено
Homde

Відповіді:


14

Навіщо вигадувати те, що вже існує в математиці?

Інтервальна нотація

Це має охоплювати вашу точку "Однозначності", оскільки вона вже існує.

Вашим єдиним питанням буде визначення кроку. Може, щось інше в математиці може допомогти у цьому?


3
Привіт, я насправді про інтервальне позначення. Однак те, що змусило мене не хотіти його використовувати, це те, що воно не було симетричним як [і], так і використовувало парантез, а також не маючи кроків (як ви згадуєте). Використання парантезу, можливо, може заплутати відповідність дужок, і я скоріше збережу їх у виразах. Використання] та [є ізостандартним і, здавалося б, ідеально покращують інтеграцію крокових дій, але це, звичайно, моя думка.
Хомде

7
@MKO: Ваша ідея використання незрівнянних дужок (як-от [1..5[) заплутає редакторів принаймні настільки ж, як і стандартне інтервальне позначення.
Девід Торнлі

2
Хм, ще одна ідея, як щодо використання! для, тобто: 1 ..! 5 або 0..5 ..! 20 (із кроком)
Homde

1
@MKO: Використання !для виключення першого або останнього елемента може бути корисним.
FrustratedWithFormsDesigner

8

Ви бачили діапазони Haskell? Їх ідея щодо кроків схожа на вашу (в середині), але позначена синтаксичною різницею (від відповіді @ luqui ):

[1,2..10] = [1,2,3,4,5,6,7,8,9,10]
[1,3..10] = [1,3,5,7,9]
[4,3..0]  = [4,3,2,1,0]
[0,5..]   = [0,5,10,15,20,25,30,35...  -- infinite
[1,1..]   = [1,1,1,1,1,1,1,1,1,1,1...  -- infinite

Я вважаю це позначення дуже інтуїтивним: ви починаєте перераховувати і пропускати по тілу, щоб позначити, де воно має закінчитися.

Це не стосується випадку "ексклюзивного", але, чесно кажучи, я б краще зрозуміти поведінку один раз (вкажіть, яка межа включена, а яка є ексклюзивною), і очікує, що користувач буде вносити коригування, якщо синтаксис не є надзвичайно зрозумілим (і не плутає мовних агностичних редакторів).


5

Ви повинні прочитати про розуміння списку мовами, які їх пропонують.

Наприклад, Python досить добре висвітлює ваші випадки з range()функцією та розумінням списку для справ, занадто складних для вираження range().


2

Я вважаю, що ваше позначення далеко не однозначне. Інтуїтивно [0..5..20]не схоже на діапазон із шириною кроку = 5. Він навіть не спрацьовує в деяких кутових випадках: як щодо вираження множини (0,2) - [0..2..2]або що я повинен ставити посередині?

Я думаю, що позначення фрагментів Python - це суцільний підхід: [start:end:step](крок є необов’язковим).

Якщо вам справді потрібна підтримка ексклюзивних та інклюзивних діапазонів, я б використовував стандартні позначення діапазону (тобто використання (та [), якщо це не вносить синтаксичні двозначності у вашу мову.


1
щодо «стандартного» нотації, європейські школи не вчать [], [[, ]]і ][, що не дужку ... і наш стандарт краще, звичайно;)
Матьє М.

@Matthieu: Насправді, тут, у Нідерландах (що є в Європі), нас також вчили цьому стандартному позначенню.
Фріц

1

Я думаю, що коли ви встановлюєте значення третього приросту, вам краще додати це в кінці, а не в середині, оскільки це необов'язкове значення і здається більш інтуїтивним для досвідчених програмістів, ніж додавання необов'язкового 3-го аргументу посередині .

тож замість [1..5..20] ви можете зробити щось на зразок [1..20] [5] або [1..20,5]


Це справедливий момент і, можливо, справа смаку, мені просто здалося, що легше буде думати "1 крок 5 до 20", а не "від 1 до 2, з кроком 5", використовуючи [1..20] [5] здається трохи захаращеним, але, можливо, підхід комами був би життєздатним. Буду вдячний більше відгуків про це
Homde

1
  • [1..5 [1,2,3,4
  • ] 1..5] 2,3,4,5
  • ] 1..5 [2,3,4

Чому б просто не використовувати [1..4], [2..5], [2..4]? Виключення діапазонів не приносить великої користі. Вам не потрібно писати MIN + 1 або MAX-1, так, але це все одно не забороняє. Занадто багато варіацій, imho. У моїй мові вибору, scala, є (від 1 до 3) та (від 1 до 3) [= (1 до 2)], але це мене просто збентежило на початку. Тепер я завжди використовую "x to y" і тому знаю, що варіант, який я не використовую, є виключенням, але, звичайно, я не отримую користі від варіанту, який я не використовую.

  • [5..1] 5,4,3,2,1

це звичайно (від 1 до MAX) (x => y = (MAX + 1) - x), але це багато котла і не є зручним для користувачів.

  • [0..5..20] 0,5,10,15,20

це звичайно (0 до 4) (x => y = x * 5) - не стільки котлован. Суперечливі.


Основна перевага виключення діапазонів, afaik, полягає в тому, що кількість елементів - це різниця кінцевих точок.
Джастін Л.

@JustinL .: 5-1 - це 4 моєї алгебри, але містить 3 елементи, виключаючи межі: 2, 3, 4.
користувачеві невідомо

1

Що щодо такого подібного:

  • [5..1] 5,4,3,2,1
  • [1..5] [i, e] 1,2,3,4
  • [5..1] [i, e] 5,4,3,2
  • [1..5] [е, i] 2,3,4,5
  • [1..5] [е, е] 2,3,4
  • [0..20] на 5 0,5,10,15,20

iІ eв другій парі квадратних дужок вказує, початку або в кінці діапазону є інклюзивним та ексклюзивним (або ви могли б використовувати incl, і exclякщо ви хочете бути більш ясним). by 5вказує інтервал кроковий. Перший і останній приклад включають в себе перше і останнє значення, тому я опустив те [i,i], що, на мою думку, було б ОК припустимо поведінку за замовчуванням.

Значення за замовчуванням можуть бути [i,i]для інклюзивного / ексклюзивного специфікатора та by 1для специфікатора кроків.

Зазвичай я запропонував би стандартне позначення, яке передбачає (і [як згадував @Dan McGrath, але я згоден, що в коді це може виглядати заплутано.


Хто-небудь може пояснити сутичку?
FrustratedWithFormsDesigner

Я не бачив нічого явно неправильного . Я виступив протистояти протистояння.
Берін Лорич

1

І переможець

Вибачте за вибір мого власного рішення, я дуже вдячний за всі коментарі та відгуки. Будь ласка, критикуйте це рішення, якщо ви виявите, що в ньому щось не так.

Тому я вирішив поїхати:

0..5           = 0,1,2,3,5
0..5..10       = 0,5,10
..3            = 0,1,3
!0..!5         = 1,2,3,4
3..            = 3 to infinity

segmented ranges
-
0..5,..5..20   = 0,1,2,3,4,5,10,15,20
0..3,10..5..20 = 0,1,2,3,10,15,20

Як ви можете бачити, що інклюзивно - це за замовчуванням для обох почуттів, саме це має інтуїтивно зрозумілий сенс, особливо під час використання крокових дій. Ви можете використовувати! щоб закінчити ексклюзив.

Мінус полягає в тому, що зазвичай ви хочете використовувати ексклюзивні, працюючи проти масиву, але знову ж таки, у більшості випадків вам, мабуть, слід використовувати щось на зразок for-кожного в цих випадках. Якщо вам дійсно потрібно працювати проти індексу, аналізатор може розпізнати, коли ви, можливо, забули маркер виключення в кінці і винести попередження

Я пішов із використанням .. з обох сторін крокової змінної замість того, щоб використовувати коми або що-небудь інше, оскільки саме це виглядало найчистішим, і я сподіваюся, що це найбільш читабельно.

Я також кинув у якийсь синтаксис із комами, щоб можна було робити діапазони, де різні частини мають різні кроки


Це здається нормальним, крім випадків, коли вказується крок. Я думаю, що це було б чистіше, як [0..10 від 5]. Діапазон сегментації може бути [0..5, ..20 на 5] тощо. Можна також вказати [нуметеми від першого за кроком], які (на відміну від інших форм) можуть передбачати розмір кроку в нуль.
supercat

0

Я б не використовував форму "[1..5 [" з однієї і тієї ж причини, з якої ви б не змішували паролі та дужки - це сплутає відповідність дужок більшості існуючих редакторів. Можливо, використовуйте маркер всередині дужок, як-от "[1 .. | 5]".

Інша річ, яку слід врахувати, - це поведінка методів отримання меж. Наприклад, 'start' / 'end' vs. 'first' / 'last' vs. 'min' / 'max'. Вони повинні бути прийнятними як для інклюзивних, так і для ексклюзивних лімітів, а також для обмежених розмірів.


0

У Ruby є позначення та об'єкт Range, який працює. По суті це виглядає приблизно так:

1..5  # range 1,2,3,4,5

Для Ruby розмір кроку - це не функція діапазону, а скоріше функція ітерації через діапазон. Ми могли б використовувати той самий діапазон вище і повторювати його по-різному, якби ми хотіли:

(1..5).step(3) { |x| puts x }
(1..5).step(2) { |x| puts x }

Отже, ось, що ви можете розглянути:

  • Додавання мовної підтримки для інклюзивних / ексклюзивних кінцевих точок може бути проблематичним. Якщо всі діапазони включені (вибір Ruby), розробники будуть відповідно коригувати кінцеві точки діапазону. Як ви представляєте кінцеві точки включеності або ексклюзивності таким чином, що візуально однозначно і однозначно за допомогою простої граматики розбору?
  • Ви використовуєте діапазон для більш ніж просто ітерації? Загальні приклади включають порівняння діапазону, сплайсинг, значення в порівнянні діапазону. Якщо так, як ви представляєте ці можливості? (Дивіться посилання на клас Range, щоб отримати ідеї до кожного з цих прикладів.)

До речі, діапазони є досить приємними, якщо ви дозволяєте їх включати в оператор перемикання, як Ruby:

switch(myval)
    when 0..33 then puts "Low"
    when 34..66 then puts "Medium"
    when 67..100 then puts "High"
end

Я не кажу, що об’єкт діапазону Ruby - це кінець усе і бути всім, але це робоча реалізація концепції, про яку ви говорите. Пограйте з ним, щоб побачити, що вам подобається, що не подобається, і що робити по-іншому.


Уважно прочитайте питання, OP вже знає діапазони Ruby:Anyways, one example of range literal I've seen is Ruby which is in the form of 1..3 for an exclusive (on the end) range and 1...3 for inclusive (on the end). You can also do 1..10.step(5).
FrustratedWithFormsDesigner

0

Одне з варіантів, яке я, безумовно, вважаю, - це використовувати перевантаження оператора, щоб дозволити, наприклад,

1+[0..3]*5

Це не обов'язково буде одразу прозорим для всіх, але як тільки вони зупиняться і думають, я сподіваюся, що більшість програмістів це зрозуміють, а люди, які регулярно використовують мову, просто вивчать її як ідіому.

Для уточнення результатом було б [1, 6, 11, 16]підняття множення, а потім додавання по діапазону. Я не розумів, що це може бути неоднозначно для користувачів Python; Я вважаю діапазони як підмножини загальних замовлень, а не як списки. і повторювати набір не має сенсу.


2
Дуже неоднозначно. list expression * 5також може означати "повторити значення в list expression5 разів", як це робиться в Python.
nikie

Це дуже дивно виглядає, і я не впевнений, що це було б ... 1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3? 1,3,6,9,12? 5,10,15? ще щось, можливо? Так чи інакше, я вважаю це позначення цілком протиконтiтивним. Схоже, це, можливо, якась дивна операція вказівника С ...
FrustratedWithFormsDesigner
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.