Rust: Проблема отслеживания для включенных диапазонов `.. =` (RFC # 1192) - изначально `...`

Созданный на 4 сент. 2015  ·  331Комментарии  ·  Источник: rust-lang/rust

Текущий статус

Мы планируем изменить синтаксис для включающих диапазонов и шаблонов на ..= . Синтаксис ... в шаблонах стабилен и пока будет (молча) устаревшим; rustfmt может переписать ... в ..= . Это происходит после долгих обсуждений. См. Этот комментарий для обоснования.

В этой ветке не следует больше обсуждать синтаксис . Любые другие предложения синтаксиса исключительного диапазона должны размещаться на форуме пользователя или внутреннем форуме после того,

Шаги, которые нужно предпринять

  • [x] Первоначальная реализация
  • [x] Измените, чтобы принять ..= как синоним ... в шаблонах и принять ..= в выражениях # 44709
  • [x] Документация

    • [x] Книга ржавчин / книга № 1134

    • [x] Ссылка питомник rust-lang / ссылка № 215

    • [x] Пример обработки ржавчины rust-lang / пример ржавчины № 1015

  • [x] https://github.com/rust-lang/rfcs/pull/1980 предложил настройку RangeInclusive
  • [x] Стабилизация # 47813

    • Примечание. Поля RangeInclusive были исключены из этого раунда стабилизации. Пожалуйста, следите за № 49022 по этой функции.

B-RFC-implemented B-unstable C-tracking-issue E-mentor T-lang T-libs disposition-merge finished-final-comment-period

Самый полезный комментарий

Команда lang снова обсудила эту функцию на нашей сегодняшней встрече и пришла примерно к следующей матрице:

  • Поддержка ... в шаблонах и .. в выражениях и ничего больше - это несостоятельный замысел; это заставляет пользователей ожидать, что синтаксис будет работать, но этого не произойдет.

  • Если разрешить ... и .. в обоих местах, это поможет, но проблема «поодиночке» вызывает серьезную озабоченность; никто из нас не хочет получать отчеты о людях, которые часами отслеживают ошибочный период.

  • Переход на ..= и .. менее эстетичен, но позволяет избежать реальных практических проблем, описанных выше. Мы также можем развернуть его очень осторожно: сначала введите ..= в качестве альтернативного синтаксиса (который rustfmt может переписать) и только после того, как он станет идиоматическим, объявите ... устаревшим.

Если вы не можете сказать точно, команда считает, что ..= и .. - наш лучший путь вперед. Этот вопрос также обсуждался до такой степени, что вряд ли возникнут новые аргументы, поэтому мы готовы сделать решительный шаг: мы ищем того, кто хотел бы реализовать нотацию ..= для обоих шаблоны и выражения, а потом перейдем к FCP!

Все 331 Комментарий

Может быть a..b| или a..b]

Я думаю, что это откроет путь для нового вида непредсказуемых ошибок в будущем из-за простой опечатки (.. vs ...). Лучше бы было .... (4 периода). Таким образом, он менее подвержен ошибкам из-за человеческого фактора, imo.

Я думаю, что https://github.com/rust-lang/rfcs/pull/1592 и https://github.com/rust-lang/rfcs/pull/1582 вместе взятые, являются аргументом в пользу использования ..= синтаксис вместо этого. Если только кто-то не придумал лучший синтаксис, чем (head..., tail) для расширения кортежа перед большим кортежем.

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

👎 для синтаксиса ... . Я думаю, что наличие синтаксиса, который легко опечатать, приводит к единичным ошибкам, было бы ошибкой.

Однако функциональность полезна, поэтому я был бы счастлив иметь ее с другим синтаксисом, например, ..=

Является ли синтаксис для этого открытым вопросом? Поскольку ... уже находится в операторах сопоставления, я предположил, что корабль отплыл.

Я лично предпочел бы включить диапазон ... , однако, поскольку уже существует эксклюзивная версия .. , я вижу возможность проблем. Посмотрев на # 23635, я бы предпочел отказаться от .. и разрешить только ... .

Я часто использую инклюзивные диапазоны для эквивалента C-подобных циклов for for i in 0..foo.len() где он идеально подходит, поэтому я бы предпочел, чтобы он оставался (мне это нужно, потому что итераторы Rust "одномерные" и часто слишком неудобно использовать с 2D-массивами или нелинейной итерацией).

Проблема с переполнением для инклюзивных диапазонов выглядит глупо, но на практике я никогда не сталкивался с этой проблемой, потому что Rust раздражает использование с любым типом, кроме usize . Если бы я не использовал приведение при создании диапазона for i in 0..(len as usize) , мне все равно пришлось бы использовать i as usize полдюжины раз внутри цикла.

Поскольку этот синтаксис все еще ограничен функциями, я надеюсь, что корабль не улетел.

Учитывая, что swift использует ... для включения и ..< для эксклюзивных диапазонов, использование ..= для включения кажется вполне разумным.

У меня нет полезной информации, но я бы хотел, чтобы инклюзивные диапазоны вышли из "экспериментального" статуса. Когда я просматривал Rust By Example, я нашел один фрагмент, который мог бы извлечь из этого выгоду:

fn fizzbuzz_to(n: u32) {
    for n in 1..n + 1 {
        fizzbuzz(n);
    }
}

Вверх ? 😄

Я хочу написать RFC для синтаксиса a ..= b и обобщенных диапазонов. Я начал обсуждение, чтобы поговорить о том, как такие диапазоны будут представлены в стандартной библиотеке.

ИМХО .. = выглядит странно. Подход Свифта ... и ... <кажется мне лучше, потому что я предпочитаю многоточие двум точкам - многоточие означает пропуск, и мы опускаем числа между началом и концом диапазона.

Я все еще думаю ... и ... было достаточно. У вас разница в 1 символ, поэтому ошибку сделать сложнее, чем +/-, x / y или что-то еще.

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

Согласно RFC-процессу Rust, это предложение уже было рассмотрено, обсуждено и одобрено в RFC pull request 1192 . В настоящем выпуске отслеживается реализация того, что там было ранее решено. В ходе обсуждения были затронуты многие вопросы, которые здесь поднимают: альтернативный синтаксис (включая отсутствие нового синтаксиса), контраст с аналогичными операторами Ruby и т. Д.

Если вы твердо уверены, что функция должна быть другой, я думаю, вам нужно пройти через тот же процесс RFC, потому что именно так вносятся изменения в язык. Но в этом выпуске не место для этого.

@jimblandy, возможно, нам стоит попросить @nikomatsakis отредактировать это вежливое напоминание и руководство в первый комментарий в Really Big Print. 😇

@shepmaster Это, вероятно, было бы неплохо добавить в шаблон, используемый для регистрации _все_ проблем с отслеживанием.

Выдвижение на обсуждение / возможный FCP

Мы обсуждали это на встрече @ rust-lang / lang. Было общее чувство недовольства этой функцией - мы рассматривали возможность отказа от поддержки, но решили пока воздержаться от этого. Есть два основных возражения против ... в его нынешнем виде:

  • простота путаницы между .. и ... ;
  • @aturon думает, что было бы лучше иметь более «полноценный» синтаксис диапазона - его также можно было бы использовать в API, таких как итерация btree и т. д.

С этой целью мы задавались вопросом, захочет ли кто-нибудь продвинуть вперед RFC, который допускает более общий синтаксис, подобный этому, позволяющий точно указать, будут ли нижняя и верхняя границы включительными или исключительными. Я думаю, @aturon был бы счастлив поработать с кем-нибудь над таким RFC.

Я знаю, что некоторое время зашел в тупик, но недавно я открыл ветку обсуждения о том, как представить эти полностью работоспособные диапазоны в libstd (ссылка выше ), но никто не прокомментировал :(

С некоторыми комментариями к вышесказанному я был бы рад помочь с новым RFC.

Недавно я открыл ветку обсуждения о том, как представить эти полностью поддерживаемые диапазоны в libstd (ссылка выше), но никто не прокомментировал :(

Это несколько отражает их полезность.
Хотя наличие произвольных включительно-исключающих диапазонов звучит неплохо, я уверен, что все, кроме .. и в гораздо меньшей степени ... , никогда не будет использоваться.

@durka

Я знаю, что некоторое время зашел в тупик, но я открыл ветку обсуждения о том, как представить эти полностью работающие диапазоны в libstd (ссылка выше), но никто не прокомментировал :(

Это примерно похоже на тот подход, который мы имели в виду, да.


@petrochenkov

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

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

Это примерно похоже на тот подход, который мы имели в виду, да.

Который из? В своем посте я предложил несколько альтернатив.

Я часто хочу перебирать инклюзивные диапазоны, и мне очень понравилось набирать 0...x вместо 0..(x + 1) . Я понимаю, что это может привести к постепенным ошибкам, но какие у нас есть альтернативы?

Предполагая, что синтаксис Rust можно свободно изменять без побочных эффектов, я вижу только несколько очевидных закономерностей:

Принимая это как есть

1..4 // 1, 2, 3
1...4 // 1, 2, 3, 4

ИМХО, это хорошее решение, которое также используется при сопоставлении с образцом.

Заимствовать из математики

[1, 4] // 1, 2, 3, 4
[1, 4[ // 1, 2, 3
]1, 4] // 2, 3, 4
]1, 4[ // 2, 3

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

Заимствовать из Python

1:1:=5 // 1, 2, 3, 4, 5
1:1:<5 // 1, 2, 3, 4

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

Когда размер шага не является частью этого обсуждения (или будущего), ..= и ..< кажутся очень разумными!

Обновление: я думаю, что ..= и ..< были бы действительно хорошим решением. Сохранение шага в качестве адаптера имеет гораздо больший смысл.

Следует ли в это обсуждение включать в себя нисходящие диапазоны? Текущее решение инвертирования диапазона довольно сбивает с толку (но, возможно, не было бы, если бы у нас были инклюзивные диапазоны).

Например, можете ли вы прочитать и понять это, не прищурившись?

for i in (1..l.len()).rev() { ... }

РЕДАКТИРОВАТЬ: а со шрифтом GitHub это еще более запутанно, поскольку l выглядит как 1

Я думаю, что достаточно отрицательного шага.

Мы могли бы использовать синтаксис Matlab, a:b и a:step:b .

4 ноября 2016 г. в 00:50 "Ott" [email protected] написал:

Я думаю, что достаточно отрицательного шага.

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment -258344460,
или отключить поток
https://github.com/notifications/unsubscribe-auth/AAC3n3kwnGH6POQb4dGwCwJ8yOGqPSBQks5q6rmDgaJpZM4F4LbW
.

@durka Итак, что было бы эквивалентом текущего .. , где нет a или b ? Просто : ?

То, что я не заметил в RFC: учитывались ли разные имена для полей?

Если есть разные типы, может быть полезно иметь разные имена полей, если они имеют разное значение. Например, «range.start» - это «нижняя включающая граница» для всех типов. Но «range.end» иногда включает в себя, а иногда исключает. Различие между «концом» и (соломинкой) «последним» проясняет это.

(Это, конечно, не имеет значения, если от разных типов отказываются в пользу Range> ...)

Я думаю, что инклюзивный диапазон по-прежнему должен реализовывать std :: collections :: range :: RangeArgument.

pub trait RangeArgument<T> {
    fn start(&self) -> Option<&T> { ... }
    fn end(&self) -> Option<&T> { ... }
}

потом

impl RangeArgument<T> for RangeToInclusive<T> {
   fn end(&self) {
     Some(self.end+1)
   }
}

Так что fn foo<T, R: RangeArgument<T>>(arg: R) может принимать как инклюзивные, так и полуоткрытые диапазоны.

@durka Проблема с синтаксисом a: b в том, что он неоднозначен с описанием типа. Вы запрашиваете переменную b или тип b ? Очевидно, что как хорошие программисты на Rust мы используем наши типы с заглавной буквы, но компилятор не может этого сделать.

.. оператор с математическими определениями (на основе комментария

[1..4] // 1, 2, 3, 4
[1..4[ // 1, 2, 3
]1..4] // 2, 3, 4
]1..4[ // 2, 3

Использование (на основе примера

fn fizzbuzz_to(n: u32) {
    for n in [1..n + 1] {
        fizzbuzz(n);
    }
}

В этом случае мы используем .. просто как подсказку, но границы задаются [ и ]

@adelarsq : В Rust нам не нужны диапазоны, не включающие начало. Но синтаксис скобок имеет смысл только тогда, когда они разрешены. Кроме того, уже используется синтаксис скобок.

Я думаю, что ..= - самый разумный выбор для инклюзивных диапазонов.
Легко визуально отличить от .. , которым ... нет. Вероятность набрать ... имея в виду .. или наоборот и не замечая, выше, чем при ..= .
(Это сравнимо с случайным вводом if(a = b) вместо if(a == b) в C, как по визуальной заметности, так и по потенциальной ошибке).
А ..= легко запомнить, потому что это символическое значение ( i ..= j означает диапазон i .. j а где i = j ).

Похоже, основная жалоба заключается в том, что ... слишком похож на .. . Я заметил, что когда делаются другие предложения, включающие большее количество символов, никто не жалуется на количество символов, а только такие вещи, как сопоставление скобок и использование в определенных местах.
Итак, как насчет .... для инклюзивных диапазонов? Он по-прежнему должен выглядеть как диапазон, и, как я уже сказал, никто не возражает против решения, которое требует дополнительного символа. Спорно, более или менее шатко, чем ..= .
for i in 0....10 { println!("just a thought"); }

Если бы поведение по умолчанию было включающим, то ..! будет использоваться оператор (почти как отрицание).

Проблема с .... том, что это может вызвать некоторую путаницу, если ... действительно существует.

Мне тоже очень не нравится ... , поскольку это как раз обратное от Ruby .

Пока что лучший вариант - ..= я думаю.

@adelarsq , .... заменит оператор ... , поэтому, если вы попытаетесь выполнить .. и добавите дополнительный . , это будет компиляция ошибка времени, если вы попытались выполнить .... и забыли точку, это также будет ошибкой.

Поскольку при сопоставлении с образцом ... используется для сопоставления включающего диапазона, имеет смысл также использовать ... для выражения включающего диапазона.
Для диапазона с шагом я предпочитаю синтаксис Haskell, например 1,3..9 => [1,3,5,7]

Для диапазонов с шагом / реверсом и т. Д. Я бы предпочел старую добрую функцию (своего рода конструктор Range ) вместо сложного литерала.

Я был бы в порядке с четырьмя точками .... (хотя ..= тоже, ИМХО, тоже хорошо). Это также может быть разрешено в сопоставлении с образцом для согласованности (и в конечном итоге ... в шаблонах может быть устаревшим).

Для меня ..= как визуальное обозначение, которого нет в .... .

Я только что кое-что заметил:

В математике вы можете написать ∀ i: 0 ≤ i < 10 что будет переводиться в

for i in 0 ..< 10 { }

Это последовательно.

Однако выражение ∀ i: 0 ≤ i ≤ 10 преобразуется в

for i in 0 ..= 10 { }

Здесь ≤ переводится в =, что кажется непоследовательным.

Это может быть велосипедная распродажа, но

for x in 0 ..<= 10 { }

кажется более правильным. Это может быть из-за моего фона C, где

for (unsigned int i = 0; i <= 10; ++i) { }

переводится как «пока i меньше или равно 10 сделайте что-нибудь». В C я предпочитаю не использовать == в условиях цикла из-за возможности перепрыгнуть через значение и попасть в бесконечный цикл. Этого не может произойти в Rust, но перевод for i in 1 ..= 10 в C может подсказать именно это.

Продолжая,

for i in 0 <..<= 10 { }

было бы самоочевидным.

Изменить: здесь был плохой обратный пример, призванный показать, как использование только = может сбивать с толку. Удален, так как был скорее запутанным, чем конструктивным.

@duesee Почему >=..> говорит само >=..> себя? Разве это не должно быть <=..> (<= 10 и> 0)?
IMO это не говорит само за себя, это загадочно и слишком долго для оператора.
(Ни один оператор не должен быть длиннее 3-х символов IMO).
Кстати, у нас уже есть способ выразить обратное направление итерации: .rev()
Нам нужны только операторы для включающих диапазонов и, возможно, .step_by() .
Для шага синтаксис может быть a .. b | s (и для включающих диапазонов: a ..= b | s ).

@norru : Ваш пример for i in (1..l.len()).rev() { ... } очень нереалистичен, так как большую часть времени вы будете использовать срезы ( for x in arr[1..].rev() { ... } ), но даже если вы вынуждены использовать итерацию в индексном стиле (в основном только когда вы изменяете элементы массива, которые не находятся в i ), мне совсем не трудно читать. (Но я обычно оставляю пробелы вокруг .. когда аргументы не являются буквальными числами: (1 .. arr.len()).rev() )

>=..> больше видов рыб в операторах Rust!

Но мне очень нравится ..<= (отредактируйте: эээ, кроме match где это выглядит как <= 0 => :()

  • Он очень отличается от простого .. ,
  • у него нет коннотации += ..= ,
  • это логически согласуется даже с ..< Swift. Возможно слияние обоих языков!
  • и, что наиболее важно, довольно ясно, что вы получаете числа в диапазоне, которые меньше или равны верхнему.

@pornel : >=..> more species of fish in Rust operators! хе-хе :-)

@Boscop : это 10 >= i > 2 . Что касается остального вашего ответа: я полностью согласен. Вторая часть была задумана как мотивация переосмыслить ..= против ..<= чтобы не вводить блокировщики для будущих расширений. Я соответствующим образом отредактирую свой ответ.

также может получить флаг для предупреждения или ошибки в нотации ..

Я не хочу, чтобы .. отображалось где-нибудь в моей кодовой базе

Я хочу еще раз проголосовать за ..=

Обратной стороной ..< и ..<= является то, что они уже являются допустимым кодом (исключительный диапазон, открываемый по праву, сравнивается с другим значением).

@thepowersgang

Обратной стороной .. <и .. <= является то, что они уже являются допустимым кодом (исключительный диапазон, открываемый правом, сравнивается с другим значением).

хотя это правда, на практике это кажется маловероятным, не так ли?

Я предпочитаю ... другим предложениям здесь ... но если бы мне пришлось выбрать альтернативный синтаксис, это было бы ..=

@nikomatsakis

Я против вариантов ..< и ..<= исключительно на том основании, что они непропорционально усложняют процесс приобретения интуитивной модели грамматики языка.

В более личном плане я нахожу их по крайней мере такими же уродливыми и неэлегантными, как турбоуб.

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

Неужели ... действительно неотличимы от .. ? Почему мне это так нравится?

@tshepang

Мне нравится ... потому что он эстетически привлекателен ... но я возражаю против этого, потому что боюсь, что он может вызвать трудно заметные ошибки, подобные написанию if (x = 2) { а не if (x == 2) { в C / C ++. (И точно установлено, какой опасностью это оказалось.)

@ssokolow

ИМО, это лучше разрешить с помощью линтинга или флагов опций. Я не вижу особого смысла смешивать нотации в одном файле / проекте.

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

@ssokolow

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

Меня устраивает. Основной камень преткновения является также ли мы хотим синтаксис для других случаев (например, <..<= ). Я лично считаю, что .. и ..= покрывают примерно 99,5% случаев. Я думаю, что основной вариант использования - это такие API, как drain , и в настоящее время мы приняли здесь особый подход .

Копия @ Rust-lang / libs

Мы можем оставить необычные случаи для непосредственного построения диапазонов, используя
структурные литералы.

В среду, 22 февраля 2017 г., в 16:50, Нико Матсакис [email protected]
написал:

@ssokolow https://github.com/ssokolow

Я бы выбрал .. для исключительного права и .. = для включения как лучший
баланс между визуальной элегантностью, грамматическими правилами, которые легко интуитивно понятны
схватить, и из-за чего их трудно перепутать.

Меня устраивает. Основным камнем преткновения является также ли мы хотим
синтаксис для других случаев (например, <.. <=). Я лично чувствую это .. и .. =
покрывает вроде бы 99,5% случаев. Я думаю, что основной вариант использования - это API, такие как слив,
и в настоящее время мы придерживаемся особого подхода
https://doc.rust-lang.org/std/collections/struct.BTreeMap.html#method.range
.

коп @ rust-lang / libs https://github.com/orgs/rust-lang/teams/libs

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-281815665 ,
или отключить поток
https://github.com/notifications/unsubscribe-auth/AAC3n-aKwYKFq4VI9RizL0GkzXXSjTPwks5rfK2ngaJpZM4F4LbW
.

Я так понимаю, ..= тоже будут доступны в шаблонах? Что будет с существующим там синтаксисом ... ?

Это может быть объявлено устаревшим. Но его существование - довольно сильный прецедент для
используя его, по крайней мере, как стенографию.

В среду, 22 февраля 2017 г., в 18:02, andrewtj [email protected] написал:

Я так понимаю .. = тоже будут доступны в шаблонах? Что будет с
существующий ... синтаксис есть?

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-281834007 ,
или отключить поток
https://github.com/notifications/unsubscribe-auth/AAC3nw_DaOMNxuIKw6ZFfXJW95QyijY4ks5rfL6DgaJpZM4F4LbW
.

@durka @andrewtj Я предполагаю, что мы его осуждаем.

..= может использоваться как оператор в том же смысле, что и += .
Я предлагаю использовать tide ~ , например 0~9 , 'A'~'Z' .

Какой операции соответствует ..= ? - явно нежизнеспособен, потому что
1-9 == -8 .

В среду, 22 февраля 2017 г., в 20:04, Цзюньфэн Лю [email protected]
написал:

.. = может использоваться как оператор в том же смысле, что и + =.
Я предлагаю использовать ~, например, 0 ~ 9, 'A' ~ 'Z'.

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-281856846 ,
или отключить поток
https://github.com/notifications/unsubscribe-auth/AAC3n7N2dM4DAzc_uc5JdHit4IJgyvYGks5rfNsPgaJpZM4F4LbW
.

@durka ..= просто выглядят как операторы присваивания, вариант использования должен быть редким. ~ - это прилив, а не подводный. Также можно использовать ... .

impl Fill for Range<String> {
   fn fill() -> String { ... }
}
impl FillAsign for RangeAssign<String> {
   fn fill(&mut self) { ... }
}
(String::new("abc") .. String::new("f")).fill()  // "abcdef"
(String::new("abc") ..= String::new("f")).fill()  //  ()

Ой, извините, в моем шрифте он выглядит так же. Я спрашивал, является ли .. = составным
оператор присваивания, например + =, какую операцию он выполняет (соответствующий
к +)?

В среду, 22 февраля 2017 г., в 20:29, Цзюньфэн Лю [email protected]
написал:

@durka https://github.com/durka .. = просто похоже на задание
операторов, вариант использования должен быть редким. ~ это прилив, а не подводный.

impl Заполнить для диапазона{
fn fill () -> Строка {...}
}
impl FillAsign для RangeAssign{
fn fill (& mut self) {...}
}
(String :: new ("abc") .. String :: new ("f")). Fill () // "abcdef"
(String :: new ("abc") .. = String :: new ("f")). Fill () // ()

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-281861478 ,
или отключить поток
https://github.com/notifications/unsubscribe-auth/AAC3n39uqbADB1rNtBh3PBTRY2XBXOUNks5rfOD-gaJpZM4F4LbW
.

@durka @nikomatsakis хорошо, надеюсь, это скоро решится. Текущая ситуация неудобна, и изменение синтаксиса тоже будет.

@pornel Устарение поддержки ... в match приведет к нарушению совместимости, поэтому это не лучшее решение. Я по-прежнему считаю ... наиболее подходящим (однако это полная противоположность Ruby, но рубисты не обсуждают подобную проблему).

@ hyst329, но ... может быть более восприимчивым к ошибкам, поскольку отсутствие или добавление одного . придаст новое значение

Устаревание ничего не ломает. Старый синтаксис необходимо будет поддерживать вечно для существующих программ, но пользователи могут быть ориентированы на новый синтаксис с помощью документации и rustfmt.

но пользователей можно направить на новый синтаксис с помощью документации и rustfmt.

Я настоятельно не рекомендую использовать для этого rustfmt. Это усугубило бы свойства пистолета ... при использовании в режиме «автоматического применения изменений», потому что оно могло незаметно переводить опечатки в вещи, которые выглядят гораздо более целеустремленными. (Таким образом, их легче не заметить при более позднем рассмотрении.)

Предупреждение компилятора в духе «проверьте, что вы имели в виду, и используйте .. или ..= », которое не может быть исправлено автоматически, будет в большей степени соответствовать существующим усилиям по минимизации шанс человеческой ошибки.

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

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

Ах. Я забыл об этом. Спасибо за напоминание.

@adelarsq На самом деле, общие ошибки, такие как 'a'..'z' или 128u8..255u8 могут быть легко интегрированы в cargo-clippy , например, в виде предупреждений. А также ширина .. и ... явно различается (конечно, при использовании моноширинного шрифта; не использовать его, как правило, плохая идея для написания исходного кода в целом, а не только для Rust) .

Мы могли бы просто сделать его синтаксисом (горизонтальные многоточия в Юникоде) вместо ... Таким образом, по крайней мере, никто не напечатает его случайно.

Изменить: о, никто не отнесся к этому предложению серьезно: cry: Извините за шум.

Не знаю, последний раз, когда я проверял, Документы Google автоматически конвертируются ... в многоточие. Крупный игрок в индустрии редактирования текста.

Кроме того , не каждый имеет Compose ключ удобно вводить Compose. . когда они действительно хотят

В Windows я могу набирать многоточие, используя Alt + 0133 с цифровой клавиатурой!

И аналогичные механизмы на основе кодовых точек существуют на разных уровнях стека на настольных компьютерах на базе X11 (я помню, что GTK + и стек ввода X11 имели свои собственные независимые решения), но запоминать кодовые точки по номерам - большая проблема.

Compose - это интуитивно понятное решение.

Единственная последовательность Windows Alt , которую я помню, - это Alt + 219 из всех меню командных файлов DOS, которые я создал в детстве.

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

Сохранение текущего синтаксиса - худшее, что мы могли сделать, поскольку у него много реальных недостатков. Это не просто разгрузка велосипедов - это нужно делать правильно. Пропуск всей цепочки, синтаксис ..= пока получил наибольшее признание ...

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

Или мы могли бы использовать буквально любой другой синтаксис в мире.

С одной стороны, я ценю эту озабоченность ... с другой стороны, текущий синтаксис сопоставления с образцом ... уже является инклюзивным, что делает его полностью совместимым с синтаксисом, уже используемым где-то еще в Rust.

И у меня лично нет проблем с распознаванием разницы, хотя я признаю, что люди с проблемами зрения или с монитором 4k и шрифтом 10pt могут.

Но похоже, что консенсус по ..= и я думаю, меня это тоже устраивает.

FWIW, у меня была такая ситуация, когда я случайно набрал ... когда имел в виду .. а затем некоторое время не замечал, но через некоторое время я задумался, почему моя программа вела себя странно.
Так что да, разница должна быть более заметной, и ..= имеет наибольший смысл.

Выдвижение на обсуждение @ rust-lang / lang. Я думаю, мы должны просто принять ..= и покончить с этим. Нужен ли нам измененный RFC? Просто сделай это? Означает ли это отказ от существующего синтаксиса ... в шаблонах? (Я так полагаю.)

Я категорически за то, чтобы не использовать ... для диапазонов. Я не знаю, упоминалось ли об этом в этом потоке или RFC-потоке, но помимо того, что ... неоправданно похож на .. , мы также можем захотеть использовать ... в будущем для вариативных дженериков, которые намного важнее, чем инклюзивные диапазоны IMO.

..= кажется ясным, и его относительное уродство оправдано тем, что оно менее распространено, чем .. .

Означает ли это отказ от существующего синтаксиса ... в шаблонах? (Я так полагаю.)

Это кажется хорошей идеей. Предупреждать о ... и поддерживать как .. и ..= в шаблонах, если мы можем.

Я обычно опасаюсь вводить предупреждения, которые могли бы повлиять на очень многих людей, не имея автоматизированного инструмента для обновления синтаксиса, но изменение с ... на ..= особенно простое. Мы также можем отказаться от рекомендаций, но отложить создание предупреждения до тех пор, пока у нас не будет такого инструмента. Что думают все остальные?

Я решительно поддерживаю ... потому что это более «обычный» синтаксис; Я не знаю ни одного языка, на котором используется ..= , но многие из них используют .. и ... .

Если настроения против ..= сильны, я бы предпочел отказаться от синтаксиса включающего диапазона (вместо этого выбрал метод (a..b).inclusive() , который мне кажется достаточно лаконичным), чтобы избежать визуальной проблемы и снова бесплатно up ... для вариативных дженериков.

РЕДАКТИРОВАТЬ: Один хороший аргумент против (a..b).inclusive() заключается в том, что у нас все еще будет ... в match и, к сожалению, не будет нового синтаксиса для его замены. :смущенный:

@steveklabnik Извинения , если это уже было сказано где - то в этом (очень долго) нить, но: какие другие языки используют как .. и ... для эксклюзивных и инклюзивных диапазонах, соответственно?

Rust имеет опыт заимствования полезных функций и синтаксиса из других языков, но выборочно и отклонения или адаптации вещей там, где это необходимо.

@joshtriplett Ruby использует оба, но с противоположными значениями ( .. - включающее, ... - исключающее). Я не верю, что это была хорошая идея в Ruby, и нам кажется еще более запутанным наличие того и другого, но наоборот.

@joshtriplett больше всего мне знакома с Руби; Я думал, что это взято из Perl, но я не совсем уверен. Меня больше устраивает обратная семантика Ruby, чем ..= .

Честно говоря, я бы предпочел стабильный синтаксис включающего диапазона всему остальному и признаю, что моя сильная неприязнь к ..= - это личное дело, с которым разумные люди могут не согласиться.

@steveklabnik Swift использует ..< , я думаю, да? Это похоже на ..= но хуже того, что он оптимизирует (imo) неправильный случай. знак равно

Swift использует .. <для исключительного и ... для включения (их условия
«полуоткрытые» и «закрытые»).

Мне до сих пор нравятся .. <(с сокращением ..) и .. =.

Но другой открытый вопрос (возможно, не входящий в компетенцию этой проблемы отслеживания) заключается в том, «просто» ли мы принимаем синтаксис для закрытых диапазонов или также синтаксисы (syntaxen?) Для диапазонов с открытой первой точкой, то есть соломенный> ..> и > .. =.

16 марта 2017 г., в 14:19, Нико Мацакис [email protected]
написал:

@steveklabnik https://github.com/steveklabnik Swift использует .. <, я думаю,
правильно? Это похоже на .. =, но хуже, потому что он оптимизирует для
(имо) неправильный случай. знак равно

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-287147321 ,
или отключить поток
https://github.com/notifications/unsubscribe-auth/AAC3n0Wop5fJh9HVo7pSqo0riHm96Gm4ks5rmX1BgaJpZM4F4LbW
.

Я бы не возражал, если бы в прелюдии была функция inclusive :

for x in inclusive(1..10) {

}

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

Я считаю, что недостатки ..= и ... оба значительны - ..= довольно странно, но ... увеличивает вероятность ошибки на 1.

Лучше иметь странно выглядящий оператор, чем такой бесконечный потенциал для ошибок (каждый язык вводит операторы, которых нет у других, например, ..< в Swift, все операции в F # и Scala). Людям в любом случае придется читать книгу о Rust.
Учитывая, что многие люди переходят на Rust из Ruby, нам не следует делать это наоборот по сравнению с Ruby. (В дополнение к аргументу, что ... увеличивает вероятность ошибки на 1.)
Как вы можете принимать ..< в Swift, но не принимать ..= в Rust? ..= не так уж и странно.

Расширение синтаксиса диапазона в шаблонах все еще остается открытым вопросом, AFAIK.
Во-первых, мы не можем сделать это полностью, потому что Enum::Variant(..) уже
действительный и изменив его на значение Enum::Variant(RangeFull) будет нарушено.

16 марта 2017 г. в 15:07 Boscop [email protected] написал:

Лучше иметь оператор необычного вида (каждый язык вводит
операторы, которых нет у других, например .. <в Swift, все операции в F #
и Scala). Людям в любом случае придется читать книгу о Rust.
Учитывая, что многие люди переходят на Rust из Ruby, мы
не должно быть наоборот по сравнению с Ruby. (В дополнение к аргументу
это ... увеличивает вероятность ошибки на 1.)
Как вы можете принимать .. <в Swift, но не принимать .. = в Rust?

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-287160485 ,
или отключить поток
https://github.com/notifications/unsubscribe-auth/AAC3nz9ZNR2utl7LPTVvQPQ_Ma8sDBGuks5rmYhmgaJpZM4F4LbW
.

Так. Я хочу иметь возможность набирать что-то вроде slice.get(10...30) и тоже есть свой торт.

Я убедил себя, что предпочитаю inclusive(0..10) любому другому синтаксису:

  • Хотя @nagisa хочет написать slice.get(10...30) , я не хочу обращать пристальное внимание на то, slice.get(10...30) или slice.get(10..30) . Я думаю, что близость синтаксиса - настоящая проблема.
  • Я думаю, что все согласны с тем, что ..= неэстетично и, вероятно, не интуитивно понятно.
  • (0..10).inclusive() - тот же синтаксис, но менее удобный. Технически inclusive prelude, вероятно, будет поддерживать оба синтаксиса.

Думаю, это будет выглядеть так:

trait IntoInclusive {
    type Inclusive;
    fn inclusive(self) -> Self::Inclusive;
}

fn inclusive<T: IntoInclusive>(range: T) -> T::IntoInclusive {
    range.inclusive()
}

Я думаю, что все согласны .. = неэстетично и, вероятно, не интуитивно понятно.

Я думаю, что такое высказывание является чрезмерным обобщением. Я считаю, что ..= более эстетичен и интуитивно понятен, чем такой метод, как inclusive() .

(Кроме того, мы не знаем, какая часть неприязни к ..= может быть подсознательными (или сознательными) попытками найти проблемы с вещами, которые не являются ... .)

.inclusive() слишком длинный для чего-то, что происходит так часто (в этой заметке, я также думаю, что должна быть более короткая форма для .enumerate() ).
Но даже если бы у нас было .inclusive() , должна быть только одна функция, а не две.
Кроме того, отсутствие синтаксиса включающего диапазона не позволит использовать их в match .
Но, может быть, нам нужен способ указать экстракторы в общем виде, как в Scala ? Чтобы в сопоставлении можно было использовать любой тип, чтобы это сопоставление неявно вызывало свой метод unapply .

(Кроме того, мы не знаем, какая часть неприязни к .. = может быть подсознательными (или сознательными) попытками найти проблемы с вещами, которые не являются ....)

Ни одного от меня. Это своего рода обвинение в недобросовестности.

Кроме того, отсутствие синтаксиса включающего диапазона не позволит использовать их в сопоставлении.

Шаблоны включающего диапазона уже поддерживаются в match . Фактически, это единственный вид диапазона, который мы сегодня поддерживаем в качестве шаблонов.

@withoutboats да, но я сказал, что «отсутствие синтаксиса включающего диапазона не позволит использовать их в матче». Прямо сейчас есть синтаксис, но мой аргумент был против .inclusive() потому что его нельзя было использовать в сопоставлении, если у нас не было экстракторов, таких как Scala. и вся суть этой проблемы в том, что синтаксис включающего диапазона не должен быть особым случаем, который работает только в сопоставлении и для определения того, каким должен быть синтаксис вместо текущего.

Включено: for i in 1..10! { }

Как человек, который работает с Java / C / C ++ более 15 лет, я считаю, что .. vs ... довольно сбивает с толку и может вызывать ошибки просто из-за ошибок при вводе. Отношение к Ruby делает это еще более запутанным. Вот почему лучше ..= или любая другая альтернатива.

кидаю свою шляпу на ринг:

for i in 1..10^

Шляпа / каретка, обозначающие, что правильное значение идет полностью _up_.

@leebenson Лично я думаю, что было бы лучше, если бы он был посередине, а не прикреплен снаружи.

for i in 1..^10

@ retep998 Я

@ retep998 Мне нравится ваше предложение ..^ намного лучше, чем ..= ; он кажется гораздо более выразительным по своему значению, и он избегает выглядеть как странный вариант оператора расширенного присваивания (например, += и *= ). Тем не менее, любой из них будет намного лучше, чем ... .

Я не могу отстать от ..^ .

На личном уровне я считаю это очень уродливым (отчасти потому, что .. так вертикально не пересекается с ^ во многих шрифтах).

Как пользователь UI / UX, я думаю, что это пример того, что вы слишком умны для вашего же блага.

Если я приду с другого языка и увижу ..^ , я могу даже не распознать его как диапазон (насколько я знаю, 5..^15 может быть каким-то странным частичным факториальным сокращением для 15! - 4! ), потому что люди мыслят контекстами, и единственная ассоциация, которую персонаж имеет в контексте основного программирования, - это возведение в степень.

(Если бы мы не думали в контексте, ... могло бы означать что-то вроде «здесь вставлен обратный вызов» или «испускает событие» по аналогии с его значением «контент пропущено» в диалоге в написании прозы, просто для того, чтобы покажите самый непосредственный пример. Придавать ему значение "идет вверх" за счет его сходства со стрелой - все равно что делать магические трюки с помощью ловкости рук, поскольку она взаимодействует с ожиданиями новичка.)

Напротив, = имеет прецедент для ссылки как на действие присваивания, так и на концепцию равенства, и нет никакого "странного синтаксиса возведения в степень" -подобного заблуждения для ..= потому что самое близкое, к которому вы можете добраться " «присваивание + равенство», которое еще не обрабатывается оператором присваивания, является «чем-то, что связано с последовательностью чисел, заканчивающейся справа» ... что является расплывчатым, но подходящим определением того, что делает синтаксис диапазона.

Я также беспокоюсь, что, даже если бы я узнал, что ..^ был синтаксисом диапазона из его использования в контексте, у меня не было бы интуитивного представления, было ли оно включающим или исключающим сначала, потому что для ^ нет смысла 2..^8 является сокращением для открытого диапазона, начинающегося с двух и переходящего в степень 8 на предыдущем шаге (т. Е. 2..Inf^8 в отличие от 2..+8 , сокращенного для "итерация от 2 до бесконечности с шагом 8".)

Этой проблемы также позволяет избежать ..= потому что люди привыкли думать в терминах < (исключая) против <= (включительно) при написании while циклов. и циклы for стиле C.

@ssokolow законный анализ.

Лично я могу обойтись либо ..= либо ..^ . Для меня имеет смысл символизировать либо «до и равно», либо просто «до» соответственно. На мой взгляд, они оба означают одно и то же.

Будет сложно придумать что-то, что удовлетворило бы всех, потому что все мы приносим историю с других языков и вместе с ней испорченные символы / предвзятость. Сначала я добавил знак ^ _after_ числа, например, потому что вставка перед имела ощущение «шага» или экспоненты, тогда как суффикс оставлял диапазон незапятнанным и каким-то образом более чистым ощущением. Но это только я.

В любом случае, я бы предпочел сокращенную нотацию в некоторой форме вызову функции, которая неявно +1 к правому значению. Я согласен с предыдущими комментариями, что это слишком распространенный синтаксис, чтобы делегировать что-то, похожее на вызов функции. Я бы даже не возражал против ... , но согласен, это, вероятно, ошибка = / == в новой одежде, и она должна выстрелить кому-то в ногу ...

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

Ненавижу даже упоминать об этом, потому что это просто больше шума, но как насчет .:
(точка с двоеточием) для включения? Это 3 точки, но 2 символа, и я думаю, что
форма делает его отличным от ..

В сб, 18 марта 2017 г., в 11:50, Ли Бенсон [email protected]
написал:

@ssokolow https://github.com/ssokolow законный анализ.

Лично я могу отставать либо .. =, либо .. ^. Символика либо
имеет смысл для меня - т.е. «до и равно» или просто «до»,
соответственно. На мой взгляд, они оба означают одно и то же.

Будет сложно придумать что-то, что удовлетворило бы всех,
потому что все мы приносим историю с других языков и вместе с ней испорчены
символика / смещение. Сначала я добавил знак ^ после числа, так как
пример, потому что вставка перед имела ощущение «шага»
или экспонента, тогда как суффикс оставлял диапазон незапятнанным и как-то более чистым
чувство. Но это только я.

В любом случае, я бы предпочел сокращенную запись в какой-либо форме, а не
вызов функции, которая неявно +1 к правому значению. Я согласен с ранее
комментирует, что это слишком распространенный синтаксис, чтобы делегировать его чему-то, что
похоже на вызов функции. Я бы даже не возражал ... но, конечно, это
вероятно, ошибка = / == в новой одежде и обязательно выстрелит в кого-нибудь в
ступня...

-
Вы получили это, потому что прокомментировали.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-287566556 ,
или отключить поток
https://github.com/notifications/unsubscribe-auth/AIhJ6jWgPwndKaQvVjULlV_OoC6WDO0Cks5rnCeLgaJpZM4F4LbW
.

О, это все еще в фазе раздачи велосипедов? 😆

Читая назад, я думаю, что согласен с @nikomatsakis, чтобы просто сделать это ..= и положить конец этому. Сходство .. ... слишком тонкое, и я бы предпочел, чтобы токен ... использовался без двусмысленности для вариативных дженериков (https://github.com/ rust-lang / rfcs / pull / 1935), где он выполняет очень четкую цель, которая должна вести к меньшему путанице между ними.

Я не уверен, сохраняется ли потребность в более обобщенном синтаксисе для всех полуоткрытых вариантов, но я думаю, что не стоит прилагать усилия для предоставления синтаксиса языка за пределами .. и ..= .

Ненавижу даже упоминать об этом, потому что это просто больше шума, но как насчет.: (Точка с двоеточием) для включения?

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

Я лично не возражаю против наличия третьей точки, кроме того, что знаю, что она обязательно сбивает с толку некоторых людей. Но это также очень легко объяснить, поэтому я не уверен, что ответственность за разработку умных обходных путей должна лежать на языке. Исключительно 2 точки; 3 точки включительно 'действительно _это_ трудно понять / отладить?

В любом случае - кто принимает окончательное решение и что делать дальше, чтобы закрыть его? 18 месяцев обсуждения третьего персонажа, вероятно, на данный момент _is_ велосипедная распродажа 😄

Согласен, ^ делает его похожим на ступеньку.
ИМО, несоответствие с другими операторами op= не является проблемой, потому что у нас никогда не будет a ..= b в смысле a = a .. b , поскольку .. является не оператор, а синтаксический сахар для создания Range (и у нас нет общей схемы перегрузки операции, где любая операция автоматически получает форму op= и .. ).
Я не говорю, что ..= понятно без просмотра документа. Но как только люди посмотрели документ, его легче запомнить, и им все равно придется смотреть документ.

Учитывая кандидатуру @nikomatsakis , я думаю, что в конечном итоге мы обсудим это на собрании lang-team на следующей неделе и, вероятно, позвоним в этот момент. Я согласен с тем, что для этого нужна команда lang, чтобы позвонить и прекратить разборку велосипедов.

Я также беспокоюсь, что, даже если бы я узнал, что ..^ был синтаксисом диапазона, исходя из его использования в контексте, у меня сначала не было бы интуитивного представления, было ли оно включающим или исключающим.

Согласованный. Фактически, я уже видел этот синтаксис в Perl 6, где он означает эксклюзивный, противоположный предложенному здесь предложению.

@solson Это очень веский аргумент против.

Perl, похоже, имеет полностью общий синтаксис, включающий .. значение (на обоих
сторон) и ^ с обеих сторон делают эту границу исключительной.

В сб, 18 марта 2017 г., в 18:51, Джош Триплетт [email protected]
написал:

@solson https://github.com/solson Это очень веский аргумент
против этого.

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-287580739 ,
или отключить поток
https://github.com/notifications/unsubscribe-auth/AAC3n7Fnn1_t9BkYOhfS-7oCaGlVff2aks5rnF_5gaJpZM4F4LbW
.

Итак, я сожалею, но когда мы обсуждали этот вопрос на встрече @ rust-lang / lang, нам не удалось достичь консенсуса. В частности, у

Некоторые основные моменты, которые мы обсудили:

  • Если у нас есть синтаксис включающего диапазона в выражениях и шаблонах, он должен быть таким же

    • то есть, если мы примем x ..= y , это означает отказ от существующего синтаксиса шаблона x...y .

  • Заманчивый вариант - «ничего не делать» и просто написать (x..y).inclusive() или что-то в этом роде. Однако это не будет работать в шаблонах (которые предположительно останутся как x...y ). Это само по себе вызывает некоторые вопросы:

    • Хотим ли мы по-прежнему эксклюзивные образцы диапазона ? например, match 3 { 1..3 => false, .. }



      • Если так, то у нас такая же потенциальная путаница!



    • @withoutboats, кажется, думает, что, возможно, нам не нужны такие шаблоны. Я и @joshtriplett сомневались в этом; Я думаю, у нас обоих было мнение, что они кажутся неуместными до тех пор, пока они вам не понадобятся, а затем они почувствуют себя абсолютно необходимыми . знак равно

  • Другая проблема, связанная с шаблонами эксклюзивного диапазона, заключается в том, что они плохо взаимодействуют с (также нестабильными) шаблонами срезов (подробности см. На https://github.com/rust-lang/rust/issues/23121).

Я думаю, что одна вещь, которая вышла из этой дискуссии, заключалась в том, что было бы хорошо принять решение сразу по всем конфликтующим факторам . Другими словами, принять решение, устанавливающее:

  • Что делать с выражениями исключительного диапазона?
  • Должны ли мы отказаться от / изменить существующие шаблоны исключительного диапазона ?
  • Что делать с паттернами инклюзивного диапазона ?
  • Что делать с узорами срезов ?

Прежде чем я начну писать, я хочу сказать, что чувствовал себя очень неуверенно, что в каждый момент разговора мы все на самом деле говорили об одной и той же концепции. Например, Нико говорит, что «шаблоны исключительного диапазона кажутся неуместными до тех пор, пока они вам не понадобятся», но я подумал, что в то время Нико и Джош говорили о выражениях включающего диапазона.

(И я думаю, что в последней части сообщения Нико первый маркер, который в настоящее время читает «выражения исключительного диапазона», должен содержать «выражения включающего диапазона».)

TL; DR мое мнение

О выражениях диапазона:

  • Мы не должны вводить какой-либо синтаксис для выражений включающего диапазона - ни ... ни ..= .
  • Мы должны добавить в прелюдию функцию, которая принимает значение исключительного диапазона и возвращает значение включающего диапазона. Таким образом, вы должны написать inclusive(0..10) (имя может быть изменено на велосипед).

О моделях диапазона:

  • Мы не должны вводить эксклюзивные шаблоны диапазонов или каким-либо образом создавать их.

Другими словами, единственное существенное изменение, которое мы должны сделать, - это изменение библиотеки: добавить функцию в прелюдию.

Выражения диапазона

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

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

В частности, недостатком каждого синтаксического решения является то, что ни одно из них на самом деле не является самодокументированным. Относительно неочевидно, что 0...10 или 0..=10 является выражением включающего диапазона. Поскольку они будут встречаться относительно нечасто, это станет камнем преткновения для пользователей, которые сталкиваются с ними впервые.

То есть, если пользователь даже замечает, что он не имеет дела с «нормальным» диапазоном .. . Конечно, это большая проблема с ... , но ..= не устраняет проблему полностью. Легко, просматривая код, пропустить этот символ = (или ^ или : или что-то еще). Не так просто, как лишние . , но я не уверен, что это достаточно заметно.

На самом деле я думаю, что существует компромисс между ... и ..= "заметность vs очевидность". Я думаю, что это более очевидно, что означает ... (если вы не пришли из Ruby, где два синтаксиса имеют противоположное значение), чем ..= , но это определенно менее примечательно .

Но я думаю, что такая функция-прелюдия, как inclusive(0..10) более очевидна и заметна, чем любой синтаксис, который мы обсуждали. Да, нужно набирать больше символов, но обратная сторона этого атрибута связана с частотой использования.

Он также обходит любые проблемы синтаксического анализа и токенизации и помогает пользователям с (очень раздражающей) проблемой приоритета диапазона и метода, которая требует, чтобы они написали (0..10).filter и тому подобное.

Шаблоны диапазонов

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

Вторая причина в том, что я считаю их довольно плохим стилем (я знаю, что другие люди с этим не согласны). Например:

if let 1..10 = x { .. }

Я думаю, это сбивает с толку, потому что 10 не соответствует шаблону, который его содержит. Нико упомянул, что это на самом деле не отличается от выражений исключительного диапазона, не дающих 10 , но я думаю, что большая разница в том, что у нас есть большой исторический прецедент (и вариант использования) в стиле Дийсктра для поддержки исключительных диапазоны. Приступая к работе с Rust, я ожидал, что итеративные и срезные диапазоны будут исключительными, но я не ожидал этого от шаблонов.

У него также есть проблема «поодиночке», которая есть у .. / ... в выражениях.

Я знаю, что Нико упомянул, что хотел бы написать:

match x {
    0..10 => { ... }
    10..20 => { ... }
}

Но я бы очень предпочел увидеть:

match x {
    0...9 => { ... }
    10...19 => { .. }
}

В любом случае, я был удивлен тем, что Нико имел в виду, что иногда он находит это «абсолютно необходимым», поэтому я хотел бы услышать больше контраргументов. Поскольку они должны быть constexpr, для меня это больше похоже на «приятно иметь», чем на «абсолютно необходимую» вещь.

Мне определенно легче повлиять на эксклюзивные образцы диапазона, чем на выражения включающего диапазона.

Аргумент непротиворечивости

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

Действительно, нет даже подключения к реализации: 1..10 производит значение Range, тогда как 1...10 соответствует целочисленному значению. Это не похоже на то, что у них есть связь структурирования / деструктурирования, как это делает большинство наших синтаксисов симметричных выражений / шаблонов.

С технической точки зрения более правильно называть шаблоны «шаблонами домена», чем «шаблонами диапазонов» 🤓, что подчеркивает их неаналогичность.

@withoutboats

Например, Нико говорит, что «шаблоны исключительного диапазона кажутся неуместными до тех пор, пока они вам не понадобятся», но я подумал, что в то время Нико и Джош говорили о выражениях включающего диапазона.

Со своей стороны, я обнаружил, что в разное время необходимы как эксклюзивные, так и включающие диапазоны (хотя я использовал эксклюзивные для обоих случаев для работы на стабильном Rust, и мне пришлось обойти это с помощью +1 в верхнем граница). Я бы хотел, чтобы они были доступны как для шаблонов, так и для выражений.

Тем не менее, лично у меня не было бы возражений против использования функции для инклюзивных диапазонов, за исключением того, что я действительно хочу иметь способ записывать как включающие, так и исключительные диапазоны в шаблонах , и я бы хотел, чтобы эти два синтаксиса не выглядели похожими до смущения. как .. и ... do. И учитывая синтаксис для записи таких диапазонов в шаблоны, я не знаю, имеет ли смысл иметь другой синтаксис для таких диапазонов в выражениях.

В частности, недостатком каждого синтаксического решения является то, что ни одно из них на самом деле не является самодокументированным. Относительно неочевидно, что 0 ... 10 или 0 .. = 10 является выражением включающего диапазона. Поскольку они будут встречаться относительно нечасто, это станет камнем преткновения для пользователей, которые сталкиваются с ними впервые.

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

Я бы не возражал, например, если бы для написания шаблона включающего диапазона требовался макрос или что-то подобное.

@joshtriplett Вот где я хочу прояснить, когда вы говорите следующее:

Я обнаружил, что в разное время необходимы как эксклюзивные, так и включающие диапазоны (хотя я использовал эксклюзивные для обоих случаев для работы над стабильным Rust, и мне пришлось обойти это с +1 в верхней границе).

Кажется очевидным, что вы говорите о выражениях , но процитированный вами раздел был о шаблонах (я знаю, что вы говорите о шаблонах в следующем абзаце, но я спрашиваю о проблеме «необходимости», которую этот абзац не затрагивает 😃) .

Статус-кво для шаблонов таков, что мы поддерживаем только шаблоны с включенным диапазоном в форме x...y . Не могли бы вы рассказать больше о том, если / когда вы обнаружили, что исключительные паттерны диапазона действительно разочаровывают, и не иметь их?

@withoutboats

Не могли бы вы рассказать больше о том, если / когда вы обнаружили, что исключительные паттерны диапазона действительно разочаровывают, и не иметь их?

Что-то типа

    match offset {
        0x0200 .. 0x0280 => { /* GICD_ISPENDR<n> */ }
        0x0280 .. 0x0300 => { /* GICD_ICPENDR<n> */ }
        0x0300 .. 0x0380 => { /* GICD_ISACTIVER<n> */ }
        0x0380 .. 0x0400 => { /* GICD_ICACTIVER<n> */ }
        0x0400 .. 0x0800 => { /* GICD_IPRIORITYR<n> */ }
    }

против

    match offset {
        0x0200 ... 0x027C => { /* GICD_ISPENDR<n> */ }
        0x0280 ... 0x02FC => { /* GICD_ICPENDR<n> */ }
        0x0300 ... 0x037C => { /* GICD_ISACTIVER<n> */ }
        0x0380 ... 0x03FC => { /* GICD_ICACTIVER<n> */ }
        0x0400 ... 0x07FC => { /* GICD_IPRIORITYR<n> */ }
    }

Я бы не сказал, что это особенно неприятно, но первый, безусловно, выглядит лучше.

@withoutboats Для ясности, в разное время мне требовались выражения исключительного диапазона, выражения включающего диапазона и шаблоны включающего диапазона. Я не могу сразу вспомнить время, когда я глубоко заботился об эксклюзивных моделях диапазона, хотя я также не стал бы возражать против них. Но даже если у нас нет шаблонов исключительного диапазона, я бы все равно очень запутался, если в шаблонах включающего диапазона используется ... а в выражениях исключительного диапазона используется .. .

@petrochenkov Я предполагаю, что они должны были заканчиваться на F , а не на C ?

Я столкнулся с тем же случаем с шаблонами шестнадцатеричных диапазонов, например, 0x8000...0x9FFF => /* body */ . Я обнаружил, что 0x8000..0xA000 имеет чуть более интуитивные свойства, например, не задумываясь об этом, я сразу вижу, что размер диапазона равен 0xA000 - 0x8000 = 0x2000 а следующий соседний диапазон начинается с 0xA000 .

Работа с +1 необходимыми для просмотра этих фактов в инклюзивном диапазоне, - небольшая разница, с которой я могу жить, но эксклюзивные диапазоны (как шаблоны, так и выражения) обычно лучше подходят для моей работы.

@petrochenkov Я понимаю, почему вы предпочитаете эксклюзивные диапазоны для шестнадцатеричных цифр (я все еще не могу, но это похоже на сделку в стиле YMMV).

Но как бы мы справились с неоднозначностью синтаксиса фрагментов?

@joshtriplett

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

Вот как работает Rust сегодня, и это не кажется серьезным источником путаницы?

@solson

Я полагаю, они должны были заканчиваться на F, а не на C?

Нет :)
(Эти вещи 32-битные, а offset кратно четырем.)

@withoutboats

Я понимаю, почему вы предпочитаете эксклюзивные диапазоны для шестнадцатеричных цифр (я все еще не могу, но это похоже на сделку в стиле YMMV).

Я должен отметить, что это не сильное предпочтение, я все равно согласен отказаться от как эксклюзивных шаблонов, так и инклюзивных диапазонов (но не одного из них, это было бы слишком смешно).

Но как бы мы справились с неоднозначностью синтаксиса фрагментов?

Без труда! PATTERN.. => .. @ PATTERN

Моя основная причина, по которой я хочу, чтобы инклюзивные диапазоны были простыми, заключается в том, что я неоднократно сталкивался с ситуациями, когда я передаю стоп-значение в переменной, и это именно максимальное значение, которое может содержать один тип переменной, поэтому единственные решения чтобы исключить переполнение во время компиляции:

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

Выработка привычки использовать инклюзивные диапазоны вместо добавления + 1 к алгоритму, где он не имеет внутренней цели, является нетривиальным способом защиты от повторного появления их позже в cargo fuzz ... и использования функция «сделать включающую из эксклюзивной» с большим количеством символов в ее имени, чем + 1 создает впечатление, что включающие диапазоны - это нечто исключительное, а не то, что вы должны обычно использовать.

Это одна из главных причин, по которой я против. Создается впечатление, что инклюзивные диапазоны - это уловка, которую следует использовать, когда доказывается, что исключительные диапазоны потерпели неудачу.

@ssokolow, но этот вариант использования удобно покрывается функцией прелюдии. Никто не считает, что iit не может создавать инклюзивные диапазоны, независимо от того, должны ли они иметь синтаксический сахар для их создания.

Мне нравится идея @withoutboats с функцией прелюдии. Я думаю, что другое место, где инклюзивные диапазоны могут быть более распространенными, - это когда вы не используете целые числа, например, путем указания границ поиска в btree (или аналогичной структуре данных).

@withoutboats Я немного отредактировал свой пост, пока вы отвечали, но суть того, что я добавил, заключается в том, что инклюзивные диапазоны становятся гражданами второго сорта, синтаксически (с синтаксисом длиннее, чем добавление + 1 в эксклюзивный диапазон ), ощущается как легкое разочарование против их использования и возможное «Увидимся в cargo fuzz позже».

По крайней мере, это бородавка обучаемости.

Rust - это не Python 3.x с его неограниченной поддержкой целых чисел. Rust не скрывает аппаратных компромиссов от пользователей, и я вижу ..= я предпочитаю, как часть использования u32 и друзей вместо int . (Особенно с учетом того, что ошибки переполнения / потери значимости до сих пор являются наиболее частой проблемой в "трофейном кейсе" cargo fuzz .)

РЕДАКТИРОВАТЬ: пожалуйста, игнорируйте любые биты, которые вы видите только в уведомлениях по электронной почте. Я только что проснулся и еще не стреляю на всю катушку.

Я вообще не считаю inclusive(n..m) разочарованием ... Я бы предпочел написать это, потому что это очень четкая конструкция, которая упрощает чтение моего кода, чем n..(m + 1) и n..=m (который я считаю излишне странным, когда мы могли бы просто сказать слово «включающий»).

n..=m - это скорее бородавка обучаемости, чем inclusive(n..m) IMO.

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

Предположительно, если бы существовал синтаксис «продолжить с предыдущего», это также решило бы проблему.

Кстати, поскольку совпадает только первый шаблон, начальный номер часто можно опустить:

    match offset {
        0 ... 0x01FF => {}
        0 ... 0x027C => { /* GICD_ISPENDR<n> */ }
        0 ... 0x02FC => { /* GICD_ICPENDR<n> */ }
        0 ... 0x037C => { /* GICD_ISACTIVER<n> */ }
        0 ... 0x03FC => { /* GICD_ICACTIVER<n> */ }
        0 ... 0x07FC => { /* GICD_IPRIORITYR<n> */ }
    }

Я допускаю, что это может быть вопросом перспективы, но:

  1. Когда я вижу .. и ..= , я думаю: «Ага. Интересно, почему у них есть два синтаксиса для такой небольшой разницы», и тогда я начал бы искать документы, на которых можно было бы сосредоточиться « 1..pivot и pivot..end » против « x..=y где y может быть максимально возможным значением».

  2. До того, как я набрался опыта, чтобы привыкнуть думать о размерах переменных, я бы просто использовал + 1 over inclusive() (если бы я даже искал его), потому что я использовал + 1 с начальной школы, он короткий и простой, а мой неопытный я привык работать на таких языках, как Python и JavaScript, где добавление, вызывающее переполнение, не является чем-то, о чем люди беспокоятся.

РЕДАКТИРОВАТЬ: ... и это то концептуальное различие в пункте 1, на котором, я думаю, мы должны сосредоточиться. (то есть, что «от X до точки поворота» и «от X до конца» должны различаться в уме программиста.)

@pornel
Это ужасно
В этом конкретном случае начало диапазона действительно очень важно для человека, читающего код, гораздо важнее, чем любые вопросы включения / исключения диапазона.

@ssokolow мне кажется, что проблема +1 заключается не в количестве символов, а в том, что вы должны справиться с возможностью переполнения. Кроме того, он также не передает намерение и требует согласования приоритетов. Все это кажется гораздо более важным, чем количество символов.

Это правда, что тот, кто не знает о переполнении, может достичь +1 перед созданием включающего диапазона, но это, похоже, не зависит от синтаксиса. Оба открытия, что ..= - это вещь, а inclusive() - вещь, представляют собой поучительный момент для изучения того, почему вам нужны именно инклюзивные диапазоны.

@petrochenkov

Я все равно согласен отбросить как эксклюзивные шаблоны, так и инклюзивные диапазоны (но не один из них, это было бы слишком смешно) .

Не могли бы вы подробнее рассказать, почему вы так сильно относитесь к этому? Я определенно вижу, что принятие эксклюзивных шаблонов имеет только обратную сторону, поскольку это может привести к тому, что пользователи будут ожидать 0...10 в качестве выражения, но мне это не кажется таким уж плохим .

Частично моя проблема с inclusive() заключается в том, что это «просто» функция, и я беспокоюсь, что люди будут делать такие вещи, как переход к индексу синтаксиса Rust, поиск «диапазона» или «итератора», а затем предполагая недостаточную рентабельность инвестиций. для "См. [ing] Итераторы".

(«Я не хочу читать учебник на случай, если найду что-нибудь полезное ... Я просто хочу перебрать диапазон и вернуться к прогрессу».)

@withoutboats Если у нас есть инклюзивный (a..b), но мы не можем использовать его в матче, это того не стоит, ИМО.
В большинстве случаев, когда я использую инклюзивные диапазоны, это связано с шаблонами совпадений!
Так почему мы не можем удалить ... и просто использовать ..= внутри и вне совпадения?

@Boscop предложение состоит не в том, чтобы удалить ... в совпадении, а в том, чтобы оставить шаблоны в точности такими, как они есть в стабильной версии.

@ssokolow кажется, что это можно довольно легко решить с помощью примечания в разделе ..

@withoutboats Но почему бы не удалить ... в совпадении и использовать вместо него ..= , чтобы это было согласованно?
(чтобы внутри и вне совпадения было ..= )

Исключительные подсказки для охвата числового диапазона с плавающей запятой. Например, одна из этих границ покрывается полностью, а другая - нет:

match x {
    0.0...3.141592653589792 => 1,
    3.141592653589793...6.283185307179585 => 2,
    6.283185307179586...10.0 => 3,
    _ => 4,
}

И писать его с перекрытиями вместо этого кажется неприятным (и морально похоже на «просто начинайте все с -∞, так как руки заказаны» выше). См. Также дату и время, например, как ISO8601 допускает T24: 00, поскольку день равен [00:00, 24:00), а не [00:00, 23:59:59]. Или строки, или рациональные числа, или ...

Если у меня есть выбор: только эксклюзив или только включено, я всегда буду брать эксклюзив.

(Кроме того: шаблон 1 <= x <= N для индексации на самом деле лучше сделать как 0 < x <= N , который также является эксклюзивным - хотя и наполовину закрытым, а не полуоткрытым - по тем же причинам, по словам Дейкстры, просто переключился на индексацию на основе 1 вместо 0.)

Этот оператор был бы очень полезен для функции зажима, которую я предложил здесь: https://github.com/rust-lang/rfcs/pull/1961, однако, поскольку это не было стабилизировано, мне, вероятно, придется изменить это предложение, чтобы вместо этого используйте два аргумента min и max. InclusiveRange также очень полезен при работе со значениями с плавающей запятой, поэтому нам не нужно делать что-то вроде:

0,0..1,0 + ЭПСИЛОН

Я даже не уверен, что это правильно, но сейчас очень сложно объявить исчерпывающий диапазон чисел с плавающей запятой.

Правильный способ сделать это - использовать nextafter , а не epsilon. т.е. x...y == x..nextafter(y) . ящик ieee754 предоставляет такую ​​функциональность

Упс, я прокомментировал синтаксис inclusive(a..b) но понял, что это неправда. В любом случае, мне это нравится, но я надеюсь, что мы сможем придумать название получше.

@durka Имя мне кажется понятным. Можете ли вы подробнее рассказать о том, что вас беспокоит?

Итак, для инклюзивных диапазонов у нас будет a ... b в match и inclusive(a..b) вне совпадения?
Почему мы не можем быть последовательными и иметь везде a ..= b ?

Есть ли что-нибудь, что препятствует формальной стабилизации ops::{RangeInclusive, RangeToInclusive} ?

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

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

Одна вещь, которую я заметил на днях по поводу RangeInclusive : это боль, если вы пытаетесь принять диапазон. В потоке зажима говорилось о разрешении .clamp(1...9) , но в итоге код выглядел примерно так:

    fn clamp(self, r: RangeInclusive<Self>) -> Self where Self : Sized {
        match r {
            RangeInclusive::Empty { .. } =>
                panic!("Cannot clamp to an empty range"),
            RangeInclusive::NonEmpty { start, end } => {
                assert!(start <= end, "Cannot clamp to a degenerate range");
                if self < start { start }
                else if self > end { end }
                else { self }
            }
        }
    }

Необходимость иметь дело с RangeInclusive::Empty кажется ненужным, поскольку цель состоит в том, чтобы просто принять пару с хорошим синтаксисом. Если бы это не было перечисление, это могло бы быть просто fn clamp(self, RangeInclusive { start, end }: RangeInclusive<Self>) и намного чище.

К сожалению, у меня нет хорошего ответа о том, что с этим делать, поскольку требование .into_iter () для включения, но не исключающего, также было бы неудачным ...

Случайная идея: видя, что синтаксис шаблона ... самом деле не связан с типами включающего диапазона, мы могли бы рассмотреть возможность отказа от его синтаксиса в пользу одного, не связанного с предложенными здесь ... .

Поскольку модель включительно диапазон более тесно связан с | шаблон, |... может быть хорошим кандидатом:

match {
    1 | 2 | 3 => ...
    1 |... 3  => ...
}

Конечным результатом будет то, что синтаксис включающего и исключительного диапазона больше не имеет отношения 1: 1 к сопоставлению с образцом и, следовательно, не должен соответствовать ему.

@scottmcm

К сожалению, у меня нет хорошего ответа о том, что с этим делать, поскольку требование .into_iter () для включения, но не исключающего, также было бы неудачным ...

Может быть, мы могли бы добавить помощника, например range.nonempty() который паникует из-за пустого диапазона и возвращает пару?

В качестве альтернативы мы могли бы реализовать IntoIterator для RangeInclusive и это было бы не так уж далеко, ИМХО.

Какой вариант использования обслуживает RangeInclusive :: Empty? Почему для инклюзивного диапазона нужна возможность представлять пустой диапазон? Как бы вы его написали? (Обратите внимание, что вы уже можете писать такие вещи, как «диапазон от 5 до 4 включительно», и эта итерация предположительно будет считаться пустой.)

@joshtriplett основной случай - переполнение, хотя есть способы решить эту проблему.

@joshtriplett start > end самом деле не работает для представления пустого включающего диапазона в одном важном случае: 0u8...255u8 . Когда вы дойдете до 255u8...255u8 и попытаетесь .next() это, вы либо запаникуете, либо перейдете к 0u8...255u8 , которое не пусто. Поэтому вместо этого мы переключаемся на вариант Empty в этот момент.

@solson А, понятно. Да, это боль, и это одна из самых больших случаев использования инклюзивных диапазонов.

(Я предполагаю, что вы имеете в виду 255u8 во всех этих случаях.)

(Я предполагаю, что вы имеете в виду 255u8 во всех этих случаях.)

Да спасибо. Отредактировано.

@solson, однако, этот случай можно исправить, поменяв местами 0 и 255 в этом случае

@clarcharr Это правда. Поскольку .next() всегда создает особый случай для генерации диапазона Empty , он всегда может сгенерировать диапазон, который будет считаться пустым.

Лично мне этот способ нравится больше, потому что он не включает пустой диапазон.

Так что эта ветка продолжается уже полтора года. Я только что закончил читать все это и хотел бы опубликовать краткое резюме для новичков и, надеюсь, помочь нам принять решение:

Что делает Rust Stable сегодня:

0..5 представляет собой полуоткрытый диапазон [0, 1, 2, 3, 4], который нельзя использовать в сопоставлении с образцом.
0...5 представляет собой закрытый диапазон [0, 1, 2, 3, 4, 5], который может использоваться только при сопоставлении с образцом.

Было предложено несколько форм для дополнительного синтаксиса закрытого диапазона, который можно использовать вне сопоставления с образцом. Я расскажу о каждом из них, а также о их преимуществах и недостатках.

0...5

Плюсы: соответствие существующему синтаксису сопоставления с образцом делает язык более связным, если в синтаксис сопоставления с образцом не вносятся изменения.

Минусы: легко опечататься и вызвать одну ошибку, также легко неправильно понять цель из-за того, что другие языки используют этот оператор для передачи различных концепций.

0..=5

Плюсы: труднее опечатать, семантически понятнее.

Минусы: несовместимы с существующим синтаксисом сопоставления с образцом. Может вызвать у пользователей вопрос: почему это ... здесь, а ... = здесь?

0..^5

Очень похоже на ..= но имеет дополнительный недостаток в том, что он выглядит как оператор возведения в степень.

inclusive(0..5)

Плюсы: Чрезвычайно семантически понятный. Не ошибусь.

Минусы: вроде как долго. Также несовместимо с синтаксисом сопоставления с образцом.

0....5

Плюсы: также позволяет избежать ошибки при вводе ...

Минусы: плохая семантика, несовместимая с синтаксисом сопоставления с образцом и похожая на синтаксис сопоставления с образцом.

[0..5] . скобки уже имеют синтаксическое значение в языке.

0..<=5 . Конфликт с существующим синтаксисом для сравнения значения с диапазоном.

Каждый из перечисленных вариантов, который имеет недостаток «несовместим с синтаксисом сопоставления с образцом», можно было бы улучшить, если бы мы изменили синтаксис сопоставления с образцом, но этот маршрут имеет проблемы с обратной совместимостью. В качестве альтернативы мы могли бы также сделать ... и (выберите здесь свой синтаксис) эквивалентом в сопоставлении с образцом, чтобы избежать нарушения обратной совместимости, но предотвратить использование ... вне сопоставления с образцом. Возможно, мы могли бы также обновить руководство по стилю, чтобы воспрепятствовать использованию ... в сопоставлении с образцом, если бы мы пошли по этому пути.

Также было некоторое обсуждение создания синтаксиса диапазона более общего назначения, который позволил бы вам сделать как верхнюю, так и нижнюю границы включительными или исключительными, но нам, вероятно, даже не нужен этот синтаксис, поскольку полуоткрытый и закрытый диапазон, вероятно, покрывает 99,9999% случаев использования.

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

@Xaeroxe Спасибо за отличное резюме.

Может быть, можно иметь инструмент (возможно, плагин rustfmt), который автоматически преобразует источники из использования ... в сопоставлении с шаблоном в новый синтаксис (например, ..= ), когда это будет принято.
Таким образом, нас не будет сдерживать «весь код, написанный по старинке».
Но это должно быть вызвано намерением авторов проекта, и на всех носителях ржавчины должно быть уведомление / заголовок, чтобы все знали об изменении.
С этими вещами, я думаю, нет проблем изменить синтаксис ... в сопоставлении с образцом на новый синтаксис.

Я думаю, что одна вещь, которую мы могли бы сделать, чтобы решить проблему с синтаксисом, - это просто стабилизировать RangeInclusive, как предложил @clarcharr . Это как минимум разблокирует людей.

Мы также могли бы добавить функцию inclusive (либо просто к std::range либо, возможно, также к прелюдии); это не мешает когда-нибудь иметь первоклассный синтаксис, но делает гораздо более удобным создание RangeInclusive прямо сейчас.

Однако все это похоже на решения библиотек, поэтому я не знаю, имеет ли команда lang юрисдикция принимать решение о стабилизации / добавлении этих элементов 😅.

Я лично предпочел бы преобразовать сам RangeInclusive во что-то, что не имеет варианта Empty , а затем сделать так, чтобы IntoIter имел этот вариант. Для меня это имеет больше смысла, учитывая, что практически невозможно создать пустой диапазон без ручного Empty { at } .

В качестве альтернативы поменяйте местами MAX и MIN в упомянутом мною крайнем случае. Это затрудняет написание более общего кода, включающего RangeInclusive , но это кажется разумным решением проблемы.

Независимо от того, что происходит, я очень поддерживаю стабилизацию типа в стандартной библиотеке, которая будет существовать независимо от синтаксических проблем. Это позволяет библиотекам писать стабильный код, который позволяет нарезать инклюзивные диапазоны, так что к тому времени, когда синтаксис стабилизируется, люди уже реализовали код, использующий типы. Синтаксис и типы не зря находятся под разными флагами функций.

@scottmcm Я согласен, что на данном этапе это, вероятно, должна быть отдельная тема.

Чтобы продолжить обсуждение синтаксиса, я предлагаю путь, который предпочел бы выбрать.

Мне больше всего нравится синтаксис ..= , поэтому я считаю, что мы должны добавить этот синтаксический сахар как равный ... в сопоставление с образцом и как InclusiveRange вне сопоставления с образцом. Затем, чтобы сохранить единообразие языка, мы должны попытаться перенести пользователей и их код на синтаксис ..= в шаблонах, используя объявления и автоматизированные инструменты. Как только мы почувствуем, что переместили достаточное количество пользователей из ... мы можем заставить его использовать предупреждение компилятора, а затем, в конечном итоге (возможно, даже через годы) ошибку компилятора.

Прошло 24 дня с момента подачи моего предложения, и никаких комментариев не было. Должны ли мы двигаться дальше по этому плану?

РЕДАКТИРОВАТЬ: На мобильном телефоне я не видел больших пальцев, поэтому не понимал, что существуют особые мнения.

@Xaeroxe Я так не думаю. Я не согласен с тем, что отказ от ... в пользу ..= является хорошим выбором по причинам, которые я уже опубликовал в этой ветке. Я не ответил на ваше конкретное предложение, потому что такая же идея уже была выдвинута и обсуждена. Единственное, что здесь ясно, это то, что у нас нет консенсуса. Думаю, многие из нас утомляются дискуссией.

РЕДАКТИРОВАТЬ: Чтобы быть более конкретным, я не хочу отказываться от ... в пользу ..= потому что:

  • Устаревший синтаксис - это огромные затраты на отток; даже если мне однозначно понравился ..= я не думаю, что стоит цикл устаревания только для того, чтобы получить включающие выражения диапазона в стабильной версии.
  • Не люблю ..= , считаю это неочевидным и непонятным; у него есть то преимущество, что он с меньшей вероятностью приведет к одной ошибке, но это не означает, что пользователь, увидев его впервые, будет знать, на что он смотрит.
  • Я не согласен с предположением, что здесь должна быть симметрия между шаблонами и выражениями, потому что они не выполняют никаких аналогичных операций структурирования / деструктурирования.

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

Я не могу прокомментировать стоимость прекращения поддержки из-за отсутствия у меня опыта работы с такими вещами. Однако я все еще поддерживаю ..= .

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

Однако наличие излишка специализированного синтаксиса может привести к тому, что язык будет больше похож на тупицу, чем мы хотим, чтобы Rust был. Поэтому мы должны быть осторожны, чтобы случаи, которые мы решили преобразовать в специальный синтаксис, на самом деле были достаточно распространены, чтобы того стоить. Если честно, теперь, когда я напечатал это, я не совсем уверен, что этот чехол того стоит. Потребность в инклюзивных диапазонах недостаточно высока, чтобы гарантировать синтаксис.

Однако меня до сих пор беспокоит непоследовательность. Наличие инклюзивной функции и ... в сопоставлении с образцом похоже на серое и серое на английском языке. Когда у нас есть возможность стандартизировать, часть меня чувствует, что мы должны это делать. Однако это изменение также сопряжено с серьезными материально-техническими проблемами. Если бы мы когда-либо спроектировали Rust 2.0 (это может быть безумием, я не имею ни малейшего представления), возможно, нам следовало бы вернуться к этому, но я думаю, что на данный момент достаточно и серого, и серого.

Я поддерживаю использование функции inclusive для экземпляров вне сопоставления с образцом и ... в сопоставлении с образцом в настоящее время.

@withoutboats

  1. Если вы никогда ничего не осуждаете, вы получите объединение всех (более или менее) плохих решений, таких как C ++. Это заставляет новичков узнавать еще больше, потому что все не так последовательно, как могло бы быть.
    Так что иногда имеет смысл отказаться от чего-либо, чтобы уступить место лучшему решению.

  2. это не означает, что пользователь, увидев его впервые, будет знать, на что он смотрит.

Так бывает с любым синтаксисом. У нас (знающих Rust) есть это предубеждение, потому что для нас код Rust кажется очевидным, но любой, кто приходит в Rust с другого языка, должен часто искать синтаксис. Это не изменится, если мы используем ..= или ... или любой другой синтаксис для инклюзивных диапазонов, потому что, например, другие языки используют ... для эксклюзивных диапазонов, поэтому им все равно придется его искать .
Нашей целью не должно быть введение только очевидных функций:
Если бы мы хотели иметь только очевидные функции, у нас не было бы большинства существующих функций в Rust. Новички все равно ДОЛЖНЫ посмотреть документ, что в этом плохого? Док хорош!


  1. Если вы заботитесь о том, чтобы свести к минимуму время, необходимое новичкам для просмотра документа, мы должны стремиться к симметрии между построением и сопоставлением инклюзивных диапазонов! (и другие конструкции)

Как сказал @withoutboats , я думаю, что многие из нас устали от этого обсуждения; Я, например, какое-то время просидел. Тем не менее, мне потребовалось время, чтобы перечитать (спасибо за резюме @Xaeroxe!) И пересмотреть свои мысли здесь.

ИМО, самая важная проблема сейчас - это неполная комбинация синтаксисов, которые мы предоставляем : ... в шаблонах, .. для выражений. Эта пара синтаксисах сильно приводит вас ожидать , что .. будет работать в шаблонах и ... в выражениях - и они этого не делают. Я считаю, что это ненадежный дизайн в долгосрочной перспективе, и очень хочу его исправить.

Я также думаю, что, учитывая, что мы предоставили синтаксис для обоих типов диапазонов, вероятно, лучше продолжать это делать. Это оставляет нам несколько вариантов:

  • Стабилизируйте ... в выражениях и добавьте .. в шаблоны. Это наименее болезненное изменение, но у него есть хорошо обсужденные недостатки в отношении единичных ошибок. Тем не менее, другие языки имеют такую ​​комбинацию и, насколько мне известно, не страдали от таких ошибок ужасно.

  • Устарело ... в шаблонах и выражениях, добавьте ..= к обоим и добавьте .. в шаблоны. Устраняет недостатки, указанные выше, является более болезненным (из-за устаревания) и открывает двери для других типов диапазонов (например, исключение слева) в будущем.

Здесь я в основном перефразирую обсуждение, и, честно говоря, я не думаю, что здесь можно много сказать; Я думаю, что мы выявили компромиссы, и нам просто нужна языковая команда, чтобы провести оценку и принять решение. Но основная направленность моего комментария - это начальная мысль о том, почему я думаю, что здесь нужно что- inclusive недостаточно, ИМО).

Тем не менее, другие языки имеют такую ​​комбинацию и, насколько мне известно, не страдали от таких ошибок ужасно.

Меня беспокоит предвзятость выбора. У нас нет надежного способа судить, являются ли проблемы незначительными или они просто редко попадают в наше внимание.

Кроме того, использование ... выглядит как противоречие с аспектом философии дизайна и появляющихся передовых практик Rust «избегать использования ножных ружей, если только компромиссы не слишком серьезны». (например, совет создавать новые типы enum вместо использования bool чтобы сложнее перепутать параметры вашей функции.)

Например, C доказал, что присваивание в операторах if полезно, если в языке нет while let , но было обнаружено, что при вводе = вы имели в виду == вполне достаточно для того, чтобы языки вроде Python отказались от него, даже если существуют ситуации, когда единственные альтернативы нехарактерно уродливы.

Если пойти в другом направлении, я заставил Клиппи поймать такой случай, когда я устал от кодирования около недели назад ...

foo == bar;  // This should be `foo = bar;`

... что кажется прекрасным примером ошибки типа "слишком много раз нажал клавишу", о которой мы здесь беспокоимся ... и, в отличие от " == не действует", здесь нет хорошего способа линтовать .. vs. ... .

@ssokolow Для ясности, меня тоже устраивает ..= ; Я не думаю, что отказ от поддержки будет таким болезненным, и это очень простое автоматическое исправление. В основном я просто хочу решить эту проблему.

Я, вероятно, смогу жить со стабилизацией .. / ... (которая уже реализуется по ночам). Я согласен с @aturon в том, что существующий язык предполагает, что это сработает.

Как я уже сказал, мне бы очень хотелось стабилизировать тип libstd при прохождении rust-lang / rfcs # 1980 без обсуждения синтаксиса.

Помимо того, что указал @aturon , возможно, было бы полезно объединить проблемы отслеживания как для этого, так и для синтаксиса эксклюзивного диапазона? Возможно, сделайте отдельную задачу отслеживания для типа и используйте это для стабилизации типа перед синтаксисом.

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

18 мая 2017 г. в 9:55:30 по тихоокеанскому времени Аарон Турон [email protected] написал:

Я повторно выдвигаюсь для обсуждения в группе языков. Я думаю это очень маловероятно
что при этом появятся существенно новые идеи или компромиссы.
точка. Нам нужно принять решение о компромиссах, которые
выложил.

Я собираюсь уехать на встречу на следующей неделе из-за конференции. Если это будет обсуждаться на собрании на следующей неделе, я выскажу свою поддержку любому решению, кроме ... , будь то ..= , inclusive или другое.

Пока мы занимаемся этим, стоит обсудить синтаксис отдыха / распространения.
Я голосую .. за исключительный диапазон, ... за включительно, .... за остаток / распространение.

take_range(..max); // exclusive range
take_range(...max); // inclusive range
take_multiple_args(....tuple); // spread
if let 0..10 = get_num() {} // exclusive range pattern
if let 0...9 = get_num() {} // inclusive range pattern
if let [first, ....rest] = get_slice() {} // rest pattern

Я бы проголосовал за ... за кусок отдыха по двум причинам:

  1. Люди, вероятно, уже знакомы с ... означающим "отдых", из таких языков, как CoffeeScript (CoffeeScript использует rest... в сигнатурах функций для varargs и называет их "splats") и английский (с использованием правильного Unicode кодовая точка или нет, это три периода, которые выглядят как многоточие, а не четыре, и люди неплохо понимают, что многоточие приблизительно означает «и есть еще кое-что, но мы не говорим это вслух» на английском языке, просто потому, что столкнулись с этим в использовании.)

  2. Если я что-то не упустил в синтаксисе Rust, использование .. и ..= для диапазонов, но ... для остальных фрагментов будет означать, что в любой ситуации ввод ... когда вы имели в виду .. или наоборот все равно будет ошибкой времени компиляции.

    Для этого я исхожу из двух предположений:

    1. То, что использование только синтаксиса rest (вне контекста распаковки последовательности) было бы запрещено как опечатывающее. (т.е. for _ in ...rest будет таким же, как for _ in rest если разрешено, но почти наверняка это опечатка.

    2. Использование открытого диапазона в качестве назначаемого шаблона было бы недопустимым. (т.е. let [first, ..rest] = будет недействительным.)

Тройная точка @ssokolow уже означает диапазон в шаблоне, поэтому изменение его на синтаксис отдыха было бы

@phaux Point. Я почему-то забыл об этом.

Возможно, что-нибудь, чтобы повесить метку «если мы когда-нибудь сделаем Rust 2.0».

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

Однако я считаю, что ... в шаблонах должно иметь выражения с обеих сторон ( a...b ), тогда как в остальном синтаксисе в качестве префикса используется ... , нет?

Команда lang снова обсудила эту функцию на нашей сегодняшней встрече и пришла примерно к следующей матрице:

  • Поддержка ... в шаблонах и .. в выражениях и ничего больше - это несостоятельный замысел; это заставляет пользователей ожидать, что синтаксис будет работать, но этого не произойдет.

  • Если разрешить ... и .. в обоих местах, это поможет, но проблема «поодиночке» вызывает серьезную озабоченность; никто из нас не хочет получать отчеты о людях, которые часами отслеживают ошибочный период.

  • Переход на ..= и .. менее эстетичен, но позволяет избежать реальных практических проблем, описанных выше. Мы также можем развернуть его очень осторожно: сначала введите ..= в качестве альтернативного синтаксиса (который rustfmt может переписать) и только после того, как он станет идиоматическим, объявите ... устаревшим.

Если вы не можете сказать точно, команда считает, что ..= и .. - наш лучший путь вперед. Этот вопрос также обсуждался до такой степени, что вряд ли возникнут новые аргументы, поэтому мы готовы сделать решительный шаг: мы ищем того, кто хотел бы реализовать нотацию ..= для обоих шаблоны и выражения, а потом перейдем к FCP!

С этой целью мы ищем кого-нибудь (или нескольких людей), которые продвинут вперед реализацию. Вероятно, это можно сделать с помощью ряда более мелких PR:

  • Для начала добавим в парсер ..= в качестве псевдонима для ... и преобразуем существующие тесты.

    • ... , конечно, должен продолжать работать, и мы хотим, чтобы это было "тихим" устареванием, чтобы не было необходимости выдавать предупреждения и т. Д. (Пока).

    • нам нужно, следовательно, держать тесты на шаблонах ...

    • Я думаю, что, вероятно, способ сделать это - изменить лексер , добавив токен DotDotEquals ( вот существующий DotDotDot ), а затем изменить синтаксический анализатор, чтобы он принимал DotDotEquals везде, где мы теперь примите DotDotDot ( пример )

    • ripgrep DotDotDot здесь ваш друг;)

  • ... в выражениях никогда не было стабильным, поэтому мы можем просто изменить его на ..= и убить старую поддержку

    • Чтобы быть добрыми к людям в дикой природе, мы могли бы пережить период устаревания, но я не уверен, что это необходимо (мысли?)

Просто обратите внимание, что при реализации синтаксис extern fn foo(a: u32, ...) не следует менять на ..= 😆

Соблазнительно принять это, поскольку это выглядит как хороший первый шаг в коде, но у меня не будет много времени в следующие 2 недели, поэтому, если кто-то захочет поднять это, не стесняйтесь!

Лично я больше предпочитаю ..^ чем ..= , поскольку a operator= b для некоторых операторов уже является псевдонимом для a = a operator b . ^ с другой стороны, используется гораздо реже, только для XOR, поэтому это должно вызывать меньше путаницы.

.. дает другой тип, нежели тип левого и правого операндов для него, поэтому я не вижу, чтобы это было проблемой для ..= . Контекст также помогает определить цель оператора, что-то вроде += возвращает () поэтому он может отображаться как отдельный оператор, обычно в отдельной строке. В то время как ..= возвращает InclusiveRange, поэтому он будет отображаться как выражение внутри других инструкций. Кроме того, как упоминалось выше, ..^ похоже больше связано с возведением в степень, чем с диапазоном.

@Xaeroxe ^ имеет ничего общего в Rust с возведением в степень (хотя он используется как таковой в других языках), а += , -= , *= all существуют в Rust. Фактически существует даже ^= .

Но, я знаю, тоже нормально иметь ..= .

Поскольку # 42134 был объединен, можем ли мы сейчас перейти к стабилизации структуры библиотеки? Я полагаю, что нам нужно подождать, пока синтаксис установится, прежде чем стабилизировать это, хотя, как я сказал ранее, было бы полезно стабилизировать структуру раньше.

@clarcharr Я считаю, что мы пришли к решению стабилизировать эту структуру, а также синтаксис ..= поэтому нам просто нужны PR, чтобы это действительно сделать.

РЕДАКТИРОВАТЬ: Ой, я был неправ. Мы реализуем это в компиляторе, для стабилизации синтаксиса необходимо дождаться окончания периода окончательного обсуждения. Я думаю, что сейчас нам следует стабилизировать структуру, но это тоже не мое решение.

Я давно перестал следить за этой темой, когда мне показалось, что ... идет к консенсусу. ..= кажутся мне просто неудобными, потому что на первый взгляд это выглядит как аффектация.

Но, что гораздо важнее, я не думаю, что этот байкешединг достаточно важен для изменения синтаксиса текущего шаблона.

этот синтаксис отстой!
= имеют значение присваивания, даже в + =, - =, * = модели, но .. = о получении чего-либо. так запутано и некрасиво.
подобно тому, как индекс массива начинается с 0, '...' - это хорошо и красиво, люди к этому привыкнут.

@zengsai
..= концептуально является производным от таких операторов, как == и <= , которые уже существуют в Rust и указывают на сравнение на равенство, а не на присваивание.

(например, 1..=5 - это сокращение от «Диапазон значений 1 <= x <= 5 », а не 1..5 означающее «Диапазон значений 1 <= x < 5 »)

РЕДАКТИРОВАТЬ: Кроме того, это не вопрос «привыкания», это вопрос того, что труднее неправильно прочитать или неправильно набрать, когда вы устали или отвлекаетесь. Такие одиночные ошибки, как известно, являются боевой техникой.

На самом деле я случайно набрал ... когда уже имел в виду .. . К счастью, я всегда нацелен на стабильный Rust, поэтому компилятор его поймал. (Однако я не могу вспомнить, был ли это мышечный спазм или мышечная память, если предположить, что я хотел набрать псевдо-многоточие, потому что я много пишу научно-популярную литературу.)

@zengsai ... слишком тонкий, слишком похож на ..

Это будет действительно ненормально, если в языке будет разное количество точек, означающих разные вещи.

Удаление ножного пистолета важнее эстетической привлекательности.

Новички: Я сделал TL; DR, потому что это очень длинный поток. Вы можете прочитать это здесь: https://github.com/rust-lang/rust/issues/28237#issuecomment -296310123

Говоря о том, что «подобные ошибки по отдельности - это классная фишка», я должен сказать: проблема с опечаткой не должна использоваться в качестве ключевой причины этого изменения.

посмотрите на это сравнение, ".." и "..." vs "=" и "==", означает ли это, что мы должны найти другой синтаксис для "==", чтобы избежать проблемы с опечаткой пользователя? если "=" и "==" в порядке, почему ".." и "..." не могут?

Я слежу за rust-lang более двух лет. и он использовался во многих моих частных проектах. Мне это нравится, но этот синтаксис действительно заставлял меня чувствовать себя некомфортно. не только эстетически привлекательно, но и влияет на беглость написания и чтения кода.

@zengsai, насколько я понимаю, речь идет прежде всего не о _ написании_ кода, а о просмотре, чтении и понимании кода. Если вы его не ищите, вам будет легче пропустить, что .. vs. ... - это ошибка, которая постепенно уменьшается, тогда как ..= определенно выделяется больше и выиграла. нет этой проблемы.

Я не уверен, что мне нравится синтаксис ..= либо с эстетической точки зрения, но я могу видеть, откуда все исходят примерно из .. и ... чтения очень похоже.

@zengsai Потому что = vs. == имеет решение, которое недоступно для .. vs. ... .

Конечно, вы можете спутать = и == в C ... но это признанный метод, и более современные языки, такие как Python и Rust, решили, что:

  1. Будет ошибкой набрать if x = y вместо if x == y (это исправление, сделанное в Rust и Python).
  2. Когда я случайно набрал x == y; вместо x = y; , я получил предупреждение о выражении, которое не действует.

У компилятора нет возможности даже распознать, что путаница .. против ... является подозрительной , не говоря уже о неправильной.

@zengsai .. и ... оценивают типы, которые реализуют все те же черты и могут использоваться по существу взаимозаменяемо (это сделано специально). Выключение на одну ошибку - очень реальная проблема.

Я хочу прояснить, что я также ненавижу этот синтаксис настолько, что я не согласен с комментарием @aturon , что текущая ситуация, когда мы используем .. и выражения и ... в паттерны «несостоятельны»; на самом деле, я думаю, что предпочтительнее иметь отключение, чем иметь этот синтаксис.

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

Если это утешает мой опыт, подавляющее большинство случаев использования никогда не нуждаются в этой функции, и поэтому она не будет появляться повсюду в вашем коде.

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

Остальная часть команды lang твердо убеждена в том, что отсутствие связи между выражениями и шаблонами недопустимо, и, хотя я не согласен, мы все выдвинули свои аргументы, и я не думаю, что навсегда оставаться в тупике - это здорово.

@ssokolow Извините, я все еще не могу с вами согласиться. компилятор может предупредить вас об этой опечатке, но что, если вы наберете «x = 5» там, где должно быть «x = 6»?

Компилятор - не лучший способ избежать опечаток, программист.

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

Сегодняшние ржавчины уже сталкиваются с проблемами чтения и записи, чем более необычный и нелогичный синтаксис, тем больше требуется обучения, не превращайте его в еще один Perl.

@withoutboats Мы с этим спорим, потому что нам это нравится. Может быть, этот аргумент слишком поздно и ничего не может изменить, просто ...

@zengsai

Конечно, придется идти на компромиссы, но у меня такое впечатление, что мы никогда не сможем прийти к соглашению о наилучшем балансе между ними.

Независимо от личных предпочтений, я рассматриваю ..= как крошечную плату за то, чтобы избежать, возможно, очень большого количества времени, потраченного впустую на отслеживание ошибок.

(Моя сфера деятельности - UI / UX-дизайн, и одно из главных правил, которым они вас учат, заключается в том, что вы должны стремиться к тому, чтобы легкость совершения ошибки была обратно пропорциональна вреду и / или времени на исправление, которое она нанесет. )

По моему небольшому мнению, 5 против 6 гораздо более очевиден, чем .. против ... .

@zengsai Я получаю слишком много писем только для этого разговора, как насчет перехода на канал IRC, чтобы лучше выразить свои чувства?

@daiheitan Это нормальное общение. Если вам это не нравится, я предлагаю вам отменить

Когда я впервые посмотрел на Rust, я был очень удивлен синтаксисом .. . (1..10).sum() - это ... сумма целых чисел от 1 до 9? Если вы представите этот синтаксис новичку и спросите его, что он означает, очень вероятно, что он будет ожидать, что он изменится от 1 до 10. И он будет прав, так как вы ожидаете, что симметричный синтаксис будет выражать симметричный диапазоны. Почему нужно включить 1, а не 10?

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

Что-то вроде синтаксиса Swift ( ..< для исключительного и ... для включения) позволило бы избежать этих проблем и улучшить читаемость. Вы можете легко угадать значение правильно, даже если вы совсем новичок в этом языке, поэтому вам нужно запомнить на одну вещь меньше. Я ожидал, что выберут что-то подобное, особенно учитывая стремление Rust к дружелюбию к новичкам.

@rkarp В какой-то степени это, вероятно,

Например, в Rust сильно влияние Python, и Python использует такие же полуоткрытые диапазоны. (т. е. Python range(1, 5) или myList[1:5] оба имеют то же поведение, что и 1..5 Rust)

Обоснование этого в Python было связано с тем, что там был только один синтаксис, а наличие полуоткрытого синтаксиса облегчало выполнение таких вещей, как head, tail = myList[:pivot], mylist[pivot:] .

Тем не менее, учитывая, что Rust прошел 1.0, существуют довольно строгие правила о том, чтобы не нарушать существующий код. .. для исключительных внешних шаблонов и ... для исключительных внутренних шаблонов должны оставаться действительными.

..= работает, потому что вы можете принимать .. (исключая) и ..= (включительно) везде и рассматривать ... как устаревший синоним для .. в узорах.

Просто скажу, что наличие ..= в качестве токена технически несовместимо, так как оно влияет :tt правила .. /* why not */ = , что я не считаю хорошей идеей)

@ssokolow Технически это ошибка типа в Rust, а не ошибка синтаксического анализа. a = 2 - это выражение, которое возвращает () , а if ожидает bool , поэтому они явно несовместимы.

Правила постепенно меняются. Технически ..= - это 3 токена, после которых первые 2 не имеют пробелов.

@eddyb : Признаюсь, я этого не совсем понимаю. Есть ли способ ввести новый токен, не влияя на то, как: tt его анализирует?

Этот код в настоящее время сообщает «Правило 2» и «Правило 4». Это изменение, если я правильно понимаю, превратило бы его в «Правило 2» и «Правило 5».

macro_rules! ex {
    ( . . )   => { "Rule 1: . ." };
    ( .. )    => { "Rule 2: .."};
    { . . = } => { "Rule 3: . . = " };
    { .. = }  => { "Rule 4: .. = " };
    { ..= }   => { "Rule 5: ..=" };
}

macro_rules! show {
    ( $($t:tt)* ) => { println!("{}", ex!($($t)*)) };
}

fn main() {
    show!(..);
    show!(..=);
}

Нет, это изменение в определении токенов. @jseyfried может лучше объяснить последствия.

Технически это ошибка типа в Rust, а не ошибка синтаксического анализа. a = 2 - это выражение, которое возвращает (), а если ожидает bool, то они явно несовместимы.

@xfix Спасибо. В прошлый раз, когда я допустил эту опечатку, я не обратил должного внимания и до сих пор не совсем привык думать в терминах языков, ориентированных на выражения.

Я скорректировал свой комментарий.

Мне не нравится синтаксис ..= и я против отказа от ... в шаблонах. Если мы боимся опечатки, мы всегда можем использовать struct RangeInclusive { start, end } вместо ... или ..= для ее сокращения.

Я только что осознал потенциальную двусмысленность:

if let 5..=x { ... }

@clarcharr Но похоже, что он не компилируется.

rustc 1.17.0 (56124baa9 2017-04-24)
error: unexpected token: `=`
 --> <anon>:3:13
  |
3 |     if let 5..=x {
  |             ^^

error: aborting due to previous error

@clarcharr @kennytm
После того, как мы введем ..= качестве одного оператора, ошибка будет такой:

error: expected one of `::` or `=`, found `{`
 --> <anon>:3:13
  |
3 |     if let 5..=x {
  |                  ^

error: aborting due to previous error

Как сейчас с let x=10; if let 5..x {}

Таким образом, эта «двусмысленность» не будет компилироваться и, следовательно, будет не более двусмысленностью, чем if let 5..x {} .

@Boscop Дело в том, что в настоящее время, если мы обрабатываем 5.. как шаблон, например Some(5) , тогда if let 5.. = x будет похож на let Some(5) = x , и последний компилируется. Мой комментарий показывает, что 5.. не является шаблоном, поэтому нет опасности совместимости с if let для введения ..= .

Если мы введем эту функцию и разрешим как ..= и .. в шаблонах, if let 5..=x всегда должно быть if let 5.. = x и он должен компилироваться: if let (single expression) не имеет смысла, поэтому я не верю в двусмысленность.

@kennytm, поэтому мы оба показали для двух разных неоднозначностей, которые они не скомпилируют. (Было непонятно, что он имел в виду. Это было несколько двусмысленно, хех.)

@daboross Как сказал kennytm, 5.. не является шаблоном и не компилируется даже сейчас. И это не изменится, если мы добавим ..= в качестве оператора. Нет никакой двусмысленности. Важно то, что теперь ..= нельзя анализировать как один оператор, но как только мы сможем проанализировать его как один оператор, двусмысленности не будет.

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

Таким образом, хотя наблюдение @clarcharr не обязательно указывает на двусмысленность при рассмотрении текущей грамматики, это, безусловно, неоднозначность при рассмотрении потенциальных будущих расширений, которые могут противоречить предложению использовать ..= для шаблонов.

Имея это в виду, я бы предложил использовать здесь какой-нибудь другой символ. ^ мне кажется вполне нормальным, поскольку он используется только в контексте выражения, в настоящее время IIRC.

(Это еще одна причина, по которой я считаю хорошей идеей стабилизировать структуру сейчас, а синтаксис - позже.)

@nagisa нет конфликта относительно if let если токен ..= добавлен до поддержки шаблона RangeFrom. Можно добавить пробел между .. и = для устранения неоднозначности, точно так же, как x <- y (размещение внутри) vs x < -y (меньше + отрицательное значение).

(Поскольку ^ является оператором исключающего -или, я нахожу ироничным использовать ..^ для включающего диапазона)

В тысячах диапазонов, которые я написал, довольно много из них полностью закрыты, может быть, даже один или два полуоткрытых неправильно, я все еще не вижу необходимости в каком-либо дополнительном синтаксисе. 1..(n+1) написать не так уж и сложно.

Это не работает для end = T :: max_value ().

29 мая 2017 г., 16:33, «Диггори Харди» [email protected] написал:

Из тысяч диапазонов, которые я написал, довольно много из них полностью закрыты,
может быть, даже один или два полуоткрытых не в ту сторону, я все еще не особо
вижу необходимость в дополнительном синтаксисе. 1 .. (n + 1) не так уж и сложно написать.

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-304662258 ,
или отключить поток
https://github.com/notifications/unsubscribe-auth/AApc0ipynL_qrZqUBldOJOX046RNY2H_ks5r-skwgaJpZM4F4LbW
.

Я бы предпочел метод на полузакрытых диапазонах, чем .. =.

29 мая 2017 г. 16:35 "Симонас Казлаускас" [email protected] написал:

Это не работает для end = T :: max_value ().

29 мая 2017 г., 16:33, «Диггори Харди» [email protected] написал:

Из тысяч диапазонов, которые я написал, немало из них полностью
закрыто, может быть, даже один или два полуоткрытых не в ту сторону, я все еще не
действительно вижу необходимость в дополнительном синтаксисе. 1 .. (n + 1) не так уж и сложно
написать.

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-304662258 ,
или отключить поток
https://github.com/notifications/unsubscribe-auth/AApc0ipynL_qrZqUBldOJOX046RNY2H_ks5r-skwgaJpZM4F4LbW
.

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

Это не работает для end = T :: max_value ().

Вы действительно хотите перебрать 2 ^ 64 значения или даже 2 ^ 8 значений? Если вы хотите перебрать только несколько последних значений, например, u32 , часто проще добавить его внутри цикла. И если вы действительно хотите перейти к 2^B-1 по какой-то непонятной причине, вы всегда можете вставить if i == END { break; } в конце цикла.

Тот факт, что наши стандартные целые числа без знака поддерживают значения 2 ^ 32 или 2 ^ 64, не означает, что очень часто используется самое высокое представимое значение. И если вы что-то делаете с u8 , не забывайте, что ЦП, вероятно, в любом случае проще использовать u32 в качестве счетчика.

Но даже если я не вижу необходимости в синтаксисе генератора замкнутого диапазона, я не могу опровергнуть аргументы команды в пользу изменений . Ну что ж :/

Как насчет этих четырех вариантов, охватывающих все возможности?

1...10
1>..10
1..<10
1>.<10

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

В качестве альтернативы мы могли бы переключить неравенства:

1...10
1<..10
1..>10
1<.>10

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

@vegai, а как насчет существующего синтаксиса a..b который уж точно не удаляется? Нет, я не думаю, что предложение новых вариантов синтаксиса что-то решит.

Хм, поэтому возникли две "потенциальные двусмысленности":

  • if let 5..= x - как уже отмечалось, это не очень неоднозначность сейчас, но это может быть своего рода. С другой стороны, такая неоднозначность возникает часто и устраняется токенизатором. То есть, если мы рассматриваем ..= как токен в нашем синтаксическом анализаторе, это не будет двусмысленным, даже если мы добавим в будущем шаблоны 5.. ; вам просто нужно написать пробел между .. и = (например, let 5.. = x ).
  • двусмысленность в отношении макро-правил. Это действительно неприятно и неприятно, и это одна из причин того, что мы перешли к другой системе для «макросов 2.0», в которой мы избегаем раскрытия набора «составных токенов» конечному пользователю.

    • в конце концов, мы можем обработать macro_rules! back-compat с помощью специального кода, если это необходимо; в любом случае, я думаю, что такого рода проблемы нельзя избежать, кроме как с помощью ... .

Перед стабилизацией включенных диапазонов, проблема № 42401 также должна быть исправлена ​​imo, так как после стабилизации исправление будет критическим изменением.

@ est31 хороший момент, я добавил это в контрольный список во главе проблемы

Проверенные срезы str сами по себе нестабильны, и устранение этой проблемы вообще не блокирует включающие диапазоны.

О, @nagisa права, это не имеет ничего общего с синтаксисом диапазона. Сможешь снова снять его с головы? Моя ошибка. Ошибка скорее связана с реализацией get и поэтому охраняется функцией str_checked_slicing :

    impl SliceIndex<str> for ops::RangeToInclusive<usize> {
        type Output = str;
        #[inline]
        fn get(self, slice: &str) -> Option<&Self::Output> {
            if slice.is_char_boundary(self.end + 1) {
                Some(unsafe { self.get_unchecked(slice) })
            } else {
                None
            }
        }
    [...]

удаленный

Еще одно обновление флажка: PR https://github.com/rust-lang/rust/pull/42134 применил настройку https://github.com/rust-lang/rfcs/pull/1980

Удар: как мы можем стабилизировать структуры хотя бы на 1,20?

Как насчет того, чтобы позаимствовать знаменитый оператор перехода из C ++ для синтаксиса включающего диапазона? 😛

@nikomatsakis и @ rust-lang / libs (я не знаю, как это пометить), как бы вы себя чувствовали, если бы я отправил PR, который переместил структуры в другую проблему отслеживания, чтобы мы могли поговорить о стабилизации для них там? Я думаю, что это был бы хороший способ продвинуться вперед в их стабилизации на более раннем этапе, пока мы ждем, пока новый синтаксис не будет реализован / урегулирован.

cc @ rust-lang / libs (только люди в команде могут отмечать свои или другие команды)

Спасибо, @eddyb!

@clarcharr На основании https://github.com/rust-lang/rust/pull/42275#discussion_r119211211 , я подозреваю, что это будет оценено.

Я слишком опаздываю на поезд для предложения синтаксиса?
Ток выглядит так, будто кто-то пытается присвоить значение срезу.

for i in a..b {} // [a..b) 
for i in a..+b {} //[a..b] 
for i in a-..b {} //(a..b) 
for i in a-..+b {} // (a..b]

Этот синтаксис сделает невозможным добавление каких-либо реализаций Add для диапазонов в будущем. Я действительно не знаю, проблема ли это, поскольку я не совсем уверен, что будет делать реализация Add .

Согласитесь на завершающий плюс. Поменял на префикс.

Поскольку a.. , ..b и .. являются допустимыми конструкциями в Rust, это по-прежнему вызывает двусмысленность с математическими операциями: /

a... / a..= / a..+ не будет действительным, но верно? Поскольку неограниченный диапазон должен включать конечную точку, на самом деле не имеет смысла.

Я бы не стал слишком беспокоиться о Add , не похоже, что это было бы слишком распространенным явлением, связанным с диапазонами, и если бы вы действительно захотели, вы могли бы сделать (x..+y) + z ?

Изменить: неважно, просто понял, что вы имели в виду. Это было бы a..+b , что бы неоднозначным, не так ли? Так как сейчас это означает a.. + b .

@daboross Не говорю, что это хорошая или плохая идея, но эта реализация (или какой-то ее вариант) может быть тем, что мы хотим для диапазонов в будущем:

impl<T> Add<T> for RangeFrom<T> where T: Add<T> {
    type Output = RangeFrom<T>;
    fn add(self, rhs: T) -> RangeFrom<T> {
        (self.start + rhs)..
    }
}

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

Еще меня беспокоит то, что весь смысл отклонения ... заключается в том, чтобы минимизировать вероятность трудно распознать опечатки и позволить парным скобкам сделать разницу между двумя разными значениями абстрактного a..+b будет двигаться в том же направлении.

Кроме того, мне еще предстоит увидеть твердое оправдание для a-..b и a-..+b помимо слов «было бы хорошо для полноты картины», в то время как текущие .. и предлагаемые ..= обоих

Вы не можете использовать для этого + потому что это делает синтаксис выражения неоднозначным.

РЕДАКТИРОВАТЬ: хотя, я полагаю, это сделало бы возможной реализацию инклюзивных диапазонов полностью в библиотеке, потому что вы просто получили бы реализацию <Range as Add<{integral}>>::Output = InclusiveRange .

Могу предложить вариант ..! . Он имеет продуктивную рифму с .. и делает дополнительный акцент на последней точке, делая ее более заметной.

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

..! имеет проблемы с интуитивностью. Новичок, еще не знакомый с синтаксисом, может легко неправильно понять, что ..! означает "до, но не ..."

Он также противоречит синтаксису «диапазон до побитового дополнения ...» (что поставило бы его в ситуацию, аналогичную использованию + )

Соглашаться. Но, с другой стороны, ..= может быть неверно истолковано как один из операторов присваивания.

Что бы вы назвали, если бы это был оператор присваивания?

На основе предложения @ snuk182 :

a...b // [a; b] shorthand for RangeIncusive
a..-b // [a; b) new Range shorthand 
a..b // [a; b) old Range shorthand exists for compatibility

Сомневаюсь, нужны ли нам другие комбинации. В любом случае его можно будет добавить позже:

a-..b // (a; b]
a-.-b // (a; b)  

Хотя последний вариант выглядит немного странно. ^_^

Пожалуйста, прекратите предлагать любой синтаксис, содержащий унарный оператор, например a..-b , a..!b , a..*b , a..&b или a?..b , они никогда не будут принятый.

..! имеет проблемы с интуитивностью. Новичок, еще не знакомый с синтаксисом, легко может неправильно понять ..! означать "до, но не ..."

..= имеет ту же проблему с интуитивностью. Любой, кто видит = ожидает аффектации или сравнения. Я уверен, что эта полнота синтаксиса решает проблему различимости, поскольку каждый раз, когда я вижу ..= , я не могу удержаться от мысли, что здесь делает этот знак равенства.

Единственный предлагаемый синтаксис, который является одновременно довольно интуитивным и совместимым с текущим синтаксисом, - это ... . Но, похоже, корабль ушел.

Новичкам в любом случае придется часто просматривать документацию. Даже с ... они смотрят документы. Этого не избежать. Но в ..= есть хорошая мнемоника ( up to и equal to ), поэтому им не придется часто просматривать документацию для этого оператора.

Что, если бы оператор ... остался бы как есть, но вместо этого мы изменим оператор .. на ..⎵ , то есть две точки и пробел (мне пришлось поставить это '⎵ 'там, потому что обычное пространство не отображается на этой веб-странице). Это было бы единственное место в языке, где пробелы имеют значение. Это также было бы критическим изменением, потому что весь код вроде a..b будет жаловаться на отсутствие такого оператора, как .. , и советует добавить хотя бы один пробел после точек. Я думаю, что пространство делает их достаточно визуально различимыми:

a.. b
a...b

@tommit Честно говоря, я не думаю, что это было бы хорошей идеей.

В настоящее время оператор довольно гибок в отношении пробелов, например: a..b и a .. b - это одно и то же. Вероятно, это сделано для согласования с другими операторами, такими как a+b и a + b . Они, конечно, делают то же самое и позволяют людям использовать разные стили синтаксиса. Это хорошо, если вы спросите меня!

Чтобы добавить к этому, обозначение ..= согласуется с обозначениями <= и >= (которые также считаются _inclusive_).

Всегда полезно проверить, какие еще есть возможности, но, вероятно, это неправильное решение.

Соглашаться. По сравнению с <= и >= , ..= выглядит правдоподобно, даже логично.

Кстати, если вы поклонник ... или просто не любите, как выглядит ..= , то компромиссным решением будет использование шрифта с программными лигатурами, например FiraCode со специальной лигатурой для ..= , который может быть сопоставлен с ... или даже с чем-то странным, например ⩷, ⩦ или ≔.

Критическое изменение всего существующего кода ржавчины с использованием диапазонов ... мертвых по прибытии,
Извините. Если у кого-то есть действительно серьезное предложение обратной совместимости,
решить проблемы, которые были подняты, и это не обсуждалось
уже, давайте послушаем, но давайте хотя бы сохраним это в качестве стандарта, да?
Эта ветка полна навесов для велосипедов, и команда уже приняла решение, поэтому
это высокая планка для очистки.

В любом случае, по поводу синтаксиса, похоже, все еще ведется много разговоров. Я подал №43086, чтобы стабилизировать хотя бы структуры, черты и имплименты, чтобы можно было использовать основные функции (похоже, спрос есть, см. Комментарий @ retep998 выше).

Слон в комнате заключается в том, что .. на самом деле является настоящей проблемой из-за его симметричного вида, но асимметричного значения. «Правильный поступок», вероятно, повлечет за собой отказ от него, но нет желания делать это, потому что очень много кода уже использует его.

Отказ от идеально согласованного ... (симметричный вид, симметричное значение) - простой выход, но за счет добавления еще одного несовместимого оператора в ..= . Это похоже на добавление плохого дизайна, чтобы обойти предыдущий плохой дизайн.

Из-за этой двойной несогласованности возникает еще одна проблема: нет хорошего способа добавить два последних оставшихся варианта включенности (исключение с обеих сторон и исключение только с левой стороны). Поскольку и .. и ..= уже будут иметь неявное значение = с левой стороны, нам придется как-то отрицать это, возможно, с помощью < . Таким образом, они должны были бы выглядеть примерно так:

  • <..= за (a; b]
  • <.. за (a; b)

Удачи, если вы новичок, правильно угадав, что они означают. Так что они, вероятно (справедливо), даже не будут считаться добавленными.

Если .. не было так закреплено или даже не существовало, придумать единый дизайн для всего этого с нуля не так сложно, например:

  • .. (или ... ) за [a; b]
  • ..< за [a; b)
  • <.. за (a; b]
  • <..< за (a; b)

У меня такое чувство, что последние два варианта могут оказаться полезными в какой-то момент, неужели мы действительно так быстро преграждаем путь к ним? В любом случае, единственная веская причина выбрать ..= вместо устаревшего .. - это ломать гораздо меньше старого кода, но в лучшем случае это было бы неизбежным злом, а не праздником.

_Редактировать: добавлен пример и несколько комментариев для большей ясности.

Я согласен с @rkarp в том, что настоящая проблема здесь .. , а не ... или ..= . Асимметричный смысл особенно плохо , учитывая , что другие (более популярные) языки на самом деле правопреемник симметричного смысл. И Kotlin, и Ruby, и Haskell считают, что 5, например, находится в диапазоне 3..5. Математические статьи также, кажется, поддерживают это. Хуже всего то, что у новичков нет шанса угадать поведение 3..5 в Rust: вы либо решите, что 4 и только 4 являются членами диапазона 3..5 (итерация по точкам), либо оба 3 и 5 также присутствуют в нем (повторение «всего, что мы можем видеть» и экстраполяция точек).

Однако я не согласен с тем, насколько сложно это изменить. Я думаю, что предложение

[1..4] // 1, 2, 3, 4
[1..4[ // 1, 2, 3
]1..4] // 2, 3, 4
]1..4[ // 2, 3

Любое появление x..y (без квадратных скобок) можно преобразовать в [x..y[ и выдать предупреждение компилятора. После нескольких выпусков компилятор может просто отказаться компилировать "голые" нотации диапазонов и, возможно, даже предложить инструменты для автоматического преобразования в новую нотацию.

https://github.com/rust-lang/rust/issues/28237#issuecomment -274216603 это не новая идея, и мы не можем использовать ее по причинам, которые мы уже упоминали.

Я полностью согласен с идеей, что, если бы мы разрабатывали язык с нуля с учетом преимуществ ретроспективного анализа, мы бы хотели рассматривать синтаксисы исключающих и включающих диапазонов вместе. Я действительно думаю, что ..= не идеальный оператор для включающего диапазона; это просто лучший вариант на данный момент. Но отказ от текущего оператора исключительного диапазона был бы чрезмерно болезненным и отталкивающим от существующих пользователей и проектов Rust.

Есть множество других предложений, которые могут сработать. Например, я не видел предложенных ..@ , а x..@y действительно вызывает воспоминания. Задача состоит в том, чтобы найти что-то более убедительное, чем текущее предложение, сохранив при этом отсутствие двусмысленности.

Я хотел выделить комментарий @ssokolow, сделанный 2 месяца назад, как мой любимый взгляд на симметрию:

  • ..4 содержит вещи < 4
  • ..=4 содержит вещи <= 4

Думаю, нам нужен только инклюзивный диапазон, это проще.
Вы всегда можете добавить +1 или -1, чтобы изменить диапазон.
И .. лучше, потому что .. проще, чем ...!

@ AlexanderChen1989 Как уже было сказано ранее в нескольких сообщениях в этой ветке, это невозможно, потому что изменение значения .. нарушит существующий код.

К тому же, на самом деле все не так просто. В частности, +1 и -1 могут вызвать целочисленное переполнение / потерю значимости.)

Вот пример, который работает в nightly (через старый кандидат на синтаксис включающего диапазона), где ...

  • ... какой бы цикл вы ни поставили первым, вызовет панику при переполнении / недостаточном заполнении в отладочных сборках
  • ... они будут вести себя полностью противоположно тому, что было запланировано в сборках релиза (т. е. «от 0 до 0» будет повторяться 256 раз, а «от 0 до 255» не будет повторяться вообще)
#![feature(inclusive_range_syntax)]
fn main() {
    let max = 255u8;
    let user_provided = 0u8;

    for x in 0...user_provided-1 {
        println!("(0 to 0, exclusive via 'inclusive - 1'): {}", x);
    }

    for x in 0..max+1 {
        println!("(0 to 255, inclusive via 'exclusive + 1'): {}", x);
    }
}

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

IMHO OP должен быть обновлен, чтобы указать, что в этом потоке больше не должно быть обсуждения синтаксиса, и любые предложения синтаксиса исключительного диапазона (т.е. диапазоны (a, b) и (a, b)) должны быть перемещены в другой поток.

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

@clarcharr Я принял в основном одностороннее решение и добавил это в OP, хорошая идея. Если шум не исчезнет, ​​я проголосую за блокировку потока.

Привет, я новичок и хотел бы начать работу над этим. Я попытаюсь написать PR, чтобы добавить ..= в качестве синонима для ... в шаблоны, исключить ... в выражениях и отобразить ошибку о том, что синтаксис был изменен на ..= . Это звучит правильно?

@ Badel2 круто. Я вообще-то начал - скоро выложу свою ветку и свяжу здесь.

@durka просто для пояснения - вы предлагаете разрешить @ Badel2 начать работу с вашей ветки? Не могли бы вы наставлять их в рамках имплементационной работы? Они находятся на канале Gitter.

Я также согласен с тем, что настоящая проблема - .. . Таким образом, более благоприятным решением является устаревание (не замена сразу, поэтому __not__ нарушит существующий код) .. в пользу чего-то вроде ..< (не будет путаницы между a..<b и (a..)<b , поскольку .. конечном итоге перестанет существовать).

@ hyst329 Пожалуйста, прочтите уже сделанные сообщения.

В самом первом сообщении жирным шрифтом написано: «В этой ветке больше не следует обсуждать синтаксис».

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

Извините, это не очень конструктивно, но каждый раз, когда я вижу ..= и пытаюсь вспомнить, что это, это выглядит как оператор присваивания, похожий на += или <<= . Это очень сбивает с толку, что это не так. (Хотя, по общему признанию, это было вне контекста, например «начальная поддержка синтаксиса ..= » https://this-week-in-rust.org/blog/2017/10/03/this-week- ин-ржавчина-202 /)

@SimonSapin Я выразил ту же критику в более конструктивном стиле выше, предложив вместо этого ..^ : https://github.com/rust-lang/rust/issues/28237#issuecomment -304325663

Для меня один важный момент, который говорит о ..= - это своего рода согласованность с swift (в котором ..< для исключительных и .. для инклюзивных диапазонов). Это заставило меня согласиться с выбором ..= .

@SimonSapin Я не думаю, что кто-то полностью доволен этим. Проблема в том, что сотни комментариев, к сожалению, подтвердили, что лучшей альтернативы нет.

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

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

... можно заменить на RangeInclusive или (Bound<T>, Bound<T>) в выражениях, которые действительно требуют их. Он более подробный, но легкий для понимания.

@UtherII

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

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

Я отметил «Изменить, чтобы принимать ..= как синоним ... в шаблонах и принимать ..= в выражениях», потому что это уже имеет место после # 44709 с Функции dotdoteq_in_patterns и inclusive_range_syntax соответственно. Осталось только документация и стабилизация.

Запрос на стабилизацию

Я бы хотел стабилизировать инклюзивный диапазон на 1,26 (бета-версия 30 марта, стабильная 11 мая) или раньше. Стабилизационный PR поступил за № 47813.

Резюме

Будут стабилизированы следующие 3 функции:

  • inclusive_range_syntax - Синтаксис a..=b и ..=b в выражении:

    for i in 1..=10 {
        println!("{:?}", &a[..=i]);
    }
    
  • dotdoteq_in_patterns - Синтаксис a..=b в шаблоне:

    match c {
        b'0'..=b'9' => c - b'0',
        b'a'..=b'z' => c - b'a' + 10,
        b'A'..=b'Z' => c - b'A' + 10,
        _ => unreachable!(),
    }
    

    (Примечание: синтаксис a...b по-прежнему принимается без предупреждений)

  • inclusive_range - Типы std::ops::{RangeInclusive, RangeInclusiveTo} и их поля:

    let r = 1..=10;
    assert_eq!(r.start, 1);
    assert_eq!(r.end, 10);
    

Документация

Несколько PR документации представлены

Тесты

Вы можете найти тестовые примеры в:

  • run-pass/range_inclusive.rs -
    базовые тесты, такие как использование a..=b в цикле for, в качестве итератора, в качестве индекса среза, приоритета оператора ..= и поведения проверки типов.
  • libcore/tests/iter.rs -
    дальнейшие тесты поведения a..=b как итератора; проверяет, что специализации nth() , min() , max() и last() работают правильно, и что после вызова (5..=5).next() диапазон становится 1..=0 .
  • liballoc/tests/str.rs , liballoc/tests/btree/map.rs и liballoc/tests/vec.rs -
    проверяет правильность работы a..=b в различных типах коллекций.
  • parse-fail/range_inclusive.rs и ui/impossible_range.rs -
    обеспечивает бессмысленные конструкции, такие как a..= и ..= поскольку выражение не может быть скомпилировано
  • parse-fail/range_inclusive_dotdotdot.rs -
    гарантирует, что мы отклоним устаревший синтаксис выражений a...b и ...b .
  • run-pass/inc-range-pat.rs -
    гарантирует, что использование a..=b и a...b в шаблоне допускается и эквивалентно.
  • compile-fail/range_traits-1.rs и compile-fail/range_traits-6.rs -
    гарантирует, что RangeInclusive и RangeInclusiveTo не реализуют PartialOrd (как и другие диапазоны), а RangeInclusive не реализуют Copy (не может реализовать Copy, поскольку они являются итераторами).
  • libcore/tests/ops.rs -
    проверяет, работает ли итерация созданного вручную экземпляра RangeInclusive .

Нерешенные вопросы

  • Использование a..=b в цикле for имеет гораздо более низкую производительность, чем a..(b+1) поскольку его next() более сложен и менее удобен для оптимизатора. В настоящее время это отслеживается в # 45222. В настоящее время это смягчается с помощью # 48012 при использовании методов итератора вместо цикла for.

    Нам может потребоваться сохранить поля RangeInclusive нестабильными, если мы еще не хотим фиксировать проект в rust-lang / rfcs # 1980.

Нам может потребоваться сохранить нестабильность полей RangeInclusive, если мы еще не хотим фиксировать проект в rust-lang / rfcs # 1980.

+1
Есть ли необходимость открывать поля диапазона напрямую, а не через какой-либо интерфейс на основе методов?

@rfcbot fcp слияние

В соответствии с резюме @kennytm , я предлагаю стабилизировать синтаксис включающего диапазона ( ..= ).

(Тем не менее, я нахожу более низкую производительность ..= слегка беспокоящей, и мне интересно, имеет ли смысл делать ..= не реализованным напрямую Iterator на данный момент, в чтобы смягчить это.)

Член команды @nikomatsakis предложил объединить это. Следующий шаг - проверка остальными отмеченными командами:

  • [x] @BurntSushi
  • [x] @Kimundi
  • [] @KodrAus
  • [x] @alexcrichton
  • [x] @aturon
  • [x] @cramertj
  • [x] @dtolnay
  • [x] @eddyb
  • [x] @nikomatsakis
  • [x] @nrc
  • [x] @pnkfelix
  • [x] @sfackler
  • [] @withoutboats

В настоящее время не перечислено никаких проблем.

Как только большинство рецензентов одобрит (и никто не возражает), наступит последний период для комментариев. Если вы заметили серьезную проблему, которая не поднималась ни на одном этапе этого процесса, сообщите об этом!

См. Этот документ для получения информации о том, какие команды могут дать мне члены команды, отмеченные тегами.

Интересно, имеет ли смысл делать .. = не реализованный напрямую Iterator в настоящее время, чтобы смягчить это.

Эти стабильные черты реализованы для RangeInclusive<T> по крайней мере для некоторых T s в текущем Nightly: Iterator , FusedIterator , ExactSizeIterator , Debug , Clone , Eq , PartialEq , Hash , TrustedLen .

@SimonSapin Я забыл, мы уже стабилизировали структуру? (Другими словами, можно ли это наблюдать?) Я предполагал, что это не так.

Тем не менее, я также очень, очень думаю, что 1..2 и 1..=2 должны использоваться во всех одних и тех же местах, что выступает против внесения каких-либо изменений здесь, и вместо этого предлагает нам просто преследовать меры по смягчению и улучшать оптимизации.

Почему не использовать специальные диапазоны, где end == MAX ? Это может привести к тому, что большинство инклюзивных диапазонов будут иметь тот же код, что и эксклюзивные, за исключением тех, которые идут непосредственно к границе, имеют больше кода. Поскольку ветвь end != Max никогда не изменит end , она может быть легко встроена оптимизатором.

@nikomatsakis Нет, на данный момент структуры нестабильны. Но предложение @kennytm включает их стабилизацию.

@SimonSapin

Нет, на данный момент структуры нестабильны. Но предложение @kennytm включает их стабилизацию.

Я понимаю; действительно, именно поэтому я упомянул, что нам придется удалить Iterator impl сейчас или никогда. знак равно

@SimonSapin Я не думаю, что мы могли бы стабилизировать синтаксис выражения a..=b без стабилизации структуры. Однако мы можем оставить поля нестабильными, если мы действительно думаем, что можем это изменить.

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

Ура для выхода из синтаксиса диапазона и стабилизации! : тада:

Учитывая машину времени, я бы поспорил, что ни один из типов Range не является :Iterator , а они просто :IntoIterator . Но в настоящее время я считаю, что соответствие Range - лучший вариант. Мы можем поместить этот случай с Chain в корзину «ну, оказывается, внутренняя итерация просто иногда

Еще одна нерешенная вещь, также связанная с итерацией: хотим ли мы зафиксировать какое-либо конкретное представление RangeInclusive после выполнения итерации? Сейчас он заканчивается на 1..=0 , но обсуждались и другие варианты . Я не знаю, будет ли документации достаточно, чтобы люди не полагались на нее, хотя текущая версия действительно делает диапазон после итераций совершенно бесполезным, что, по крайней мере, отталкивает его.

Мы можем поместить этот случай с цепочкой в ​​корзину «ну, оказывается, внутренняя итерация просто иногда быстрее».

Я думаю, что нам действительно нужно исправить это, чтобы иметь не меньшую производительность, чем у эксклюзивной линейки; для этого нет фундаментальной причины.

для этого нет _основных_ причин.

Это зависит от того, какие инварианты мы можем применить. В двух предыдущих формулировках с дополнительным битом состояния не было ничего, что могло бы гарантировать, что этот бит был фактически установлен, когда мы закончили итерацию (и на самом деле он _ не_ был установлен для литералов вроде 100..=0 ), поэтому цикл Условие выхода должно быть составным, а это означает, что LLVM больше не хочет разворачивать его за нас, поэтому производительность снижается. Полное исправление этого, похоже, означает либо увеличение размера структуры и отсутствие полей pub, создание RangeInclusive: !Iterator , либо улучшение LLVM в оптимизации таких циклов.

Тем не менее, я пробовал несколько разных способов написания RangeInclusive::next , и похоже, что мой прошлый выбор сопоставить с Option<Ordering> очень огорчает LLVM - просто добавление операторов сравнения вместо этого дает намного лучшая сборка. Отредактируйте PR: https://github.com/rust-lang/rust/pull/48057

Учитывая машину времени, я бы сказал, что ни один из типов Range не является: Iterator, а они просто: IntoIterator. Но в настоящее время я считаю, что соответствие Range - лучший вариант. Мы можем поместить этот случай с цепочкой в ​​корзину «ну, оказывается, внутренняя итерация просто иногда быстрее».

Я в принципе согласен с этим.

: bell: Сейчас наступает последний период для комментариев , как указано в обзоре выше . : звонок:

: bell: Сейчас наступает последний период для комментариев , как указано в обзоре выше . : звонок:

@rfcbot fcp отменить

@withoutboats и @KodrAus не отметили свои флажки.

Предложение @cramertj отменено.

Член команды @cramertj предложил объединить это. Следующий шаг - проверка остальными отмеченными командами:

  • [x] @alexcrichton
  • [x] @aturon
  • [x] @cramertj
  • [x] @dtolnay
  • [x] @eddyb
  • [x] @nikomatsakis
  • [x] @nrc
  • [x] @pnkfelix
  • [x] @sfackler
  • [] @withoutboats

В настоящее время не перечислено никаких проблем.

Как только большинство рецензентов одобрит (и никто не возражает), наступит последний период для комментариев. Если вы заметили серьезную проблему, которая не поднималась ни на одном этапе этого процесса, сообщите об этом!

См. Этот документ для получения информации о том, какие команды могут дать мне члены команды, отмеченные тегами.

: bell: Сейчас наступает последний период для комментариев , как указано в обзоре выше . : звонок:

@rfcbot Обеспокоенность https://github.com/rust-lang/rust/issues/48501.

( @petrochenkov Синтаксис: <strong i="6">@rfcbot</strong> concern KEYWORD , без fcp . Однако я думаю, что только отмеченный член команды может зарегистрировать проблему.)

Последний период комментариев подошел к концу.

Если # 48501 достаточно, чтобы заблокировать стабилизацию, я полагаю, нам придется подождать, пока # 48500 объединится (и стабилизируется)? Ух, надеюсь, мы найдем более быстрый путь. Эта функция появилась так давно, и сейчас она находится в опасном состоянии, когда сообщения об ошибках указывают людям на нестабильный синтаксис.

@durka
Я не думаю, что для этой стабилизации нужно ждать стабилизации https://github.com/rust-lang/rust/pull/48500.
... в шаблонах все еще существует, и у него все еще есть старый приоритет, поэтому, если у вас есть &BEGIN ... END в шаблоне (это должно быть довольно редко, я подозреваю), всегда есть возможность не менять его на ..= на некоторое время.

Думаю, # 48500 можно стабилизировать довольно быстро.

Лично я был бы в порядке с посадкой "insta-stable"

inclusive range был стабилизирован, поскольку запрос на перенос # 47813 был объединен, но его нет в версии 1.25, почему? Хотя запрос на перенос был объединен 16 марта

@mominul функция доступна только после того, как она была объединена с основной веткой, поэтому ..= доступен начиная с 1.26, а не с 1.25.

Таким образом, вы можете тестировать их в бета-версии и каждую ночь, прежде чем они станут стабильными.

Спасибо за вклад @kennytm и @clarcharr ! Релиз Rust 1.26 точно не наскучил по крайней мере для меня! :улыбка:

Я знаю, что уже слишком поздно начинать это обсуждение, но почему бы не полностью отказаться от синтаксиса .. и вместо этого использовать слова?

В Scala у вас есть 1 to 4 который генерирует [1, 2, 3, 4] , 1 until 4 который генерирует [1, 2, 3] , и необязательное ключевое слово by которое следует за ним, которое указывает размер шага : 1 to 10 by 2 = [1, 3, 5, 7, 9] .

Это и проясняет замысел, и позволяет избежать ошибки «по одному», которая всех так беспокоит.

Конечно, это нарушает весь существующий код, если исходный синтаксис не поддерживается.

@ElectricCoffee в диапазонах ржавчины поддерживает все типы, а не только числа. Я думаю, что нам нужно ввести to и until качестве ключевых слов, чтобы поддержать это, и это было бы гораздо более серьезным изменением.

Он хорошо работает в Scala, но варианты дизайна Rust сильно различаются.

@ElectricCoffee, хотя

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

Хотя to и until не являются словами, используемыми в std (насколько мне известно), я уверен, что это общие слова, используемые в других ящиках и проекты.

@daboross , на самом деле это справедливый момент, который я не a .. b в каком-то смысле означает a to b , независимо от того, что a и b самом деле есть.

И да, @timvisee, наверное, так и есть.

@ElectricCoffee Но если to означало ..= а until означало .. вам нужно было бы написать a until b , а не a to b вместо a .. b . Как видите, использование этих слов не «более» интуитивно, чем операторы. Но было бы более многословно писать until везде, где используется .. , потому что это гораздо чаще, чем ..= (поэтому, если использовались слова, .. должно быть назначено более короткое слово).

И вы абсолютно правы насчет этого @Boscop , однако это был всего лишь пример того, как можно

Мне кажется, я видел to для эксклюзивного и upto для включения на некоторых языках.
Все это было задумано как идея.

В Scala включающий диапазон используется чаще, чем исключительный, поэтому ему дается более короткое слово.

@timvisee Можно просто использовать a.to(b) и a.until(b) , никаких дополнительных ключевых слов не требуется (и это не делает синтаксис намного более неуклюжим).

@ hyst329 Я даже не думал об этом. Должен сказать, мне очень нравится эта идея! Вы действительно правы.

Я не верю, что это будет полноценная замена текущего (/ нового) синтаксиса. Но было бы неплохим дополнением.

Я должен согласиться с комментарием Боскопа об интуитивности. Помимо таких слов, как «включая» и «исключение», повседневный английский на самом деле не различает инклюзивные и исключительные диапазоны достаточно сильно, чтобы можно было создать готовый ярлык.

Если он не используется в контексте, где также используется «от A до B», неясно, означает ли «от A до B» включающий или исключительный диапазон в повседневной речи здесь, на юге Онтарио, Канада, и «до» связано со временем достаточно сильно, чтобы при использовании в этом более свободном смысле неясно, является ли «событие», которое «до« ассоциируется с »,« до тех пор, пока мы не увидим X »или« пока мы не обработаем X ».

@ hyst329 Однако использование их в качестве методов ограничило бы диапазоны

Я предполагаю, что мы могли бы добавить новую универсальную черту к прелюдии для создания диапазонов, но это все еще граничит с критическим изменением для вещей, которые имеют фактические методы to и until .

Признаюсь, я подумал, что предложение ключевых слов было первоапрельской шуткой.
Синтаксис .. = стабилизирован.

5 апреля 2018 г. в 13:53 Дэвид Росс [email protected] написал:

@ hyst329 https://github.com/hyst329 Использование их в качестве методов ограничило бы
диапазоны к числовым типам, однако. Я бы действительно предпочел не иметь единого синтаксиса для
диапазоны чисел и другое для диапазонов других вещей.

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

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-379021814 ,
или отключить поток
https://github.com/notifications/unsubscribe-auth/AAC3nwBj-b985q1Ez0OHDEHkG6DWV_5nks5tlloZgaJpZM4F4LbW
.

Да, у нас было 300+ комментариев по этой проблеме, и в самом первом комментарии говорится:

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

Я собираюсь сейчас заблокировать эту проблему, извините, если я наступлю на пальцы!

Я считаю, что все, о чем идет речь в этом вопросе, сделано. Пожалуйста, откройте и обновите контрольный список в исходном сообщении проблемы, если есть что-то еще.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги