Rust: Problema de rastreamento para `.. =` intervalos inclusivos (RFC # 1192) - originalmente `...`

Criado em 4 set. 2015  ·  331Comentários  ·  Fonte: rust-lang/rust

Status atual

Estamos planejando mudar a sintaxe de intervalos e padrões inclusivos para ..= . A sintaxe ... em padrões é estável e permanecerá (silenciosamente) obsoleta por enquanto; rustfmt pode reescrever ... em ..= . Isso vem depois de muita discussão. Veja este comentário para justificativa.

Não deve haver mais discussão sobre a sintaxe neste tópico . Quaisquer propostas diferentes de sintaxe de intervalo exclusivo devem ocorrer no fórum do usuário ou fórum interno , depois de você ter lido todos os comentários existentes e seus fundamentos aqui. Notavelmente, quebrar a compatibilidade com versões anteriores é um obstáculo.

Passos a dar

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

Comentários muito úteis

A equipe de lang discutiu esse recurso novamente em nossa reunião de hoje e chegou a aproximadamente a seguinte matriz:

  • Suportar ... em padrões e .. em expressões, e nada mais, é um design insustentável; faz com que os usuários esperem que a sintaxe funcione de outra forma.

  • Permitir ... e .. em ambos os lugares ajudaria, mas o problema um a um é uma preocupação real; nenhum de nós está ansioso para receber relatos de pessoas que passam horas rastreando um período incorreto.

  • Mudar para ..= e .. é menos atraente esteticamente, mas evita os problemas práticos muito reais acima. Também podemos implementá-lo de uma maneira muito suave: primeiro introduza ..= como uma sintaxe alternativa (para a qual o rustfmt pode reescrever) e, somente depois que se tornar idiomática, desative ... .

Caso você não saiba, a equipe sente que ..= e .. são o nosso melhor caminho a seguir. Esta questão também foi discutida a ponto de ser muito improvável que novos argumentos sejam levantados, então estamos prontos para mergulhar: estamos procurando alguém que gostaria de implementar a notação ..= para ambos padrões e expressões, e subsequentemente iremos para FCP!

Todos 331 comentários

Talvez a..b| ou a..b]

Acho que isso abrirá caminho para novos tipos de erros imprevisíveis no futuro devido a um erro de digitação simples (.. vs ...). Melhor se fosse .... (4 períodos). Dessa forma, é menos sujeito a erros do fator humano, imo.

Acho que https://github.com/rust-lang/rfcs/pull/1592 e https://github.com/rust-lang/rfcs/pull/1582 combinados ..= sintaxe em vez disso. A menos que alguém possa pensar em uma sintaxe melhor do que (head..., tail) para expandir uma tupla na frente de uma tupla maior.

Encontrei esse problema porque tinha erro _desligado-por-um- ponto _ em meu código quando pretendia usar intervalo exclusivo.

👎 para a sintaxe ... . Acho que ter uma sintaxe fácil de digitar incorretamente que causa erros aleatórios seria uma footgun.

A funcionalidade é útil, então eu ficaria feliz em tê-la com uma sintaxe diferente, por exemplo, ..=

A sintaxe para esta é uma questão em aberto? Como ... já está nas declarações de correspondência, presumi que o navio havia partido.

Eu pessoalmente prefiro a faixa inclusiva ... , entretanto, como já existe a versão exclusiva .. , vejo o potencial de problemas. Depois de olhar para # 23635, no entanto, prefiro descontinuar .. e permitir apenas ... .

Eu uso intervalos inclusivos muito para o equivalente a C para loops for i in 0..foo.len() onde se encaixa perfeitamente, então eu prefiro que fique (eu preciso disso, porque os iteradores de Rust são "unidimensionais" e frequentemente muito estranho para usar com matrizes 2D ou iteração não linear).

O problema com estouro para intervalos inclusivos parece bobo, mas na prática nunca tive esse problema, porque Rust é irritante de usar com qualquer tipo diferente de usize . Se eu não tivesse lançado ao criar o intervalo for i in 0..(len as usize) , então eu teria que usar i as usize meia dúzia de vezes dentro do loop de qualquer maneira.

Como essa sintaxe ainda está bloqueada por recursos, espero que o navio não tenha navegado.

Considerando que o swift usa ... para inclusivos e ..< para intervalos exclusivos, usar ..= para inclusivos parece bastante razoável.

Não tenho nenhuma ideia útil, mas gostaria que os intervalos inclusivos saíssem do status "experimental". Enquanto eu examinava Rust By Example, encontrei um snippet que pode se beneficiar disso:

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

Acima ? 😄

Quero escrever um RFC para a sintaxe a ..= b e intervalos generalizados. Comecei um tópico de

IMHO .. = parece estranho. A abordagem do Swift de ... e .. <parece melhor para mim, porque eu prefiro reticências a dois pontos - reticências significam omissão e estamos omitindo os números entre o início e o fim do intervalo.

Eu ainda acho ... e ... foi bom o suficiente. Você tem 1 caractere de diferença, então o erro é mais difícil de cometer do que +/- ou x / y ou qualquer outro.

Já que eu mesmo não entendi isso antes (e então excluí meu comentário):

De acordo com o processo RFC de Rust, esta proposta já foi revisada, discutida e aprovada na solicitação pull RFC 1192 . A presente edição acompanha a implementação do que foi previamente decidido ali. A discussão cobriu muitos dos pontos que as pessoas estão levantando aqui: sintaxe alternativa (incluindo nenhuma sintaxe nova), o contraste com operadores semelhantes de Ruby, etc.

Se você acredita que o recurso deve ser diferente, acho que precisa passar pelo mesmo processo de RFC, porque é assim que as alterações no idioma são feitas. Mas este problema não é o lugar para isso.

@jimblandy talvez devêssemos fazer com que @nikomatsakis editasse aquele lembrete educado e orientação no primeiro comentário em letras grandes. 😇

@shepmaster Isso provavelmente seria uma boa coisa para adicionar a um modelo usado para arquivar _todos_ os problemas de rastreamento.

Nomeação para discussão / possível FCP

Discutimos isso na reunião @rust-lang / lang. Havia uma sensação geral de infelicidade com esse recurso - consideramos mudar para o uso suspenso, mas decidimos adiar por enquanto. Existem duas objeções principais a ... como está:

  • a facilidade de confusão entre .. e ... ;
  • @aturon tem pensado que seria melhor ter uma sintaxe de intervalo mais "totalmente capaz" - isso também poderia ser usado em APIs como iteração btree e assim por diante.

Para esse fim, gostaríamos de saber se alguém estaria disposto a apresentar um RFC que permitisse uma sintaxe mais geral como aquela que permitisse às pessoas especificar com precisão se os limites inferior e superior seriam inclusivos ou exclusivos. Acho que @aturon ficaria feliz em trabalhar com alguém em tal RFC.

Eu sei que parei por um tempo, mas recentemente abri um tópico de discussão sobre como representar esses intervalos totalmente capazes em libstd (link acima ), mas ninguém comentou :(

Com algumas sugestões acima, ficarei feliz em ajudar com um novo RFC.

Recentemente, abri um tópico de discussão sobre como representar esses intervalos totalmente capazes em libstd (link acima), mas ninguém comentou :(

Isso reflete um pouco sua utilidade.
Embora ter intervalos arbitrários inclusivos-exclusivos pareça uma boa ideia, tenho quase certeza de que tudo, exceto .. e, em muito menos grau, ... nunca será usado.

@durka

Eu sei que parei por um tempo, mas abri o tópico de discussão sobre como representar esses intervalos totalmente capazes em libstd (link acima), mas ninguém comentou :(

Isso se parece muito com a abordagem que tínhamos em mente, sim.


@petrochenkov

Embora ter intervalos inclusivos-exclusivos arbitrários pareça uma boa ideia, tenho certeza de que tudo, exceto ... e em muito menos grau ... nunca será usado.

Para ser honesto, concordo, mas ainda acho que pode valer a pena buscar uma sintaxe mais geral. Em particular, acho que ... é subótimo, mas se mudarmos para ..= ou algo mais explícito, provavelmente não faz mal fazer algo um pouco mais geral, mesmo que raramente usava. Ou seja, se o tornarmos sistemático, não parece muito mais difícil de aprender, e certamente não haveria confusão se .. ou ... significa "mais números "

Isso se parece muito com a abordagem que tínhamos em mente, sim.

Qual deles? Eu sugeri várias alternativas em meu post.

Freqüentemente, desejo iterar em intervalos inclusivos e realmente gostei de digitar 0...x vez de 0..(x + 1) . Eu entendo que isso pode introduzir erros um a um, mas que alternativas temos?

Supondo que a sintaxe de Rust pudesse ser alterada livremente sem efeitos colaterais, vejo apenas alguns padrões óbvios:

Tomando como está

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

que é uma boa solução IMHO e também usada na correspondência de padrões.

Pegar emprestado da matemática

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

que é a sintaxe mais completa, mas quebra a mesma regra de colchetes de abertura e fechamento e é visualmente mais difícil de analisar.

Pegar emprestado de Python

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

que é um padrão conhecido e também pode incorporar um tamanho de etapa. Não sei como funciona o processo RFC, mas acho que um tamanho de passo também deve ser considerado ao falar sobre intervalos.

Quando o tamanho do passo não faz parte desta discussão (ou futura), ..= e ..< parecem muito razoáveis!

Atualização: acho que ..= e ..< seriam uma solução muito boa. Manter o tamanho do passo como um adaptador faz muito mais sentido.

Essa discussão deve incorporar faixas descendentes? A solução atual de inverter o intervalo é bastante confusa (mas talvez não fosse se tivéssemos intervalos inclusivos).

por exemplo, você pode ler e entender isso sem apertar os olhos?

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

EDITAR: e com a fonte do GitHub é ainda mais confuso porque l parece com 1

Acho que um tamanho de passo negativo seria suficiente.

Poderíamos usar a sintaxe do Matlab, a:b e a:step:b .

Em 4 de novembro de 2016, 00:50, "Ott" [email protected] escreveu:

Acho que um tamanho de passo negativo seria suficiente.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment -258344460,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AAC3n3kwnGH6POQb4dGwCwJ8yOGqPSBQks5q6rmDgaJpZM4F4LbW
.

@durka Então, qual seria o equivalente do atual .. , onde não há a ou b ? Apenas : ?

Algo que não vi observado no RFC: foram considerados nomes diferentes para os campos?

Se houver tipos diferentes, pode ser útil ter nomes de campo diferentes quando eles têm significados diferentes. Por exemplo, "range.start" é "o limite inclusivo inferior" em todos os tipos. Mas "range.end" às vezes é inclusivo e às vezes exclusivo. Uma distinção entre "fim" e (espantalho) "último" torna isso mais claro.

(Isso é, obviamente, irrelevante se os diferentes tipos forem abandonados em favor do intervalo> ...)

Acho que o intervalo inclusivo ainda deve implementar std :: Collections :: range :: RangeArgument.

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

Então

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

Assim, fn foo<T, R: RangeArgument<T>>(arg: R) pode assumir intervalos inclusivos ou semi-abertos.

@durka O problema com a sintaxe a: b é que ela é ambígua com a atribuição de tipo. Você está pedindo uma variável b ou um tipo b ? Obviamente, como bons programadores de Rust, capitalizamos nossos tipos, mas o compilador não pode inferir isso.

.. operador com definições matemáticas (com base no comentário @duesee ):

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

Usando (com base no exemplo @ 0tt ):

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

Neste caso, usamos .. apenas como uma dica, mas os limites são dados por [ e ]

@adelarsq : No Rust, não precisamos de intervalos que não incluam o início. Mas a sintaxe dos colchetes só faz sentido quando são permitidos. Além disso, a sintaxe de colchetes já é usada.

Acho que ..= é a escolha mais razoável para intervalos inclusivos.
Fácil de distinguir visualmente de .. , o que ... não é. A chance de digitar ... quando significa .. ou vice-versa e não perceber é maior do que com ..= .
(É comparável a digitar acidentalmente if(a = b) vez de if(a == b) em C, tanto em visibilidade visual quanto em potencial de bug).
E ..= é fácil de memorizar porque é simbólico por seu significado ( i ..= j significa o intervalo i .. j e onde i = j ).

Parece que a principal reclamação é que ... é muito semelhante a .. . Percebi que quando outras sugestões são feitas que envolvem mais caracteres, ninguém reclama do número de caracteres, apenas coisas como correspondência de colchetes e uso em determinados lugares.
Então, que tal .... para intervalos inclusivos? Ele ainda deve se parecer com um intervalo e, como eu disse, ninguém parece se importar com uma solução que exige um caractere extra. É discutível se é mais ou menos complicado do que ..= .
for i in 0....10 { println!("just a thought"); }

Se o comportamento padrão fosse inclusivo, o ..! operador seria usado (quase como uma negação).

O problema com .... é que haveria alguma confusão se ... realmente existisse.

Eu também não gosto de ... , já que é exatamente o inverso do Ruby .

A melhor opção até agora é ..= eu acho.

@adelarsq , o operador .... substituiria o operador ... , então se você tentasse fazer .. e adicionasse um . extra, seria uma compilação erro de tempo, se você tentou fazer .... e esqueceu um ponto, isso também seria um erro.

Como na correspondência de padrões, ... é usado para corresponder ao intervalo inclusivo, portanto, faz sentido também usar ... para a expressão do intervalo inclusivo.
Para intervalo com etapa, prefiro a sintaxe Haskell, por exemplo, 1,3..9 => [1,3,5,7]

Para intervalos com step / reverse, etc. Eu prefiro uma boa função antiquada (algum tipo de construtor Range ) em vez de um literal complexo.

Eu ficaria bem com quad-dot .... (embora ..= seja IMHO bom também). Também poderia ser permitido na correspondência de padrões para consistência (e eventualmente ... em padrões poderia ser descontinuado).

Para mim, ..= como uma significação visual que .... não tem.

Acabei de notar algo:

Em matemática, você poderia escrever ∀ i: 0 ≤ i < 10 que se traduziria em

for i in 0 ..< 10 { }

Isso é consistente.

No entanto, a declaração ∀ i: 0 ≤ i ≤ 10 se traduziria em

for i in 0 ..= 10 { }

Aqui, ≤ se traduz em =, o que parece inconsistente.

Isso pode ser bicicleta, mas

for x in 0 ..<= 10 { }

parece mais correto. Isso pode ser devido à minha formação em C, onde

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

se traduz em "desde que i seja menor ou igual a 10 faça algo". Em CI prefira não usar == em condições de loop, devido à possibilidade de pular o valor e terminar em um loop infinito. Isso não pode acontecer no Rust, mas traduzir for i in 1 ..= 10 para C pode sugerir exatamente isso.

Indo mais longe,

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

seria autoexplicativo.

Edit: aqui estava um mau exemplo reverso para mostrar como usar apenas = pode ser confuso. Excluído por ser mais confuso do que construtivo.

@duesee Como >=..> autoexplicativo? Não deveria ser <=..> (<= 10 e> 0)?
IMO não é autoexplicativo, é enigmático e muito longo como um operador.
(Nenhum operador deve ter mais de 3 caracteres IMO).
A propósito, já temos uma maneira de expressar a direção da iteração reversa: .rev()
Precisamos apenas de operadores para intervalos inclusivos e talvez .step_by() .
Para a etapa, a sintaxe pode ser a .. b | s (e para intervalos inclusivos: a ..= b | s ).

@norru : Seu exemplo for i in (1..l.len()).rev() { ... } é muito irreal, pois na maioria das vezes você usaria fatias ( for x in arr[1..].rev() { ... } ), mas mesmo se você for forçado a usar o estilo de índice de iteração (basicamente apenas quando você modifica elementos do array que não estão em i ), não acho difícil de ler. (Mas geralmente deixo espaços em torno de .. quando os argumentos não são números literais: (1 .. arr.len()).rev() )

>=..> mais espécies de peixes nos operadores Rust!

Mas eu gosto muito de ..<= (editar: uhh, exceto em match onde parece <= 0 => :()

  • É muito diferente do simples .. ,
  • não tem a conotação += de ..= ,
  • é logicamente consistente mesmo com ..< Swift. É possível que os dois idiomas convergam!
  • e o mais importante, é bastante claro que você obtém números no intervalo que são menores ou iguais ao superior.

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

@Boscop : é autoexplicativo se você lê-lo como uma definição em matemática: 10 >= i > 2 . Quanto ao resto da sua resposta: concordo absolutamente. A segunda parte foi pensada como uma motivação para repensar ..= vs. ..<= para não introduzir bloqueadores para extensões futuras. Vou editar minha resposta de acordo.

também pode obter um sinalizador para avisar ou erro na notação ..

Não quero que .. apareça em nenhum lugar da minha base de código

Eu gostaria de colocar outro voto em ..=

A desvantagem de ..< e ..<= é que eles já são códigos válidos (um intervalo exclusivo aberto à direita sendo comparado a outro valor).

@thepowersgang

A desvantagem de .. <e .. <= é que eles já são códigos válidos (um intervalo exclusivo aberto à direita sendo comparado a outro valor).

embora seja verdade, parece bastante improvável que isso seja um problema na prática, não?

Eu prefiro ... às outras sugestões aqui .. mas se eu tivesse que escolher uma sintaxe alternativa, seria ..=

@nikomatsakis

Sou contra as opções ..< e ..<= simplesmente porque complicam desproporcionalmente o processo de aquisição de um modelo intuitivo da gramática da língua.

Em uma nota mais pessoal, eu os acho pelo menos tão feios e deselegantes quanto os peixes turbo.

Eu escolheria .. para direito exclusivo e ..= para inclusivo como o melhor equilíbrio entre elegância visual, regras gramaticais que são fáceis de entender intuitivamente e tornando as duas difíceis de confundir.

... realmente tão indistinto de .. ? Por que eu gosto tanto disso?

@tshepang

Gosto de ... porque é esteticamente atraente ... mas argumento contra porque me preocupo que tenha o potencial de causar bugs difíceis de notar semelhantes a escrever if (x = 2) { vez de if (x == 2) { em C / C ++. (E está bem estabelecido o perigo que acabou sendo.)

@ssokolow

IMO que é melhor resolvido por linting ou sinalizadores de opção. Não vejo muita utilidade em misturar notações em um único arquivo / projeto.

Também prefira .... sobre as outras opções, ter o dobro da largura / espaçamento deve ser bastante óbvio, especialmente considerando que eles serão flanqueados em ambos os lados por símbolos que farão o espaço negativo mais pronunciado do que isolado.

@ssokolow

Eu escolheria .. para direito exclusivo e .. = para inclusivo como o melhor equilíbrio entre elegância visual, regras gramaticais que são fáceis de entender intuitivamente e tornando as duas difíceis de confundir.

Funciona para mim. O principal ponto de discórdia é se também queremos uma sintaxe para outros casos (por exemplo, <..<= ). Pessoalmente, acho que .. e ..= cobrem 99,5% dos casos. Acho que o principal caso de uso são APIs como drain , e atualmente adotamos uma abordagem distinta lá .

cc @ rust-lang / libs

Podemos deixar os casos incomuns para construir diretamente os intervalos usando
literais de estrutura.

Na quarta-feira, 22 de fevereiro de 2017 às 4:50 PM, Niko Matsakis [email protected]
escreveu:

@ssokolow https://github.com/ssokolow

Eu escolheria .. para direito exclusivo e .. = para inclusivo como o melhor
equilíbrio entre elegância visual, regras gramaticais fáceis de intuitivamente
agarrar, e tornando os dois difíceis de confundir.

Funciona para mim. O principal problema é se também queremos um
sintaxe para outros casos (por exemplo, <.. <=). Eu pessoalmente sinto que .. e .. =
cobre cerca de 99,5% dos casos. Acho que o principal caso de uso são APIs como dreno,
e atualmente adotamos uma abordagem distinta lá
https://doc.rust-lang.org/std/collections/struct.BTreeMap.html#method.range
.

cc @ rust-lang / libs https://github.com/orgs/rust-lang/teams/libs

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-281815665 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AAC3n-aKwYKFq4VI9RizL0GkzXXSjTPwks5rfK2ngaJpZM4F4LbW
.

Presumo que ..= também estará disponível em padrões? O que acontecerá com a sintaxe ... lá?

Ele pode ser descontinuado. Mas sua existência é um precedente muito forte para
usando-o, pelo menos como uma abreviação.

Na quarta-feira, 22 de fevereiro de 2017 às 18h02, andrewtj [email protected] escreveu:

Suponho que .. = será disponibilizado em padrões também? O que vai ser de
o existente ... sintaxe lá?

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-281834007 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AAC3nw_DaOMNxuIKw6ZFfXJW95QyijY4ks5rfL6DgaJpZM4F4LbW
.

@durka @andrewtj Eu presumiria que iríamos descontinuá-lo.

..= pode ser usado como um operador no mesmo sentido de += .
Eu sugiro usar a maré ~ , por exemplo, 0~9 , 'A'~'Z' .

A qual operação ..= corresponderia? - é obviamente inviável porque
1-9 == -8 .

Na quarta-feira, 22 de fevereiro de 2017 às 20h04, Junfeng Liu [email protected]
escreveu:

.. = pode ser usado como um operador no mesmo sentido de + =.
Eu sugiro usar ~, por exemplo, 0 ~ 9, 'A' ~ 'Z'.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-281856846 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AAC3n7N2dM4DAzc_uc5JdHit4IJgyvYGks5rfNsPgaJpZM4F4LbW
.

@durka ..= apenas se parecem com operadores de atribuição, o caso de uso deve ser raro. ~ é a maré não sub. Usar ... também está ok.

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()  //  ()

Oh, desculpe, parece o mesmo na minha fonte. Eu estava perguntando se .. = é um composto
operador de atribuição como + =, que operação ele executa (correspondente
para +)?

Na quarta-feira, 22 de fevereiro de 2017 às 20:29, Junfeng Liu [email protected]
escreveu:

@durka https://github.com/durka .. = apenas parece uma atribuição
operadores, o caso de uso deve ser raro. ~ é a maré não sub.

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

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-281861478 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AAC3n39uqbADB1rNtBh3PBTRY2XBXOUNks5rfOD-gaJpZM4F4LbW
.

@durka @nikomatsakis ok, bem, espero que isso seja resolvido em breve. A situação atual é estranha e mudar a sintaxe também.

@pornel Remover ... em match quebraria a compatibilidade, então não é uma boa solução. Eu ainda acho ... o mais adequado (no entanto, é o inverso exato do Ruby, mas nenhum problema semelhante é discutido pelos Rubistas).

@ hyst329 mas ... pode ser mais suscetível a erros, já que omitir ou adicionar . dará um novo significado

A suspensão de uso não quebra as coisas. A sintaxe antiga terá que ser suportada para sempre pelos programas existentes, mas os usuários podem ser direcionados para a nova sintaxe por meio de documentação e rustfmt.

mas os usuários podem ser orientados para a nova sintaxe por meio de documentação e rustfmt.

Eu recomendo fortemente contra o uso de rustfmt para isso. Isso exacerbaria as qualidades do estilo footgun de ... quando usado no modo "aplicar alterações automaticamente" porque poderia traduzir silenciosamente erros de digitação em coisas que parecem muito mais objetivas. (Assim, tornando-os mais fáceis de ignorar em um exame posterior.)

Um aviso do compilador no estilo "verifique o que você quis dizer e use .. ou ..= ", que não pode ser corrigido automaticamente, estaria muito mais de acordo com os esforços existentes para minimizar o chance de erro humano.

Observe que eu estava falando no contexto dos padrões existentes de ... em, onde não existe footgun. Atualmente o Rust está em uma situação temporária sem footgun onde os padrões permitem apenas ... e as expressões permitem apenas .. , então ambos estão protegidos contra erros de digitação.

É claro que eu não recomendaria converter ... em expressões em ..= , já que isso, obviamente, tornaria o erro de digitação permanente.

Ahh. Eu tinha me esquecido disso. Obrigado por me lembrar.

@adelarsq Na verdade, erros comuns como 'a'..'z' ou 128u8..255u8 podem ser facilmente integrados em cargo-clippy como avisos, por exemplo. E também, a largura de .. e ... é claramente diferente (ao usar fonte monoespaçada, é claro; não usá-la geralmente é uma má ideia para escrever código-fonte em geral - não apenas Rust) .

Poderíamos simplesmente fazer a sintaxe para ele ser (elipses horizontais unicode) em vez de ... Dessa forma, pelo menos ninguém digitaria por acidente.

Edit: oh ninguém estava tratando essa sugestão a sério: choro: Desculpe pelo barulho.

Não sei, a última vez que verifiquei o Google Docs converte automaticamente ... em reticências. Importante player na indústria de edição de texto.

Além disso, nem todo mundo tem uma tecla Compor para digitar convenientemente o texto . . quando eles querem

No Windows, posso digitar reticências usando Alt + 0133 com o teclado numérico!

E mecanismos semelhantes baseados em pontos de código existem em várias camadas da pilha em desktops baseados em X11 (eu me lembro do GTK + e da pilha de entrada X11 tendo suas próprias soluções independentes), mas é um grande incômodo lembrar pontos de código por número.

Compose é uma solução ṽèŕÿ intuitiva.

A única sequência Alt do Windows de que me lembro é Alt + 219 de todos os menus de arquivo do DOS que fiz quando era criança.

A sintaxe atual já existe há muito tempo, vamos apenas estabilizá-la e parar com essa interminável bicicleta.

Manter a sintaxe atual é o pior que poderíamos fazer, pois tem muitas desvantagens reais . Não se trata apenas de andar de bicicleta - deve ser feito da maneira certa. Pulando todo o tópico, a sintaxe ..= teve a maior aceitação até agora ...

Eu sinto um pouco como se estivesse batendo em um cavalo morto neste ponto, mas quando você pensa sobre isso ... A diferença entre .. e ... é literalmente uma cópia do menor caractere possível que você pode digitar ou ler, misturado com um grupo de caracteres idênticos e tem o potencial de criar uma classe de erro extremamente comum e muitas vezes irritantemente difícil de encontrar (erros por um) em casos que são completamente indistinguíveis de ambos ao homem e à máquina.

Ou poderíamos fazer literalmente qualquer outra sintaxe do mundo.

Por um lado, agradeço essa preocupação ... por outro lado, a sintaxe de correspondência de padrões atual ... já é inclusiva, tornando-a perfeitamente consistente com a sintaxe já usada em outros lugares do Rust.

E pessoalmente não tenho problemas em reconhecer a diferença, embora reconheça que as pessoas com problemas de visão, ou com um monitor de 4k e uma fonte de 10pt, talvez.

Mas parece que o consenso está em ..= e acho que estou bem com isso também.

FWIW, tive aquela situação em que acidentalmente digitei ... quando queria dizer .. e não percebi por um tempo, mas depois de um tempo me perguntei por que meu programa se comportou de maneira estranha.
Portanto, sim, deve haver uma diferença mais visível e ..= faz mais sentido.

Indicando para discussão @ rust-lang / lang. Acho que devemos apenas adotar ..= e encerrar o dia. Precisamos de um RFC alterado? Apenas faça? Isso envolve a descontinuação da sintaxe ... nos padrões? (Eu presumo que sim.)

Sou fortemente a favor de não usar ... para intervalos. Não sei se já foi mencionado neste tópico ou no tópico RFC, mas além de ... ser excessivamente semelhante a .. , também podemos usar ... no futuro para genéricos variados, que são muito mais importantes do que os intervalos inclusivos IMO.

..= parece claro, e sua feiura relativa é justificada por ser menos comum do que .. .

Isso envolve a descontinuação da sintaxe ... existente nos padrões? (Eu presumo que sim.)

Parece uma boa ideia. Avise sobre ... e apóie .. e ..= em padrões, se pudermos.

Em geral, tenho medo de introduzir avisos que afetariam tantas pessoas sem também ter uma ferramenta automatizada para atualizar a sintaxe, mas ... para ..= é uma alteração particularmente simples. Também poderíamos suspender o uso, mas adiar, tornando-o um aviso até que tenhamos essa ferramenta. O que todo mundo pensa?

Eu sou fortemente a favor de ... porque é uma sintaxe mais "usual"; Não conheço nenhuma linguagem que use ..= , mas muitas que usam .. e ... .

Se o sentimento contra ..= for forte, eu preferiria não usar nenhuma sintaxe de intervalo inclusivo (em vez de optar por um método (a..b).inclusive() , que parece conciso o suficiente para mim) para evitar o problema visual e novamente gratuito até ... para genéricos variados.

EDITAR: Um bom argumento contra (a..b).inclusive() é que ainda teremos ... em match e nenhuma nova sintaxe para substituí-lo, infelizmente. :confuso:

@steveklabnik Desculpas se isso já é mencionado em algum lugar deste (muito longa) segmento, mas: o que as outras línguas usam ambos .. e ... para faixas exclusivos e inclusivos, respectivamente?

Rust tem um histórico de adotar características úteis e sintaxe de outras linguagens, mas seletivamente , e rejeitar ou adaptar coisas quando apropriado.

@joshtriplett Ruby usa ambos, mas com significados opostos ( .. é inclusivo, ... é exclusivo). Não acredito que tenha sido uma boa ideia em Ruby, e parece ainda mais potencialmente confuso para nós ter os dois, mas ao contrário.

@joshtriplett, o que estou mais familiarizado é Ruby; Achei que fosse do Perl, mas não tenho certeza. Estou mais satisfeito com a semântica sendo retroativa de Ruby do que com ..= .

Honestamente, eu preferiria uma sintaxe de intervalo inclusiva estável a qualquer outra coisa, e reconhecer que minha intensa aversão por ..= é uma coisa pessoal, da qual pessoas razoáveis ​​podem discordar.

@steveklabnik Swift usa ..< , eu acho, certo? O que parece semelhante a ..= mas pior, porque otimiza para (imo) o caso errado. =)

O Swift usa .. <para exclusivo e ... para inclusivo (seus termos são
"meio aberto" e "fechado").

Eu ainda gosto de .. <(com .. como abreviação) e .. =.

Mas outra questão em aberto (talvez não dentro do escopo deste problema de rastreamento) é se "apenas" adotamos uma sintaxe para intervalos fechados, ou também sintaxes (sintaxe?) Para intervalos com o primeiro ponto aberto, ou seja, espantalho> ..> e > .. =.

Em quinta-feira, 16 de março de 2017 às 14h19, Niko Matsakis [email protected]
escreveu:

@steveklabnik https://github.com/steveklabnik Swift usa .. <, eu acho,
direito? Que parece semelhante a .. = mas pior, porque otimiza para
(imo) o caso errado. =)

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-287147321 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AAC3n0Wop5fJh9HVo7pSqo0riHm96Gm4ks5rmX1BgaJpZM4F4LbW
.

Eu não me importaria de ter uma função inclusive no prelúdio:

for x in inclusive(1..10) {

}

Nunca achei que a simetria com o fósforo fosse um argumento convincente. Acho que decidimos adicionar padrões exclusivos de .. , mas também não gosto deles - um valor no padrão agora não corresponde ao padrão! Combinar um intervalo é fundamentalmente diferente de iterar por um intervalo, não há razão para que eles tenham que ser simétricos. Eu teria uma leve preferência em não permitir .. em padrões se ainda for uma opção, mas acho que não é?

Acho que as desvantagens de ..= e ... são significativas - ..= é bastante estranho, mas ... aumenta a probabilidade de erro em 1.

É melhor ter um operador de aparência estranha do que um potencial interminável para bugs (cada linguagem apresenta operadores que outros não têm, por exemplo, ..< em Swift, todos os ops em F # e Scala). As pessoas terão que ler o livro Rust de qualquer maneira.
Considerando que muitas pessoas estão vindo do Ruby para o Rust, não deveríamos fazer isso ao contrário em comparação com o Ruby. (Além do argumento de que ... aumenta a probabilidade de erros off em 1.)
Como você pode aceitar ..< em Swift, mas não aceitar ..= em Rust? ..= não é tão estranho.

Estender a sintaxe de intervalo em padrões ainda é uma questão em aberto também AFAIK.
Por um lado, não podemos fazer isso totalmente, porque Enum::Variant(..) já está
válido e mudá-lo para significar que Enum::Variant(RangeFull) estaria quebrando.

Na quinta-feira, 16 de março de 2017 às 15h07, Boscop [email protected] escreveu:

É melhor ter um operador de aparência estranha (cada linguagem apresenta
operadores que outros não têm, por exemplo .. <em Swift, todas as operações em F #
e Scala). As pessoas terão que ler o livro Rust de qualquer maneira.
Considerando que muitas pessoas estão vindo de Ruby para Rust, nós
não deveria ser invertido em comparação com Ruby. (Além do argumento
que ... aumenta a probabilidade de erro em 1.)
Como você pode aceitar .. <no Swift, mas não aceitar .. = no Rust?

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-287160485 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AAC3nz9ZNR2utl7LPTVvQPQ_Ma8sDBGuks5rmYhmgaJpZM4F4LbW
.

Assim. Quero poder digitar coisas como slice.get(10...30) e comer meu bolo também.

Eu me convenci de que prefiro fortemente inclusive(0..10) a qualquer uma das outras sintaxes:

  • Embora @nagisa queira escrever slice.get(10...30) , não quero ter que prestar atenção se isso é slice.get(10...30) ou slice.get(10..30) . Acho que a proximidade da sintaxe é um problema real.
  • Acho que todos concordam que ..= é estético e provavelmente não é intuitivo.
  • (0..10).inclusive() é a mesma sintaxe, mas menos conveniente. Tecnicamente, inclusive prelude provavelmente suportaria ambas as sintaxes.

Eu acho que seria assim:

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

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

Acho que todos concordam .. = não é estético e provavelmente não é intuitivo.

Acho que dizer isso é um pouco mais de generalização. Acho ..= mais estético e intuitivo do que um método como inclusive() seria.

(Além disso, não sabemos o quanto da antipatia por ..= pode ser um esforço subconsciente (ou consciente) para encontrar problemas com coisas que não são ... .)

.inclusive() é muito longo para algo que ocorre com tanta frequência (nessa nota, também acho que deveria haver um formulário mais curto para .enumerate() ).
Mas mesmo se tivéssemos .inclusive() , deveria haver apenas uma função, não duas.
Além disso, não ter uma sintaxe de intervalo inclusiva não permitiria que eles fossem usados ​​em match .
Mas talvez precisemos de uma maneira de especificar extratores de uma maneira geral, como em Scala ? Para que qualquer tipo possa ser usado em uma correspondência, essa correspondência implicitamente chamará seu método unapply .

(Além disso, não sabemos quanto antipatia por .. = podem ser esforços subconscientes (ou conscientes) para encontrar problemas com coisas que não são ....)

Nada de mim. Isso é uma espécie de acusação de má-fé.

Além disso, não ter uma sintaxe de intervalo inclusiva não permitiria que eles fossem usados ​​em correspondência.

Os padrões de alcance inclusivos já são suportados em match . Na verdade, eles são o único tipo de intervalo que aceitamos como padrões hoje.

@semoutboats sim, mas eu disse "não ter uma sintaxe de intervalo inclusiva não permitiria que eles fossem usados ​​na correspondência". No momento há uma sintaxe, mas meu argumento era contra .inclusive() porque ela não poderia ser usada na correspondência, a menos que tivéssemos extratores como Scala. e todo o ponto desse problema é que a sintaxe de intervalo inclusivo não deve ser um caso especial que só funciona em correspondência e para determinar qual deve ser a sintaxe em vez da atual.

Inclusivo: for i in 1..10! { }

Como alguém que trabalha mais de 15 anos com Java / C / C ++, acho que .. vs ... é muito confuso e pode causar bugs apenas por erros de digitação. Além disso, a relação com Ruby torna isso ainda mais confuso. É por isso que ..= ou qualquer outra alternativa é melhor.

jogando meu 'chapéu' no ringue:

for i in 1..10^

O chapéu / circunflexo simbolizando que o valor correto vai até o fim _up_.

@leebenson Pessoalmente, acho que seria melhor se estivesse no meio, não pregado do lado de fora.

for i in 1..^10

@ retep998 Considerei que depois de clicar em enviar ... provavelmente é mais agradável na verdade.

@ retep998 Gostei da sua sugestão de ..^ muito mais do que ..= ; parece muito mais evocativo de seu significado e evita parecer uma variante estranha de um operador de atribuição aumentada (como += e *= ). Dito isso, qualquer um deles seria muito melhor do que ... .

Não consigo ficar atrás de ..^ .

Em um nível pessoal, acho isso muito feio (em parte porque .. é tão verticalmente separado dos ^ em muitas fontes).

Como um cara de UI / UX, acho que é um exemplo de ser muito inteligente para o seu próprio bem.

Se eu vier de outro idioma e vir ..^ , posso nem mesmo reconhecê-lo como um intervalo (pelo que sei, 5..^15 poderia ser uma forma abreviada de fatorial parcial esquisita para 15! - 4! ) porque os humanos pensam em contextos e a única associação que o personagem tem em um contexto de programação convencional é a exponenciação.

(Se não pensássemos em contextos, ... poderia significar algo como "retorno de chamada é inserido aqui" ou "evento de emissão" por analogia ao seu "conteúdo omitido" - como significado no diálogo na escrita da prosa, apenas para mostre o exemplo mais imediato. Dar a ele um significado "vai até o alto" por meio de sua semelhança com uma flecha é como fazer truques de mágica por meio de prestidigitação, no que diz respeito à forma como ele interage com as expectativas do recém-chegado.)

Por outro lado, = tem precedente para se referir tanto à ação de atribuição quanto ao conceito de igualdade e não há "sintaxe de exponenciação estranha" - como equívoco para ..= porque o mais próximo que você pode chegar de " atribuição + igualdade "que ainda não foi tratada pelo operador de atribuição é" algo a ver com uma sequência de números, terminando no lado direito "... que é uma definição vaga, mas apropriada do que a sintaxe de intervalo faz.

Eu também me preocupo que, mesmo se eu reconhecesse que ..^ era uma sintaxe de intervalo de seu uso no contexto, eu não teria nenhuma ideia intuitiva se era inclusiva ou exclusiva no início, porque não há significado para ^ no contexto relevante, exceto para a possibilidade de que 2..^8 seja uma abreviação para um intervalo aberto começando em dois e avançando ao dar o passo anterior à potência de 8. (ou seja, 2..Inf^8 em oposição a 2..+8 sendo uma abreviação de "iterar de 2 ao infinito em etapas de 8".)

Esse problema também é evitado por ..= porque as pessoas estão acostumadas a pensar em termos de < (exclusivo) vs. <= (inclusive) ao escrever while loops e loops de estilo C for .

análise legítima @ssokolow .

Pessoalmente, posso ficar atrás de ..= ou ..^ . A simbologia de qualquer um deles faz sentido para mim - isto é, 'até e igual a' ou simplesmente 'até', respectivamente. Ambos significam a mesma coisa, na minha opinião.

Vai ser difícil chegar a algo que satisfaça a todos, porque todos nós trazemos história de outras línguas e com ela, simbologia / preconceito contaminado. Eu inicialmente adicionei o sinal ^ _após_ o número, por exemplo, porque inserir antes tinha a sensação de representar um 'passo' ou expoente, enquanto um sufixo deixava o intervalo imaculado e, de alguma forma, mais puro. Mas isso sou só eu.

Em qualquer caso, eu preferiria uma notação abreviada de alguma forma em vez de uma chamada de função que implicitamente + 1s o val do lado direito. Concordo com comentários anteriores de que esta é uma sintaxe muito comum para delegar a algo que parece uma chamada de função. Eu nem me importaria de ... , mas concedido, é provavelmente o bug de = / == em roupas novas e prestes a atirar no pé de alguém ...

muitas pessoas parecem não gostar ativamente .. = ninguém disse nada negativo
sobre .... foi apenas silenciosamente ignorado (exceto por alguns polegares para cima) I
pensei em trazer isso à tona novamente e fazer as pessoas considerarem e darem um
razão para não usá-lo se forem contra.

Eu odeio até mesmo mencionar isso porque é apenas mais barulho, mas e quanto a isso.:
(ponto e vírgula) para inclusivo? São 3 pontos, mas 2 caracteres, e acho que
forma o torna distinto de ..

No sábado, 18 de março de 2017 às 11h50, Lee Benson [email protected]
escreveu:

@ssokolow https://github.com/ssokolow análise legítima.

Pessoalmente, posso ficar atrás de .. = ou .. ^. A simbologia de qualquer
faz sentido para mim - ou seja, 'até e igual a' ou simplesmente 'até',
respectivamente. Ambos significam a mesma coisa, na minha opinião.

Vai ser difícil chegar a algo que satisfaça a todos,
porque todos nós trazemos história de outras línguas e com ela, contaminada
simbologia / preconceito. Eu inicialmente adicionei o sinal ^ após o número, para
exemplo, porque inserir antes tinha a sensação de representar um 'passo'
ou expoente, ao passo que um sufixo deixou o intervalo intacto e, de alguma forma, mais puro
sentimento. Mas isso sou só eu.

Em qualquer caso, eu preferiria uma notação abreviada de alguma forma em vez de um
chamada de função que implicitamente + 1s o val do lado direito. Eu concordo com antes
comenta que esta é uma sintaxe muito comum para delegar a algo que
parece uma chamada de função. Eu nem me importaria ..., mas concedido, é
provavelmente o = / == bug em roupas novas e prestes a atirar em alguém no
pé...

-
Você está recebendo isto porque comentou.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-287566556 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AIhJ6jWgPwndKaQvVjULlV_OoC6WDO0Cks5rnCeLgaJpZM4F4LbW
.

Oh, ainda está em uma fase de ciclismo? 😆

Lendo novamente, acho que concordo com @nikomatsakis em apenas torná-lo ..= e encerrar o dia. A similaridade de .. vs ... é muito sutil, e eu prefiro ver o token ... ser usado sem ambigüidade para genéricos variados (https://github.com/ rust-lang / rfcs / pull / 1935), onde cumpre um propósito muito distinto que deve levar a menos confusão entre os dois.

Não tenho certeza se o desejo de uma sintaxe mais generalizada para todas as variantes semiabertas ainda existe, mas acho que não vale o esforço para fornecer uma sintaxe de linguagem fora de .. e ..= .

Eu odeio mencionar isso porque é apenas mais barulho, mas e quanto a.: (Ponto e vírgula) para inclusivo?

Acho que @ssokolow fez alguns pontos importantes sobre: ​​UI / ser inteligente. Eu diria que mudar a direção do terceiro ponto para enganar seus olhos e fazê-los ver outra coisa provavelmente estaria nessa categoria.

Eu pessoalmente tenho objeção _zero_ à existência de um terceiro ponto, além de saber que ele pode fazer algumas pessoas tropeçarem eventualmente. Mas também é muito fácil de explicar, então não tenho certeza se a responsabilidade deveria recair sobre a linguagem para criar soluções alternativas inteligentes. É '2 pontos exclusivos; 3 pontos inclusive 'realmente _que_ difícil de entender / depurar?

Em qualquer caso - quem toma a decisão final e qual é o próximo passo para encerrar isso? 18 meses discutindo o terceiro personagem provavelmente _é_ passeio de bicicleta neste momento 😄

Concordo, ^ faz com que pareça um passo.
IMO, a inconsistência com outros op= operadores não é problema porque nunca teríamos a ..= b no sentido de a = a .. b , uma vez que .. é não um operador, mas um açúcar sintático para construir um Range (e não temos um esquema geral de sobrecarga de op onde qualquer op obtém automaticamente a forma de op= e .. ).
Não estou dizendo que ..= está claro sem olhar para o documento. Mas, uma vez que as pessoas olham para o documento, é mais fácil memorizá-lo e, de qualquer maneira, elas terão que olhar para o documento.

Dada a nomeação de @nikomatsakis , acho que vamos acabar discutindo isso na reunião da equipe lang da próxima semana e provavelmente ligando nesse momento. Eu concordo que isso só precisa da equipe lang para fazer uma ligação e encerrar o casamento de bicicletas.

Eu também me preocupo que, mesmo se eu reconhecesse que ..^ era uma sintaxe de intervalo de seu uso no contexto, eu não teria nenhuma ideia intuitiva se era inclusiva ou exclusiva no início

Acordado. Na verdade, eu já vi essa sintaxe no Perl 6 onde significa exclusivo, o oposto da proposta aqui.

@solson Esse é um argumento muito convincente contra isso.

Perl parece ter uma sintaxe totalmente geral, com .. o significado inclusivo (em ambos
lados) e ^ em cada lado torna esse limite exclusivo.

No sábado, 18 de março de 2017 às 18:51, Josh Triplett [email protected]
escreveu:

@solson https://github.com/solson Esse é um argumento muito convincente
contra isso.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-287580739 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AAC3n7Fnn1_t9BkYOhfS-7oCaGlVff2aks5rnF_5gaJpZM4F4LbW
.

Lamento dizer, mas quando discutimos esse assunto na reunião @rust-lang / lang, não chegamos a um consenso. @withoutboats em particular tem algumas reservas severas que espero que eles possam

Alguns pontos principais que discutimos:

  • Se tivermos uma sintaxe de intervalo inclusivo em expressões e padrões, deve ser o mesmo

    • ou seja, se adotarmos x ..= y , isso implica em descontinuar a sintaxe do padrão x...y .

  • Uma opção tentadora é "não fazer nada" e apenas escrever (x..y).inclusive() ou algo parecido. No entanto, isso não funcionará em padrões (que provavelmente permaneceriam como x...y ). Isso levanta algumas questões por si só:

    • Ainda queremos padrões de alcance exclusivos ? por exemplo, match 3 { 1..3 => false, .. }



      • Nesse caso, teremos a mesma confusão potencial!



    • @semoutboats parece pensar que talvez não queiramos tais padrões. Eu e @joshtriplett duvidávamos disso; Acho que ambos tínhamos a opinião de que eles são o tipo de coisa que parece irrelevante até que você os deseja e, então, parecem absolutamente necessários . =)

  • Outro problema em torno dos padrões de intervalo exclusivos é que eles interagem mal com os padrões de fatia (também instáveis) (consulte https://github.com/rust-lang/rust/issues/23121 para obter detalhes).

Acho que uma coisa que saiu dessa discussão foi que seria bom tomar uma decisão sobre todos os fatores conflitantes de uma vez . Em outras palavras, para adotar uma decisão que resolva:

  • O que fazer com as expressões de intervalo exclusivo?
  • Precisamos descontinuar / alterar os padrões de alcance exclusivos existentes?
  • O que fazer com os padrões de alcance inclusivo ?
  • O que fazer com os padrões de fatia ?

Antes de começar a escrever, quero dizer que me senti muito inseguro de que, a cada momento da conversa, estávamos todos falando sobre o mesmo conceito. Por exemplo, Niko diz que "padrões de alcance exclusivos parecem irrelevantes até que você os queira", mas pensei que Niko e Josh estivessem falando sobre expressões de alcance inclusivo naquela época.

(E eu acho que na última parte da postagem de Niko, o primeiro marcador que atualmente lê "expressões de intervalo exclusivo" deveria dizer "expressões de intervalo inclusivo".)

TL; DR minha opinião

Sobre expressões de intervalo:

  • Não devemos introduzir nenhuma sintaxe para expressões de intervalo inclusivo - nem ... nem ..= .
  • Devemos adicionar ao prelúdio uma função que assume um valor de intervalo exclusivo e retorna um valor de intervalo inclusivo. Então, você escreveria inclusive(0..10) (o nome pode ser encaixado em bicicletas).

Sobre os padrões de alcance:

  • Não devemos introduzir padrões de alcance exclusivos, ou qualquer forma de criar um.

Em outras palavras, a única mudança material que devemos fazer é uma mudança na biblioteca: adicione uma função ao prelúdio.

Expressões de intervalo

Fundamental para o meu argumento é o fato de que iterar por meio de um valor de intervalo inclusivo é uma necessidade incomum. Acho que isso é confirmado pelo fato de que, apesar da RFC ter sido aceita 18 meses atrás, ainda não estabilizamos esse recurso - não por causa de problemas de implementação, mas porque não estamos satisfeitos com a troca.

Acho que as expressões de intervalo inclusivas são necessárias com freqüência suficiente para que possamos oferecer suporte a uma maneira direta de criá-las, mas não com freqüência suficiente para que superem qualquer uma das desvantagens das sintaxes que discutimos até agora.

Em particular, uma desvantagem que cada solução sintática compartilhou é que nenhuma delas é realmente autodocumentada. É relativamente não óbvio que 0...10 ou 0..=10 é uma expressão de intervalo inclusiva . Como eles serão encontrados com pouca frequência, isso será um obstáculo para os usuários que os encontrarem pela primeira vez.

Isto é, se o usuário perceber que não está lidando com uma faixa "normal" de .. . Claro, este é o grande problema de ... , mas ..= não elimina totalmente o problema. É fácil, ao folhear o código, perder aquele caractere = (ou ^ ou : ou qualquer outro). Não é tão fácil quanto os . extras, mas não estou convencido de que seja perceptível o suficiente.

Na verdade, acho que há uma troca "perceptibilidade x obviedade" entre ... e ..= . Eu acho que é mais óbvio o que ... significa (a menos que você esteja vindo de Ruby, onde as duas sintaxes têm o significado oposto) do que ..= , mas é definitivamente menos perceptível .

Mas acho que uma função de prelúdio como inclusive(0..10) é mais óbvia e mais perceptível do que qualquer sintaxe que discutimos. Sim, são mais caracteres para digitar, mas a desvantagem desse atributo é relativa à frequência de uso.

Ele também contorna qualquer um dos problemas de análise e tokenização, e ajuda os usuários com o (muito irritante) problema de precedência de método vs intervalo que exige que eles escrevam (0..10).filter e outros semelhantes.

Padrões de alcance

A principal razão pela qual acho que não devemos adicionar .. é que isso introduz ambigüidade em torno dos padrões de fatia, que acho úteis. Eu gostaria de resolver esse problema não tendo que resolvê-lo.

A segunda razão é que eu acho que eles são um estilo muito ruim (eu sei que outras pessoas discordam). Por exemplo:

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

Acho isso confuso, porque 10 não corresponde ao padrão que o contém. Niko mencionou que isso não é realmente diferente de expressões de intervalo exclusivo que não rendem 10 , mas acho que a grande diferença é que temos muitos precedentes históricos (e casos de uso) no estilo Dijsktra para oferecer suporte exclusivo gamas. Chegando ao Rust, eu esperava que os intervalos iterativos e de fatiamento fossem exclusivos, mas não tinha essa expectativa para os padrões.

Ele também tem o problema "off-by-one" que .. / ... em expressões tem.

Eu sei que Niko mencionou que gostaria de escrever:

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

Mas eu realmente preferiria ver:

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

De qualquer forma, fiquei surpreso que Niko quisesse dizer que às vezes acha isso "absolutamente necessário", então gostaria de ouvir mais contra-argumentos. Já que eles têm que ser um constexpr, parece muito mais um 'bom ter' do que uma coisa 'absolutamente necessária' para mim.

Eu definitivamente me sinto mais fácil de influenciar padrões de alcance exclusivo do que expressões de alcance inclusivo.

O argumento de consistência

Niko mencionou que ter .. e ... em ambas as expressões e padrões é importante para ele por causa da consistência. Estou basicamente totalmente indiferente a esse argumento. Iterar por um intervalo e combinar em um intervalo não são operações realmente análogas, e faz sentido que haja diferenças entre como os tratamos.

Na verdade, não há nem mesmo uma conexão de implementação: 1..10 produz um valor de intervalo, enquanto 1...10 corresponde a um valor inteiro. Não é como se eles tivessem uma conexão de estruturação / desestruturação da maneira que a maioria de nossas expressões simétricas / sintaxes de padrão têm.

Parece mais tecnicamente correto chamar os padrões de "padrões de domínio" do que de "padrões de alcance" 🤓, o que destaca a não analogia.

@withoutboats

Por exemplo, Niko diz que "padrões de alcance exclusivos parecem irrelevantes até que você os queira", mas pensei que Niko e Josh estivessem falando sobre expressões de alcance inclusivo naquela época.

De minha parte, encontrei intervalos exclusivos e inclusivos necessários em vários momentos (embora eu tenha usado o exclusivo para ambos os casos para trabalhar no Rust estável e tive que contorná-lo com +1 na parte superior limite). Eu gostaria de tê-los disponíveis para padrões e expressões.

Dito isso, pessoalmente, eu não teria objeções ao uso de uma função para intervalos inclusivos, exceto que eu quero ter uma maneira de escrever intervalos inclusivos e exclusivos em padrões e gostaria que essas duas sintaxes não parecessem confusamente semelhantes como .. e ... fazem. E dada uma sintaxe para escrever tais intervalos em padrões, não sei se faz sentido ter uma sintaxe diferente para tais intervalos em expressões.

Em particular, uma desvantagem que cada solução sintática compartilhou é que nenhuma delas é realmente autodocumentada. É relativamente não óbvio que 0 ... 10 ou 0 .. = 10 é uma expressão de intervalo inclusiva. Como eles serão encontrados com pouca frequência, isso será um obstáculo para os usuários que os encontrarem pela primeira vez.

Eu concordo com isso. Isso ocorre com tanta frequência que eu não faria objeções a uma sintaxe menos compacta. Gostaria, no entanto, de ter algum mecanismo para escrever intervalos inclusivos e exclusivos em expressões e padrões.

Eu não me importaria, por exemplo, se escrever um padrão de intervalo inclusivo exigisse uma macro ou algo semelhante.

@joshtriplett É aqui que quero ser bem claro quando você diz o seguinte:

Eu descobri que os intervalos exclusivos e inclusivos eram necessários em vários momentos (embora eu tenha usado o exclusivo para ambos os casos para trabalhar no Rust estável e tive que trabalhar em torno dele com +1 no limite superior).

Parece claro que você está falando sobre expressões , mas a seção que você citou foi sobre padrões (eu sei que você fala sobre padrões no próximo parágrafo, mas estou perguntando sobre a questão da "necessidade" que esse parágrafo não aborda 😃) .

O status quo para padrões é que só oferecemos suporte a padrões de intervalo inclusivos, da forma x...y . Você pode falar mais sobre se / quando você achou padrões de alcance exclusivos realmente frustrantes de não ter?

@withoutboats

Você pode falar mais sobre se / quando você achou padrões de alcance exclusivos realmente frustrantes de não ter?

Algo como

    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> */ }
    }

vs

    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> */ }
    }

Eu não diria que é especialmente frustrante, mas o primeiro certamente parece melhor.

@withoutboats Para maior clareza, em vários momentos eu quis expressões de intervalo exclusivas, expressões de intervalo inclusivas e padrões de intervalo inclusivos. Não consigo pensar em uma ocasião em que me preocupei profundamente em ter padrões de alcance exclusivos, embora também não me oponha a eles. Mas mesmo se não tivermos padrões de intervalo exclusivos, ainda seria muito confuso se os padrões de intervalo inclusivos usassem ... e as expressões de intervalo exclusivo usassem .. .

@petrochenkov Presumo que isso terminasse em F , não em C ?

Eu encontrei o mesmo caso com padrões de intervalo hexadecimal, por exemplo, 0x8000...0x9FFF => /* body */ . Acho que 0x8000..0xA000 tem propriedades um pouco mais intuitivas, como, sem ter que pensar sobre isso, vejo imediatamente que o tamanho do intervalo é 0xA000 - 0x8000 = 0x2000 e que o próximo intervalo adjacente começa em 0xA000 .

Lidar com os +1 necessários para ver esses fatos em uma faixa inclusiva é uma pequena diferença com a qual posso conviver, mas faixas exclusivas (padrões e expressões) geralmente se adaptam melhor ao meu trabalho.

@petrochenkov Eu posso ver porque você prefere intervalos exclusivos para hexdigits (eu ainda posso não, mas isso parece um negócio muito YMMV).

Porém, como lidaríamos com as ambigüidades da sintaxe da fatia?

@joshtriplett

Ainda seria muito confuso se os padrões de intervalo inclusivo usassem ... e as expressões de intervalo exclusivo usassem .. .

É assim que o Rust funciona hoje e não parece ser uma fonte significativa de confusão?

@solson

Presumo que isso terminasse em F, não em C?

Não :)
(Essas coisas são de 32 bits e offset é um múltiplo de quatro.)

@withoutboats

Eu posso ver porque você prefere intervalos exclusivos para hexdigits (eu ainda posso não, mas isso parece um negócio muito YMMV).

Devo observar que esta não é uma preferência forte, eu ainda estaria bem em descartar padrões exclusivos e intervalos inclusivos (mas nenhum deles, isso seria muito ridículo).

Porém, como lidaríamos com as ambigüidades da sintaxe da fatia?

Facilmente! PATTERN.. => .. @ PATTERN

Meu principal motivo para querer que os intervalos inclusivos sejam simples é que já passei por situações mais de uma vez em que estou passando um valor de parada em uma variável e é exatamente o valor máximo que um tipo de variável pode conter, portanto, as únicas soluções para descartar o estouro em tempo de compilação são:

  1. Usando um intervalo inclusivo (mais limpo, mas não estável)
  2. Upcasting antes de + 1 (presume que ainda não estou em u64 e não estou elegante)
  3. Pegando o menor do valor e o máximo menos um para o intervalo e, em seguida, executando a tarefa mais uma vez, se apropriado.

Construir o hábito de usar intervalos inclusivos em vez de adicionar + 1 a um algoritmo onde não tem propósito inerente é uma maneira não trivial de se proteger contra encontrá-los novamente mais tarde em cargo fuzz ... e usar uma função "tornar inclusivo de exclusivo" com mais caracteres em seu nome do que + 1 dá a impressão de que intervalos inclusivos são uma coisa excepcional, ao invés de algo que você deveria estar usando habitualmente.

Esse é um dos maiores motivos pelos quais sou contra. Ele transmite a impressão de que intervalos inclusivos são um hack, a ser usado quando intervalos exclusivos são demonstrados como tendo falhado.

@ssokolow, mas esse caso de uso é confortavelmente coberto por uma função de prelúdio. Ninguém está assumindo a posição de que não deveria ser possível criar intervalos inclusivos, apenas se eles deveriam ou não ter açúcar sintático para criá-los.

Eu gosto da ideia @withoutboats de uma função de prelúdio. Acho que o outro lugar onde os intervalos inclusivos podem ser mais comuns é quando você não usa números inteiros, por exemplo, especificando os limites de uma pesquisa em uma btree (ou estrutura de dados semelhante).

@semoutboats Eu editei um pouco em minha postagem enquanto você respondia, mas a essência do que eu adicionei é que fazer intervalos inclusivos cidadãos de segunda classe, sintaticamente (com uma sintaxe mais longa do que adicionar + 1 a um intervalo exclusivo ), parece um sutil desânimo contra seu uso e uma possível footgun do tipo "Te vejo em cargo fuzz mais tarde".

Se nada mais, é uma verruga ensinável.

Rust não é Python 3.x, com seu suporte a números inteiros ilimitados. A ferrugem não esconde as desvantagens de hardware dos usuários, e vejo ..= que prefiro apenas como parte do uso de u32 e amigos em vez de int . (Especialmente porque os erros de estouro / estouro negativo são a coisa mais comum na "caixa de troféus" de cargo fuzz até agora.)

EDITAR: Por favor, ignore quaisquer bits que você vê apenas nas notificações de e-mail para isso. Acabei de acordar e não estou disparando em todos os cilindros ainda.

Não vejo inclusive(n..m) como um desânimo ... Prefiro escrevê-lo porque é uma construção muito clara que torna meu código mais fácil de ler do que n..(m + 1) e n..=m (que passei a considerar desnecessariamente esquisito quando poderíamos apenas dizer a palavra "inclusivo").

n..=m é mais uma verruga ensinável do que inclusive(n..m) IMO.

Eu acho que para a correspondência existe um desejo de ter uma cobertura completa do intervalo numérico, ao invés de um tipo específico de padrão.

Presumivelmente, se houvesse uma sintaxe "continuar da anterior", isso também resolveria o problema.

BTW, uma vez que apenas o primeiro padrão corresponde, o número inicial pode muitas vezes ser omitido:

    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> */ }
    }

Admito que pode ser uma questão de perspectiva, mas:

  1. Quando vejo .. e ..= , penso "Huh. Eu me pergunto por que eles têm duas sintaxes para uma diferença tão pequena", o que me levaria a procurar documentos que poderiam se concentrar em " 1..pivot e pivot..end " vs. " x..=y onde y pode ser o valor máximo possível".

  2. Antes de ter experiência suficiente para pensar habitualmente em termos de tamanhos variáveis, eu teria usado + 1 vez de inclusive() (se eu fosse procurar por ele), porque tenho usado + 1 desde a escola primária, é curto e fácil de digitar, e meu eu inexperiente está acostumado a trabalhar em linguagens como Python e JavaScript, onde adição que causa estouro não é algo com que as pessoas se preocupem.

EDITAR: ... e é essa distinção conceitual no ponto 1 que acho que devemos nos concentrar. (ou seja, que "de X para o pivô" e "de X para o fim" deve ser diferente na mente do programador.)

@pornel
Isso é horrível 😄
Neste caso específico, o início do intervalo é realmente muito importante para uma pessoa que lê o código, muito mais importante do que quaisquer questões de intervalo inclusivo / exclusivo.

@ssokolow , parece-me que o que torna +1 um problema não é o número de caracteres, mas o fato de você ter que lidar com o potencial de estouro. Além disso, também não comunica a intenção e requer a troca de parênteses de precedência. Tudo isso parece muito mais importante do que o número de caracteres.

É verdade que alguém que não sabe sobre estouro pode alcançar +1 antes de criar um intervalo inclusivo, mas isso não parece dependente da sintaxe. Ambos descobrindo que ..= é uma coisa e que inclusive() é uma coisa - o momento de aprender sobre por que você gostaria de intervalos inclusivos especificamente.

@petrochenkov

Eu ainda estaria bem em descartar os padrões exclusivos e intervalos inclusivos (mas nenhum deles, isso seria muito ridículo) .

Você poderia explicar por que você se sente tão fortemente sobre isso? Definitivamente, vejo a aceitação de padrões exclusivos como tendo uma desvantagem, pois pode levar os usuários a esperar 0...10 como uma expressão, mas não parece tão ruim para mim.

Parte do meu problema com inclusive() é que é "apenas" uma função e me preocupo que as pessoas façam coisas como ir para o índice de sintaxe Rust, pesquisar por "intervalo" ou "iterador" e, em seguida, presumir um ROI insuficiente para "Ver [ing] Iteradores".

("Não quero ler um livro na chance de encontrar algo útil ... Só quero iterar em um intervalo e voltar a fazer progressos.")

@semoutboats Se tivermos inclusivo (a..b), mas não pudermos usar em correspondência, não vale a pena IMO.
Na maioria das vezes, quando estou usando intervalos inclusivos, são em padrões de correspondência!
Então, por que não podemos remover ... e apenas usar ..= dentro e fora da partida?

@Boscop, a proposta não é remover ... da correspondência, mas deixar os padrões exatamente como estão estáveis.

@ssokolow parece que pode ser resolvido facilmente com uma nota na seção ..

@withoutboats Mas por que não remover ... da correspondência e usar ..= vez disso, para que seja consistente?
(de modo que seria ..= dentro e fora da partida)

Para cobertura de faixa numérica em ponto flutuante, ajudas exclusivas. Por exemplo, um desses limites é totalmente coberto, mas não o outro:

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

E escrevê-lo com sobreposições, em vez disso, parece nojento (e moralmente semelhante a "apenas comece tudo a partir de -∞ já que os braços estão ordenados" acima). Veja também horários, como ISO8601 permite T24: 00, já que um dia é [00:00, 24:00), não [00:00, 23:59:59]. Ou cordas, ou racionais, ou ...

Dada a escolha de apenas exclusivo ou apenas inclusivo, vou escolher exclusivo todas as vezes.

(À parte: o padrão 1 <= x <= N para indexação é realmente melhor feito como 0 < x <= N , que também é exclusivo - embora meio fechado em vez de meio aberto - pelas mesmas razões que Dijkstra disse, apenas alternado para indexação baseada em 1 em vez de baseada em 0.)

Este operador teria sido muito útil para a função de grampo que propus aqui: https://github.com/rust-lang/rfcs/pull/1961, no entanto, uma vez que isso não foi estabilizado, provavelmente terei que modificar essa proposta para use dois argumentos mínimo e máximo. InclusiveRange é muito útil ao trabalhar com valores de ponto flutuante também, então não temos que fazer algo como:

0.0..1.0 + EPSILON

Eu nem tenho certeza se isso está correto, mas agora é muito difícil declarar um intervalo inclusivo de números de ponto flutuante.

A maneira correta de fazer isso seria com nextafter , não épsilon. ou seja, x...y == x..nextafter(y) . ieee754 crate expõe tal funcionalidade

Opa, fiz um comentário sobre a sintaxe inclusive(a..b) mas percebi que não era verdade. De qualquer forma, eu gosto, mas espero que possamos encontrar um nome melhor.

@durka O nome parece claro para mim. Você pode explicar suas preocupações com isso?

Portanto, para intervalos inclusivos, teremos a ... b em match e inclusive(a..b) fora da correspondência?
Por que não podemos ser consistentes e ter a ..= b todos os lugares?

Há algo impedindo ops::{RangeInclusive, RangeToInclusive} de ser formalmente estabilizado?

No momento, parece que o principal bloqueador é o debate sobre a sintaxe, embora, independentemente desse debate, eu tenha certeza de que os intervalos inclusivos existirão independentemente de qual seja a sintaxe final.

Seria bom ter esses tipos para bibliotecas estáveis ​​implementarem, e então os consumidores dessas bibliotecas podem decidir habilitar o sinalizador de recurso se quiserem usar a sintaxe especial.

Uma coisa que notei sobre RangeInclusive outro dia: é uma dor de código se você está tentando aceitar um intervalo. O segmento de grampo estava falando sobre permitir .clamp(1...9) , mas o código acaba parecendo algo assim:

    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 }
            }
        }
    }

Ter de lidar com RangeInclusive::Empty parece desnecessário, pois o objetivo é apenas aceitar o par com uma sintaxe agradável. Se não fosse um enum, poderia ser apenas fn clamp(self, RangeInclusive { start, end }: RangeInclusive<Self>) e muito mais limpo.

Infelizmente, não tenho uma boa resposta sobre o que fazer a respeito, pois exigir .into_iter () em inclusivo, mas não exclusivo, também seria lamentável ...

Ideia aleatória: vendo como a sintaxe do padrão ... não está realmente relacionada aos tipos de intervalo inclusivos, podemos considerar a depreciação de sua sintaxe em favor de uma não relacionada às ... propostas aqui.

Visto que um padrão de intervalo inclusivo está mais relacionado ao padrão | , |... pode ser um bom candidato:

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

O resultado final seria que a sintaxe de intervalo inclusiva e exclusiva não tem mais relação 1: 1 com a correspondência de padrões e, portanto, não precisa ser consistente com ela.

@scottmcm

Infelizmente, não tenho uma boa resposta sobre o que fazer a respeito, pois exigir .into_iter () em inclusivo, mas não exclusivo, também seria lamentável ...

Talvez pudéssemos adicionar um auxiliar como range.nonempty() que entra em pânico por um intervalo vazio e retorna um par?

Alternativamente, poderíamos implementar IntoIterator para RangeInclusive e não ficaria muito longe de IMHO.

Qual caso de uso RangeInclusive :: Empty serve? Por que um intervalo inclusivo precisa ser capaz de representar um intervalo vazio? Como você escreveria um? (Observe que você já pode escrever coisas como "o intervalo de 5 a 4, inclusive", que a iteração presumivelmente trataria como vazio.)

@joshtriplett o caso principal é o estouro, embora existam maneiras de resolver esse problema.

@joshtriplett start > end na verdade não funciona para representar a faixa inclusiva vazia em um caso importante: 0u8...255u8 . Quando você chegar a 255u8...255u8 e tentar .next() it, você entrará em pânico ou embrulhará em 0u8...255u8 , que não está vazio. Então, em vez disso, mudamos para a variante Empty nesse ponto.

@solson Ah, entendo. Sim, isso é uma dor e é um dos maiores casos de uso para intervalos inclusivos.

(Presumo que você queira dizer 255u8 em todos esses casos.)

(Presumo que você queira dizer 255u8 em todos esses casos.)

Sim, obrigado. Editado.

@solson no entanto, este caso pode ser retificado trocando 0 e 255 nesse caso

@clarcharr Isso é verdade. Uma vez que .next() sempre tem como caso especial a geração de um intervalo Empty , ele sempre pode gerar um intervalo que será tratado como vazio.

Pessoalmente, gosto mais dessa forma porque não envolve o intervalo vazio.

Portanto, este tópico já existe há um ano e meio. Acabei de ler tudo isso e gostaria de postar uma recapitulação concisa para os recém-chegados e para nos ajudar a tomar uma decisão:

O que Rust Stable faz hoje:

0..5 representa um intervalo semiaberto, [0, 1, 2, 3, 4] que não pode ser usado na correspondência de padrões
0...5 representa um intervalo fechado [0, 1, 2, 3, 4, 5] que só pode ser usado na correspondência de padrões.

Várias formas foram propostas para uma sintaxe de intervalo fechado adicional que pode ser usada fora da correspondência de padrões. Abordarei cada um e as vantagens e desvantagens deles.

0...5

Prós: Consistente com a sintaxe de correspondência de padrão existente, faz com que a linguagem pareça mais coesa, assumindo que nenhuma alteração seja feita na sintaxe de correspondência de padrão.

Contras: Fácil de digitar incorretamente e causar alguns erros, também fácil de interpretar mal a intenção devido a outras linguagens que usam esse operador para comunicar conceitos diferentes.

0..=5

Prós: mais difícil de digitar incorretamente, mais claro semanticamente

Contras: Inconsistente com a sintaxe de correspondência de padrão existente. Pode fazer com que os usuários perguntem: Por que está ... aqui, mas .. = aqui?

0..^5

Muito semelhante a ..= mas tem uma desvantagem adicional em que se parece com um operador de exponenciação.

inclusive(0..5)

Prós: extremamente claro semanticamente. Não será digitado incorretamente.

Contras: meio longo. Também inconsistente com a sintaxe de correspondência de padrões.

0....5

Prós: também evita o problema de erro de digitação de ...

Contras: Semântica pobre, inconsistente com a sintaxe de correspondência de padrões e semelhante à sintaxe de correspondência de padrões.

[0..5] Inutilizável. colchetes já têm significado sintático na linguagem.

0..<=5 Inutilizável. Conflita com a sintaxe existente para comparar um valor a um intervalo.

Cada opção listada que tem um con de "inconsistente com a sintaxe de correspondência de padrão" poderia ser melhorada se mudássemos a sintaxe de correspondência de padrão, mas essa rota tem problemas de compatibilidade com versões anteriores. Alternativamente, também poderíamos fazer ... e (escolha sua sintaxe aqui) equivalente na correspondência de padrões para evitar a quebra da compatibilidade com versões anteriores, mas evitar o uso de ... fora da correspondência de padrões. Talvez pudéssemos também atualizar o guia de estilo para desencorajar o uso de ... na correspondência de padrões se seguirmos por esse caminho.

Também houve alguma discussão sobre a criação de uma sintaxe de intervalo de propósito mais geral que permitiria que você tornasse os limites superior e inferior inclusivos ou exclusivos, mas provavelmente nem precisamos dessa sintaxe, pois ter intervalo semi-aberto e fechado provavelmente cobre 99,9999% dos casos de uso.

Tentei representar essa discussão da melhor maneira que pude. Se você acha que não expressei seu ponto de maneira adequada, por favor, me avise para que eu possa atualizar isto.

@Xaeroxe Obrigado pelo excelente resumo.

Talvez seja possível ter uma ferramenta (talvez um plugin de rustfmt) que converte automaticamente as fontes usando ... na correspondência de padrões para a nova sintaxe (por exemplo, ..= ) quando isso for decidido.
Dessa forma, não seremos impedidos por "todo o código escrito da maneira antiga".
Mas deve ser invocado com a intenção dos autores do projeto e deve haver uma notificação / título em todos os meios de ferrugem para que todos estejam cientes da mudança.
Com essas coisas, acho que não há problema em alterar a sintaxe ... na correspondência de padrões com a nova sintaxe.

Acho que uma coisa que poderíamos fazer para resolver o problema de sintaxe é apenas estabilizar o RangeInclusive, como sugeriu @clarcharr . Isso pelo menos desbloqueará as pessoas.

Também poderíamos adicionar a função inclusive (apenas para std::range ou possivelmente também para o prelúdio); isso não impede que haja uma sintaxe de primeira classe algum dia, mas torna muito mais conveniente construir um RangeInclusive agora.

No entanto, tudo isso parece ser uma decisão de libs, então não sei se a equipe de lang tem jurisdição para decidir estabilizar / adicionar esses itens 😅.

Eu pessoalmente prefiro converter RangeInclusive em algo que não tenha uma variante Empty e então fazer com que IntoIter tenha a variante. Faz mais sentido para mim, considerando como é essencialmente impossível construir um intervalo vazio sem manualmente Empty { at } .

Alternativamente, troque MAX e MIN na caixa de ponta que mencionei. Isso torna mais difícil escrever um código mais geral envolvendo RangeInclusive , mas parece uma solução razoável para o problema.

Independentemente do que aconteça, apóio fortemente a estabilização do tipo na biblioteca padrão, que existirá independentemente das questões de sintaxe. Ele permite que as bibliotecas escrevam código estável que permite fracionamento com intervalos inclusivos, de forma que, no momento em que a sintaxe esteja estabilizada, as pessoas já tenham implementado o código que usa os tipos. A sintaxe e os tipos estão sob diferentes sinalizadores de recursos por um motivo.

@scottmcm Concordo que provavelmente deve ser um tópico separado neste momento.

Na tentativa de manter a discussão sobre a sintaxe em andamento, vou oferecer o caminho que prefiro seguir.

Gosto muito da sintaxe ..= , então acho que devemos adicionar este açúcar sintático igual a ... na correspondência de padrões e como um InclusiveRange fora da correspondência de padrões. Então, para manter a linguagem consistente, devemos tentar migrar os usuários e seus códigos para a sintaxe ..= em padrões, usando anúncios e ferramentas automatizadas. Quando sentirmos que migramos um número suficiente de usuários de ... , podemos usar um aviso do compilador e, eventualmente (possivelmente daqui a alguns anos), um erro do compilador.

Já se passaram 24 dias desde que minha proposta foi fornecida e nenhum comentário foi dado. Devemos seguir em frente com esse plano?

EDIT: No celular, não vi os polegares para baixo, então não percebi que havia opiniões divergentes.

@Xaeroxe Acho que não. Não concordo que depreciar ... em favor de ..= seja uma boa escolha pelos motivos que já postei neste tópico. Não respondi à sua proposta específica porque a mesma ideia já havia sido apresentada e discutida. A única coisa que fica clara aqui é que não temos consenso. Acho que muitos de nós nos sentimos cansados ​​com a discussão.

EDITAR: Para ser mais específico, não quero descontinuar ... em favor de ..= porque:

  • A depreciação da sintaxe é um custo enorme na rotatividade; mesmo que eu tenha gostado exclusivamente de ..= , não acho que valeria a pena o ciclo de depreciação apenas para obter expressões de intervalo inclusivas no stable.
  • Eu não gosto de ..= , acho que não é óbvio e confuso; tem a vantagem de ser menos provável que cause um erro, mas isso não significa que um usuário, vendo-o pela primeira vez, saberá o que está olhando.
  • Não concordo com a premissa de que é necessário haver uma simetria entre padrões e expressões aqui, porque eles não realizam nenhum tipo de operação de estruturação / desestruturação análoga.

(Mudo um pouco de opinião durante este comentário, decidi deixar tudo para que outros pudessem ver meu processo de pensamento e por que cheguei às conclusões que fiz)

Não posso comentar sobre o custo da suspensão de uso devido à minha falta de experiência com essas coisas. No entanto, ainda apóio ..= .

Acho que, a certa altura, temos que estar dispostos a pedir aos usuários que aprendam alguma coisa. A programação como um todo é algo a ser aprendido, a sintaxe especializada em geral sempre tem algum custo para a semântica. Não espero que as pessoas reconheçam a sintaxe à primeira vista, .. é tão ruim quanto a este respeito.

No entanto, ter uma superabundância de sintaxe especializada pode resultar em uma linguagem parecendo mais próxima do cérebro de merda do que queremos que Rust seja. Portanto, devemos ter cuidado para que os casos que escolhemos transformar em sintaxe especial sejam realmente comuns o suficiente para valer a pena. Para ser honesto, agora que digitei isso, não tenho certeza se esse caso vale isso. A necessidade de intervalos inclusivos não é alta o suficiente para garantir uma sintaxe.

No entanto, a inconsistência ainda me incomoda. Ter uma função inclusiva e ... em correspondência de padrões dá a sensação de ter cinza e cinza na língua inglesa. Quando temos a oportunidade de padronizar isso, uma parte de mim sente que devemos. No entanto, também existem problemas logísticos reais em fazer essa mudança. Se fôssemos projetar um Rust 2.0 (isso pode ser loucura, não tenho ideia), talvez devêssemos revisitar isso, mas acho que por agora ter tanto cinza quanto cinza é bom o suficiente.

Eu apóio o uso de uma função inclusive para instâncias fora da correspondência de padrões e ... em correspondência de padrões neste momento.

@withoutboats

  1. Se você nunca desaprova nada, você acaba com a união de todas (mais ou menos) decisões ruins como C ++. Isso força os novatos a aprender ainda mais porque as coisas não são tão consistentes quanto poderiam ser.
    Então, às vezes, faz sentido descontinuar coisas para abrir caminho para uma solução melhor.

  2. isso não significa que um usuário, vendo pela primeira vez, saberá o que está olhando.

Esse é o caso com qualquer sintaxe. Nós (que conhecemos o Rust) temos esse viés porque, para nós, o código do Rust parece óbvio, mas qualquer um que venha para o Rust de outra linguagem tem que procurar a sintaxe com frequência. Não muda se usarmos ..= ou ... ou qualquer outra sintaxe para intervalos inclusivos porque, por exemplo, outras línguas usam ... para intervalos exclusivos, então eles têm que procurar de qualquer maneira .
Não deve ser nosso objetivo apresentar apenas recursos de aparência óbvia:
Se quiséssemos ter apenas recursos que parecessem óbvios, não poderíamos ter a maioria dos recursos existentes no Rust. Os novatos TÊM que olhar para o médico de qualquer maneira, o que há de tão errado nisso? O doc é bom!


  1. Se você se preocupa em minimizar o tempo que os novatos têm de olhar para o documento, devemos nos esforçar para obter uma simetria entre a construção e a correspondência de intervalos inclusivos! (e outras construções)

Como @withoutboats disse, acho que muitos de nós estão cansados ​​dessa discussão; Eu, pelo menos, estive sentado por um tempo. Dito isso, levei algum tempo para reler (obrigado pelo resumo @Xaeroxe!) E revisitar meus pensamentos aqui.

IMO, o problema mais importante agora é a combinação incompleta de sintaxes que fornecemos : ... em padrões, .. em expressões. Este par de sintaxes fortemente leva você a esperar que .. funcionaria em padrões e ... em expressões - e não funcionam. Eu acredito que este não é um design sustentável a longo prazo e realmente quero consertá-lo.

Também acho que, visto que fornecemos sintaxe para os dois tipos de intervalo, é provavelmente melhor continuar fazendo isso. Isso nos deixa com algumas opções:

  • Estabilize ... em expressões e adicione .. aos padrões. Essa é a mudança menos dolorosa, mas tem desvantagens bem discutidas em torno de erros aleatórios. Mesmo assim, outras línguas têm essa combinação e, que eu saiba, não sofreram terrivelmente com esses erros.

  • Despreze ... em padrões e expressões, adicione ..= a ambos e adicione .. aos padrões. Resolve as desvantagens acima, é mais doloroso (devido à depreciação) e abre a porta para outros tipos de intervalos (como exclusivo à esquerda) no futuro.

Neste ponto, estou em grande parte reformulando a discussão e, honestamente, não acho que haja muito mais a ser dito neste momento; Acho que expusemos as desvantagens e só precisamos que a equipe da linguagem faça uma avaliação e chegue a uma decisão. Mas o ponto principal do meu comentário é o ponto inicial, sobre por que acho que algo precisa mudar aqui (e por que apenas adicionar inclusive não é suficiente, IMO).

Mesmo assim, outras línguas têm essa combinação e, que eu saiba, não sofreram terrivelmente com esses erros.

Eu me preocupo com o viés de seleção aqui. Não temos uma maneira confiável de julgar se os problemas são menores ou se raramente chegam ao nosso conhecimento.

Além disso, usar ... parece ir contra o aspecto "evite armas de fogo, a menos que as compensações sejam muito severas" da filosofia de design do Rust e das melhores práticas emergentes. (por exemplo, o conselho para criar novos tipos enum vez de usar bool por isso é mais difícil misturar os parâmetros de sua função.)

Por exemplo, C provou que a atribuição em if instruções é útil se uma linguagem não tem while let , mas foi reconhecido que digitar = quando você quis dizer == é o suficiente para que linguagens como Python o recusem, mesmo quando existem situações em que as únicas alternativas são estranhamente feias.

Indo na outra direção, na verdade fiz Clippy pegar um caso como este quando eu estava cansado de programar cerca de uma semana atrás ...

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

... que parece um exemplo perfeito do tipo de erro "apertou a tecla muitas vezes" que nos preocupa aqui ... e, ao contrário de " == não tem efeito", há nenhuma boa maneira de furar para .. vs. ... .

@ssokolow Para ser claro, também estou bem com ..= ; Não acho que a suspensão de uso será tão dolorosa e é uma correção automática muito fácil. Principalmente, eu só quero que esse problema seja resolvido.

Provavelmente posso viver estabilizando .. / ... (que já está implementado todas as noites). Eu concordo com @aturon que a linguagem, conforme existe, sugere que isso funcionará.

Como eu disse, eu realmente gostaria de estabilizar o tipo libstd quando rust-lang / rfcs # 1980 for aprovado sem exigir uma discussão de sintaxe.

Junto com o que @aturon apontou, talvez seja útil mesclar os problemas de rastreamento para esta sintaxe de intervalo exclusiva. Talvez faça um problema de rastreamento separado para o tipo e use-o para estabilizar o tipo antes da sintaxe.

Estou renomeando para discussão da equipe lang. Acho que é muito improvável que ideias ou compensações significativamente novas surjam neste ponto. Precisamos chegar a uma decisão sobre as compensações que foram estabelecidas.

Em 18 de maio de 2017 9:55:30 PDT, Aaron Turon [email protected] escreveu:

Estou renomeando para discussão da equipe lang. Eu acho muito improvável
que ideias significativamente novas ou compensações irão surgir neste
ponto. Precisamos chegar a uma decisão sobre as compensações que foram
colocado para fora.

Eu estarei fora para a reunião da próxima semana devido a uma conferência. Caso isso seja discutido na reunião da próxima semana, expressarei meu apoio para qualquer solução diferente de ... , seja ..= , inclusive ou outra.

Valeria a pena discutir a sintaxe de repouso / propagação enquanto estamos nisso.
Eu voto .. para faixa exclusiva, ... para inclusive, .... para descanso / spread.

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

Eu votaria em ... por uma fatia de descanso por dois motivos:

  1. As pessoas provavelmente já estão familiarizadas com ... significa "descanso" de linguagens como CoffeeScript (CoffeeScript usa rest... em assinaturas de função para varargs e as chama de "splats") e Inglês (usando o Unicode correto ponto de código ou não, são três períodos que parecem uma elipse, não quatro, e as pessoas fazem um trabalho decente de compreensão da elipse para significar aproximadamente "e há mais, mas não estamos dizendo isso em voz alta" em inglês, puramente por encontrar em uso.)

  2. A menos que eu esteja perdendo algo sobre a sintaxe de Rust, usar .. e ..= para intervalos, mas ... para fatias restantes significaria que, em todas as situações, digitar ... quando você quis dizer .. ou vice-versa ainda seria um erro em tempo de compilação.

    Para isso, estou operando com duas suposições:

    1. Que usar a sintaxe rest sozinha (fora de um contexto de descompactação de sequência) não seria permitido como um ambiente autônomo sujeito a erros de digitação. (ou seja, for _ in ...rest seria o mesmo que for _ in rest se permitido, mas quase certamente um erro de digitação.

    2. Que usar um intervalo aberto como um padrão a ser atribuído seria inválido. (ou seja, let [first, ..rest] = seria inválido.)

@ssokolow ponto triplo já significa um intervalo no padrão, de modo que seria uma alteração importante alterá-lo para a sintaxe restante.

@phaux Point. Eu tinha me esquecido disso por algum motivo.

Algo para pendurar a tag "se algum dia fizermos Rust 2.0", talvez.

ponto triplo já significa um intervalo no padrão, de modo que seria uma alteração importante alterá-lo para a sintaxe restante.

No entanto, o ... nos padrões deve ter uma expressão em ambos os lados, creio eu ( a...b ), enquanto a sintaxe restante usa ... como prefixo, não?

A equipe de lang discutiu esse recurso novamente em nossa reunião de hoje e chegou a aproximadamente a seguinte matriz:

  • Suportar ... em padrões e .. em expressões, e nada mais, é um design insustentável; faz com que os usuários esperem que a sintaxe funcione de outra forma.

  • Permitir ... e .. em ambos os lugares ajudaria, mas o problema um a um é uma preocupação real; nenhum de nós está ansioso para receber relatos de pessoas que passam horas rastreando um período incorreto.

  • Mudar para ..= e .. é menos atraente esteticamente, mas evita os problemas práticos muito reais acima. Também podemos implementá-lo de uma maneira muito suave: primeiro introduza ..= como uma sintaxe alternativa (para a qual o rustfmt pode reescrever) e, somente depois que se tornar idiomática, desative ... .

Caso você não saiba, a equipe sente que ..= e .. são o nosso melhor caminho a seguir. Esta questão também foi discutida a ponto de ser muito improvável que novos argumentos sejam levantados, então estamos prontos para mergulhar: estamos procurando alguém que gostaria de implementar a notação ..= para ambos padrões e expressões, e subsequentemente iremos para FCP!

Para isso, estamos procurando alguém (ou algumas pessoas) para impulsionar a implementação. Provavelmente, isso pode ser feito em vários PRs menores:

  • Para começar, vamos adicionar ..= ao analisador como um apelido para ... e converter os testes existentes.

    • ... deve continuar trabalhando, é claro, e queremos que isso seja uma depreciação "silenciosa", então não há necessidade de emitir avisos etc. (ainda).

    • precisaremos, portanto, manter os testes nos padrões de ...

    • Acho que provavelmente a maneira de fazer isso é modificar o lexer adicionando o token DotDotEquals ( aqui está o DotDotDot ) e, em seguida, modificando o analisador para aceitar DotDotEquals todos os lugares que agora aceite DotDotDot ( exemplo )

    • ripgrep DotDotDot é seu amigo aqui;)

  • ... em expressões nunca foi estável, então podemos apenas mudar isso para ..= e eliminar o suporte antigo

    • para ser legal com as pessoas na natureza, poderíamos passar por um período de depreciação, mas não tenho certeza se isso é necessário (pensamentos?)

Apenas para notar que, ao implementar, a sintaxe extern fn foo(a: u32, ...) não deve ser alterada para ..= 😆

Estou tentado a pegá-lo porque parece um bom primeiro passo no código, mas não terei muito tempo nas próximas 2 semanas, então se alguém quiser pegá-lo, fique à vontade!

Pessoalmente, sou mais a favor de ..^ que ..= , pois a operator= b já é, para alguns operadores, um apelido para a = a operator b . ^ por outro lado é usado muito menos, apenas para XOR, então deve causar menos confusão.

.. produz um tipo diferente do tipo dos operandos esquerdo e direito para ele, então não vejo isso sendo um problema para ..= . O contexto também ajuda a identificar o propósito do operador, algo como += retorna () para que possa aparecer como sua própria instrução, normalmente em sua própria linha. Enquanto ..= retorna InclusiveRange, então ele aparecerá como uma expressão dentro de outras instruções. Além disso, como mencionado acima, ..^ parece ter mais a ver com exponenciação do que um intervalo.

@Xaeroxe ^ não tem nada a ver com Rust com exponenciação (embora seja usado como tal em outras línguas), enquanto += , -= , *= all existe em Rust. Na verdade, até ^= existe.

Mas idk, não há problema em ter ..= também.

Uma vez que # 42134 foi mesclado, podemos mover para estabilizar a estrutura da biblioteca agora? Acho que vamos querer esperar a sintaxe se estabelecer antes de estabilizar isso, embora, como eu disse antes, seja útil estabilizar a estrutura mais cedo.

@clarcharr Eu acredito que chegamos à decisão de estabilizar essa estrutura, bem como a sintaxe ..= então só precisamos de alguns PRs para realmente fazer isso.

EDIT: Woops, eu estava errado. Estamos implementando isso no compilador, para estabilizar a sintaxe, será necessário aguardar o período de comentário final. Acho que devemos estabilizar a estrutura neste momento, mas essa também não é minha decisão.

Parei de acompanhar o assunto há muito tempo, quando me pareceu que ... estava chegando a um consenso. ..= parece simplesmente estranho para mim, pois parece apenas uma afetação à primeira vista.

Mas, muito mais importante, não acho que esse biquíni seja importante o suficiente para mudar a sintaxe do padrão atual.

essa sintaxe é uma merda!
= tem significado de atribuição, mesmo em + =, - =, * = modelo, mas .. = trata-se de obter algo. tão confuso e feio.
como o índice do array começa em 0, '...' é bom e bonito, as pessoas vão se acostumar com isso.

@zengsai
..= é conceitualmente derivado de operadores como == e <= , que já existem em Rust e indicam comparação de igualdade, não atribuição.

(ou seja, 1..=5 é uma abreviatura de "Intervalo acima dos valores 1 <= x <= 5 " em oposição a 1..5 significa "Intervalo acima dos valores 1 <= x < 5 ")

EDIT: Além disso, não é uma questão de "se acostumar com isso", é uma questão de qual é mais difícil de ler ou digitar mal quando você está cansado ou distraído. Erros esporádicos como esse são famosos por espingardas.

Na verdade, eu digitei acidentalmente ... quando já queria dizer .. . Felizmente, sempre tenho como alvo o Rust estável, então o compilador o pegou. (No entanto, não consigo me lembrar se foi um espasmo muscular ou memória muscular, supondo que eu queria digitar uma pseudo-elipse porque escrevo muito não-ficção.)

@zengsai ... é muito sutil, parece muito semelhante a ..

Será realmente anormal um idioma ter um número diferente de pontos significando coisas diferentes

Remover uma arma de fogo é mais importante do que ser esteticamente atraente.

Recém-chegados: Fiz um TL; DR, porque esse é um tópico muito longo. Você pode ler aqui: https://github.com/rust-lang/rust/issues/28237#issuecomment -296310123

Falando em "Erros pontuais como esse são famosos por ser" footgun-y ", eu tenho que dizer: o problema de digitação não deve ser usado como o principal motivo dessa mudança.

veja esta comparação, ".." e "..." vs "=" e "==", isso significa que devemos encontrar outra sintaxe para "==" para evitar o problema de digitação do usuário? se "=" e "==" estão bem, por que ".." e "..." não podem?

Acompanho Rust-Lang há mais de dois anos. e tem sido usado em muitos de meus projetos privados. Eu adoro isso, mas essa sintaxe realmente me deixa desconfortável. não apenas o esteticamente atraente, mas também afeta a escrita e a fluência de leitura do código.

@zengsai , eu entendi que não se trata principalmente de _writing_ código, mas sim de revisar, ler e entender o código. Se você não estiver procurando por isso, pode facilmente deixar de notar que .. vs. ... é um erro indeterminado, enquanto ..= definitivamente se destaca mais e venceu não tenho esse problema.

Não tenho certeza se gosto da sintaxe ..= do ponto de vista estético, mas posso ver de onde todos estão vindo sobre .. e ... lendo de forma muito semelhante.

@zengsai Porque = vs. == tem uma solução que não está disponível para .. vs. ... .

Claro, você pode confundir = e == em C ... mas isso é um footgun reconhecido e linguagens mais modernas como Python e Rust resolveram isso:

  1. É um erro se você digitar if x = y vez de if x == y (esta é a correção feita por Rust e Python)
  2. Quando digitei acidentalmente x == y; vez de x = y; , recebi um aviso sobre uma expressão que não tem efeito.

Não há como o compilador reconhecer que uma confusão .. vs. ... é suspeita , quanto mais errada.

@zengsai .. e ... avaliam os tipos que implementam todas as mesmas características e podem ser usados ​​essencialmente de forma intercambiável (isso é por design). Desligar por um erro é um problema muito real.

Quero deixar claro que também odeio essa sintaxe, tanto que não concordo com o comentário de @aturon de que a situação atual em que usamos .. e expressões e ... em padrões é "insustentável"; na verdade, acho preferível ter a desconexão do que essa sintaxe.

Mas está claro que nunca teremos um consenso sobre isso, que não há novos argumentos a serem apresentados neste tópico, e que a maioria dos usuários ativamente investidos (assim como o resto da equipe de linguagem) favoreceu essa mudança. Portanto, estou de lado para que possamos resolver o problema.

Se for algum consolo em minha experiência, a grande maioria dos casos de uso nunca precisa realmente desse recurso e, portanto, ele não aparecerá em todo o seu código.

Na verdade, ainda estou muito insatisfeito com a descontinuação de ... em padrões e basicamente vou cerrar os dentes para que esse problema seja resolvido. Toda a equipe lang concorda que ter .. e ... expressões seria uma verruga terrível, levando alguns usuários a passar horas depurando um problema de digitação totalmente silencioso.

O resto da equipe lang sente fortemente que ter uma desconexão entre expressões e padrões é inaceitável e, embora eu não concorde, todos nós apresentamos nossos argumentos e não acho que ficar em um impasse para sempre seja saudável.

@ssokolow Desculpe, ainda não concordo com você. O compilador pode alertá-lo sobre esse tipo de erro de digitação, mas e se você digitar "x = 5" onde deveria estar "x = 6"?

O compilador não é o ideal para evitar erros de digitação, o programador é.

se essa alteração não tiver efeitos colaterais, concordo totalmente. mas isso fez com que a linguagem perdesse a fluência estética, de escrita e de leitura, o que não vale apenas na minha opinião pessoal.

A ferrugem de hoje já encontra problemas de leitura e escrita, quanto mais incomum e contra-intuitiva sintaxe mais curva de aprendizado, não faça disso outro Perl.

@semoutboats Discutimos com isso, porque adoramos. Talvez este argumento seja tarde demais e não possa mudar nada, apenas ...

@zengsai

Certamente há compensações a serem feitas, mas tenho a impressão de que nunca chegaremos a um acordo sobre o melhor ponto de equilíbrio entre elas.

Independentemente do gosto pessoal, vejo ..= como um pequeno preço a pagar para evitar o que pode ser uma grande perda de tempo tentando rastrear bugs.

(Minha área de foco é design de UI / UX e uma das maiores regras que eles ensinam é que você deve tentar tornar a facilidade de cometer um erro inversamente proporcional ao dano e / ou tempo para consertar que ele irá causar. )

Na minha opinião, 5 vs. 6 é muito mais óbvio de se ver do que .. vs. ... .

@zengsai Estou recebendo muitos e-mails apenas para esta conversa, que tal mudar para um canal IRC enferrujado para expressar melhor seus sentimentos?

@daiheitan Esta é uma comunicação normal. Se você não gostar, sugiro que cancele a

Quando vi Rust pela primeira vez, fiquei realmente surpreso com a sintaxe .. . (1..10).sum() é ... a soma dos inteiros de 1 a 9? Se você apresentar essa sintaxe a um recém-chegado e perguntar a ele o que significa, é muito provável que ele espere que vá de 1 a 10. E ele estaria certo em fazer isso, já que você esperaria que a sintaxe simétrica expressasse simetria gamas. Por que o 1 deve ser incluído, mas não o 10?

Adicionar outra forma assimétrica ..= para um intervalo simétrico torna isso ainda mais visualmente inconsistente. Alguém pode perguntar por que o lado esquerdo não precisa de = para ser inclusivo, então seria =..= para intervalos inclusivos em ambos os lados.

Algo como a sintaxe Swift ( ..< para exclusivo e ... para inclusivo) evitaria esses problemas e melhoraria a legibilidade. Você pode facilmente adivinhar o significado corretamente, mesmo se for completamente novo no idioma, então há uma coisa a menos para lembrar. Eu esperava que algo assim fosse escolhido, especialmente considerando o impulso de Rust para ser amigável para recém-chegados.

@rkarp Até certo ponto, isso provavelmente se deve a um preconceito pré-existente.

Por exemplo, há muita influência do Python no Rust e o Python usa o mesmo tipo de intervalos semiabertos. (ou seja, range(1, 5) ou myList[1:5] Python têm o mesmo comportamento de 1..5 Rust)

A justificativa para isso em Python estava ligada ao fato de haver apenas uma sintaxe e ter uma sintaxe entreaberta tornava mais fácil fazer coisas como head, tail = myList[:pivot], mylist[pivot:] .

Dito isso, dado que o Rust passou 1.0, existem regras bastante rígidas sobre não quebrar o código existente. .. para padrões externos exclusivos e ... para padrões internos exclusivos devem permanecer válidos.

..= funciona porque você pode aceitar .. (exclusivo) e ..= (inclusive) em qualquer lugar e tratar ... como um sinônimo obsoleto para .. em padrões.

Apenas dizendo, ter ..= como token é tecnicamente uma alteração incompatível, pois afeta as regras de :tt em macros. Provavelmente não seria problemático, mas você pode querer verificar se alguém não faz isso, considerando que pode muito bem ser uma mudança silenciosa. (a alternativa é permitir .. /* why not */ = , o que não acho uma boa ideia)

@ssokolow Tecnicamente, é um erro de tipo no Rust, não um erro de análise. a = 2 é uma expressão que retorna () , e if espera bool , então eles são claramente incompatíveis.

As regras estão mudando lentamente. Tecnicamente ..= são 3 tokens onde os 2 primeiros não têm espaço depois deles.

@eddyb : Eu admito, não entendo muito bem. Existe uma maneira de introduzir um novo token sem afetar como: tt o analisa?

Este código atualmente reporta "Regra 2" e "Regra 4". Se eu entendi corretamente, essa alteração mudaria para "Regra 2" e "Regra 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!(..=);
}

Não, é uma mudança na forma como os tokens são definidos. @jseyfried pode explicar melhor as consequências.

Tecnicamente, é um erro de tipo no Rust, não um erro de análise. a = 2 é uma expressão que retorna (), e se espera bool, então eles são claramente incompatíveis.

Obrigado @xfix . Não estava prestando a devida atenção da última vez que cometi aquele erro de digitação e ainda não estou completamente acostumado a pensar em termos de linguagens orientadas a expressão.

Eu ajustei meu comentário.

Não gosto da sintaxe ..= e sou contra ... em padrões. Se tivermos medo do erro de digitação, sempre podemos usar a estrutura RangeInclusive { start, end } vez de ... ou ..= abreviação.

Ambiguidade potencial que acabei de perceber:

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

@clarcharr Parece que não compila.

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
Depois de introduzir ..= como um operador, o erro seria:

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

error: aborting due to previous error

Assim como agora com let x=10; if let 5..x {}

Portanto, essa "ambigüidade" não compilaria e, portanto, não seria mais ambígua do que if let 5..x {} .

@Boscop A questão é, atualmente , se tratarmos 5.. como um padrão como Some(5) , então if let 5.. = x seria semelhante a let Some(5) = x , e o último compila. Meu comentário mostra que 5.. não é um padrão, então não há nenhum risco de compatibilidade de if let por introduzir ..= .

Se introduzirmos este recurso e permitirmos ..= e .. nos padrões, if let 5..=x deve ser sempre if let 5.. = x e deve compilar: if let (single expression) não faz sentido, então não acredito que haja qualquer ambigüidade.

@kennytm, então nós dois mostramos para 2 ambigüidades diferentes que eles não compilarão. (Não ficou claro a qual ele se referia. Era meio ambíguo, heh.)

@daboross Como kennytm disse, 5.. não é um padrão e não compila, mesmo agora. E isso não mudará se adicionarmos ..= como um operador. Não há ambigüidade. O que é importante é que agora ..= não pode ser analisado como um operador, mas uma vez que podemos analisá-lo como um operador, não há ambigüidade.

5.. não é um padrão válido atualmente, nem temos padrões de intervalo semifechados. Dito isso, a falta de padrões de intervalo semicerrados é algo que frequentemente está sendo visto como uma fonte de inconsistência quando comparado a expressões de intervalo e pode acabar sendo implementado para padrões também. Também podemos querer adicionar a capacidade de omitir um lado do intervalo em padrões posteriormente, por exemplo, correspondências inteiras exaustivas.

Portanto, embora a observação de @clarcharr não esteja necessariamente apontando ambigüidade quando a gramática atual é considerada, é certamente uma ambigüidade ao considerar possíveis expansões futuras que podem entrar em conflito com a proposta de usar ..= para padrões.

Com isso em mente, sugiro usar algum outro símbolo aqui. ^ parece razoavelmente bom para mim, já que só é usado em um contexto de expressão atualmente IIRC.

(Esse é outro motivo pelo qual acho uma boa ideia mover para estabilizar a estrutura agora e a sintaxe depois.)

@nagisa não há conflito em relação a if let se o token ..= for adicionado antes que o padrão RangeFrom seja suportado. Pode-se adicionar um espaço entre .. e = para desambiguar, assim como x <- y (colocação em) vs x < -y (menos que + negativo).

(Uma vez que ^ é o operador -ou exclusivo , acho irônico usar ..^ para a faixa inclusiva )

Nos milhares de intervalos que escrevi, alguns deles totalmente fechados, talvez até um ou dois meio abertos ao contrário, ainda não vejo a necessidade de qualquer sintaxe extra. 1..(n+1) não é tão difícil de escrever.

Isso não funciona para end = T :: max_value ().

Em 29 de maio de 2017 16:33, "Diggory Hardy" [email protected] escreveu:

Nos milhares de intervalos que escrevi, alguns deles totalmente fechados,
talvez até mesmo um ou dois entreabertos ao contrário, eu ainda não
veja a necessidade de qualquer sintaxe extra. 1 .. (n + 1) não é tão difícil de escrever.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-304662258 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AApc0ipynL_qrZqUBldOJOX046RNY2H_ks5r-skwgaJpZM4F4LbW
.

Eu preferiria um método em intervalos semicerrados para .. = embora.

Em 29 de maio de 2017 16:35, "Simonas Kazlauskas" [email protected] escreveu:

Isso não funciona para end = T :: max_value ().

Em 29 de maio de 2017 16:33, "Diggory Hardy" [email protected] escreveu:

Nos milhares de intervalos que escrevi, alguns deles totalmente
fechada, talvez até uma ou duas entreabertas ao contrário, ainda não
realmente vejo a necessidade de qualquer sintaxe extra. 1 .. (n + 1) não é tão difícil de
escrever.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-304662258 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AApc0ipynL_qrZqUBldOJOX046RNY2H_ks5r-skwgaJpZM4F4LbW
.

Eu realmente gostaria que já estabilizássemos as características e tipos com um método para construí-los, porque tenho certeza de que não há desacordo sobre isso. Por favor, não deixe que o uso de bicicletas sobre a sintaxe atrapalhe a estabilização da funcionalidade central em si.

Isso não funciona para end = T :: max_value ().

Você realmente deseja iterar mais de 2 ^ 64 valores, ou mesmo 2 ^ 8 valores? Se você deseja iterar apenas os últimos valores de, por exemplo, um u32 , geralmente é mais fácil adicionar um dentro do loop. E se você realmente deseja iterar para 2^B-1 por algum motivo obscuro, você sempre pode colocar if i == END { break; } no final de um loop.

Só porque nossos números inteiros sem sinal padrão suportam valores de 2 ^ 32 ou 2 ^ 64, não significa que o valor representável mais alto seja usado com muita frequência. E se você estiver fazendo algo com u8 , não se esqueça de que provavelmente é mais fácil para a CPU usar u32 contador.

Mas mesmo que eu não veja a necessidade de uma sintaxe de gerador de intervalo fechado, não posso refutar os argumentos da equipe para a mudança . Ah bem :/

Que tal esses quatro para abranger todas as opções de inclusão?

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

Eu imagino que alguém deva ser capaz de entender o que eles implicam sem maiores explicações, dado que os operadores da desigualdade foram martelados na mente de todos desde o jardim de infância em diante ... não sei se isso seria uma dor de outras maneiras, no entanto.

Como alternativa, podemos mudar as desigualdades:

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

... apenas para que o último não parecesse um Cartman zangado.

@vegai e quanto à sintaxe a..b que certamente não será removida? Não, eu não acho que sugerir novas opções de sintaxe vai resolver nada.

Hmm, então houve duas "ambigüidades potenciais" levantadas:

  • if let 5..= x - como observado, isso não é realmente uma ambigüidade agora , mas poderia ser. Por outro lado, esse tipo de ambigüidade surge com frequência e é abordado pelo tokenizer. Ou seja, se considerarmos ..= como um token em nosso analisador, ele não será ambíguo mesmo se adicionarmos 5.. padrões no futuro; você simplesmente precisa escrever um espaço entre .. e = (por exemplo, let 5.. = x ).
  • a ambigüidade com respeito às macrorregras. Isso é realmente uma pena e um dos motivos pelos quais estamos mudando para um sistema diferente para "macros 2.0", onde evitamos expor o conjunto de "tokens compostos" para o usuário final.

    • no final, podemos lidar com macro_rules! back-compat por meio de algum código de caso especial, se necessário; em qualquer caso, acho que não há como evitar esse tipo de problema, exceto usando ... .

Antes de estabilizar as faixas inclusivas, o problema # 42401 também deve ser corrigido imediatamente, pois após a estabilização, a correção seria uma alteração significativa.

@ est31 bom ponto, eu adicionei isso à lista de verificação no início da edição

O corte de str verificado é por si só instável e corrigir esse problema não bloqueia os intervalos inclusivos de forma alguma.

Oh, @nagisa está certo, não tem nada a ver com a sintaxe de intervalo. Você pode removê-lo da cabeça novamente? Meu erro. O bug está mais na implementação de get e, portanto, protegido pelo recurso 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
            }
        }
    [...]

removido

Outra atualização da caixa de seleção: PR https://github.com/rust-lang/rust/pull/42134 aplicou o https://github.com/rust-lang/rfcs/pull/1980 ajuste

Bump: alguma maneira de conseguirmos pelo menos estabilizar as estruturas por 1,20?

Que tal pegarmos emprestado o famoso operador go-to do C ++ para a sintaxe de intervalo inclusivo? 😛

@nikomatsakis e @rust-lang / libs (não sei como marcar isso), como você se sentiria se eu enviasse um PR que mudou os structs para um problema de rastreamento diferente, para que possamos conversar sobre a estabilização para eles lá? Acho que essa seria uma boa maneira de avançar na estabilização deles mais cedo, enquanto esperamos a nova sintaxe ser implementada / resolvida.

cc @ rust-lang / libs (apenas pessoas em uma equipe podem marcar a sua ou outras equipes)

Obrigado, @eddyb!

@clarcharr Baseado em https://github.com/rust-lang/rust/pull/42275#discussion_r119211211 , eu suspeito que seria apreciado.

Estou muito atrasado para o trem da proposta de sintaxe?
A corrente parece quando alguém tenta atribuir o valor à fatia.

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]

Essa sintaxe tornaria impossível adicionar quaisquer Add implementações para intervalos no futuro. Eu realmente não sei se isso é um problema, pois não tenho certeza do que uma implementação Add faria.

Concordar com o plus à direita. Alterado para prefixo.

Como a.. , ..b e .. são construções válidas em Rust, isso ainda produz ambigüidades com operações matemáticas: /

a... / a..= / a..+ não seria válido, certo? Uma vez que ter um intervalo ilimitado incluindo um ponto final, realmente não faz sentido.

Eu não ficaria muito preocupado com Add , não parece que seria algo muito comum a se fazer com intervalos e, se você quisesse, poderia fazer (x..+y) + z ?

Edit: não importa, acabei de perceber o que você quis dizer. Seria a..+b ambíguo, certo? Já que agora significa a.. + b .

@daboross Não

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)..
    }
}

Este implemento específico pode ou não ser uma boa ideia, mas não demorei muito para apresentá-lo como um possível caso de uso futuro. Acho que seria uma má ideia excluir a possibilidade de isso ou algo parecido ser adicionado devido a decisões de sintaxe existentes.

Minha outra preocupação é que o objetivo de descartar ... é minimizar a chance de erros de digitação difíceis de reconhecer e permitir que os parênteses façam a diferença entre dois significados diferentes do abstrato a..+b estaria se movendo de volta naquela direção.

Além disso, ainda não vi uma justificativa sólida para a-..b e a-..+b além de "não seria bom por uma questão de integridade" enquanto o atual .. e o ..= ambos têm fundamentos conhecidos e válidos.

Você não pode usar + para isso porque torna a sintaxe da expressão ambígua.

EDITAR: embora, suponho, tornaria possível a implementação de intervalos inclusivos inteiramente na biblioteca, porque você acabaria tendo uma implementação de <Range as Add<{integral}>>::Output = InclusiveRange .

Posso sugerir a variante ..! . Tem uma rima produtiva com .. e dá ênfase adicional ao último ponto, tornando-o mais perceptível.

É claro que ele colidiria com o operador ! , mas, falando honestamente, eu não poderia imaginar a situação em que seria necessário colocar ! na subexpressão vinculada.

..! tem um problema de intuição. Um recém-chegado ainda não familiarizado com a sintaxe pode facilmente interpretar mal ..! com o significado de "até, mas não ..."

Ele também colide com a sintaxe de "intervalo até o complemento bit a bit de ..." (o que o colocaria em uma situação semelhante ao uso de + )

Aceita. Mas, por outro lado, ..= pode ser mal interpretado como um dos operadores de atribuição.

O que você estaria atribuindo se fosse um operador de atribuição?

Com base na proposta de @ 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

Duvido que precisemos de outras combinações. Em qualquer caso, pode ser adicionado posteriormente:

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

Embora a última opção pareça um pouco estranha. ^_^

Pare de propor qualquer sintaxe que contenha um operador unário, ou seja, a..-b , a..!b , a..*b , a..&b ou a?..b , estes nunca serão aceitaram.

..! tem um problema com a intuição. Um recém-chegado que ainda não está familiarizado com a sintaxe pode facilmente interpretar mal ..! para significar "até, mas não ..."

..= tem o mesmo problema com a intuição. Qualquer pessoa que vir um = espera uma afetação ou uma comparação. Reconheço que essa sintaxe resolve completamente o problema de distinção, pois toda vez que vejo ..= , não consigo me impedir de me perguntar o que esse sinal de igual está fazendo aqui.

A única sintaxe proposta que é bastante intuitiva e consistente com a sintaxe atual é ... . Mas parece que o navio partiu.

Os recém-chegados terão que consultar os documentos com frequência de qualquer maneira. Mesmo com ... eles examinariam os documentos. Isso não é evitável. Mas ..= tem um bom mnemônico ( up to e equal to ) então eles não terão que olhar a documentação deste operador freqüentemente.

E se o operador ... permanecer como está, mas em vez disso, mudarmos o operador .. para ..⎵ , ou seja, dois pontos e um espaço (eu tive que colocar isso '⎵ 'porque um espaço regular não seria mostrado nesta página). Seria o único lugar na linguagem em que o espaço em branco é importante. Também seria uma alteração importante, porque todo código como a..b reclamaria que não existe tal operador como .. , e um conselho para adicionar pelo menos um espaço após os pontos. Acho que o espaço os torna visualmente distintos o suficiente:

a.. b
a...b

@tommit Não acho que seria uma boa ideia para ser honesto.

O operador atualmente é bastante flexível em relação aos espaços em branco, por exemplo: a..b e a .. b são iguais. Provavelmente, isso o torna consistente com outros operadores, como a+b e a + b . É claro que eles fazem o mesmo e permitem que as pessoas usem estilos de sintaxe diferentes. Isso é uma coisa boa se você me perguntar!

Para adicionar a isso, a notação ..= é consistente com as notações <= e >= (que também são consideradas _inclusivas_).

É sempre bom verificar quais outras possibilidades existem, mas provavelmente essa não é a solução certa.

Aceita. Quando comparado com <= e >= , ..= parece plausível, até lógico.

A propósito, se você é fã de ... ou simplesmente não gosta da aparência de ..= , a solução de compromisso seria usar alguma fonte com ligaduras de programação, como FiraCode com ligaduras especiais para ..= , que pode ser mapeado para ... , ou mesmo algo estranho, como ⩷, ⩦ ou ≔.

Quebrando a mudança em todos os códigos de ferrugem existentes usando intervalos ... morto na chegada,
Desculpe. Se alguém tem uma proposta compatível com versões anteriores realmente séria para
abordar as preocupações que foram levantadas e não foram discutidas
já, vamos ouvir, mas vamos pelo menos manter isso como o padrão, certo?
Esse tópico está cheio de galpões de bicicletas e a equipe já tomou uma decisão então
essa é uma barreira alta a ser eliminada.

Em qualquer caso, ainda parece haver muita confusão acontecendo sobre a sintaxe real. Solicitei o número 43086 para estabilizar pelo menos as estruturas e características e impls para que a funcionalidade central possa ser usada (parece haver demanda, consulte o comentário de @ retep998 acima).

O elefante na sala é que .. é realmente o problema real aqui por causa de sua aparência simétrica, mas significado assimétrico. A "coisa certa a fazer" provavelmente implicaria em descontinuá-lo, mas não há vontade de fazer isso porque muito código já o usa.

Reprovar o perfeitamente consistente ... (aparência simétrica, significado simétrico) é a saída fácil, mas ao custo de adicionar outro operador inconsistente em ..= . Parece que adicionar um design ruim para contornar o design anterior ruim.

Há outro problema com isso por causa dessa dupla inconsistência: não há uma boa maneira de adicionar as duas últimas variantes de inclusão restantes (exclusivas em ambos os lados e exclusivas apenas no lado esquerdo). Uma vez que .. e ..= já teriam um = implícito no lado esquerdo, teríamos que negar isso de alguma forma, possivelmente com um < . Então, eles teriam que ser parecidos com isto:

  • <..= para (a; b]
  • <.. para (a; b)

Boa sorte em adivinhar corretamente o que isso significa para um recém-chegado. Portanto, eles provavelmente (com razão) nunca seriam considerados para serem adicionados.

Se .. não estava tão arraigado ou nem existia, criar um design consistente para tudo isso do zero não parece tão difícil, por exemplo:

  • .. (ou ... ) para [a; b]
  • ..< para [a; b)
  • <.. para (a; b]
  • <..< para (a; b)

Tenho a sensação de que as duas últimas variantes podem ser úteis em algum ponto, devemos realmente bloquear o caminho em direção a elas tão rapidamente? Em qualquer caso, a única boa razão para escolher ..= vez de descontinuar .. é quebrar o código muito menos antigo, mas seria na melhor das hipóteses um mal necessário, nada a ser celebrado.

_Editar: Adicionou um exemplo e alguns comentários para maior clareza._

Eu concordo com @rkarp sobre que .. é o problema real aqui, não ... ou ..= . O significado assimétrica é especialmente ruim considerando que outras línguas (mais populares) realmente fazer atribuir um significado simétrica a ele. Tanto Kotlin, Ruby e Haskell consideram 5 no intervalo 3..5, por exemplo. Os trabalhos matemáticos também parecem favorecer isso. A pior coisa aqui é que os iniciantes não têm chance de adivinhar o comportamento de 3..5 em Rust: você decidiria que 4 e apenas 4 é um membro do intervalo 3..5 (iteração sobre os pontos) ou que ambos 3 e 5 também estão nele (iteração sobre 'tudo o que podemos ver' e a extrapolação dos pontos).

Eu discordo sobre a dificuldade de mudar isso, no entanto. Acho que a sugestão do @adelarsq pode ser implementada de forma relativamente indolor. Para referência:

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

Qualquer ocorrência de x..y (sem colchetes) pode ser traduzida para [x..y[ e emitir um aviso do compilador. Depois de alguns lançamentos, o compilador pode simplesmente se recusar a compilar notações de intervalo "nuas" e talvez até mesmo oferecer ferramentas para converter automaticamente para a nova notação.

https://github.com/rust-lang/rust/issues/28237#issuecomment -274216603 essa não é uma ideia nova e não podemos usá-la pelos motivos que já mencionamos.

Eu concordo totalmente com a ideia de que, se estivéssemos projetando a linguagem do zero com o benefício de uma visão retrospectiva, deveríamos considerar as sintaxes de faixas exclusivas e inclusivas juntas. Eu realmente acho que ..= não é o operador ideal para um intervalo inclusivo; é simplesmente a melhor opção atualmente na mesa. Mas descontinuar o atual operador de alcance exclusivo seria excessivamente doloroso e desanimador para os usuários e projetos existentes do Rust.

Existem inúmeras outras propostas que poderiam funcionar. Por exemplo, eu não vi ..@ proposto, e x..@y parece evocativo. O desafio é encontrar algo mais atraente do que a proposta atual, mantendo a falta de ambigüidade.

Eu queria destacar o comentário de @ssokolow de 2 meses atrás, como minha visão favorita da simetria:

  • ..4 contém coisas < 4
  • ..=4 contém coisas <= 4

Acho que só precisamos de alcance inclusivo, isso é mais simples.
Você sempre pode adicionar + 1 ou -1 para alterar o intervalo.
E .. é melhor, porque .. é mais simples que ...!

@ AlexanderChen1989 Como foi dito antes em vários posts neste tópico, isso não é possível porque alterar o significado de .. quebraria o código existente.

Além disso, não é tão simples assim. Mais notavelmente, +1 e -1 podem causar estouro / estouro negativo.)

Aqui está um exemplo que funciona em nightly (por meio do antigo candidato para sintaxe de intervalo inclusivo) onde ...

  • ... qualquer loop que você colocar primeiro entrará em pânico com estouro / subfluxo em compilações de depuração
  • ... eles se comportarão de forma completamente oposta ao pretendido nas compilações de lançamento (ou seja, o "0 a 0" irá iterar 256 vezes e o "0 a 255" não irá iterar de forma alguma)
#![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 propostas de sintaxe mortas na chegada foram feitas desde que a equipe de linguagem tomou sua decisão. Novatos, por favor, leiam o tópico. Tínhamos motivos muito bons para tomar as decisões que tomamos, prometo.

IMHO o OP deve ser atualizado para apontar que nenhuma discussão de sintaxe mais deve ser feita neste encadeamento, e quaisquer propostas de sintaxe de intervalo exclusivo (ou seja, intervalos (a, b) e (a, b]) devem ser movidas para outro encadeamento.

Isso deve falar apenas sobre coisas que precisam ser feitas para estabilizar o plano atual.

@clarcharr Tomei uma decisão unilateral e adicionei isso ao OP, boa ideia. Se o barulho continuar, eu votaria por bloquear o tópico.

Olá, sou novo e gostaria de começar a trabalhar neste. Vou tentar escrever o PR para adicionar ..= como sinônimo de ... em padrões, descontinuar ... em expressões e exibir um erro dizendo que a sintaxe foi alterada para ..= . Isso soa correto?

@ Badel2 legal. Na verdade, eu comecei - vou empurrar meu branch em breve e vinculá-lo aqui.

@durka só para esclarecer - você está se oferecendo para deixar @ Badel2 começar a partir de sua filial? Você poderia orientá-los como parte do trabalho do período de implementação? Eles estão no canal Gitter.

Também concordo que o problema real é .. . Portanto, a solução mais favorável é descontinuar (não substituir imediatamente, então __não__ quebraria o código existente) o .. em favor de algo como ..< (não haverá confusão entre a..<b e (a..)<b , já que .. eventualmente deixará de existir).

@ hyst329 Por favor, leia as postagens já feitas.

A primeira postagem diz, em negrito, "Nenhuma discussão de sintaxe mais deve ser realizada neste tópico."

Deixando isso de lado, o que você descreve já foi proposto aqui várias vezes por outras pessoas que não leram a discussão existente e há vários motivos dados em resposta pelo qual não é uma opção viável.

Desculpe, isso não é muito construtivo, mas sempre que vejo ..= e tento me lembrar o que é, parece um operador de atribuição semelhante a += ou <<= . É muito confuso que não seja. (Embora isso esteja fora de contexto, por exemplo, “suporte inicial para sintaxe de ..= ” https://this-week-in-rust.org/blog/2017/10/03/this-week- em ferrugem-202 /)

@SimonSapin Eu expressei essa mesma crítica de uma forma mais construtiva acima, sugerindo ..^ vez disso: https://github.com/rust-lang/rust/issues/28237#issuecomment -304325663

Para mim, um grande ponto que fala por ..= é uma espécie de consistência com swift (que tem ..< para faixas exclusivas e .. para faixas inclusivas). Isso me deixou bem com a escolha de ..= .

@SimonSapin Acho que ninguém está completamente feliz com isso. O problema é que centenas de comentários infelizmente confirmaram que não há alternativa melhor.

Este patch conseguiu me convencer do que não fazer nada é melhor do que bagunçar a sintaxe do padrão atual apenas para cobrir casos extremos.

.. tem muito poucos casos de uso em padrões e você sempre pode lidar sem eles.

... pode ser substituído por RangeInclusive ou (Bound<T>, Bound<T>) em expressões que realmente os requeiram. É mais detalhado, mas fácil de entender.

@UtherII

... e eu estava convencido de que ... é insustentável quando fui salvo de um bug sutil pela mensagem "Você não pode usar sintaxe de intervalo inclusiva no estável" do compilador.

É muito fácil acertar acidentalmente . uma vez a mais (ou, dada a mecânica envolvida, uma vez a menos) quando você pressiona várias vezes em rápida sucessão.

Marquei a opção “Alterar para aceitar ..= como sinônimo de ... em padrões e aceitar ..= em expressões” porque já é o caso depois de # 44709 com o dotdoteq_in_patterns e inclusive_range_syntax recursos respectivamente. O que resta é apenas documentação e estabilização.

Pedido de Estabilização

Gostaria de estabilizar o intervalo inclusivo em 1,26 (beta em 30 de março, estável em 11 de maio) ou antes. Um PR de estabilização foi apresentado como # 47813.

Resumo

Os três recursos a seguir serão estabilizados:

  • inclusive_range_syntax - A sintaxe a..=b e ..=b em uma expressão:

    for i in 1..=10 {
        println!("{:?}", &a[..=i]);
    }
    
  • dotdoteq_in_patterns - A sintaxe a..=b em um padrão:

    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!(),
    }
    

    (Observação: a sintaxe a...b ainda é aceita sem avisos)

  • inclusive_range - Os tipos std::ops::{RangeInclusive, RangeInclusiveTo} e seus campos:

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

Documentação

Diversos PRs de documentação são enviados por @alercah , obrigado!

Testes

Você pode encontrar casos de teste em:

Questões não resolvidas

  • Usar a..=b em um loop for tem desempenho muito menor do que a..(b+1) devido ao fato de next() ser mais complexo e menos amigável ao otimizador. Isso está sendo rastreado no momento em # 45222. Isso é atualmente mitigado por # 48012 ao usar métodos iteradores em vez de um loop for.

    Podemos precisar para manter os campos de RangeInclusive instável se não querem se comprometer com o projeto de ferrugem-lang / rfcs # 1980 ainda.

Podemos precisar manter os campos de RangeInclusive instáveis ​​se não quisermos nos comprometer com o design em rust-lang / rfcs # 1980 ainda.

+1
Existe alguma necessidade de expor campos de intervalo diretamente, em vez de por meio de alguma interface baseada em método?

@rfcbot fcp merge

De acordo com o resumo de @kennytm , proponho que estabilizemos a sintaxe de intervalo inclusivo ( ..= ).

(Dito isso, acho o desempenho inferior de ..= moderadamente preocupante, e me pergunto se faz sentido que ..= não seja implementado diretamente Iterator por enquanto, em a fim de mitigar isso.)

O membro da equipe @nikomatsakis propôs fundir isso. A próxima etapa é revisada pelo restante das equipes marcadas:

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

Nenhuma preocupação listada atualmente.

Assim que a maioria dos revisores aprovar (e nenhum objeção), isso entrará em seu período final para comentários. Se você identificar uma questão importante que não foi levantada em algum momento deste processo, fale!

Consulte este documento para obter informações sobre quais comandos os membros da equipe marcados podem me dar.

Eu me pergunto se faz sentido fazer .. = não implementado diretamente Iterator por enquanto, a fim de mitigar isso.

Essas características estáveis ​​são implementadas para RangeInclusive<T> por pelo menos T s no Nightly atual: Iterator , FusedIterator , ExactSizeIterator , Debug , Clone , Eq , PartialEq , Hash , TrustedLen .

@SimonSapin Eu esqueci, já estabilizamos a estrutura? (Em outras palavras, isso é observável?) Eu estava assumindo que não.

Dito isso, eu também realmente acho que 1..2 e 1..=2 devem ser usados ​​nos mesmos lugares, o que argumenta contra fazer qualquer alteração aqui e, em vez disso, sugere que devemos apenas buscar mitigações e melhorias otimizações.

Por que não intervalos de casos especiais onde end == MAX ? Isso poderia fazer com que a maioria dos intervalos inclusivos tivesse o mesmo código que os exclusivos, com a exceção de que aqueles que vão diretamente para a fronteira têm mais código. Como o branch end != Max nunca modificaria end , ele poderia ser facilmente embutido pelo otimizador.

@nikomatsakis Não, as estruturas estão instáveis ​​no momento. Mas a proposta de @kennytm inclui estabilizá-los.

@SimonSapin

Não, as estruturas estão instáveis ​​no momento. Mas a proposta de @kennytm inclui estabilizá-los.

Eu vejo; na verdade, é por isso que mencionei que teríamos que remover o Iterator impl agora ou nunca. =)

@SimonSapin Não acho que poderíamos estabilizar a sintaxe da expressão a..=b sem estabilizar a estrutura. No entanto, podemos deixar os campos instáveis, se pensarmos que podemos alterá-los.

Certo, eu não quis dizer que não devemos estabilizar os tipos ao estabilizar a sintaxe para construir valores desses tipos.

Huzzah por escapar da sintaxe de alcance e estabilizar! : tada:

Dada uma máquina do tempo, eu argumentaria que nenhum dos tipos Range sendo :Iterator , e eles sendo apenas :IntoIterator . Mas do jeito que está agora, acho que a consistência com o intervalo é a melhor opção. Podemos colocar este caso com Chain no balde "bem, parece que a iteração interna é apenas mais rápida às vezes".

Outra coisa que não foi resolvida, também relacionada à iteração: queremos nos comprometer com alguma representação específica do RangeInclusive depois de concluída a iteração? No momento , termina em 1..=0 , mas havia outras opções discutidas . Não sei se a documentação seria suficiente para evitar que as pessoas dependessem dela, embora a atual torne o intervalo de pós-iteração totalmente inútil, o que pelo menos o desencoraja.

Podemos colocar este caso com Chain no balde "bem, parece que a iteração interna é apenas mais rápida às vezes".

Acho que realmente precisamos consertá-lo para não ter menos desempenho do que um intervalo exclusivo; não há nenhuma razão fundamental para que seja.

não há razão _fundamental_ para que seja.

Depende de quais invariantes podemos impor. Nas duas formulações anteriores com um bit extra de estado, não havia nada que imponha que esse bit fosse realmente definido quando terminamos a iteração (e na verdade _não_ foi definido em literais como 100..=0 ), então o loop A condição de saída precisa ser composta, o que significa que o LLVM não está mais disposto a desenrolá-lo para nós, então temos um desempenho pior. Consertar totalmente isso parece significar tornar a estrutura maior e não ter campos pub, tornando RangeInclusive: !Iterator , ou tornar o LLVM melhor na otimização desses tipos de loops.

Dito isso, eu tentei algumas maneiras diferentes de escrever RangeInclusive::next , e parece que a escolha do meu eu passado para combinar com um Option<Ordering> está deixando o LLVM muito triste - apenas colocar os operadores de comparação lá é dar muito melhor montagem. Editar PR up: https://github.com/rust-lang/rust/pull/48057

Dada uma máquina do tempo, eu argumentaria que nenhum dos tipos Range era: Iterator, e eles eram apenas: IntoIterator. Mas do jeito que está agora, acho que a consistência com o intervalo é a melhor opção. Podemos colocar este caso com Chain no balde "bem, parece que a iteração interna é apenas mais rápida às vezes".

Eu basicamente concordo com isso.

: bell: Isso agora está entrando em seu período de comentários final , de acordo com a revisão acima . :Sino:

: bell: Isso agora está entrando em seu período de comentários final , de acordo com a revisão acima . :Sino:

@rfcbot fcp cancel

@withoutboats e @KodrAus não

Proposta @cramertj cancelada.

O membro da equipe @cramertj propôs fundir isso. A próxima etapa é revisada pelo restante das equipes marcadas:

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

Nenhuma preocupação listada atualmente.

Assim que a maioria dos revisores aprovar (e nenhum objeção), isso entrará em seu período final para comentários. Se você identificar uma questão importante que não foi levantada em algum momento deste processo, fale!

Consulte este documento para obter informações sobre quais comandos os membros da equipe marcados podem me dar.

: bell: Isso agora está entrando em seu período de comentários final , de acordo com a revisão acima . :Sino:

@rfcbot fcp concern Os padrões de intervalo têm um problema de prioridade do operador - https://github.com/rust-lang/rust/issues/48501.

( @petrochenkov A sintaxe é <strong i="6">@rfcbot</strong> concern KEYWORD , sem fcp . No entanto, acho que apenas o membro da equipe marcado pode registrar uma preocupação.)

O período de comentários final agora está completo.

Se # 48501 for suficiente para bloquear a estabilização, suponho que tenhamos que esperar até que # 48500 se mescle (e estabilize). Ugh, espero que possamos encontrar um caminho mais rápido. Esse recurso demorou muito para chegar e agora está em um estado precário, onde mensagens de erro apontam as pessoas para sintaxe instável.

@durka
Não acho que essa estabilização requer a espera para estabilizar https://github.com/rust-lang/rust/pull/48500.
... em padrões ainda existe e ainda tem a prioridade antiga, então se você tiver &BEGIN ... END em um padrão (isso deve ser muito raro, eu suspeito), há sempre uma opção para não alterá-lo para ..= por algum tempo.

Acho que podemos estabilizar # 48500 muito rapidamente

Pessoalmente, eu ficaria bem com "instável estável"

inclusive range foi estabilizado como # 47813 solicitação pull foi mesclada, mas não está na versão 1.25, por quê? Embora a solicitação de pull tenha sido fundida em 16 de março

@mominul um recurso está disponível somente após ter sido mesclado no branch master, portanto, ..= está disponível a partir de 1.26, não 1.25.

Dessa forma, você pode testá-los em beta e todas as noites antes de serem colocados no estável.

Obrigado pelas entradas @kennytm e @clarcharr ! O lançamento do Rust 1.26 definitivamente não é entediante, pelo menos para mim! :sorriso:

Eu sei que é tarde demais para entrar nessa discussão, mas por que não omitir a sintaxe .. inteiramente e usar palavras em seu lugar?

No Scala você tem 1 to 4 que gera [1, 2, 3, 4] , 1 until 4 que gera [1, 2, 3] e uma palavra-chave opcional by que se segue indica o tamanho do passo : 1 to 10 by 2 = [1, 3, 5, 7, 9] .

Isso torna a intenção mais clara e evita o erro "um por um" com o qual todos parecem tão preocupados.

Concedido, isso quebra todo o código existente, se a sintaxe original não permanecer com suporte.

@ElectricCoffee em faixas de ferrugem suporta todos os tipos, não apenas números. Acho que precisaríamos introduzir to e until como palavras-chave para oferecer suporte a isso, e isso seria uma mudança muito maior.

Funciona bem no Scala, mas as opções de design de Rust são muito diferentes.

@ElectricCoffee, embora eu goste da sensação disso, não acho que seja desejável adicionar palavras-chave adicionais para ele.

Acredito que as palavras-chave da linguagem integrada devem ser mantidas no mínimo, pois podem colidir com nomes de funções ou variáveis.

Embora to e until não sejam palavras usadas em std (até onde eu sei), tenho certeza de que são palavras comuns usadas em outras caixas e projetos.

@daboross esse é realmente um ponto justo que eu não considerei, embora dito isso, a .. b significa em certo sentido a to b , independentemente de a e b realmente são.

E sim, provavelmente são @timvisee .

@ElectricCoffee Mas se to significasse ..= e until significasse .. você teria que escrever a until b , não a to b vez de a .. b . Como você pode ver, não é "mais" intuitivo usar essas palavras do que os operadores .. Mas seria mais prolixo escrever until todos os lugares em que .. é usado, porque é muito mais comum do que ..= (então se palavras foram usadas, .. deve ser atribuído à palavra mais curta).

E você está absolutamente certo sobre esse @Boscop , no entanto, foi apenas um exemplo de como as palavras podem ser feitas.

Eu acredito que já vi to como exclusivo e upto como incluído em alguns idiomas também.
Tudo foi concebido como uma ideia.

Em Scala, o intervalo inclusivo é mais usado do que o exclusivo e, portanto, recebe a palavra mais curta.

@timvisee One simplesmente pode usar a.to(b) e a.until(b) , nenhuma palavra-chave adicional é necessária (e isso não torna a sintaxe muito mais complicada).

@ hyst329 Nem pensei nisso. Devo dizer que gosto muito dessa ideia! Você está realmente correto.

Eu não acredito que esta seja uma substituição completa adequada para a sintaxe atual (/ nova). Mas seria uma boa adição.

Tenho que concordar com o comentário de Boscop sobre a intuição. Além de palavras como "incluindo" e "exceto", o inglês do dia-a-dia realmente não distingue entre faixas inclusivas e exclusivas com força suficiente para que haja um atalho pronto.

A menos que seja usado em um contexto onde "A a B" também é usado, é ambíguo se "A a B" significa um intervalo inclusivo ou exclusivo na fala do dia-a-dia aqui no sul de Ontário, Canadá, e "até" está associado com o tempo forte o suficiente para que, quando usado neste sentido mais amplo, não fique claro se o "evento" que "até" se associa a é "até vermos X" ou "até que tenhamos processado X".

@ hyst329 Tê-los como métodos limitaria os intervalos aos tipos de número, no entanto. Eu realmente prefiro não ter uma sintaxe para intervalos de números e outra para intervalos de outras coisas.

Eu acho que poderíamos adicionar uma nova característica geral ao prelúdio para a criação de intervalos, mas isso ainda está beirando uma mudança significativa para coisas que têm métodos reais to e until .

Confesso que achei a sugestão de palavras-chave uma piada do primeiro de abril.
A sintaxe .. = foi estabilizada.

Na quinta-feira, 5 de abril de 2018 às 13h53, David Ross [email protected] escreveu:

@ hyst329 https://github.com/hyst329 Tê-los como métodos limitaria
varia para tipos de número, no entanto. Eu realmente prefiro não ter uma sintaxe para
intervalos de números e outro para intervalos de outras coisas.

Acho que poderíamos adicionar um novo traço abrangente ao prelúdio para a criação
intervalos, mas isso ainda está à beira de uma mudança significativa para coisas que têm
métodos reais para e até.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-379021814 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AAC3nwBj-b985q1Ez0OHDEHkG6DWV_5nks5tlloZgaJpZM4F4LbW
.

Sim, recebemos mais de 300 comentários sobre esse problema, e o primeiro comentário diz:

nenhuma mais discussão de sintaxe deve ser feita neste tópico . Quaisquer propostas diferentes de sintaxe de intervalo exclusivo devem ocorrer no fórum do usuário ou fórum interno, depois de você ter lido todos os comentários existentes e seus fundamentos aqui. Notavelmente, quebrar a compatibilidade com versões anteriores é um obstáculo.

Vou bloquear esse problema por enquanto, desculpe se estou pisando em qualquer coisa!

Acredito que tudo o que está coberto por esta edição está feito. Abra novamente e atualize a lista de verificação na mensagem original do problema, se houver algo mais.

Esta página foi útil?
0 / 5 - 0 avaliações