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

Creado en 4 sept. 2015  ·  331Comentarios  ·  Fuente: rust-lang/rust

Estado actual

Estamos planeando cambiar la sintaxis para rangos y patrones inclusivos a ..= . La sintaxis ... en los patrones es estable y permanecerá (silenciosamente) en desuso por el momento; rustfmt puede reescribir ... en ..= . Esto viene después de mucha discusión. Vea este comentario para justificación.

No se debe tener más discusión sobre la sintaxis en este hilo . Cualquier propuesta diferente de sintaxis de rango exclusivo debe tener lugar en el foro del usuario o en el foro interno , después de haber leído todos los comentarios existentes y su justificación aquí. En particular, romper la compatibilidad con versiones anteriores no es un comienzo.

Pasos a seguir

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

Comentario más útil

El equipo de lang discutió esta característica nuevamente en nuestra reunión de hoy y llegó aproximadamente a la siguiente matriz:

  • Soportar ... en patrones y .. en expresiones, y nada más, es un diseño insostenible; lleva a los usuarios a esperar que funcione una sintaxis que no funcionará.

  • Permitir ... y .. en ambos lugares ayudaría, pero el problema de uno por uno es una preocupación real; ninguno de nosotros está ansioso por recibir informes de personas que pasan horas rastreando un período errante.

  • Pasar a ..= y .. es menos atractivo estéticamente, pero evita los problemas prácticos muy reales anteriores. También podemos implementarlo de una manera muy suave: primero introduzca ..= como una sintaxis alternativa (en la que rustfmt puede reescribir), y solo después de que se haya vuelto idiomático, desapruebe ... .

En caso de que no pueda decirlo, el equipo siente que ..= y .. es nuestro mejor camino a seguir. Este tema también se ha discutido hasta el punto de que es muy poco probable que surjan nuevos argumentos, por lo que estamos listos para dar el paso: estamos buscando a alguien a quien le gustaría implementar la notación ..= para ambos patrones y expresiones, y posteriormente iremos a FCP!

Todos 331 comentarios

Quizás a..b| o a..b]

Creo que esto abrirá el camino para un nuevo tipo de errores impredecibles en el futuro debido a un simple error tipográfico (.. vs ...). Mejor si fuera .... (4 puntos). De esta manera, es menos propenso a errores que el factor humano, en mi opinión.

Creo que https://github.com/rust-lang/rfcs/pull/1592 y https://github.com/rust-lang/rfcs/pull/1582 combinados hacen un caso para usar el ..= sintaxis en su lugar. A menos que alguien pueda pensar en una mejor sintaxis que (head..., tail) para expandir una tupla al principio de una tupla más grande.

Encontré este problema porque tuve un error _off-by-one- dot _ en mi código cuando tenía la intención de usar un rango exclusivo.

👎 para la sintaxis ... . Creo que tener una sintaxis fácil de escribir incorrectamente que cause errores de uno por uno sería un arma de fuego.

Sin embargo, la funcionalidad es útil, por lo que estaría feliz de tenerla con una sintaxis diferente, por ejemplo, ..=

¿Es la sintaxis de esto una pregunta abierta? Como ... ya está en las declaraciones de coincidencia, asumí que el barco había zarpado.

Personalmente, preferiría el rango inclusivo ... , sin embargo, dado que ya existe la versión exclusiva .. , veo el potencial de problemas. Después de mirar # 23635, prefiero desaprobar .. y solo permitir ... .

Utilizo mucho rangos inclusivos para el equivalente de bucles for C-like for i in 0..foo.len() donde encaja perfectamente, así que prefiero que se quede (lo necesito, porque los iteradores de Rust son "unidimensionales" y a menudo demasiado incómodo para usar con matrices 2D o iteración no lineal).

El problema con el desbordamiento para rangos inclusivos parece tonto, pero en la práctica nunca me encontré con este problema, porque Rust es molesto de usar con cualquier tipo que no sea usize . Si no lancé al crear el rango for i in 0..(len as usize) , entonces tendría que usar i as usize media docena de veces dentro del ciclo de todos modos.

Dado que esta sintaxis todavía está activada, espero que el barco no haya zarpado.

Teniendo en cuenta que swift usa ... para inclusivo y ..< para rangos exclusivos, usar ..= para inclusivo parece bastante razonable.

No tengo ninguna información útil, pero me gustaría que los rangos inclusivos salieran del estado "experimental". Mientras repasaba Rust By Example, encontré un fragmento que podría beneficiarse de esto:

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

Arriba ? 😄

Quiero escribir un RFC para a ..= b sintaxis y rangos generalizados. Comencé un hilo de discusión para hablar sobre cómo se representarían tales rangos en la biblioteca estándar.

En mi humilde opinión .. = parece extraño. El enfoque de Swift de ... y .. <me parece mejor, porque prefiero la elipsis sobre dos puntos: la elipsis significa omisión y estamos omitiendo los números entre el inicio y el final del rango.

Sigo pensando ... y ... fue lo suficientemente bueno. Tienes 1 carácter de diferencia, por lo que el error es más difícil de cometer que +/- o x / y o lo que sea.

Dado que yo mismo entendí mal esto antes (y por lo tanto eliminé mi comentario):

Según el proceso RFC de Rust, esta propuesta ya ha sido revisada, discutida y aprobada en la solicitud de extracción RFC 1192 . El presente número rastrea la implementación de lo que se decidió previamente allí. La discusión cubrió muchos de los puntos que la gente está planteando aquí: sintaxis alternativa (sin incluir sintaxis nueva), el contraste con los operadores similares de Ruby, etc.

Si cree firmemente que la función debería ser diferente, creo que debe llevarla a cabo por el mismo proceso de RFC, porque así es como se realizan los cambios en el idioma. Pero este tema no es el lugar para eso.

@jimblandy tal vez deberíamos hacer que @nikomatsakis edite ese amable recordatorio y guía en el primer comentario en Really Big Print. 😇

@shepmaster Eso probablemente sería bueno para agregar a una plantilla utilizada para archivar _todos_ los problemas de seguimiento.

Nominación para discusión / posible FCP

Hablamos de esto en la reunión @ rust-lang / lang. Hubo una sensación general de descontento con esta función; consideramos pasar a desaprobarlo, pero decidimos postergarlo por el momento. Hay dos objeciones principales a ... tal como está:

  • la facilidad de confusión entre .. y ... ;
  • @aturon ha estado pensando que sería mejor tener una sintaxis de rango más "completamente capaz"; esto también podría usarse en API como iteración btree, etc.

Con ese fin, nos preguntábamos si alguien estaría dispuesto a impulsar un RFC que permitiera una sintaxis más general como la que permitiera a las personas especificar con precisión si los límites inferior y superior serían inclusivos o exclusivos. Creo que @aturon estaría feliz de trabajar con alguien en tal RFC.

Sé que me estanqué por un tiempo, pero recientemente abrí un hilo de discusión sobre cómo representar esos rangos totalmente capaces en libstd (vinculado arriba ), pero nadie comentó :(

Con algunos comentarios sobre lo anterior, me complacerá ayudar con un nuevo RFC.

Recientemente abrí un hilo de discusión sobre cómo representar esos rangos totalmente capaces en libstd (vinculado arriba), pero nadie comentó :(

Eso refleja de alguna manera su utilidad.
Si bien tener rangos arbitrarios inclusivos-exclusivos parece una buena idea, estoy bastante seguro de que todo, excepto .. y, en mucho menos, ... nunca se usará.

@durka

Sé que me estanqué por un tiempo, pero abrí el hilo de discusión sobre cómo representar esos rangos totalmente capaces en libstd (vinculado arriba), pero nadie comentó :(

Este parece más o menos el enfoque que teníamos en mente, sí.


@petrochenkov

Si bien tener rangos arbitrarios inclusivos-exclusivos suena como una buena idea, estoy bastante seguro de que todo excepto ... y en mucho menos grado ... nunca se usará.

Para ser honesto, estoy de acuerdo, pero sigo pensando que puede valer la pena seguir una sintaxis más general. En particular, creo que ... es subóptimo, pero si pasamos a ..= o algo más explícito, probablemente no esté de más hacer algo un poco más general, incluso si rara vez es usado. Es decir, si lo hacemos sistemático, no parece mucho más difícil de aprender, y seguramente no habrá confusión en cuanto a si .. o ... significa "más números ".

Este parece más o menos el enfoque que teníamos en mente, sí.

¿Cuál? Sugerí varias alternativas en mi publicación.

A menudo quiero iterar sobre rangos inclusivos y realmente me gustó escribir 0...x lugar de 0..(x + 1) . Entiendo que esto puede introducir errores uno por uno, pero ¿qué alternativas tenemos?

Suponiendo que la sintaxis de Rust se pueda cambiar libremente sin efectos secundarios, veo solo algunos patrones obvios:

Tomándolo como es

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

que es una buena solución en mi humilde opinión y también se utiliza en la coincidencia de patrones.

Tomar prestado de las matemáticas

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

que es la sintaxis más completa, pero rompe la misma cantidad de reglas de llaves de apertura y cierre y es visualmente más difícil de analizar.

Pedir prestado de Python

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

que es un patrón conocido y también podría incorporar un tamaño de paso. No sé cómo funciona el proceso RFC, pero creo que también se debe considerar un tamaño de paso cuando se habla de rangos.

Cuando el tamaño del paso no es parte de esta discusión (o de una futura), ..= y ..< parecen muy razonables.

Actualización: Creo que ..= y ..< serían una muy buena solución. Mantener el tamaño del escalón como adaptador tiene mucho más sentido.

¿Debería esta discusión incorporar rangos descendentes? La solución actual de invertir el rango es bastante confusa (pero quizás no lo haría si tuviéramos rangos inclusivos).

por ejemplo, ¿puede leer y comprender esto sin entrecerrar los ojos?

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

EDITAR: y con la fuente de GitHub es aún más confuso ya que l parece 1

Creo que bastaría con un tamaño de paso negativo.

Podríamos seguir la sintaxis de Matlab, a:b y a:step:b .

El 4 de noviembre de 2016 a las 00:50, "Ott" [email protected] escribió:

Creo que bastaría con un tamaño de paso negativo.

-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment -258344460,
o silenciar el hilo
https://github.com/notifications/unsubscribe-auth/AAC3n3kwnGH6POQb4dGwCwJ8yOGqPSBQks5q6rmDgaJpZM4F4LbW
.

@durka Entonces, ¿cuál sería el equivalente del actual .. , donde no hay a o b ? ¿Solo : ?

Algo que no vi anotado en el RFC: ¿Se consideraron diferentes nombres para los campos?

Si hay diferentes tipos, puede ser útil tener diferentes nombres de campo cuando tienen diferentes significados. Por ejemplo, "range.start" es "el límite inclusivo inferior" en todos los tipos. Pero "range.end" es a veces inclusivo y a veces exclusivo. Una distinción entre "fin" y (hombre de paja) "último" lo aclara más.

(Esto es, por supuesto, irrelevante si los diferentes tipos se abandonan a favor de Range> ...)

Creo que el rango inclusivo aún debería implementar std :: collections :: range :: RangeArgument.

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

Entonces

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

De modo que fn foo<T, R: RangeArgument<T>>(arg: R) puede tomar rangos inclusivos o semiabiertos.

@durka El problema con la sintaxis a: b es que es ambigua con la adscripción de tipos. ¿Está pidiendo una variable b , o un tipo b ? Obviamente, como buenos programadores de Rust, capitalizamos nuestros tipos, pero el compilador no puede inferir eso.

.. operador con definiciones matemáticas (basado en el comentario de @duesee ):

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

Usando (basado en el ejemplo de @ 0tt ):

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

En este caso usamos .. solo como una pista, pero los límites están dados por [ y ]

@adelarsq : En Rust no necesitamos rangos que no incluyan el inicio. Pero la sintaxis de corchetes solo tiene sentido cuando están permitidos. Además, la sintaxis de corchetes ya se usa.

Creo que ..= es la opción más razonable para rangos inclusivos.
Fácil de distinguir visualmente de .. , que ... no lo es. La posibilidad de escribir ... cuando significa .. o viceversa y no darse cuenta es mayor que con ..= .
(Es comparable a escribir accidentalmente if(a = b) lugar de if(a == b) en C, tanto en notoriedad visual como en potencial de errores).
Y ..= es fácil de memorizar porque es simbólico por su significado ( i ..= j significa el rango i .. j y donde i = j ).

Parece que la principal queja es que ... es demasiado similar a .. . Me di cuenta de que cuando se hacen otras sugerencias que involucran a más caracteres, nadie se queja de la cantidad de caracteres, solo cosas como la coincidencia de corchetes y el uso en ciertos lugares.
Entonces, ¿qué pasa con .... para rangos inclusivos? Todavía debería verse como un rango, y como dije, a nadie parece importarle una solución que requiera un carácter adicional. Es discutible si es más o menos inestable que ..= .
for i in 0....10 { println!("just a thought"); }

Si el comportamiento predeterminado fuera inclusivo el ..! se usaría el operador (casi como una negación).

El problema con .... es que sería algo confuso si ... realmente existe.

Realmente no me gusta ... tampoco, ya que es exactamente lo inverso de Ruby .

La mejor opción hasta ahora es ..= , creo.

@adelarsq , el operador .... reemplazaría al operador ... , por lo que si intentas hacer .. y agregas un . adicional, sería una compilación error de tiempo, si trataste de hacer .... y olvidaste un punto, eso también sería un error.

Dado que en la coincidencia de patrones, ... se usa para hacer coincidir el rango inclusivo, por lo que tiene sentido usar también ... para la expresión de rango inclusivo.
Para rango con paso, prefiero la sintaxis de Haskell, por ejemplo, 1,3..9 => [1,3,5,7]

Para rangos con paso / retroceso, etc. Preferiría una buena función pasada de moda (algún tipo de constructor Range ) en lugar de un literal complejo.

Estaría bien con quad-dot .... (aunque ..= está bien en mi humilde opinión). También podría permitirse en la coincidencia de patrones para mantener la coherencia (y eventualmente ... en patrones podrían quedar obsoletos).

Para mí ..= como un significado visual que .... no tiene.

Acabo de notar algo:

En matemáticas, podría escribir ∀ i: 0 ≤ i < 10 que se traduciría en

for i in 0 ..< 10 { }

Esto es consistente.

Sin embargo, la declaración ∀ i: 0 ≤ i ≤ 10 se traduciría en

for i in 0 ..= 10 { }

Aquí, ≤ se traduce en =, lo que se siente inconsistente.

Esto podría ser un derrumbe de bicicletas, pero

for x in 0 ..<= 10 { }

se siente más correcto. Esto puede deberse a mi experiencia en C donde

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

se traduce en "siempre que i sea ​​menor o igual a 10 hacer algo". En CI prefiero no usar == en condiciones de bucle, debido a la posibilidad de saltar sobre el valor y terminar en un bucle infinito. Esto no puede suceder en Rust, pero traducir for i in 1 ..= 10 a C podría sugerir exactamente eso.

Llevándolo más lejos

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

sería autoexplicativo.

Editar: aquí hay un mal ejemplo inverso destinado a mostrar cómo usar solo = puede ser confuso. Suprimido, ya que era más confuso que constructivo.

@duesee ¿ >=..> se explica por sí mismo? ¿No debería ser <=..> (<= 10 y> 0)?
En mi opinión, no se explica por sí mismo, es críptico y demasiado largo como operador.
(Ningún operador debe tener más de 3 caracteres en mi opinión).
Por cierto, ya tenemos una forma de expresar la dirección de iteración inversa: .rev()
Solo necesitamos operadores para rangos inclusivos y tal vez .step_by() .
Para el paso, la sintaxis podría ser a .. b | s (y para rangos inclusivos: a ..= b | s ).

@norru : Su ejemplo for i in (1..l.len()).rev() { ... } es muy poco realista, ya que la mayoría de las veces usaría cortes ( for x in arr[1..].rev() { ... } ), pero incluso si se ve obligado a usar el estilo de iteración de índice (básicamente solo cuando modifica los elementos de la matriz que no están en i ), no me resulta difícil leer en absoluto. (Pero generalmente dejo espacios alrededor de .. cuando los argumentos no son números literales: (1 .. arr.len()).rev() )

>=..> más especies de peces en los operadores de Rust!

Pero me gusta mucho ..<= (editar: uhh, excepto en match donde se ve como <= 0 => :()

  • Es muy distinto del simple .. ,
  • no tiene la connotación += de ..= ,
  • es lógicamente consistente incluso con ..< Swift. ¡Es posible que ambos idiomas converjan!
  • y lo más importante, es bastante claro que obtienes números en el rango que son menores o iguales que el superior.

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

@Boscop : se explica por sí mismo si lo lees como una definición en matemáticas: 10 >= i > 2 . Para el resto de su respuesta: estoy absolutamente de acuerdo. La segunda parte fue pensada como una motivación para repensar ..= frente a ..<= para no introducir bloqueadores para futuras extensiones. Editaré mi respuesta en consecuencia.

también puede obtener una bandera para advertir o error en la notación ..

No quiero que .. aparezca en ninguna parte de mi base de código

Me gustaría poner otro voto por ..=

La desventaja de ..< y ..<= es que ya son códigos válidos (un rango exclusivo de apertura por la derecha se compara con otro valor).

@elpowersgang

La desventaja de .. <y .. <= es que ya son códigos válidos (un rango exclusivo de apertura por la derecha se compara con otro valor).

si bien es cierto, parece bastante improbable que esto sea un problema en la práctica, ¿no?

Prefiero mucho ... a las otras sugerencias aquí ... pero si tuviera que elegir una sintaxis alternativa, sería ..=

@nikomatsakis

Estoy en contra de las opciones ..< y ..<= simplemente porque complican desproporcionadamente el proceso de adquirir un modelo intuitivo de la gramática del idioma.

En una nota más personal, los encuentro al menos tan feos y poco elegantes como el turbofish.

Yo iría con .. para derecho exclusivo y ..= para inclusivo como el mejor equilibrio entre elegancia visual, reglas gramaticales que son fáciles de comprender intuitivamente y que hacen que los dos sean difíciles de confundir.

¿Es ... realmente tan indistinto de .. ? ¿Por qué me gusta tanto?

@tshepang

Me gusta ... porque es estéticamente atractivo ... pero discuto en contra porque me preocupa que tenga el potencial de causar errores difíciles de notar similares a escribir if (x = 2) { lugar de if (x == 2) { en C / C ++. (Y está bien establecido el peligro que resultó).

@ssokolow

En mi opinión, eso se resuelve mejor con banderas de opciones o linting. No veo mucho uso para mezclar notaciones en un solo archivo / proyecto.

También prefiera .... sobre las otras opciones, tener el doble de ancho / espaciado debería hacerlo lo suficientemente obvio, especialmente considerando que estarán flanqueados en ambos lados por símbolos que harán que ese espacio negativo sea más pronunciado que de forma aislada.

@ssokolow

Yo iría con .. para derecho exclusivo y .. = para inclusivo como el mejor equilibrio entre la elegancia visual, las reglas gramaticales que son fáciles de comprender intuitivamente y hacen que los dos sean difíciles de confundir.

Esto funciona para mi. El principal problema es si también queremos una sintaxis para otros casos (por ejemplo, <..<= ). Personalmente, creo que .. y ..= cubren como el 99,5% de los casos. Creo que el caso de uso principal son las API como drain , y actualmente hemos adoptado un enfoque distinto allí .

cc @ rust-lang / libs

Podemos dejar los casos poco comunes para construir directamente los rangos usando
literales de estructura.

El miércoles 22 de febrero de 2017 a las 4:50 p.m., Niko Matsakis [email protected]
escribió:

@ssokolow https://github.com/ssokolow

Yo iría con .. por derecho exclusivo y .. = por inclusivo como el mejor
equilibrio entre elegancia visual, reglas gramaticales que son fáciles de intuitivamente
agarrar, y hacer que los dos sean difíciles de confundir.

Esto funciona para mi. El principal escollo es si también queremos una
sintaxis para otros casos (por ejemplo, <.. <=). Yo personalmente siento que .. y .. =
cubre como el 99,5% de los casos. Creo que el caso de uso principal son las API como drenaje,
y actualmente hemos adoptado un enfoque distinto allí
https://doc.rust-lang.org/std/collections/struct.BTreeMap.html#method.range
.

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

-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-281815665 ,
o silenciar el hilo
https://github.com/notifications/unsubscribe-auth/AAC3n-aKwYKFq4VI9RizL0GkzXXSjTPwks5rfK2ngaJpZM4F4LbW
.

Supongo que ..= también estarán disponibles en patrones. ¿Qué será de la sintaxis ... allí?

Puede quedar obsoleto. Pero su existencia es un precedente bastante sólido para
usándolo, al menos como una abreviatura.

El miércoles 22 de febrero de 2017 a las 6:02 p.m., andrewtj [email protected] escribió:

Supongo que ... = ¿también estará disponible en patrones? Que será de
la sintaxis existente ... allí?

-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-281834007 ,
o silenciar el hilo
https://github.com/notifications/unsubscribe-auth/AAC3nw_DaOMNxuIKw6ZFfXJW95QyijY4ks5rfL6DgaJpZM4F4LbW
.

@durka @andrewtj Supongo que lo desaprobaríamos.

..= se puede usar como operador en el mismo sentido que += .
Sugiero usar tide ~ , por ejemplo, 0~9 , 'A'~'Z' .

¿A qué operación correspondería ..= ? - es obviamente inviable porque
1-9 == -8 .

El miércoles 22 de febrero de 2017 a las 8:04 p.m., Junfeng Liu [email protected]
escribió:

.. = se puede utilizar como operador en el mismo sentido de + =.
Sugiero usar ~, por ejemplo, 0 ~ 9, 'A' ~ 'Z'.

-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-281856846 ,
o silenciar el hilo
https://github.com/notifications/unsubscribe-auth/AAC3n7N2dM4DAzc_uc5JdHit4IJgyvYGks5rfNsPgaJpZM4F4LbW
.

@durka ..= simplemente parecen operadores de asignación, el caso de uso debe ser poco común. ~ es marea no sub. Usar ... también está bien.

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, lo siento, se ve igual en mi fuente. Preguntaba, si .. = es un compuesto
operador de asignación como + =, qué operación realiza (correspondiente
a +)?

El miércoles 22 de febrero de 2017 a las 8:29 p.m., Junfeng Liu [email protected]
escribió:

@durka https://github.com/durka .. = solo parece una asignación
operadores, el caso de uso debe ser poco común. ~ es marea no sub.

relleno implícito para rango{
fn fill () -> String {...}
}
impl FillAsign para RangeAssign{
fn fill (& mut self) {...}
}
(Cadena :: nuevo ("abc") .. Cadena :: nuevo ("f")). Fill () // "abcdef"
(Cadena :: nuevo ("abc") .. = Cadena :: nuevo ("f")). Fill () // ()

-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-281861478 ,
o silenciar el hilo
https://github.com/notifications/unsubscribe-auth/AAC3n39uqbADB1rNtBh3PBTRY2XBXOUNks5rfOD-gaJpZM4F4LbW
.

@durka @nikomatsakis está bien, bueno, espero que esto se resuelva pronto. La situación actual es incómoda y el cambio de sintaxis también lo será.

@pornel Dejar de lado ... en match rompería la compatibilidad, por lo que no es una buena solución. Todavía encuentro ... el más adecuado (sin embargo, es un inverso exacto de Ruby, pero los rubyists no discuten un problema similar).

@ hyst329 pero ... puede ser más susceptible a errores, ya que faltar o agregar uno . dará un nuevo significado

La depreciación no rompe las cosas. La sintaxis anterior tendrá que ser compatible para siempre con los programas existentes, pero los usuarios pueden dirigirse hacia la nueva sintaxis a través de la documentación y rustfmt.

pero los usuarios pueden dirigirse hacia la nueva sintaxis a través de documentación y rustfmt.

Recomiendo encarecidamente no usar rustfmt para eso. Aumentaría las cualidades de ... cuando se usa en el modo "aplicar cambios automáticamente" porque podría traducir silenciosamente los errores tipográficos en cosas que parecen mucho más útiles. (Haciéndolos más fáciles de pasar por alto en un examen posterior).

Una advertencia del compilador en la línea de "por favor verifique lo que quiso decir y use .. o ..= " que no se pueden arreglar automáticamente estaría mucho más en línea con los esfuerzos existentes para minimizar el posibilidad de error humano.

Tenga en cuenta que estaba hablando en el contexto de los patrones de ... , donde no existe ninguna pistola. Actualmente, Rust se encuentra en una situación temporal sin pistolas donde los patrones solo permiten ... y las expresiones solo permiten .. , por lo que ambos están a salvo de errores tipográficos.

Por supuesto, no recomendaría convertir ... en expresiones a ..= , ya que eso, por supuesto, solo haría que el error tipográfico fuera permanente.

Ah. Me había olvidado de eso. Gracias por recordarme.

@adelarsq En realidad, errores comunes como 'a'..'z' o 128u8..255u8 pueden integrarse fácilmente en cargo-clippy como advertencias, por ejemplo. Y también, el ancho de .. y ... es claramente diferente (cuando se usa una fuente monoespaciada, por supuesto; no usarla suele ser una mala idea para escribir código fuente en general, no solo Rust) .

Podríamos hacer que la sintaxis sea (elipses horizontales Unicode) en lugar de ... esa manera al menos nadie lo escribiría por accidente.

Editar: oh, nadie estaba tratando esta sugerencia en serio: llorar: Perdón por el ruido.

No sé, la última vez que verifiqué Google Docs se convierte automáticamente ... en puntos suspensivos. Jugador importante en la industria de la edición de texto.

Además, no todo el mundo tiene una tecla Redactar para escribir cómodamente Redactar . . cuando ellos quieren

¡En Windows puedo escribir puntos suspensivos usando Alt + 0133 con el teclado numérico!

Y existen mecanismos similares basados ​​en puntos de código en varias capas de la pila en escritorios basados ​​en X11 (recuerdo que GTK + y la pila de entrada X11 tienen sus propias soluciones independientes) pero es una molestia importante recordar los puntos de código por número.

Compose es una solución ṽèŕÿ intuitiva.

La única secuencia de Windows Alt que recuerdo es Alt + 219 de todos los menús de archivos de DOS Batch que hice cuando era niño.

La sintaxis actual existe desde hace mucho tiempo, simplemente estabilicémosla y detengamos este interminable derrumbe de bicicletas.

Mantener la sintaxis actual es lo peor que podríamos hacer, ya que tiene muchas desventajas reales . Esto no es solo un desprendimiento de bicicletas, debe hacerse bien. Saltando todo el hilo, la sintaxis ..= obtuvo la mayor aceptación hasta ahora ...

Siento un poco como si estuviera ganando un caballo muerto en este punto, pero cuando lo piensas ... La diferencia entre .. y ... es literalmente una copia del carácter más pequeño posible que Puede escribir o leer, mezclado con un grupo de caracteres idénticos, y tiene el potencial de crear una clase de error extremadamente común y, a menudo, irritantemente difícil de encontrar (errores uno por uno) en casos que de otra manera serían completamente indistinguibles. al hombre y la máquina.

O podríamos hacer literalmente cualquier otra sintaxis del mundo.

Por un lado, aprecio esa preocupación ... por otro lado, la sintaxis actual de coincidencia de patrones ... ya es inclusiva, lo que la hace perfectamente consistente con la sintaxis que ya se usa en otras partes de Rust.

Y personalmente no tengo ningún problema para reconocer la diferencia, aunque reconozco que las personas con problemas de visión, o con un monitor de 4k y una fuente de 10 puntos, podrían hacerlo.

Pero parece que el consenso está en ..= y creo que eso también me parece bien.

FWIW, tuve esa situación en la que accidentalmente escribí ... cuando me refería a .. y luego no me di cuenta por un tiempo, pero después de un tiempo me pregunté por qué mi programa se comportaba de manera extraña.
Entonces sí, debería haber una diferencia más visible, y ..= tiene más sentido.

Nominación para el debate @ rust-lang / lang. Creo que deberíamos adoptar ..= y terminarlo. ¿Necesitamos una RFC modificada? ¿Solo hazlo? ¿Implica esto desaprobar la sintaxis ... en los patrones? (Asumo que sí.)

Estoy totalmente a favor de no usar ... para rangos. No sé si ya se ha mencionado en este hilo o en el hilo RFC, pero además de que ... un aspecto irrazonablemente similar a .. , es posible que también queramos usar ... en el futuro para genéricos variadic, que son mucho más importantes que los rangos inclusivos en mi opinión.

..= parece claro, y su relativa fealdad se justifica por ser menos común que .. .

¿Implica esto desaprobar la sintaxis ... existente en los patrones? (Asumo que sí.)

Esto parece una buena idea. Advertir sobre ... y apoyar tanto .. como ..= en patrones si podemos.

En general, desconfío de introducir advertencias que afectarían a tanta gente sin tener también una herramienta automatizada para actualizar la sintaxis, pero ... a ..= es un cambio particularmente simple. También podríamos desaprobarlo, pero posponerlo como advertencia hasta que tengamos una herramienta de este tipo. ¿Qué piensa todo el mundo?

Estoy totalmente a favor de ... porque es una sintaxis más "habitual"; No conozco ningún idioma que use ..= , pero muchos que usan .. y ... .

Si el sentimiento contra ..= es fuerte, preferiría ir sin una sintaxis de rango inclusivo (en lugar de optar por un método (a..b).inclusive() , que me parece lo suficientemente conciso) para evitar el problema visual y nuevamente gratis hasta ... para genéricos variadic.

EDITAR: Un buen argumento en contra de (a..b).inclusive() es que todavía tendremos ... en match y sin una nueva sintaxis para reemplazarlo, desafortunadamente. :confundido:

@steveklabnik Disculpas si esto ya se ha mencionado en algún lugar de este hilo (muy larga), pero: ¿qué otros lenguajes usan tanto .. y ... para los rangos de exclusión e inclusión, respectivamente?

Rust tiene un historial de adoptar características útiles y sintaxis de otros lenguajes, pero de forma selectiva y rechazar o adaptar cosas cuando sea apropiado.

@joshtriplett Ruby usa ambos, pero con significados opuestos ( .. es inclusivo, ... es exclusivo). No creo que fuera una buena idea en Ruby, y parece incluso más potencialmente confuso para nosotros tener ambos, pero al revés.

@joshtriplett con el que estoy más familiarizado es Ruby; Pensé que lo había obtenido de Perl, pero no estoy del todo seguro. Estoy más de acuerdo con que la semántica sea al revés de Ruby que con ..= .

Honestamente, preferiría una sintaxis de rango inclusivo estable sobre cualquier otra cosa, y reconozco que mi intensa aversión por ..= es algo personal, con lo que personas razonables pueden estar en desacuerdo.

@steveklabnik Swift usa ..< , creo, ¿verdad? Lo que parece similar a ..= pero peor, ya que optimiza (en mi opinión) el caso equivocado. =)

Swift usa .. <para exclusivo y ... para inclusivo (sus términos son
"semiabierto" y "cerrado").

Todavía me gusta .. <(con .. como taquigrafía) y .. =.

Pero otra pregunta abierta (quizás no dentro del alcance de este problema de seguimiento) es si "simplemente" adoptamos una sintaxis para rangos cerrados, o también sintaxis (¿sintaxis?) Para rangos con el primer punto abierto, es decir, hombre de paja> ..> y > .. =.

El jueves 16 de marzo de 2017 a las 2:19 p.m., Niko Matsakis [email protected]
escribió:

@steveklabnik https://github.com/steveklabnik Swift usa .. <, creo,
¿derecho? Lo que parece similar a .. = pero peor, en que optimiza para
(imo) el caso equivocado. =)

-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-287147321 ,
o silenciar el hilo
https://github.com/notifications/unsubscribe-auth/AAC3n0Wop5fJh9HVo7pSqo0riHm96Gm4ks5rmX1BgaJpZM4F4LbW
.

No me importaría tener una función inclusive en el preludio:

for x in inclusive(1..10) {

}

Nunca he sentido que la simetría con la coincidencia sea un argumento convincente. Creo que decidimos agregar patrones exclusivos .. , pero también me desagradan: ¡un valor en el patrón ahora no coincide con el patrón! Hacer coincidir un rango es fundamentalmente diferente de iterar a través de un rango, no hay ninguna razón por la que tengan que ser simétricos. Tendría una preferencia leve para no permitir .. en patrones si todavía es una opción, pero creo que no lo es.

Siento que las desventajas de ..= y ... son significativas: ..= es bastante extraño, pero ... aumenta la probabilidad de error en 1 error.

Es mejor tener un operador de aspecto extraño que un potencial interminable de errores (cada idioma presenta operadores que otros no tienen, por ejemplo, ..< en Swift, todas las operaciones en F # y Scala). La gente tendrá que leer el libro de Rust de todos modos.
Teniendo en cuenta que mucha gente viene a Rust desde Ruby, no deberíamos tenerlo al revés en comparación con Ruby. (Además del argumento de que ... aumenta la probabilidad de error en 1 error).
¿Cómo puedes aceptar ..< en Swift pero no aceptar ..= en Rust? ..= no es tan extraño.

La extensión de la sintaxis del rango en los patrones sigue siendo una pregunta abierta también AFAIK.
Por un lado, no podemos hacerlo por completo, porque Enum::Variant(..) ya está
válido y cambiarlo para significar que Enum::Variant(RangeFull) se rompería.

El jueves 16 de marzo de 2017 a las 3:07 p.m., Boscop [email protected] escribió:

Es mejor tener un operador de aspecto extraño (todos los idiomas introducen
operadores que otros no tienen, por ejemplo .. <en Swift, todas las operaciones en F #
y Scala). La gente tendrá que leer el libro de Rust de todos modos.
Teniendo en cuenta que mucha gente viene a Rust desde Ruby,
no debería tenerlo al revés en comparación con Ruby. (Además del argumento
que ... aumenta la probabilidad de error en 1 error.)
¿Cómo puedes aceptar .. <en Swift pero no aceptar .. = en Rust?

-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-287160485 ,
o silenciar el hilo
https://github.com/notifications/unsubscribe-auth/AAC3nz9ZNR2utl7LPTVvQPQ_Ma8sDBGuks5rmYhmgaJpZM4F4LbW
.

Entonces. Quiero poder escribir cosas como slice.get(10...30) y comerme mi pastel también.

Me he convencido de que prefiero fuertemente inclusive(0..10) a cualquiera de las otras sintaxis:

  • Si bien @nagisa quiere escribir slice.get(10...30) , no quiero tener que prestar mucha atención a si eso es slice.get(10...30) o slice.get(10..30) . Creo que la cercanía de la sintaxis es un problema real.
  • Creo que todos están de acuerdo en que ..= es estético y probablemente poco intuitivo.
  • (0..10).inclusive() es la misma sintaxis pero menos conveniente. Técnicamente, inclusive prelude probablemente admitiría ambas sintaxis.

Creo que se vería así:

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

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

Creo que todo el mundo está de acuerdo .. = es antiestético y probablemente poco intuitivo.

Creo que decir eso es una generalización excesiva. Encuentro que ..= es más estético e intuitivo de lo que sería un método como inclusive() .

(Además, no sabemos cuánto de la aversión por ..= podría deberse a esfuerzos subconscientes (o conscientes) para encontrar problemas con cosas que no son ... ).

.inclusive() es demasiado largo para algo que ocurre con tanta frecuencia (en esa nota, también creo que debería haber una forma más corta para .enumerate() ).
Pero incluso si tuviéramos .inclusive() , debería haber solo una función, no dos.
Además, no tener una sintaxis de rango inclusiva no permitiría que se usen en match .
¿Pero tal vez necesitemos una forma de especificar extractores de una manera general, como en Scala ? Para que se pueda usar cualquier tipo en una coincidencia, esa coincidencia llamará implícitamente a su método unapply .

(Además, no sabemos cuánto de la aversión por .. = podría deberse a esfuerzos subconscientes (o conscientes) para encontrar problemas con cosas que no lo son ...)

Ninguno de mi parte. Es una especie de acusación de mala fe.

Además, no tener una sintaxis de rango inclusivo no permitiría que se usen en la coincidencia.

Los patrones de rango inclusivo ya se admiten en match . De hecho, son el único tipo de rango que admitimos como patrones en la actualidad.

@withoutboats sí, pero dije que "no tener una sintaxis de rango inclusivo no permitiría que se usen en una coincidencia". En este momento hay una sintaxis, pero mi argumento estaba en contra de .inclusive() porque no se podía usar en una coincidencia a menos que tuviéramos extractores como Scala. y el objetivo de este problema es que la sintaxis de rango inclusivo no debería ser un caso especial que solo funcione en coincidencia y para determinar cuál debería ser la sintaxis en lugar de la actual.

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

Como alguien que trabaja más de 15 años con Java / C / C ++, encuentro que .. vs ... es bastante confuso y puede causar errores con solo escribir errores. Además, la relación con Ruby hace que esto sea aún más confuso. Es por eso que ..= o cualquier otra alternativa es mejor.

tirando mi 'sombrero' en el ring:

for i in 1..10^

El sombrero / símbolo de intercalación que simboliza que el valor correcto va todo el camino _hacia arriba_.

@leebenson Personalmente, creo que sería mejor si estuviera en el medio, no en el exterior.

for i in 1..^10

@ retep998 Lo consideré después de presionar enviar ... probablemente sea mejor en realidad.

@ retep998 Me gusta tu sugerencia de ..^ mucho mejor que ..= ; parece mucho más evocador de su significado y evita parecer una variante extraña de un operador de asignación aumentado (como += y *= ). Dicho esto, cualquiera de los dos sería mucho mejor que ... .

No puedo atrasarme ..^ .

A nivel personal, lo encuentro muy feo (en parte porque el .. es tan verticalmente disjunto del ^ en muchas fuentes).

Como chico de UI / UX, creo que es un ejemplo de ser demasiado inteligente para tu propio bien.

Si vengo de otro idioma y veo ..^ , es posible que ni siquiera lo reconozca como un rango (por lo que sé, 5..^15 podría ser una taquigrafía factorial parcial extraña para 15! - 4! ) porque los humanos piensan en contextos y la única asociación que tiene ese personaje en un contexto de programación convencional es la exponenciación.

(Si no pensáramos en contextos, ... podría significar algo como "la devolución de llamada se inserta aquí" o "emitir evento" por analogía con su "contenido omitido", como el significado del diálogo en la escritura en prosa, solo para mostrar el ejemplo más inmediato. Darle un significado de "sube todo el camino" a través de su parecido con una flecha es como hacer trucos de magia mediante un juego de manos, en cuanto a cómo interactúa con las expectativas de un recién llegado).

Por el contrario, = tiene un precedente para referirse tanto a la acción de asignación como al concepto de igualdad y no hay una "sintaxis de exponenciación extraña", como un concepto erróneo para ..= porque es lo más cercano a " asignación + igualdad "que aún no es manejada por el operador de asignación es" algo que ver con una secuencia de números, terminando en el de la derecha "... que es una definición vaga pero apropiada de lo que hace la sintaxis de rango.

También me preocupa que, incluso si reconociera que ..^ era una sintaxis de rango por su uso en contexto, no tendría una idea intuitiva de si era inclusivo o exclusivo al principio, porque no hay significado para ^ en el contexto relevante, excepto por la posibilidad de que 2..^8 sea ​​la abreviatura de un rango abierto que comienza en dos y avanza dando el paso anterior a la potencia de 8. (es decir, 2..Inf^8 en lugar de 2..+8 es la abreviatura de "iterar de 2 a infinito en pasos de 8").

Ese problema también se evita con ..= porque la gente está acostumbrada a pensar en términos de < (exclusivo) frente a <= (inclusive) al escribir while bucles y bucles de estilo C for .

@ssokolow análisis legítimo.

Personalmente, puedo atrasarme ..= o ..^ . La simbología de cualquiera tiene sentido para mí, es decir, "hasta e igual a" o simplemente "hasta", respectivamente. Ambos significan lo mismo, en mi opinión.

Va a ser difícil encontrar algo que satisfaga a todos, porque todos traemos la historia de otros idiomas y con ella, simbología / sesgo contaminado. Inicialmente agregué el signo ^ _después_ del número, por ejemplo, porque insertar antes tenía la sensación de representar un 'paso' o exponente, mientras que un sufijo dejaba el rango sin manchar, y de alguna manera una sensación más pura. Pero ese soy solo yo.

En cualquier caso, preferiría una notación abreviada de alguna forma frente a una llamada de función que implícitamente hace +1 en el valor de la derecha. Estoy de acuerdo con los comentarios anteriores de que esta es una sintaxis demasiado común para delegarla en algo que se siente como una llamada de función. Incluso no me importaría ... , pero concedido, probablemente sea el error = / == en ropa nueva y seguramente disparará a alguien en el pie ...

mucha gente parece no gustar activamente .. = nadie dijo nada negativo
sobre ... fue simplemente ignorado en silencio (excepto por unos pocos pulgares arriba)
Pensé que lo sacaría a relucir de nuevo y que la gente lo considerara y le diera una
razón para no usarlo si están en contra.

Odio incluso mencionarlo porque es más ruido, pero ¿qué pasa?:
(punto y dos puntos) para inclusivo? Son 3 puntos pero 2 caracteres, y creo que el
la forma lo distingue de ..

El sábado 18 de marzo de 2017 a las 11:50 a. M., Lee Benson [email protected]
escribió:

@ssokolow https://github.com/ssokolow análisis legítimo.

Personalmente, puedo atrasarme .. = o .. ^. La simbología de cualquiera
tiene sentido para mí, es decir, "hasta e igual a" o simplemente "hasta",
respectivamente. Ambos significan lo mismo, en mi opinión.

Va a ser difícil encontrar algo que satisfaga a todos,
porque todos traemos la historia de otros idiomas y con ella, manchada
simbología / sesgo. Inicialmente agregué el signo ^ después del número, por
ejemplo, porque insertar antes tenía la sensación de representar un 'paso'
o exponente, mientras que un sufijo deja el rango sin manchar, y de alguna manera más puro
sentimiento. Pero ese soy solo yo.

En cualquier caso, preferiría una notación abreviada de alguna forma frente a una
llamada de función que implícitamente + 1s el val de la derecha. Estoy de acuerdo con antes
comenta que esta es una sintaxis demasiado común para delegarla en algo que
se siente como una llamada de función. Ni siquiera me importaría ..., pero concedido, es
probablemente el = / == error en ropa nueva y destinado a disparar a alguien en el
pie...

-
Estás recibiendo esto porque comentaste.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-287566556 ,
o silenciar el hilo
https://github.com/notifications/unsubscribe-auth/AIhJ6jWgPwndKaQvVjULlV_OoC6WDO0Cks5rnCeLgaJpZM4F4LbW
.

Oh, ¿esto todavía está en una fase de eliminación de bicicletas? 😆

Volviendo a leer, creo que estoy de acuerdo con @nikomatsakis para que sea ..= y termine el día. La similitud de .. vs ... es demasiado sutil, y prefiero ver que el token ... se use sin ambigüedad para genéricos variadic (https://github.com/ rust-lang / rfcs / pull / 1935), donde cumple un propósito muy distinto que debería conducir a una menor confusión entre los dos.

No estoy seguro de si el deseo de una sintaxis más generalizada para todas las variantes semiabiertas sigue ahí, pero creo que no vale la pena el esfuerzo de proporcionar una sintaxis de lenguaje fuera de .. y ..= .

Odio incluso mencionarlo porque es más ruido, pero ¿qué pasa con.: (Punto dos puntos) para inclusivo?

Creo que @ssokolow hizo algunos puntos importantes con respecto a la interfaz de usuario / ser inteligente. Yo diría que cambiar la dirección del tercer punto para engañar a sus ojos para que vean algo más probablemente estaría en esa categoría.

Personalmente, tengo una objeción _ cero_ a que haya un tercer punto, aparte de saber que eventualmente hará tropezar a algunas personas. Pero también es muy fácil de explicar, por lo que no estoy seguro de que la responsabilidad deba estar en el lenguaje para diseñar soluciones alternativas inteligentes. Es exclusivo de 2 puntos; 3 puntos incluidos '¿realmente _ tan_ difícil de entender / depurar?

En cualquier caso, ¿quién toma la decisión final y cuál es el siguiente paso para cerrar esto? 18 meses discutiendo el tercer personaje probablemente _es_ un derrame de bicicletas en este punto 😄

De acuerdo, ^ hace que parezca un paso.
En mi opinión, la inconsistencia con otros operadores op= no es un problema porque no hay forma de que tengamos a ..= b en el sentido de a = a .. b , ya que .. es no un operador, sino azúcar sintáctico para construir un rango (y no tenemos un esquema de sobrecarga de operaciones general donde cualquier operación obtiene automáticamente una forma de op= y .. ).
No estoy diciendo que ..= esté claro sin mirar el documento. Pero una vez que la gente miró el documento, es más fácil de memorizar, y tendrán que mirar el documento de todos modos.

Dada la nominación de @nikomatsakis , creo que terminaremos discutiéndolo en la reunión del equipo de

También me preocupa que, incluso si reconociera que ..^ era una sintaxis de rango por su uso en contexto, no tendría una idea intuitiva de si era inclusivo o exclusivo al principio

Acordado. De hecho, ya he visto esta sintaxis en Perl 6 donde significa exclusivo, lo contrario de la propuesta aquí.

@solson Ese es un argumento muy convincente en su contra.

Perl parece tener una sintaxis completamente general, con .. significado inclusivo (en ambos
lados) y ^ en cualquier lado hace que ese límite sea exclusivo.

El sábado 18 de marzo de 2017 a las 6:51 p.m., Josh Triplett [email protected]
escribió:

@solson https://github.com/solson Ese es un argumento muy convincente
En contra.

-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-287580739 ,
o silenciar el hilo
https://github.com/notifications/unsubscribe-auth/AAC3n7Fnn1_t9BkYOhfS-7oCaGlVff2aks5rnF_5gaJpZM4F4LbW
.

Entonces, lamento decirlo, pero cuando discutimos este tema en la reunión de @ rust-lang / lang, no pudimos llegar a un consenso. @withoutboats en particular tiene algunas reservas severas que, con suerte, pueden ventilar por sí mismos.

Algunos puntos importantes que discutimos:

  • Si tenemos una sintaxis de rango inclusivo en expresiones y patrones, debería ser la misma

    • es decir, si adoptamos x ..= y , eso implica desaprobar la sintaxis del patrón x...y .

  • Una opción tentadora es "no hacer nada" y simplemente escribir (x..y).inclusive() o algo por el estilo. Sin embargo, eso no funcionará en patrones (que presumiblemente permanecerían como x...y ). Esto plantea algunas preguntas propias:

    • ¿Todavía queremos patrones de gama exclusivos ? por ejemplo, match 3 { 1..3 => false, .. }



      • Si es así, ¡entonces tenemos la misma confusión potencial!



    • @withoutboats parece pensar que tal vez no queremos tales patrones. Yo y @joshtriplett dudamos de esto; Creo que ambos teníamos la opinión de que son el tipo de cosas que parecen irrelevantes hasta que las quieres, y luego se sienten absolutamente necesarias . =)

  • Otro problema relacionado con los patrones de rango exclusivos es que interactúan mal con los patrones de corte (también inestables) (consulte https://github.com/rust-lang/rust/issues/23121 para obtener más detalles).

Creo que una cosa que surgió de esta discusión fue que sería bueno tomar una decisión sobre todos los factores en conflicto a la vez . En otras palabras, adoptar una decisión que resuelva:

  • ¿Qué hacer con las expresiones de rango exclusivo?
  • ¿Tenemos que desaprobar / cambiar los patrones de rango exclusivo existentes?
  • ¿Qué hacer con los patrones de rango inclusivo ?
  • ¿Qué hacer con los patrones de corte ?

Antes de comenzar este artículo, quiero decir que me sentí muy inseguro de que en cada momento de la conversación todos estuviéramos hablando del mismo concepto. Por ejemplo, Niko dice que "los patrones de rango exclusivo parecen irrelevantes hasta que los quieres", pero pensé que Niko y Josh estaban hablando de expresiones de rango inclusivo en ese momento.

(Y creo que en la última parte de la publicación de Niko, la primera viñeta que actualmente dice "expresiones de rango exclusivo" debería decir "expresiones de rango inclusivo").

TL; DR mi opinión

Acerca de las expresiones de rango:

  • No deberíamos introducir ninguna sintaxis para expresiones de rango inclusivo, ni ... ni ..= .
  • Deberíamos agregar al preludio una función que toma un valor de rango exclusivo y devuelve un valor de rango inclusivo. Entonces, escribirías inclusive(0..10) (el nombre se puede quitar en bicicleta).

Acerca de los patrones de rango:

  • No deberíamos introducir patrones de gama exclusivos, ni ninguna forma de crear uno.

En otras palabras, el único cambio material que deberíamos hacer es un cambio de libs: agregue una función al preludio.

Expresiones de rango

Fundamental para mi argumento es el hecho de que iterar a través de un valor de rango inclusivo es una necesidad poco común. Creo que esto se ve confirmado por el hecho de que, a pesar de que se aceptó el RFC hace 18 meses, todavía no hemos estabilizado esta función, no por problemas de implementación, sino porque no estamos contentos con la compensación.

Creo que las expresiones de rango inclusivo se necesitan con la suficiente frecuencia como para admitir una forma sencilla de crearlas, pero no con la suficiente frecuencia como para que superen cualquiera de las desventajas de las sintaxis que hemos discutido hasta ahora.

En particular, una desventaja que todas las soluciones sintácticas han compartido es que ninguna de ellas es realmente autodocumentada. Es relativamente no obvio que 0...10 o 0..=10 sea ​​una expresión de rango inclusivo . Dado que se encontrarán con relativa poca frecuencia, esto será un obstáculo para los usuarios que los encuentren por primera vez.

Es decir, si el usuario se da cuenta de que no se trata de un rango .. "normal". Por supuesto, este es el gran problema con ... , pero ..= no elimina totalmente el problema. Es fácil, al hojear el código, perder ese carácter = (o ^ o : o cualquier otra cosa). No es tan fácil como los . adicionales, pero no estoy convencido de que se note lo suficiente.

De hecho, creo que hay una compensación de "notoriedad frente a obviedad" entre ... y ..= . Creo que es más obvio lo que significa ... (a menos que vengas de Ruby, donde las dos sintaxis tienen el significado opuesto) que ..= , pero definitivamente es menos notorio .

Pero creo que una función de preludio como inclusive(0..10) es más obvia y más notoria que cualquier sintaxis que hemos discutido. Sí, hay más caracteres para escribir, pero la desventaja de ese atributo es relativa a la frecuencia de uso.

También elude cualquiera de los problemas de análisis y tokenización, y ayuda a los usuarios con el (muy molesto) problema de precedencia de rango vs método que requiere que escriban (0..10).filter y demás.

Patrones de rango

La razón principal por la que creo que no deberíamos agregar .. es que introduce ambigüedad en los patrones de corte, que creo que son útiles. Me gustaría resolver ese problema sin tener que resolverlo.

La segunda razón es que creo que tienen un estilo bastante malo (sé que otras personas no están de acuerdo). Por ejemplo:

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

Creo que esto es confuso, porque 10 no coincide con el patrón que lo contiene. Niko mencionó que esto no es realmente diferente de las expresiones de rango exclusivo que no producen 10 , pero creo que la gran diferencia es que tenemos una gran cantidad de precedentes históricos (y casos de uso) al estilo de Dijsktra para admitir exclusivos rangos. Al entrar en Rust, esperaba que los rangos iterativos y de corte fueran exclusivos, pero no tenía esa expectativa para los patrones.

También tiene el problema de "uno por uno" que tiene .. / ... en las expresiones.

Sé que Niko ha mencionado que le gustaría escribir:

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

Pero realmente preferiría ver:

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

De todos modos, me sorprendió que Niko quisiera decir que a veces los encuentra "absolutamente necesarios", así que me gustaría escuchar más contraargumentos. Ya que tienen que ser un constexpr, me parece mucho más algo 'agradable de tener' que algo 'absolutamente necesario'.

Definitivamente me siento más fácil influir en patrones de rango exclusivo que en expresiones de rango inclusivo.

El argumento de la coherencia

Niko mencionó que tener tanto .. como ... tanto en expresiones como en patrones es importante para él debido a la coherencia. Básicamente, este argumento no me conmueve en absoluto. Iterar a través de un rango y hacer coincidir un rango no son realmente operaciones análogas, y tiene sentido que haya diferencias entre cómo las tratamos.

De hecho, ni siquiera hay una conexión de implementación: 1..10 produce un valor de Rango, mientras que 1...10 coincide con un valor entero. No es como si tuvieran una conexión de estructuración / desestructuración de la forma en que lo hacen la mayoría de nuestras sintaxis simétricas de expresión / patrón.

Parece más técnicamente correcto llamar a los patrones "patrones de dominio" que "patrones de rango" 🤓, lo que resalta la no análoga.

@sin barcos

Por ejemplo, Niko dice que "los patrones de rango exclusivo parecen irrelevantes hasta que los quieres", pero pensé que Niko y Josh estaban hablando de expresiones de rango inclusivo en ese momento.

Por mi parte, he encontrado que los rangos exclusivos e inclusivos son necesarios en varios momentos (aunque he usado exclusivo para ambos casos para trabajar en Rust estable, y tuve que solucionarlo con un +1 en la parte superior Unido). Me gustaría tenerlos disponibles tanto para patrones como para expresiones.

Dicho esto, personalmente, no tendría objeciones al uso de una función para rangos inclusivos, excepto que quiero tener una forma de escribir rangos inclusivos y exclusivos en patrones , y me gustaría que esas dos sintaxis no parezcan confusamente similares como .. y ... . Y dada una sintaxis para escribir tales rangos en patrones, no sé si tiene sentido tener una sintaxis diferente para tales rangos en expresiones.

En particular, una desventaja que todas las soluciones sintácticas han compartido es que ninguna de ellas es realmente autodocumentada. Es relativamente no obvio que 0 ... 10 o 0 .. = 10 es una expresión de rango inclusivo. Dado que se encontrarán con relativa poca frecuencia, esto será un obstáculo para los usuarios que los encuentren por primera vez.

Estoy de acuerdo con esto. Esto aparece con poca frecuencia como para no tener objeciones a una sintaxis menos compacta. Sin embargo, me gustaría tener algún mecanismo para escribir rangos inclusivos y exclusivos tanto en expresiones como en patrones.

No me importaría, por ejemplo, si escribir un patrón de rango inclusivo requiriera una macro o similar.

@joshtriplett Aquí es donde quiero ser realmente claro, cuando dices esto:

He encontrado rangos exclusivos e inclusivos necesarios en varios momentos (aunque he usado exclusivo para ambos casos para trabajar en Rust estable, y tuve que solucionarlo con un +1 en el límite superior).

Parece claro que está hablando de expresiones , pero la sección que citó fue sobre patrones (sé que habla de patrones en su próximo párrafo, pero estoy preguntando sobre el problema de la "necesidad" que ese párrafo no aborda 😃) .

El status quo para los patrones es que solo admitimos patrones de rango inclusivos, de la forma x...y . ¿Puedes hablar más sobre si / cuando has encontrado patrones de rango exclusivo realmente frustrante de no tener?

@sin barcos

¿Puedes hablar más sobre si / cuando has encontrado patrones de rango exclusivo realmente frustrante de no tener?

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

No diría que es especialmente frustrante, pero el primero ciertamente se ve mejor.

@withoutboats Para mayor claridad, en varias ocasiones he querido expresiones de rango exclusivas, expresiones de rango inclusivas y patrones de rango inclusivos. No puedo pensar en un momento en el que me haya preocupado mucho por tener patrones de rango exclusivos, aunque tampoco me opondría a ellos. Pero incluso si no tenemos patrones de rango exclusivos, todavía sería muy confuso si los patrones de rango inclusivos usan ... y las expresiones de rango exclusivo usan .. .

@petrochenkov Supongo que estaban destinados a terminar en F , no C ?

Me he encontrado con el mismo caso con patrones de rango hexadecimal, por ejemplo, 0x8000...0x9FFF => /* body */ . Encuentro que 0x8000..0xA000 tiene propiedades un poco más intuitivas, como sin tener que pensar en ello, inmediatamente veo que el tamaño del rango es 0xA000 - 0x8000 = 0x2000 y que el siguiente rango adyacente comienza en 0xA000 .

Tratar con los +1 requeridos para ver estos hechos en un rango inclusivo es una pequeña diferencia con la que puedo vivir, pero los rangos exclusivos (tanto patrones como expresiones) generalmente se adaptan mejor a mi trabajo.

@petrochenkov Puedo ver por qué preferirías rangos exclusivos para hexdigits (es posible que todavía no, pero esto se siente como un trato muy YMMV).

Sin embargo, ¿cómo lidiaríamos con las ambigüedades de sintaxis de los segmentos?

@joshtriplett

Todavía sería muy confuso si los patrones de rango inclusivo usan ... y las expresiones de rango exclusivo usan .. .

¿Así es como funciona Rust hoy y no parece ser una fuente significativa de confusión?

@solson

Supongo que estaban destinados a terminar en F, no en C.

No :)
(Esas cosas son de 32 bits y offset es un múltiplo de cuatro).

@sin barcos

Puedo ver por qué preferiría rangos exclusivos para hexdigits (es posible que todavía no, pero esto se siente como un trato muy YMMV).

Debo tener en cuenta que esta no es una preferencia fuerte, todavía estaría de acuerdo con eliminar tanto los patrones exclusivos como los rangos inclusivos (pero ninguno de ellos, eso sería demasiado ridículo).

Sin embargo, ¿cómo lidiaríamos con las ambigüedades de sintaxis de los segmentos?

¡Fácilmente! PATTERN.. => .. @ PATTERN

Mi principal razón para querer que los rangos inclusivos sean simples es que me he encontrado con situaciones más de una vez en las que paso un valor de parada en una variable y es exactamente el valor máximo que puede contener un tipo de variable, por lo que las únicas soluciones para descartar el desbordamiento en tiempo de compilación son:

  1. Usando una gama inclusiva (más limpia, pero no estable)
  2. Upcasting antes de + 1 (se supone que aún no estoy en u64 y no es elegante)
  3. Tomando el valor menor y el máximo menos uno para el rango, luego ejecute la tarea una vez más si corresponde.

Desarrollar el hábito de usar rangos inclusivos en lugar de agregar + 1 a un algoritmo donde no tiene un propósito inherente es una forma no trivial de evitar volver a encontrarlos más adelante en cargo fuzz ... y usar una función "hacer inclusivo desde exclusivo" con más caracteres en su nombre que + 1 da la impresión de que los rangos inclusivos son algo excepcional, en lugar de algo que debería usar habitualmente.

Esa es una de las principales razones por las que estoy en contra. Transmite la impresión de que los rangos inclusivos son un truco, que se utilizará cuando se demuestre que los rangos exclusivos han fallado.

@ssokolow, pero ese caso de uso está cómodamente cubierto por una función de preludio. Nadie está adoptando la posición de que no debería ser posible crear rangos inclusivos, solo si deberían o no tener azúcar sintáctico para crearlos.

Me gusta la idea de @withoutboats de una función de preludio. Creo que el otro lugar donde los rangos inclusivos pueden ser más comunes es cuando no usa números enteros, por ejemplo, especificando los límites de una búsqueda en un árbol b (o estructura de datos similar).

@withoutboats Edité un poco en mi publicación mientras respondías, pero la esencia de lo que agregué es que hacer que los rangos inclusivos sean ciudadanos de segunda clase, sintácticamente (con una sintaxis más larga que agregar + 1 a un rango exclusivo ), se siente como un sutil desánimo en contra de su uso y un posible "Te veré en cargo fuzz más tarde".

Si nada más, es una verruga de enseñanza.

Rust no es Python 3.x, con su soporte de enteros ilimitado. Rust no oculta las compensaciones de hardware a los usuarios, y veo el ..= que prefiero como parte del uso de u32 y amigos en lugar de int . (Especialmente dado que los errores de desbordamiento / subdesbordamiento son lo más común en la "vitrina de trofeos" de cargo fuzz hasta ahora).

EDITAR: Por favor ignore cualquier parte que solo vea en las notificaciones por correo electrónico para esto. Me acabo de despertar y todavía no estoy disparando a todos los cilindros.

No veo inclusive(n..m) como un desánimo en absoluto ... Preferiría escribirlo porque es una construcción muy clara que hace que mi código sea más fácil de leer que n..(m + 1) y n..=m (que he llegado a considerar innecesariamente extraño cuando solo podíamos decir la palabra "inclusivo").

n..=m es más una verruga de enseñanza que inclusive(n..m) IMO.

Creo que para la coincidencia existe el deseo de tener una cobertura completa del rango numérico, en lugar de un tipo específico de patrón.

Presumiblemente, si hubiera una sintaxis "continuar desde anterior", también resolvería el problema.

Por cierto, dado que solo coincide el primer patrón, el número inicial a menudo se puede omitir:

    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 esto puede ser una cuestión de perspectiva, pero:

  1. Cuando veo .. y ..= , pienso "Eh. Me pregunto por qué tienen dos sintaxis para una diferencia tan pequeña", lo que me llevaría a buscar documentos que pudieran centrarse en " 1..pivot y pivot..end " frente a " x..=y donde y puede ser el valor máximo posible".

  2. Antes de tener la experiencia suficiente para pensar habitualmente en términos de tamaños variables, solo habría usado + 1 sobre inclusive() (si hubiera ido a buscarlo), porque he estado usando + 1 desde la escuela primaria, es corto y fácil de escribir, y mi yo inexperto está acostumbrado a trabajar en lenguajes como Python y JavaScript donde la adición que causa desbordamiento no es algo de lo que la gente se preocupe.

EDITAR: ... y es esa distinción conceptual en el punto 1 en la que creo que deberíamos centrarnos. (es decir, que "de X al pivote" y "de X al final" deben ser distintos en la mente del programador).

@pornel
Esto es horrible 😄
En este caso específico, el inicio del rango es realmente muy importante para una persona que lee el código, mucho más importante que cualquier problema de rango inclusivo / exclusivo.

@ssokolow, me parece que lo que hace que +1 un problema no es la cantidad de caracteres, sino que debes manejar el potencial de desbordamiento. Además, tampoco comunica la intención y requiere discutir los parens de precedencia. Todos estos parecen mucho más importantes que la cantidad de caracteres.

Es cierto que alguien que no sepa sobre el desbordamiento podría alcanzar +1 antes de crear un rango inclusivo, pero esto no parece depender de la sintaxis. Al descubrir que ..= es una cosa y que inclusive() es una cosa, es un momento de aprendizaje para aprender por qué querría rangos inclusivos específicamente.

@petrochenkov

Todavía estaría de acuerdo con eliminar tanto los patrones exclusivos como los rangos inclusivos (pero ninguno de ellos, eso sería demasiado ridículo) .

¿Podría explicar por qué se siente tan fuertemente acerca de esto? Definitivamente veo que aceptar patrones exclusivos solo tiene una desventaja, ya que podría llevar a los usuarios a esperar 0...10 como expresión, pero no me parece tan malo .

Parte de mi problema con inclusive() es que es "solo" una función y me preocupa que la gente haga cosas como ir al índice de sintaxis de Rust, buscar "rango" o "iterador" y luego asumir un ROI insuficiente para "Ver [ing] iteradores".

("No quiero leer un libro de texto en la remota posibilidad de que encuentre algo útil ... solo quiero iterar sobre un rango y volver a progresar").

@withoutboats Si tenemos inclusivo (a..b), pero no podemos usarlo en el partido, no vale la pena en mi opinión.
La mayoría de las veces, cuando uso rangos inclusivos, ¡es en patrones de coincidencia!
Entonces, ¿por qué no podemos eliminar ... y simplemente usar ..= dentro y fuera de la coincidencia?

@Boscop, la propuesta no es eliminar ... en la coincidencia, sino dejar los patrones exactamente como están estables.

@ssokolow parece que se puede resolver con bastante facilidad con una nota en la sección ..

@withoutboats Pero, ¿por qué no eliminar ... en la coincidencia y usar ..= lugar, para que sea coherente?
(para que sea ..= dentro y fuera de la coincidencia)

Para cobertura de rango numérico en punto flotante, ayudas exclusivas. Por ejemplo, uno de estos límites está completamente cubierto, pero no el otro:

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

Y escribirlo con superposiciones, en cambio, se siente repugnante (y moralmente similar a "empezar todo desde -∞ ya que los brazos están ordenados" arriba). Consulte también las fechas y horas, por ejemplo, cómo ISO8601 permite T24: 00, ya que un día es [00:00, 24:00), no [00:00, 23:59:59]. O cadenas, o racionales, o ...

Dada la opción de solo exclusivo o solo inclusivo, tomaré exclusivo cada vez.

(Aparte: el patrón 1 <= x <= N para indexar en realidad se hace mejor como 0 < x <= N , que también es exclusivo, aunque medio cerrado en lugar de medio abierto, por las mismas razones que Dijkstra dijo, simplemente cambiado para indexación basada en 1 en lugar de basada en 0).

Este operador habría sido muy útil para la función de sujeción que propuse aquí: https://github.com/rust-lang/rfcs/pull/1961 sin embargo, dado que esto no se ha estabilizado, probablemente tenga que modificar esa propuesta para use dos argumentos mínimo y máximo en su lugar. InclusiveRange también es muy útil cuando se trabaja con valores de punto flotante para que no tengamos que hacer algo como:

0.0..1.0 + EPSILON

Ni siquiera estoy seguro de si eso es correcto, pero en este momento es muy difícil declarar un rango inclusivo de números de punto flotante.

La forma correcta de hacer esto sería con nextafter , no con epsilon. es decir, x...y == x..nextafter(y) . La caja ieee754 expone dicha funcionalidad.

Vaya, hice un comentario sobre la sintaxis inclusive(a..b) pero me di cuenta de que no era cierto. De todos modos, me gusta, pero espero que podamos poner un nombre mejor en bicicleta.

@durka El nombre me parece claro. ¿Puede explicar sus preocupaciones con él?

Entonces, para rangos inclusivos, tendremos a ... b en match y inclusive(a..b) fuera de la coincidencia.
¿Por qué no podemos ser consistentes y tener a ..= b todas partes?

¿Hay algo que impida que ops::{RangeInclusive, RangeToInclusive} se estabilice formalmente?

En este momento, parece que el principal bloqueador es el debate sobre la sintaxis, aunque independientemente de ese debate, estoy bastante seguro de que existirán rangos inclusivos independientemente de cuál sea la sintaxis final.

Sería bueno tener estos tipos para implementar bibliotecas estables, y luego los consumidores de estas bibliotecas pueden decidir habilitar el indicador de función si desean usar la sintaxis especial.

Una cosa que noté sobre RangeInclusive el otro día: es difícil codificar si estás tratando de aceptar un rango. El hilo de la abrazadera hablaba de permitir .clamp(1...9) , pero el código termina pareciéndose a esto:

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

Necesitar lidiar con RangeInclusive::Empty allí se siente innecesario ya que el objetivo es simplemente aceptar el par con una buena sintaxis. Si no fuera una enumeración, podría ser fn clamp(self, RangeInclusive { start, end }: RangeInclusive<Self>) y mucho más limpio.

Desafortunadamente, no tengo una buena respuesta sobre qué hacer al respecto, ya que requerir .into_iter () en inclusivo pero no exclusivo también sería desafortunado ...

Idea aleatoria: al ver que la sintaxis del patrón ... no está realmente relacionada con los tipos de rango inclusivos, podríamos considerar desaprobar su sintaxis a favor de una no relacionada con las ... propuestas aquí.

Dado que un patrón de rango inclusivo está más estrechamente relacionado con el patrón | , |... podría ser un buen candidato:

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

El resultado final sería que la sintaxis de rango inclusivo y exclusivo ya no tiene una relación 1: 1 con la coincidencia de patrones y, por lo tanto, no es necesario que sea coherente con ella.

@scottmcm

Desafortunadamente, no tengo una buena respuesta sobre qué hacer al respecto, ya que requerir .into_iter () en inclusivo pero no exclusivo también sería desafortunado ...

¿Quizás podríamos agregar un ayudante como range.nonempty() que entra en pánico por un rango vacío y devuelve un par?

Alternativamente, podríamos implementar IntoIterator por RangeInclusive y no estaría demasiado lejos en mi humilde opinión.

¿Qué caso de uso sirve RangeInclusive :: Empty? ¿Por qué un rango inclusivo necesita la capacidad de representar un rango vacío? ¿Cómo escribirías uno? (Tenga en cuenta que ya puede escribir cosas como "el rango de 5 a 4, inclusive", que la iteración presumiblemente trataría como vacía).

@joshtriplett el caso principal es el desbordamiento, aunque hay formas de solucionar ese problema.

@joshtriplett start > end realidad no funciona para representar el rango inclusivo vacío en un caso importante: 0u8...255u8 . Cuando llegue a 255u8...255u8 e intente .next() , entrará en pánico o pasará a 0u8...255u8 , que no está vacío. Entonces, en su lugar, cambiamos a la variante Empty en ese punto.

@solson Ah, ya veo. Sí, eso es una molestia, y es uno de los casos de uso más grandes para rangos inclusivos.

(Supongo que te refieres a 255u8 en todos esos casos).

(Supongo que te refieres a 255u8 en todos esos casos).

Si gracias. Editado.

@solson sin embargo, este caso se puede rectificar intercambiando 0 y 255 en ese caso

@clarcharr Eso es cierto. Dado que .next() siempre tiene que aplicar un caso especial a la generación de un rango Empty , siempre podría generar un rango que se tratará como vacío.

Personalmente, me gusta más esa forma porque no involucra el rango vacío.

Así que este hilo ha estado sucediendo durante un año y medio. Acabo de terminar de leerlo todo y me gustaría publicar un resumen conciso para los recién llegados y, con suerte, ayudarnos a tomar una decisión:

Lo que hace Rust Stable hoy:

0..5 representa un rango medio abierto, [0, 1, 2, 3, 4] que no se puede usar en la coincidencia de patrones
0...5 representa un rango cerrado [0, 1, 2, 3, 4, 5] que solo se puede usar en la coincidencia de patrones.

Se han propuesto varias formas para una sintaxis de rango cerrado adicional que se puede usar fuera de la coincidencia de patrones. Cubriré cada uno y los beneficios e inconvenientes de ellos.

0...5

Ventajas: de acuerdo con la sintaxis de coincidencia de patrones existente, hace que el lenguaje se sienta más cohesivo suponiendo que no se realicen cambios en la sintaxis de coincidencia de patrones.

Contras: Fácil de escribir mal y causar errores por uno, también fácil de malinterpretar la intención debido a que otros lenguajes usan este operador para comunicar diferentes conceptos.

0..=5

Ventajas: más difícil de escribir mal, más claro semánticamente

Contras: Inconsistente con la sintaxis de coincidencia de patrones existente. Puede hacer que los usuarios pregunten: ¿Por qué está ... aquí pero ... = aquí?

0..^5

Muy similar a ..= pero tiene una desventaja adicional en el sentido de que parece un operador de exponenciación.

inclusive(0..5)

Ventajas: Extremadamente semánticamente claro. No estará mal escrito.

Contras: algo largo. También es incompatible con la sintaxis de coincidencia de patrones.

0....5

Ventajas: también evita el problema de la escritura incorrecta de ...

Contras: Semántica deficiente, inconsistente con la sintaxis de coincidencia de patrones y similar a la sintaxis de coincidencia de patrones.

[0..5] Inutilizable. los corchetes ya tienen un significado sintáctico en el idioma.

0..<=5 Inutilizable. Entra en conflicto con la sintaxis existente para comparar un valor con un rango.

Todas las opciones enumeradas que tienen una desventaja de "inconsistente con la sintaxis de coincidencia de patrones" podrían mejorarse si cambiamos la sintaxis de coincidencia de patrones, pero esa ruta tiene problemas de compatibilidad con versiones anteriores. Alternativamente, también podríamos hacer que ... y (elija su sintaxis aquí) sean equivalentes dentro de la coincidencia de patrones para evitar romper la compatibilidad con versiones anteriores, pero evitar el uso de ... fuera de la coincidencia de patrones. Quizás también podríamos actualizar la guía de estilo para desalentar el uso de ... en la coincidencia de patrones si tuviéramos que seguir ese camino.

También se ha debatido sobre la creación de una sintaxis de rango de propósito más general que le permitiría hacer que los límites superior e inferior sean inclusivos o exclusivos, pero probablemente ni siquiera necesitemos esa sintaxis, ya que el rango medio abierto y cerrado probablemente cubre más 99,9999% de casos de uso.

Traté de representar esta discusión lo mejor que pude. Si cree que no expresé su punto de manera adecuada, hágamelo saber para que pueda actualizar esto.

@Xaeroxe Gracias por el excelente resumen.

Tal vez sea posible tener una herramienta (tal vez un complemento de rustfmt) que convierta automáticamente las fuentes del uso de ... en la coincidencia de patrones con la nueva sintaxis (por ejemplo, ..= ) cuando se decida.
De esa forma, no nos retendremos "todo el código escrito a la antigua".
Pero debe ser invocado con la intención de los autores del proyecto y debe haber una notificación / titular en todos los medios de rust para que todos estén al tanto del cambio.
Con esas cosas, creo que no hay problema para cambiar la sintaxis ... en la coincidencia de patrones con la nueva sintaxis.

Creo que una cosa que podríamos hacer para resolver el problema de la sintaxis es simplemente estabilizar RangeInclusive, como sugirió @clarcharr . Esto desbloqueará a las personas al menos.

También podríamos agregar la función inclusive (ya sea solo a std::range o posiblemente también al preludio); esto no excluye tener una sintaxis de primera clase algún día, pero hace que sea mucho más conveniente construir un RangeInclusive ahora mismo.

Sin embargo, todas estas parecen decisiones de libs, así que no sé si el equipo de lang tiene jurisdicción para decidir estabilizar / agregar estos elementos 😅.

Personalmente, preferiría convertir RangeInclusive en sí mismo en algo que no tenga una variante Empty , luego hacer que IntoIter tenga la variante. Tiene más sentido para mí considerando que es esencialmente imposible construir un rango vacío sin Empty { at } manualmente.

Alternativamente, intercambie MAX y MIN en el caso de un borde que mencioné. Eso hace que sea más difícil escribir un código más general que involucre RangeInclusive , pero parece una solución razonable al problema.

Independientemente de lo que suceda, estoy a favor de estabilizar el tipo en la biblioteca estándar, que existirá independientemente de las preocupaciones de sintaxis. Permite a las bibliotecas escribir código estable que permite cortar con rangos inclusivos, de modo que cuando la sintaxis se estabilice, la gente ya haya implementado el código que usa los tipos. La sintaxis y los tipos están bajo diferentes marcas de características por una razón.

@scottmcm Estoy de acuerdo en que probablemente debería ser un hilo separado en este punto.

En un intento de que la discusión sobre la sintaxis siga avanzando, voy a ofrecer la ruta que preferiría tomar.

Lo que más me gusta es la sintaxis ..= , así que creo que deberíamos agregar este azúcar sintáctico como igual a ... en la coincidencia de patrones y como un InclusiveRange fuera de la coincidencia de patrones. Luego, para mantener la coherencia del lenguaje, deberíamos intentar migrar a los usuarios y su código a la sintaxis ..= en patrones, utilizando anuncios y herramientas automatizadas. Una vez que sentimos que hemos migrado suficientes usuarios de ... , podemos hacer que su uso sea una advertencia del compilador y luego eventualmente (posiblemente incluso años a partir de ahora) un error del compilador.

Han pasado 24 días desde que se entregó mi propuesta y no se han dado comentarios. ¿Deberíamos seguir adelante con ese plan?

EDITAR: En el móvil no vi los pulgares hacia abajo, así que no me di cuenta de que había opiniones disidentes.

@Xaeroxe No lo creo. No estoy de acuerdo en que desaprobar ... a favor de ..= sea ​​una buena opción por las razones que ya he publicado en este hilo. No respondí a su propuesta específica porque ya se había presentado y discutido la misma idea. Lo único que está claro aquí es que no tenemos consenso. Creo que muchos de nosotros nos sentimos fatigados por la discusión.

EDITAR: Para ser más específico, no quiero desaprobar ... a favor de ..= porque:

  • La sintaxis obsoleta es un costo enorme en la rotación; incluso si me gustó unívocamente ..= , no creo que valga la pena el ciclo de depreciación solo para obtener expresiones de rango inclusivas en estable.
  • No me gusta ..= , creo que no es obvio y no está claro; tiene la ventaja de que es menos probable que provoque un error, pero eso no significa que un usuario, al verlo por primera vez, sepa lo que está viendo.
  • No estoy de acuerdo con la premisa de que debe haber una simetría entre patrones y expresiones aquí, porque no realizan ningún tipo de operaciones análogas de estructuración / desestructuración.

(Cambié un poco de opinión durante este comentario, decidí dejarlo todo para que otros pudieran ver mi proceso de pensamiento y por qué llegué a las conclusiones que hice)

Realmente no puedo comentar sobre el costo de la depreciación debido a mi falta de experiencia con tales cosas. Sin embargo, sigo apoyando ..= .

Creo que en cierto punto tenemos que estar dispuestos a pedirles a los usuarios que aprendan algo. La programación en su conjunto es algo que debe aprenderse, la sintaxis especializada en general siempre tiene algún costo para la semántica. No espero que la gente reconozca la sintaxis a primera vista, .. es tan malo en este sentido.

Sin embargo, tener una sobreabundancia de sintaxis especializada puede resultar en un lenguaje que parezca más parecido al cerebro de lo que queremos que sea Rust. Por lo tanto, debemos tener cuidado de que los casos que elegimos convertir en sintaxis especial sean lo suficientemente comunes como para que valgan la pena. Para ser honesto, ahora que escribí esto, no estoy del todo seguro de que este caso valga la pena. La necesidad de rangos inclusivos no es lo suficientemente alta como para justificar una sintaxis.

Sin embargo, la inconsistencia todavía me molesta. Tener una función inclusiva y ... en la coincidencia de patrones se siente como tener tanto gris como gris en el idioma inglés. Cuando tenemos la oportunidad de estandarizar eso, una parte de mí siente que deberíamos hacerlo. Sin embargo, también existen problemas logísticos reales para realizar ese cambio. Si alguna vez diseñáramos un Rust 2.0 (eso podría ser una locura, no tengo idea) tal vez deberíamos revisar esto, pero supongo que por ahora tener tanto gris como gris es suficiente.

Estoy a favor del uso de una función inclusive para instancias fuera de la coincidencia de patrones y ... en la coincidencia de patrones en este momento.

@sin barcos

  1. Si nunca desprecias nada, terminas con la unión de todas (más o menos) malas decisiones como C ++. Esto obliga a los principiantes a aprender aún más porque las cosas no son tan consistentes como podrían ser.
    Entonces, a veces tiene sentido desaprobar cosas para dar paso a una mejor solución.

  2. eso no significa que un usuario, al verlo por primera vez, sepa lo que está viendo.

Este es el caso de cualquier sintaxis. Nosotros (que conocemos a Rust) tenemos este sesgo porque para nosotros, el código de Rust parece obvio, pero cualquiera que llegue a Rust desde otro idioma tiene que buscar la sintaxis a menudo. No cambia si usamos ..= o ... o cualquier otra sintaxis para rangos inclusivos porque, por ejemplo, otros idiomas usan ... para rangos exclusivos, por lo que tienen que buscarlo de todos modos .
Nuestro objetivo no debería ser solo presentar características de apariencia obvia:
Si quisiéramos tener solo características que parezcan obvias, no podríamos tener la mayoría de las características existentes en Rust. Los novatos TIENEN que mirar el documento de todos modos, ¿qué tiene de malo eso? ¡El doctor es bueno!


  1. Si le interesa minimizar el tiempo que los novatos tienen que mirar el documento, ¡deberíamos esforzarnos por lograr la simetría entre la construcción y la coincidencia de rangos inclusivos! (y otras construcciones)

Como dijo @withoutboats , creo que muchos de nosotros estamos cansados ​​de esta discusión; Por mi parte, he estado sentado por un tiempo. Dicho esto, me tomé un tiempo para volver a leer (¡gracias por el resumen @Xaeroxe!) Y revisar mis pensamientos aquí.

En mi opinión, el problema más importante en este momento es la combinación incompleta de sintaxis que proporcionamos : ... en patrones, .. para expresiones. Este par de sintaxis lo lleva .. funcionaría en patrones y ... en expresiones, y no es así. Creo que este no es un diseño sostenible a largo plazo y realmente quiero arreglarlo.

También creo que, dado que hemos proporcionado sintaxis para ambos tipos de rangos, probablemente sea mejor continuar haciéndolo. Eso nos deja con un par de opciones:

  • Estabilice ... en expresiones y agregue .. a los patrones. Este es el cambio menos doloroso, pero tiene desventajas bien discutidas en torno a los errores uno por uno. Aún así, otros idiomas tienen esta combinación y, que yo sepa, no han sufrido terriblemente con tales errores.

  • Desaproveche ... en patrones y expresiones, agregue ..= a ambos y agregue .. a los patrones. Resuelve las desventajas anteriores, es más doloroso (debido a la desaprobación) y abre la puerta a otros tipos de rangos (como el exclusivo por la izquierda) en el futuro.

En este punto, estoy repitiendo en gran medida la discusión y, honestamente, no creo que haya mucho más que decir en este momento; Creo que hemos expuesto las compensaciones y solo necesitamos que el equipo de lang haga una evaluación y tome una decisión. Pero la idea central de mi comentario es el punto inicial, acerca de por qué creo que algo debe cambiar aquí (y por qué simplemente agregar inclusive no es suficiente, en mi opinión).

Aún así, otros idiomas tienen esta combinación y, que yo sepa, no han sufrido terriblemente con tales errores.

Me preocupa el sesgo de selección aquí. No tenemos una forma confiable de juzgar si los problemas son menores o si rara vez nos llaman la atención.

Además, usar ... parece ir en contra del aspecto de "evitar pistolas a menos que las compensaciones sean demasiado severas" de la filosofía de diseño de Rust y las mejores prácticas emergentes. (p. ej., el consejo de crear nuevos tipos enum lugar de usar bool por lo que es más difícil mezclar los parámetros de su función).

Por ejemplo, C ha demostrado que la asignación en declaraciones if es útil si un idioma no tiene while let , pero se ha reconocido que escribir = cuando se refería a == es suficiente para que lenguajes como Python lo rechacen, incluso cuando existen situaciones en las que las únicas alternativas son inusualmente feas.

Yendo en la otra dirección, hice que Clippy detectara un caso como este cuando estaba cansado de codificar hace una semana ...

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

... que parece un ejemplo perfecto del tipo de error de "presionar la tecla demasiadas veces" que nos preocupa aquí ... y, a diferencia de " == no tiene ningún efecto", hay no hay buena forma de pelusa por .. frente a ... .

@ssokolow Para ser claros, estoy bien con ..= también; No creo que la desaprobación sea tan dolorosa, y es una solución automática muy fácil. Sobre todo, solo quiero resolver este problema.

Probablemente pueda vivir con la estabilización de .. / ... (que ya está implementado por la noche). Estoy de acuerdo con @aturon en que el lenguaje tal como existe sugiere que esto funcionará.

Como dije, realmente me gustaría estabilizar el tipo libstd cuando pasa rust-lang / rfcs # 1980 sin requerir una discusión de sintaxis.

Además de lo que señaló @aturon , ¿quizás sería útil fusionar los problemas de seguimiento para esta sintaxis de rango exclusivo y para esta? Quizás cree un problema de seguimiento por separado para el tipo y utilícelo para estabilizar el tipo antes de la sintaxis.

Voy a volver a nominar para la discusión del equipo de lang. Creo que es muy poco probable que surjan ideas o compensaciones significativamente nuevas en este momento. Necesitamos tomar una decisión sobre las compensaciones que se han establecido.

El 18 de mayo de 2017 a las 9:55:30 a.m. PDT, Aaron Turon [email protected] escribió:

Voy a volver a nominar para la discusión del equipo de lang. Creo que es muy improbable
que van a surgir ideas o compensaciones significativamente nuevas en este
punto. Necesitamos tomar una decisión sobre las compensaciones que se han
Dispuesto.

Voy a estar fuera para la reunión de la próxima semana debido a una conferencia. En caso de que esto se discuta en la reunión de la próxima semana, expresaré mi apoyo para cualquier solución que no sea ... , ya sea ..= , inclusive u otra.

Valdría la pena discutir la sintaxis rest / spread mientras estamos en eso.
Voto .. por rango exclusivo, ... por inclusivo, .... por resto / 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

Votaría ... por una porción de descanso por dos razones:

  1. Es probable que la gente ya esté familiarizada con ... significa "descanso" de lenguajes como CoffeeScript (CoffeeScript usa rest... en firmas de funciones para varargs y los llama "splats") e inglés (usando el código Unicode correcto punto de código o no, son tres puntos que parecen puntos suspensivos, no cuatro, y la gente hace un buen trabajo al entender que los puntos suspensivos significan aproximadamente "y hay más, pero no lo decimos en voz alta" en inglés, simplemente por encontrarlo en uso.)

  2. A menos que me esté perdiendo algo sobre la sintaxis de Rust, usar .. y ..= para rangos pero ... para segmentos de descanso significaría que, en cada situación, escribir ... cuando quisiste decir .. o viceversa seguiría siendo un error en tiempo de compilación.

    Para esto, estoy operando con dos suposiciones:

    1. Que el uso de la sintaxis de descanso solo (fuera de un contexto de desempaquetado de secuencias) no se permitiría como una operación prohibida propensa a errores tipográficos. (es decir, for _ in ...rest sería lo mismo que for _ in rest si está permitido, pero es casi seguro que se trate de un error tipográfico.

    2. Que usar un rango abierto como patrón para ser asignado sería inválido. (es decir, let [first, ..rest] = no sería válido).

@ssokolow triple dot ya significa un rango en el patrón, por lo que sería un cambio importante cambiarlo a la sintaxis de reposo.

@phaux Point. Me había olvidado de eso por alguna razón.

Algo para colgar de la etiqueta "si alguna vez hacemos Rust 2.0", tal vez.

El punto triple ya significa un rango en el patrón, por lo que sería un cambio importante cambiarlo a la sintaxis de reposo.

Sin embargo, el ... en los patrones debe tener una expresión en ambos lados, creo ( a...b ), mientras que el resto de la sintaxis usa ... como prefijo, ¿no?

El equipo de lang discutió esta característica nuevamente en nuestra reunión de hoy y llegó aproximadamente a la siguiente matriz:

  • Soportar ... en patrones y .. en expresiones, y nada más, es un diseño insostenible; lleva a los usuarios a esperar que funcione una sintaxis que no funcionará.

  • Permitir ... y .. en ambos lugares ayudaría, pero el problema de uno por uno es una preocupación real; ninguno de nosotros está ansioso por recibir informes de personas que pasan horas rastreando un período errante.

  • Pasar a ..= y .. es menos atractivo estéticamente, pero evita los problemas prácticos muy reales anteriores. También podemos implementarlo de una manera muy suave: primero introduzca ..= como una sintaxis alternativa (en la que rustfmt puede reescribir), y solo después de que se haya vuelto idiomático, desapruebe ... .

En caso de que no pueda decirlo, el equipo siente que ..= y .. es nuestro mejor camino a seguir. Este tema también se ha discutido hasta el punto de que es muy poco probable que surjan nuevos argumentos, por lo que estamos listos para dar el paso: estamos buscando a alguien a quien le gustaría implementar la notación ..= para ambos patrones y expresiones, y posteriormente iremos a FCP!

Con ese fin, estamos buscando a alguien (o algunas personas) para impulsar la implementación. Probablemente esto se pueda hacer en varios RP más pequeños:

  • Para empezar, agreguemos ..= al analizador como un alias para ... y convierta las pruebas existentes.

    • ... debería seguir funcionando, por supuesto, y queremos que esto sea una desaprobación "silenciosa", por lo que no es necesario emitir advertencias, etc. (todavía).

    • por lo tanto, necesitaremos mantener las pruebas en ... patrones

    • Creo que probablemente la forma de hacer esto es modificar el lexer agregando el token DotDotEquals ( aquí está el DotDotDot ) y luego modificando el analizador para aceptar DotDotEquals todas partes ahora acepta DotDotDot ( ejemplo )

    • ripgrep DotDotDot es tu amigo aquí;)

  • ... en expresiones nunca fue estable, por lo que podemos cambiar eso a ..= y eliminar el soporte anterior

    • para ser amables con la gente en la naturaleza, podríamos pasar por un período de desaprobación, pero no estoy seguro de que sea necesario (¿pensamientos?)

Solo tenga en cuenta que, al implementar, la sintaxis extern fn foo(a: u32, ...) no debe cambiarse a ..= 😆

Estoy tentado a tomarlo ya que parece un buen primer paso en el código, pero no voy a tener mucho tiempo en las próximas 2 semanas, así que si alguien quiere retomarlo, ¡no dude en hacerlo!

Personalmente, estoy más a favor de ..^ que de ..= , ya que a operator= b ya es, para algunos operadores, un alias de a = a operator b . ^ por otro lado se usa mucho menos, solo para XOR, por lo que debería causar menos confusión.

.. produce un tipo diferente al tipo de los operandos izquierdo y derecho, por lo que no veo que eso sea un problema para ..= . El contexto también ayuda a identificar el propósito del operador, algo como += devuelve () para que pueda aparecer como su propia declaración, generalmente en su propia línea. Mientras que ..= devuelve InclusiveRange por lo que aparecerá como una expresión dentro de otras instrucciones. Además, como se mencionó anteriormente, ..^ parece que tiene más que ver con la potenciación que con un rango.

@Xaeroxe ^ no tiene nada que ver en Rust con exponenciación (aunque se usa como tal en otros idiomas), mientras que += , -= , *= all existen en Rust. De hecho, incluso ^= existe.

Pero idk, está bien tener ..= también.

Dado que # 42134 se fusionó, ¿podemos movernos para estabilizar la estructura de la biblioteca ahora? Me imagino que vamos a querer esperar a que la sintaxis se estabilice antes de estabilizar eso, aunque como dije antes, sería útil estabilizar la estructura antes.

@clarcharr Creo que hemos tomado la decisión de estabilizar esa estructura, así como la sintaxis ..= por lo que solo necesitamos algunos PR para hacer eso.

EDITAR: Woops, estaba equivocado. Lo estamos implementando en el compilador, para estabilizar la sintaxis será necesario esperar a que transcurra el período de comentario final. Creo que deberíamos estabilizar la estructura en este momento, pero esa tampoco es mi decisión.

Dejé de seguir el tema hace mucho tiempo, cuando me pareció que ... estaba haciendo consenso. ..= parece incómodo, ya que parece una afectación a primera vista.

Pero mucho más importante, no creo que este derrame de bicicletas sea lo suficientemente importante como para cambiar la sintaxis del patrón actual.

esta sintaxis apesta!
= tiene significado de asignación, incluso en + =, - =, * = modelo, pero .. = se trata de obtener algo. tan confuso y feo.
como el índice de la matriz comienza en 0, '...' es bueno y hermoso, la gente se acostumbrará.

@zengsai
..= se deriva conceptualmente de operadores como == y <= , que ya existen en Rust e indican comparación de igualdad, no asignación.

(es decir, 1..=5 es la abreviatura de "Rango sobre valores 1 <= x <= 5 " en contraposición a 1..5 significa "Rango sobre valores 1 <= x < 5 ")

EDITAR: Además, no se trata de "acostumbrarse", se trata de qué es más difícil de leer o escribir mal cuando estás cansado o distraído. Los errores de uno en uno como ese son famosos por el pistoletazo de salida.

De hecho, accidentalmente escribí ... cuando ya me refería a .. . Afortunadamente, siempre apunto a Rust estable, por lo que el compilador lo detectó. (Sin embargo, no puedo recordar si fue un espasmo muscular o una memoria muscular asumiendo que quería escribir una pseudoelipsis porque escribo mucho de no ficción).

@zengsai ... es demasiado sutil, se parece demasiado a ..

Será realmente anormal que un idioma tenga un número diferente de puntos que signifiquen cosas diferentes

Quitarse una pistola de pie es más importante que ser estéticamente atractivo.

Recién llegados: hice un TL; DR, porque este es un hilo muy largo. Puede leerlo aquí: https://github.com/rust-lang/rust/issues/28237#issuecomment -296310123

Hablando de "errores de uno en uno como esos son famosos por pistolas", tengo que decir: el problema del error tipográfico no debe usarse como la razón clave de este cambio.

mire esta comparación, ".." y "..." vs "=" y "==", ¿eso significa que deberíamos encontrar otra sintaxis para "==" para evitar el problema de error tipográfico del usuario? si "=" y "==" están bien, ¿por qué ".." y "..." no pueden?

Llevo más de dos años siguiendo a Rust-Lang. y se ha utilizado en muchos de mis proyectos privados. Me encanta, pero esta sintaxis realmente me hace sentir incómodo. no solo es estéticamente atractivo, sino que también afecta la fluidez en la escritura y lectura del código.

@zengsai tenía entendido que no se trata principalmente de cuando _escribir_ código, sino de revisar, leer y comprender el código. Si no lo está buscando, podría perder más fácilmente .. frente a ... siendo un error de uno por uno, mientras que ..= definitivamente se destaca más y ganó No tengo este problema.

No estoy seguro de que me guste la sintaxis ..= desde un punto de vista estético, pero puedo ver de dónde vienen todos alrededor de .. y ... leyendo de manera muy similar.

@zengsai Porque = vs. == tiene una solución que no está disponible para .. vs. ... .

Claro, puedes confundir = y == en C ... pero esa es una pistola reconocida y lenguajes más modernos como Python y Rust resolvieron eso:

  1. Es un error si escribe if x = y lugar de if x == y (esta es la solución que hicieron Rust y Python)
  2. Cuando escribí accidentalmente x == y; lugar de x = y; , recibí una advertencia sobre una expresión que no tiene ningún efecto.

No hay forma de que el compilador reconozca siquiera que una confusión de .. frente a ... es sospechosa , y mucho menos incorrecta.

@zengsai .. y ... evalúan tipos que implementan los mismos rasgos y se pueden usar esencialmente de manera intercambiable (esto es por diseño). El apagado por un error es un problema muy real.

Quiero dejar claro que también odio esta sintaxis, tanto que no estoy de acuerdo con el comentario de @aturon de que la situación actual en la que usamos .. y expresiones y ... en patrones es "insostenible"; de hecho, creo que es preferible tener la desconexión que tener esta sintaxis.

Pero está claro que nunca tendremos consenso sobre esto, que no hay nuevos argumentos en este hilo y que la mayoría de los usuarios que invirtieron activamente (así como el resto del equipo de idiomas) favorecieron este cambio. Así que me hago a un lado para que podamos resolver el problema.

Si en mi experiencia es un consuelo, la gran mayoría de los casos de uso nunca necesitan realmente esta función, por lo que no aparecerá en todo su código.

En realidad, todavía estoy muy descontento por desaprobar ... en los patrones, y básicamente voy a apretar los dientes para que este problema se pueda resolver. Todo el equipo de lang está de acuerdo en que tener expresiones .. y ... sería una verruga terrible, lo que llevaría a algunos usuarios a pasar horas depurando un problema de error tipográfico totalmente silencioso.

El resto del equipo de lang cree firmemente que tener una desconexión entre las expresiones y los patrones es inaceptable, y aunque no estoy de acuerdo, todos hemos argumentado y no creo que estar en un punto muerto para siempre sea saludable.

@ssokolow Lo siento, todavía no puedo estar de acuerdo contigo. El compilador puede advertirle de este tipo de error tipográfico, pero ¿qué sucede si escribe "x = 5" en el lugar donde debería estar "x = 6"?

El compilador no es el perfecto para evitar errores tipográficos, el programador sí lo es.

si este cambio no tiene efectos secundarios, estoy totalmente de acuerdo. pero esto hizo que el lenguaje perdiera estética, fluidez en la escritura y la lectura, lo cual no vale solo en mi opinión personal.

El óxido de hoy ya encuentra problemas de lectura y escritura, cuanto más poco común y contraintuitiva sea la sintaxis, más curva de aprendizaje, no lo convierta en otro Perl.

@withoutboats Discutimos con eso, porque nos encanta. Tal vez este argumento sea demasiado tarde y no pueda cambiar nada, solo ...

@zengsai

Ciertamente hay que hacer concesiones, pero tengo la impresión de que nunca nos pondremos de acuerdo sobre el mejor punto de equilibrio entre ellas.

Independientemente del gusto personal, veo ..= como un pequeño precio a pagar para evitar lo que puede ser una gran cantidad de tiempo perdido tratando de rastrear errores.

(Mi área de enfoque es el diseño de UI / UX y una de las reglas más importantes que te enseñan es que debes apuntar a hacer que la facilidad para cometer un error sea inversamente proporcional al daño y / o al tiempo de reparación que causará. )

En mi pequeña opinión, 5 frente a 6 es mucho más obvio de ver que .. frente a ... .

@zengsai Estoy recibiendo demasiados correos electrónicos solo para esta conversación, ¿qué pasamos al canal Rust de IRC para expresar mejor sus sentimientos?

@daiheitan Esta es una comunicación normal, si no le gusta, le sugiero que cancele su

Cuando vi por primera vez en Rust, me quedé muy sorprendido por la .. sintaxis. (1..10).sum() es ... la suma de números enteros del 1 al 9? Si presenta esta sintaxis a un recién llegado y le pregunta qué significa, es muy probable que espere que vaya de 1 a 10. Y estaría en lo correcto al hacerlo, ya que esperaría que la sintaxis simétrica exprese simétrica rangos. ¿Por qué debería incluirse el 1 pero no el 10?

Agregar otra forma asimétrica ..= para un rango simétrico hace que esto sea aún más inconsistente visualmente. Uno podría preguntarse por qué el lado izquierdo no necesita = para ser inclusivo, por lo que sería =..= para rangos inclusivos en ambos lados.

Algo como la sintaxis Swift ( ..< para exclusivo y ... para inclusivo) evitaría estos problemas y mejoraría la legibilidad. Puede adivinar fácilmente el significado correctamente incluso si es completamente nuevo en el idioma, por lo que hay una cosa menos que recordar. Hubiera esperado que se eligiera algo como esto, especialmente considerando el impulso de Rust hacia la amistad con los recién llegados.

@rkarp Hasta cierto punto, probablemente se deba a un sesgo preexistente.

Por ejemplo, hay mucha influencia de Python en Rust y Python usa el mismo tipo de rangos medio abiertos. (es decir, range(1, 5) o myList[1:5] Python tienen el mismo comportamiento que 1..5 Rust)

La justificación para eso en Python estaba ligada a que solo había una sintaxis y tener una sintaxis semiabierta facilitaba hacer cosas como head, tail = myList[:pivot], mylist[pivot:] .

Dicho esto, dado que Rust ha pasado 1.0, existen reglas bastante estrictas sobre no romper el código existente. .. para el exterior exclusivo de los patrones y ... para los patrones interiores exclusivos deben seguir siendo válidos.

..= funciona porque puede aceptar .. (exclusivo) y ..= (incluido) en todas partes y tratar ... como un sinónimo obsoleto de .. en patrones.

Solo digo que tener ..= como token es técnicamente un cambio incompatible, ya que afecta las reglas de :tt en las macros. Probablemente no sería problemático, pero es posible que desee verificar para asegurarse de que alguien no lo haga, considerando que también puede ser un cambio silencioso. (la alternativa es permitir .. /* why not */ = , que no creo que sea una buena idea)

@ssokolow Técnicamente, es un error de tipo en Rust, no un error de análisis. a = 2 es una expresión que devuelve () , y if espera bool , por lo que son claramente incompatibles.

Las reglas están cambiando lentamente. Técnicamente, ..= son 3 tokens donde los 2 primeros no tienen espacio después de ellos.

@eddyb : Lo admito, no lo entiendo del todo. ¿Hay alguna manera de introducir un nuevo token sin afectar cómo: tt lo analiza?

Este código informa actualmente "Regla 2" y "Regla 4". Este cambio, si lo entiendo correctamente, lo cambiaría a "Regla 2" y "Regla 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!(..=);
}

No, es un cambio en cómo se definen los tokens. @jseyfried puede explicar mejor las consecuencias.

Técnicamente, es un error de tipo en Rust, no un error de análisis. a = 2 es una expresión que devuelve (), y si espera bool, entonces son claramente incompatibles.

@xfix Gracias. No estaba prestando la debida atención la última vez que cometí ese error tipográfico y todavía no estoy completamente acostumbrado a pensar en términos de lenguajes orientados a expresiones.

He ajustado mi comentario.

No me gusta la sintaxis ..= y estoy en contra de desaprobar ... en los patrones. Si tenemos miedo al error tipográfico, siempre podemos usar la estructura RangeInclusive { start, end } lugar de ... o ..= como abreviatura.

Ambigüedad potencial me acabo de dar cuenta:

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

@clarcharr Sin embargo, parece que no se 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
Después de introducir ..= como un operador, el error sería:

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

error: aborting due to previous error

Como ahora con let x=10; if let 5..x {}

Por lo tanto, esta "ambigüedad" no se compilaría y, por lo tanto, no sería más ambigüedad que if let 5..x {} .

@Boscop El punto es que, actualmente , si tratamos 5.. como un patrón como Some(5) , entonces if let 5.. = x sería similar a let Some(5) = x , y este último se compilará. Mi comentario muestra que 5.. no es un patrón, por lo que no hay peligro de compatibilidad de if let por introducir ..= .

Si introducimos esta función y permitimos ..= y .. en patrones, if let 5..=x siempre debería ser if let 5.. = x y debería compilar: if let (single expression) no tiene sentido, así que no creo que haya ninguna ambigüedad.

@kennytm, así que ambos mostramos 2 ambigüedades diferentes que no compilarán. (No estaba claro a cuál se refería. Era un poco ambiguo, je).

@daboross Como dijo kennytm, 5.. no es un patrón y no se compila, incluso ahora. Y esto no cambiará si agregamos ..= como operador. No hay ambigüedad. Lo que es importante es que ahora, ..= no se puede analizar como un operador, pero una vez que podemos analizarlo como un solo operador, no hay ambigüedad.

5.. no es un patrón válido actualmente, ni tenemos patrones de intervalo medio cerrados. Dicho esto, la falta de patrones de intervalo medio cerrados es algo que a menudo se considera una fuente de inconsistencia en comparación con las expresiones de rango y podría terminar implementándose también para los patrones. También podríamos querer agregar la capacidad de omitir un lado del intervalo en patrones más adelante para, por ejemplo, coincidencias enteras exhaustivas.

Entonces, si bien la observación de @ clarcharr no necesariamente señala ambigüedad cuando se considera la gramática actual, ciertamente es una ambigüedad al considerar posibles expansiones futuras que podrían entrar en conflicto con la propuesta de usar ..= para patrones.

Con eso en mente, sugeriría usar algún otro símbolo aquí. ^ parece bastante bien, ya que solo se usa en un contexto de expresión actualmente IIRC.

(Esta es otra razón por la que creo que es una buena idea moverse para estabilizar la estructura ahora y la sintaxis más adelante).

@nagisa no hay conflicto con respecto a if let si el token ..= se agrega antes de que se admita el patrón RangeFrom. Se podría agregar un espacio entre .. y = para eliminar la ambigüedad, al igual que x <- y (ubicación en) vs x < -y (menos de + negativo).

(Dado que ^ es el operador exclusivo -o me parece irónico usar ..^ para el rango

En los miles de rangos que he escrito, bastantes de ellos completamente cerrados, tal vez incluso uno o dos medio abiertos al revés, todavía no veo la necesidad de ninguna sintaxis adicional. 1..(n+1) no es tan difícil de escribir.

Eso no funciona para end = T :: max_value ().

El 29 de mayo de 2017 a las 16:33, "Diggory Hardy" [email protected] escribió:

En los miles de rangos que he escrito, algunos de ellos completamente cerrados,
tal vez incluso uno o dos medio abiertos al revés, todavía no
vea la necesidad de cualquier sintaxis adicional. 1 .. (n + 1) no es tan difícil de escribir.

-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-304662258 ,
o silenciar el hilo
https://github.com/notifications/unsubscribe-auth/AApc0ipynL_qrZqUBldOJOX046RNY2H_ks5r-skwgaJpZM4F4LbW
.

Preferiría un método en rangos medio cerrados a .. = aunque.

El 29 de mayo de 2017 a las 16:35, "Simonas Kazlauskas" [email protected] escribió:

Eso no funciona para end = T :: max_value ().

El 29 de mayo de 2017 a las 16:33, "Diggory Hardy" [email protected] escribió:

En los miles de rangos que he escrito, bastantes de ellos completamente
cerrado, tal vez incluso uno o dos medio abiertos al revés, todavía no
Realmente veo la necesidad de una sintaxis adicional. 1 .. (n + 1) no es tan difícil de
escribir.

-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-304662258 ,
o silenciar el hilo
https://github.com/notifications/unsubscribe-auth/AApc0ipynL_qrZqUBldOJOX046RNY2H_ks5r-skwgaJpZM4F4LbW
.

Realmente desearía que ya estabilizáramos los rasgos y tipos con un método para construirlos porque estoy bastante seguro de que no hay desacuerdo al respecto. Por favor, no permita que la eliminación de bicicletas sobre la sintaxis impida la estabilización de la funcionalidad principal en sí.

Eso no funciona para end = T :: max_value ().

¿Realmente desea iterar sobre 2 ^ 64 valores, o incluso 2 ^ 8 valores? Si solo desea iterar sobre los últimos valores de, por ejemplo, un u32 , a menudo es más fácil agregar uno dentro del ciclo. Y si realmente desea iterar hasta 2^B-1 por alguna extraña razón, siempre puede pegar if i == END { break; } al final de un ciclo.

El hecho de que nuestros enteros sin signo estándar admitan valores 2 ^ 32 o 2 ^ 64 no significa que el valor representable más alto se use con mucha frecuencia. Y si está haciendo algo con u8 , no olvide que probablemente sea más fácil para la CPU usar u32 para un contador de todos modos.

Pero incluso si no veo la necesidad de una sintaxis de generador de rango cerrado, no puedo refutar los argumentos del equipo para el cambio . Oh bien :/

¿Qué tal estos cuatro para abarcar todas las opciones de inclusión?

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

Me imagino que uno debería ser capaz de entender lo que implican sin más explicaciones, dado que los operadores de desigualdad han sido martillados en la mente de todos desde el jardín de infantes en adelante ... aunque no sé si serían un dolor de otras maneras.

Alternativamente, podríamos cambiar las desigualdades:

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

... solo para que el último no se vea como un Cartman enojado.

@vegai y ¿qué pasa con la sintaxis a..b que ciertamente no se eliminará? No, no creo que sugerir nuevas opciones de sintaxis vaya a resolver nada.

Mmm, entonces han surgido dos "posibles ambigüedades":

  • if let 5..= x - como se señaló, esto no es realmente una ambigüedad ahora , pero podría serlo. Por otro lado, este tipo de ambigüedad surge con frecuencia y es abordado por el tokenizador. Es decir, si consideramos ..= como un token en nuestro analizador, no es ambiguo incluso si agregamos 5.. patrones en el futuro; simplemente necesita escribir un espacio entre .. y = (por ejemplo, let 5.. = x ).
  • la ambigüedad con respecto a las macro-reglas. De hecho, esto es doloroso y desafortunado, y es una de las razones por las que nos hemos movido hacia un sistema diferente para "macros 2.0", donde evitamos exponer el conjunto de "tokens compuestos" al usuario final.

    • al final, podemos manejar macro_rules! retrocompatibilidad a través de algún código de caso especial si es necesario; en cualquier caso, creo que no hay forma de evitar este tipo de problema excepto usando ... .

Antes de estabilizar los rangos inclusivos, el problema # 42401 también debe solucionarse en mi opinión, ya que después de la estabilización, la solución sería un cambio rotundo.

@ est31 buen punto, lo agregué a la lista de verificación al

El corte de str comprobado es en sí mismo inestable y solucionar ese problema no bloquea los rangos inclusivos en absoluto.

Oh, @nagisa tiene razón, no tiene nada que ver con la sintaxis de rango. ¿Puedes quitarlo de la cabeza de nuevo? Mi error. El error está más bien en la implementación de get y, por lo tanto, está protegido por la función 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
            }
        }
    [...]

remoto

Otra actualización de la casilla de verificación: PR https://github.com/rust-lang/rust/pull/42134 aplicó el ajuste https://github.com/rust-lang/rfcs/pull/1980

Bump: ¿alguna forma de que podamos estabilizar al menos las estructuras para 1.20?

¿Qué tal si tomamos prestado el famoso operador de

@nikomatsakis y @ rust-lang / libs (no sé cómo etiquetar esto), ¿cómo te sentirías si enviara un PR que moviera las estructuras a un problema de seguimiento diferente, para que podamos hablar sobre la estabilización para ellos? ¿allí? Creo que esta sería una buena manera de avanzar para estabilizarlos antes mientras esperamos que se implemente / establezca la nueva sintaxis.

cc @ rust-lang / libs (solo las personas de un equipo pueden etiquetar el suyo o de otros equipos)

¡Gracias, @eddyb!

@clarcharr Basado en https://github.com/rust-lang/rust/pull/42275#discussion_r119211211 , sospecho que se agradecería.

¿Es demasiado tarde para el tren de la propuesta de sintaxis?
La corriente parece cuando alguien intenta asignar el valor al segmento.

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]

Esta sintaxis haría imposible agregar implementaciones Add para rangos en el futuro. Sin embargo, realmente no sé si eso es un problema, ya que no estoy realmente seguro de qué haría una implementación Add .

Acepte el plus final. Cambiado a prefijo.

Debido a que a.. , ..b y .. son construcciones válidas en Rust, esto aún produce ambigüedades con las operaciones matemáticas: /

a... / a..= / a..+ no sería válido, ¿verdad? Dado que tener un rango ilimitado que incluya un punto final, realmente no tiene sentido.

No estaría demasiado preocupado por Add , no parece que sea demasiado común hacer algo con rangos, y si quisieras, podrías hacer (x..+y) + z ?

Editar: no importa, acabo de darme cuenta de lo que querías decir. Sería a..+b que sería ambiguo, ¿verdad? Ya que ahora significa a.. + b .

@daboross No digo que sea una buena o una mala idea, pero esta implementación (o alguna variación de ella) podría ser algo que queramos para los rangos en el futuro:

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

Esta implicación específica puede o no ser una buena idea, pero no me tomó mucho tiempo encontrarla como un posible caso de uso futuro. Creo que sería una mala idea excluir la posibilidad de que esto o algo así se agregue debido a decisiones de sintaxis existentes.

Mi otra preocupación es que el objetivo de descartar ... es minimizar la posibilidad de errores tipográficos difíciles de reconocer y permitir que los parens marquen la diferencia entre dos significados diferentes del abstracto a..+b siente así estaría retrocediendo en esa dirección.

Además, todavía tengo que ver una justificación sólida para a-..b y a-..+b más allá de "¿no sería bueno en aras de la integridad" mientras que el actual .. y el propuesto ..= ambos tienen fundamentos válidos conocidos.

No puede usar + para esto porque hace que la sintaxis de la expresión sea ambigua.

EDITAR: aunque, supongo, haría posible la implementación de rangos inclusivos por completo en la biblioteca, porque terminaría teniendo una implementación de <Range as Add<{integral}>>::Output = InclusiveRange .

Puedo sugerir la variante ..! . Tiene una rima productiva con .. y pone un énfasis adicional en el último punto haciéndolo más notorio.

Por supuesto, colisionaría con el operador ! pero, hablando honestamente, no podría imaginar la situación en la que se necesitaría poner ! en subexpresión limitada.

..! tiene un problema de intuición. Un recién llegado que aún no esté familiarizado con la sintaxis podría fácilmente malinterpretar ..! como "hasta, pero no ..."

También choca con la sintaxis de "rango hasta el complemento bit a bit de ..." (lo que lo colocaría en una situación similar a usar + )

Estar de acuerdo. Pero, por otro lado, ..= puede malinterpretarse como uno de los operadores de asignación.

¿Qué le estaría asignando si este fuera un operador de asignación?

Basado en la propuesta 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

Dudo que necesitemos otras combinaciones. En cualquier caso, se puede agregar posteriormente:

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

Aunque la última opción parece un poco extraña. ^_^

Deje de proponer cualquier sintaxis que contenga un operador unario, es decir, a..-b , a..!b , a..*b , a..&b o a?..b , estos nunca serán aceptado.

..! tiene un problema con la intuición. Un principiante que aún no esté familiarizado con la sintaxis podría malinterpretar fácilmente ...! para significar "hasta, pero no ..."

..= tiene el mismo problema con la intuición. Cualquiera que vea un = espera una afectación o una comparación. Reconozco que esta sintaxis resuelve completamente el problema de la distinción, ya que cada vez que veo ..= , no puedo evitar preguntarme qué hace este signo igual aquí.

La única sintaxis propuesta que es bastante intuitiva y coherente con la sintaxis actual es ... . Pero parece que el barco ha zarpado.

De todos modos, los recién llegados tendrán que consultar los documentos con frecuencia. Incluso con ... mirarían los documentos. Esto no se puede evitar. Pero ..= tiene un mnemónico agradable ( up to y equal to ) por lo que no tendrán que mirar los documentos de este operador con frecuencia.

¿Qué pasa si el operador ... permanece como está, pero en su lugar cambiamos el operador .. a ..⎵ , es decir, dos puntos y un espacio (tuve que poner ese '⎵ 'allí porque un espacio normal no se mostraría en esta página web). Sería el único lugar del idioma donde los espacios en blanco son importantes. También sería un cambio importante, porque todo código como a..b se quejaría de que no existe un operador como .. , y un consejo para agregar al menos un espacio después de los puntos. Creo que el espacio los hace visualmente lo suficientemente distintos:

a.. b
a...b

@tommit No creo que sea una buena idea para ser honesto.

Actualmente, el operador es bastante flexible con respecto a los espacios en blanco, por ejemplo: a..b y a .. b son lo mismo. Esto probablemente sea para que sea coherente con otros operadores, como a+b y a + b . Estos, por supuesto, hacen lo mismo y permiten que las personas usen diferentes estilos de sintaxis. ¡Eso es bueno si me preguntas!

Para agregar a eso, la notación ..= es consistente con las notaciones <= y >= (que también se consideran _inclusivas_).

Siempre es bueno comprobar qué otras posibilidades existen, pero probablemente esta no sea la solución correcta.

Estar de acuerdo. En comparación con <= y >= , ..= parece plausible, incluso lógico.

Por cierto, si eres fanático de ... o simplemente no te gusta cómo se ve ..= , entonces la solución de compromiso sería usar alguna fuente con ligaduras de programación, como FiraCode con ligadura especial por ..= , que puede asignarse a ... , o incluso a algo extraño, como ⩷, ⩦ o ≔.

Rompiendo el cambio a todo el código de oxidación existente usando rangos ... muerto a la llegada,
lo siento. Si alguien tiene una propuesta retrocompatible realmente seria para
abordar las preocupaciones que se han planteado, y no se ha discutido
ya, escuchémoslo, pero al menos mantengamos eso como estándar, ¿no?
Este hilo está lleno de cobertizos para bicicletas y el equipo ya tomó una decisión así que
eso es un listón alto para superar.

En cualquier caso, todavía parece haber muchas discusiones sobre la sintaxis real. Presenté el número 43086 para estabilizar al menos las estructuras, los rasgos y las implicaciones para que se pueda usar la funcionalidad principal (parece haber demanda, consulte el comentario de @ retep998 más arriba).

El elefante en la habitación es que .. es en realidad el verdadero problema aquí debido a su apariencia simétrica pero su significado asimétrico. Lo "correcto" probablemente implicaría desaprobarlo, pero no hay voluntad de hacerlo porque ya hay mucho código que lo usa.

Despreciar el ... perfectamente consistente (aspecto simétrico, significado simétrico) es la salida fácil, pero a costa de agregar otro operador inconsistente en ..= . Parece como agregar un mal diseño para solucionar un mal diseño anterior.

Hay otro problema con esto debido a esta doble inconsistencia: no hay una buena manera de agregar las dos últimas variantes de inclusividad restantes (exclusivas en ambos lados y exclusivas solo en el lado izquierdo). Dado que tanto .. como ..= ya tendrían un = implícito en el lado izquierdo, tendríamos que negarlo de alguna manera, posiblemente con un < . Entonces tendrían que verse así:

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

Buena suerte adivinando correctamente lo que significan estos como recién llegado. Por lo tanto, probablemente (con razón) nunca se consideraría que se agregaron.

Si .. no estaba tan arraigado o ni siquiera existía, crear un diseño coherente para todo esto desde cero no parece tan difícil, por ejemplo:

  • .. (o ... ) por [a; b]
  • ..< por [a; b)
  • <.. por (a; b]
  • <..< por (a; b)

Tengo la sensación de que las dos últimas variantes podrían ser útiles en algún momento, ¿deberíamos realmente bloquear el camino hacia ellas tan rápido? En cualquier caso, la única buena razón para elegir ..= en lugar de desaprobar .. es romper un código mucho menos antiguo, pero en el mejor de los casos sería un mal necesario, nada que celebrar.

_Editar: Se agregó un ejemplo y algunos comentarios para mayor claridad.

Estoy de acuerdo con @rkarp en que .. es el problema real aquí, no ... o ..= . El significado asimétrica es especialmente mal teniendo en cuenta que otros idiomas (más populares) realmente hacen asignar un significado simétrica a la misma. Tanto Kotlin, Ruby y Haskell consideran que 5 está en el rango de 3-5, por ejemplo. Los artículos matemáticos también parecen favorecer eso. Lo peor aquí es que los principiantes no tienen ninguna posibilidad de adivinar el comportamiento de 3..5 en Rust: usted decidiría que 4 y solo 4 es un miembro del rango 3..5 (iteración sobre los puntos) o que ambos 3 y 5 también están en él (iterando sobre 'todo lo que podemos ver' y la extrapolación de los puntos).

Sin embargo, no estoy de acuerdo con la dificultad de cambiar esto. Creo que la sugerencia de @adelarsq podría implementarse con relativa facilidad. Para referencia:

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

Cualquier aparición de x..y (sin corchetes) podría traducirse a [x..y[ y emitir una advertencia del compilador. Después de algunas versiones, el compilador podría simplemente negarse a compilar notaciones de rango "desnudas" y tal vez incluso ofrecer herramientas para convertir automáticamente a la nueva notación.

https://github.com/rust-lang/rust/issues/28237#issuecomment -274216603 esa no es una idea nueva y no podemos usarla por las razones que ya hemos mencionado.

Estoy absolutamente de acuerdo con la idea de que, si estuviéramos diseñando el lenguaje desde cero con el beneficio de la retrospectiva, querríamos considerar las sintaxis de los rangos exclusivos e inclusivos juntos. Creo que ..= no es el operador ideal para un rango inclusivo; es simplemente la mejor opción actualmente sobre la mesa. Pero desaprobar el operador de rango exclusivo actual sería excesivamente doloroso y desagradable para los usuarios y proyectos existentes de Rust.

Hay muchas otras propuestas que podrían funcionar. Por ejemplo, no he visto ..@ propuesto, y x..@y parece evocador. El desafío es encontrar algo más convincente que la propuesta actual, manteniendo la falta de ambigüedad.

Quería resaltar el comentario de @ssokolow de hace 2 meses, como mi vista favorita de la simetría:

  • ..4 contiene cosas < 4
  • ..=4 contiene cosas <= 4

Creo que solo necesitamos un rango inclusivo, eso es más simple.
Siempre puede agregar + 1 o -1 para cambiar el rango.
Y .. es mejor, porque .. es más simple que ...!

@ AlexanderChen1989 Como se ha dicho antes en varias publicaciones de este hilo, eso no es posible porque cambiar el significado de .. rompería el código existente.

Además, en realidad no es tan simple. En particular, +1 y -1 pueden causar desbordamiento / subdesbordamiento de enteros).

Aquí hay un ejemplo que funciona en nightly (a través del candidato anterior para la sintaxis de rango inclusivo) donde ...

  • ... cualquier bucle que coloque primero entrará en pánico en el desbordamiento / subdesbordamiento en las compilaciones de depuración
  • ... se comportarán de manera completamente opuesta a lo previsto en las versiones de lanzamiento (es decir, el "0 a 0" se repetirá 256 veces y el "0 a 255" no se repetirá en absoluto)
#![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);
    }
}

Se han realizado 8 propuestas de sintaxis muertas al llegar desde que el equipo de idiomas tomó su decisión. Los recién llegados por favor lean el hilo. Teníamos muy buenas razones para tomar las decisiones que tomamos, lo prometo.

En mi humilde opinión, el OP debe actualizarse para señalar que no se debe tener más discusión de sintaxis en este hilo, y cualquier propuesta de sintaxis de rango exclusivo (es decir, (a, b) y (a, b] rangos) debe moverse a otro hilo.

Esto solo debería hablar de las cosas que se deben hacer para estabilizar el plan actual.

@clarcharr Tomé una decisión mayoritariamente unilateral y la agregué al OP, buena idea. Si el ruido continúa, votaría por cerrar el hilo.

Hola, soy nuevo y me gustaría empezar a trabajar en este. Intentaré escribir el PR para agregar ..= como sinónimo de ... en patrones, desaprobar ... en expresiones y mostrar un error que dice que la sintaxis se ha cambiado a ..= . ¿Suena esto correcto?

@ Badel2 genial. De hecho, comencé; pronto enviaré mi rama y la vincularé aquí.

@durka solo para aclarar: ¿se ofrece a permitir que @ Badel2 proceda a partir de su sucursal? ¿Podrías guiarlos como parte del trabajo del período implícito? Están en el canal de Gitter.

También estoy de acuerdo en que el problema real es .. . Entonces, la solución más favorable es desaprobar (no reemplazar de una vez, por lo que __no__ rompería el código existente) el .. a favor de algo como ..< (no habrá confusión entre a..<b y (a..)<b , ya que .. eventualmente dejarán de existir).

@ hyst329 Por favor lea las publicaciones ya hechas.

La primera publicación dice, en negrita, "No se debe tener más discusión sobre la sintaxis en este hilo".

Aparte de eso, lo que usted describe ya ha sido propuesto aquí varias veces por otros que no leyeron la discusión existente y hay múltiples razones dadas en respuesta de por qué no es una opción viable.

Lo siento, esto no es muy constructivo, pero cada vez que veo ..= y trato de recordar qué es, parece un operador de asignación similar a += o <<= . Se siente muy confuso que no lo sea. (Aunque es cierto que esto ha estado fuera de contexto, por ejemplo, "soporte inicial para la sintaxis de ..= " https://this-week-in-rust.org/blog/2017/10/03/this-week- en-óxido-202 /)

@SimonSapin He expresado esa misma crítica de una manera más constructiva arriba, sugiriendo ..^ lugar: https://github.com/rust-lang/rust/issues/28237#issuecomment -304325663

Para mí, un gran punto que habla a favor de ..= es una especie de coherencia con swift (que tiene ..< para rangos exclusivos y .. para rangos inclusivos). Esto me hizo aceptar la elección de ..= .

@SimonSapin No creo que haya nadie que esté completamente feliz con eso. El problema es que, lamentablemente, cientos de comentarios han confirmado que no existe una alternativa mejor.

Este parche logró convencerme de que no hacer nada es mejor que estropear la sintaxis del patrón actual solo para cubrir casos extremos.

.. tiene muy pocos casos de uso en los patrones y siempre puedes lidiar sin él.

... puede ser reemplazado por RangeInclusive o (Bound<T>, Bound<T>) en expresiones que realmente los requieran. Es más detallado pero fácil de entender.

@UtherII

... y estaba convencido de que ... es insostenible por las veces que fui salvado de un error sutil por el mensaje del compilador "No se puede usar la sintaxis de rango inclusivo en estable".

Es demasiado fácil presionar accidentalmente . una vez demasiadas (o, dadas las mecánicas involucradas, una vez muy pocas) cuando presionas varias veces en rápida sucesión.

He marcado "Cambiar para aceptar ..= como sinónimo de ... en patrones y aceptar ..= en expresiones" porque ya es el caso después de # 44709 con el dotdoteq_in_patterns y inclusive_range_syntax características respectivamente. Lo que queda es solo documentación y estabilización.

Solicitud de estabilización

Me gustaría estabilizar el rango inclusivo en 1,26 (beta el 30 de marzo, estable el 11 de mayo) o antes. Se ha enviado un RP de estabilización como # 47813.

Resumen

Se estabilizarán las siguientes 3 características:

  • inclusive_range_syntax - La sintaxis a..=b y ..=b en una expresión:

    for i in 1..=10 {
        println!("{:?}", &a[..=i]);
    }
    
  • dotdoteq_in_patterns - La sintaxis a..=b en un patrón:

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

    (Nota: la sintaxis a...b todavía se acepta sin advertencias)

  • inclusive_range - Los tipos std::ops::{RangeInclusive, RangeInclusiveTo} y sus campos:

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

Documentación

@Alercah envía varios RP de documentación, ¡gracias!

Pruebas

Puede encontrar casos de prueba en:

Preguntas sin resolver

  • El uso de a..=b en un bucle for tiene un rendimiento mucho más bajo que a..(b+1) debido a que su next() es más complejo y menos compatible con el optimizador. Esto se está rastreando actualmente en # 45222. Esto está actualmente mitigado por # 48012 cuando se usan métodos de iterador en lugar de un bucle for.

    Es posible que necesitemos mantener los campos de RangeInclusive inestables si no queremos comprometernos con el diseño en rust-lang / rfcs # 1980 todavía.

Es posible que necesitemos mantener inestables los campos de RangeInclusive si no queremos comprometernos con el diseño en rust-lang / rfcs # 1980 todavía.

+1
¿Es necesario exponer los campos de rango directamente, en lugar de a través de alguna interfaz basada en métodos?

@rfcbot fcp fusionar

De acuerdo con el resumen de @kennytm , propongo que estabilicemos la sintaxis del rango inclusivo ( ..= ).

(Dicho esto, encuentro el rendimiento más bajo de ..= ligeramente preocupante, y me pregunto si tiene sentido hacer que ..= no se implemente directamente Iterator por el momento, en para mitigar esto.)

El miembro del equipo @nikomatsakis ha propuesto fusionar esto. El siguiente paso es la revisión por parte del resto de equipos etiquetados:

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

No hay preocupaciones actualmente enumeradas.

Una vez que la mayoría de los revisores aprueben (y ninguno objete), entrará en su período de comentarios final. Si detecta un problema importante que no se ha planteado en ningún momento de este proceso, ¡hable!

Consulte este documento para obtener información sobre los comandos que pueden darme los miembros del equipo etiquetados.

Me pregunto si tiene sentido hacer .. = Iterator no implementado directamente por el momento, para mitigar esto.

Estos rasgos estables se implementan por RangeInclusive<T> durante al menos algunos T s en Nightly actual: Iterator , FusedIterator , ExactSizeIterator , Debug , Clone , Eq , PartialEq , Hash , TrustedLen .

@SimonSapin Lo olvido, ¿ya estabilizamos la estructura? (En otras palabras, ¿es eso observable?) Estaba asumiendo que no lo era.

Dicho esto, también realmente, realmente creo que 1..2 y 1..=2 deberían poder usarse en los mismos lugares, lo que argumenta en contra de realizar cambios aquí, y en cambio sugiere que deberíamos buscar mitigaciones y mejoras optimizaciones.

¿Por qué no rangos de casos especiales donde end == MAX ? Eso podría llevar a que la mayoría de los rangos inclusivos tengan el mismo código que los exclusivos, con la excepción de que los que van directamente al límite tienen más código. Debido a que la rama end != Max nunca modificaría end , el optimizador podría insertarla fácilmente.

@nikomatsakis No, las estructuras son inestables en este momento. Pero la propuesta de @ kennytm incluye estabilizarlos.

@SimonSapin

No, las estructuras son inestables en este momento. Pero la propuesta de @ kennytm incluye estabilizarlos.

Veo; de hecho, esta es la razón por la que mencioné que tendríamos que eliminar la implícita Iterator ahora o nunca. =)

@SimonSapin No creo que podamos estabilizar la sintaxis de la expresión a..=b sin estabilizar la estructura. Sin embargo, podríamos dejar los campos inestables, si pensamos que podemos cambiarlo.

Bien, no quise decir que no deberíamos estabilizar los tipos al estabilizar la sintaxis para construir valores de estos tipos.

¡Huzzah por escapar de la sintaxis de rango bikeshed y estabilizar! : tada:

Dada una máquina del tiempo, yo diría que ninguno de los tipos de rango es :Iterator , y que solo son :IntoIterator . Pero tal como está ahora, creo que la coherencia con Range es la mejor opción. Podemos poner este caso con Chain en el grupo "bueno, resulta que la iteración interna es más rápida a veces".

Otra cosa que no se resolvió, también relacionada con la iteración: ¿queremos comprometernos con alguna representación particular de RangeInclusive una vez que terminemos de iterar? En este momento termina en 1..=0 , pero se discutieron otras opciones . No sé si la documentación sería suficiente para evitar que la gente confíe en ella, aunque la actual hace que el rango posterior a la iteración sea bastante inútil, lo que al menos lo desalienta.

Podemos poner este caso con Chain en el grupo "bueno, resulta que la iteración interna es más rápida a veces".

Creo que realmente necesitamos arreglarlo para que no tenga menos rendimiento que una gama exclusiva; no hay una razón

no hay ninguna razón _fundamental_ para que sea así.

Depende de las invariantes que podamos hacer cumplir. En las dos formulaciones anteriores con un poco de estado adicional, no había nada que obligara a que ese bit se estableciera realmente cuando terminamos de iterar (y, de hecho, no se estableció en literales como 100..=0 ), por lo que el ciclo La condición de salida debe ser compuesta, lo que significa que LLVM ya no está dispuesta a desenrollarla por nosotros, por lo que obtenemos un peor rendimiento. Arreglar completamente eso parece significar hacer la estructura más grande y no tener campos de publicación, hacer RangeInclusive: !Iterator , o hacer que LLVM sea mejor para optimizar este tipo de bucles.

Dicho esto, probé algunas formas diferentes de escribir RangeInclusive::next , y parece que la elección de mi yo anterior de coincidir en un Option<Ordering> está haciendo que LLVM sea muy triste; solo poner operadores de comparación allí es dar mucho mejor montaje. Edite PR arriba: https://github.com/rust-lang/rust/pull/48057

Dada una máquina del tiempo, yo diría que ninguno de los tipos de rango es: Iterator, y que simplemente son: IntoIterator. Pero tal como está ahora, creo que la coherencia con Range es la mejor opción. Podemos poner este caso con Chain en el grupo "bueno, resulta que la iteración interna es más rápida a veces".

Básicamente estoy de acuerdo con esto.

: bell: Esto ahora está entrando en su período de comentarios final , según la revisión anterior . :campana:

: bell: Esto ahora está entrando en su período de comentarios final , según la revisión anterior . :campana:

@rfcbot fcp cancelar

@withoutboats y @KodrAus no han marcado sus casillas.

Propuesta de @cramertj cancelada.

El miembro del equipo @cramertj ha propuesto fusionar esto. El siguiente paso es la revisión por parte del resto de equipos etiquetados:

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

No hay preocupaciones actualmente enumeradas.

Una vez que la mayoría de los revisores aprueben (y ninguno objete), entrará en su período de comentarios final. Si detecta un problema importante que no se ha planteado en ningún momento de este proceso, ¡hable!

Consulte este documento para obtener información sobre los comandos que pueden darme los miembros del equipo etiquetados.

: bell: Esto ahora está entrando en su período de comentarios final , según la revisión anterior . :campana:

Preocupación de @rfcbot fcp Los patrones de rango tienen un problema de prioridad del operador: https://github.com/rust-lang/rust/issues/48501.

( @petrochenkov La sintaxis es <strong i="6">@rfcbot</strong> concern KEYWORD , sin fcp . Sin embargo, creo que solo el miembro del equipo etiquetado puede registrar una inquietud).

El período de comentarios final ahora está completo.

Si el # 48501 es suficiente para bloquear la estabilización, supongo que tendremos que esperar a que el # 48500 se fusione (y se estabilice). Uf, espero que podamos encontrar un camino más rápido. Esta característica ha tardado tanto en aparecer y ahora se encuentra en un estado precario en el que los mensajes de error señalan a las personas con una sintaxis inestable.

@durka
No creo que esta estabilización requiera esperar para estabilizar https://github.com/rust-lang/rust/pull/48500.
... en patrones todavía existe y todavía tiene la prioridad anterior, por lo que si tiene &BEGIN ... END en un patrón (sospecho que esto debería ser bastante raro) siempre hay una opción para no cambiarlo a ..= por algún tiempo.

Creo que podemos estabilizar # 48500 bastante rápido

Personalmente, estaría bien con aterrizarlo "insta-estable"

inclusive range se ha estabilizado ya que la solicitud de extracción # 47813 se ha fusionado pero no está en la versión 1.25, ¿por qué? Aunque la solicitud de extracción se fusionó el 16 de marzo

@mominul una función está disponible solo después de que se haya fusionado en la rama maestra, por lo que ..= está disponible a partir de 1.26, no 1.25.

De esa manera, puede probarlos en beta y todas las noches antes de que se conviertan en estables.

¡Gracias por las aportaciones @kennytm y @clarcharr ! ¡El lanzamiento de Rust 1.26 definitivamente no es aburrido al menos para mí! :sonrisa:

Sé que es demasiado tarde para participar en esta discusión, pero ¿por qué no omitir la sintaxis .. completo y usar palabras en su lugar?

En Scala tiene 1 to 4 que genera [1, 2, 3, 4] , 1 until 4 que genera [1, 2, 3] , y una palabra clave opcional by que sigue que indica el tamaño del paso : 1 to 10 by 2 = [1, 3, 5, 7, 9] .

Esto hace que la intención sea más clara y evita el error de "uno por uno" por el que todo el mundo parece estar tan preocupado.

Por supuesto, esto rompe todo el código existente, si la sintaxis original no sigue siendo compatible.

Sin embargo, to y until como palabras clave para respaldar eso, y ese sería un cambio radical mucho mayor.

Funciona bien en Scala, pero las opciones de diseño de Rust difieren en gran medida.

@ElectricCoffee, aunque me gustaría tener esa sensación, no creo que sea conveniente agregar palabras clave adicionales.

Creo que las palabras clave integradas en el lenguaje deben mantenerse al mínimo, ya que podrían colisionar con los nombres de funciones o variables.

Aunque to y until no son palabras que se usan en std (hasta donde yo sé), estoy seguro de que son palabras comunes que se usan en otras cajas y proyectos.

@daboross ese es en realidad un punto justo que no consideré, aunque dicho esto, a .. b en cierto sentido significa a to b , independientemente de lo que a y b realidad lo son.

Y sí, @timvisee probablemente lo sean.

@ElectricCoffee Pero si to significa ..= y until significa .. , tendrías que escribir a until b , no a to b lugar de a .. b . Como puede ver, no es "más" intuitivo usar estas palabras que operadores ... Pero sería más detallado escribir until todos los lugares donde se usa .. , porque es mucho más común que ..= (por lo tanto, si se usaron palabras, a .. debería asignar la palabra más corta).

Y tienes toda la razón sobre eso @Boscop , sin embargo, fue solo un ejemplo de cómo se podían hacer las palabras.

Creo que he visto to para exclusivo y upto para inclusivo también en algunos idiomas.
Todo fue pensado como una idea.

En Scala, el rango inclusivo se usa más que el exclusivo y, por lo tanto, se le da la palabra más corta.

@timvisee Uno simplemente puede usar a.to(b) y a.until(b) , no se necesitan palabras clave adicionales (y eso no hace que la sintaxis sea mucho más torpe).

@ hyst329 Ni siquiera pensé en eso. Debo decir que me gusta mucho esa idea. De hecho, tienes razón.

Sin embargo, no creo que esto sea un reemplazo completo adecuado para la sintaxis actual (/ nueva). Pero sería una buena adición.

Tengo que estar de acuerdo con el comentario de Boscop sobre la intuición. Aparte de palabras como "incluyendo" y "excepto", el inglés del día a día realmente no distingue entre rangos inclusivos y exclusivos lo suficiente como para que haya un atajo listo para usar.

A menos que se use en un contexto en el que también se use "A a B", es ambiguo si "A to B" significa un rango inclusivo o exclusivo en el habla cotidiana aquí en el sur de Ontario, Canadá, y "hasta" está asociado con el tiempo lo suficientemente fuerte como para que, cuando se use en este sentido más flexible, no esté claro si el "evento" con el que "hasta" se asocia es "hasta que veamos X" o "hasta que hayamos procesado X".

@ hyst329 Sin

Supongo que podríamos agregar un nuevo rasgo general al preludio para crear rangos, pero eso aún está al borde de un cambio radical para las cosas que tienen métodos reales to y until .

Lo confieso, pensé que la sugerencia de palabras clave era una broma de los inocentes.
La sintaxis .. = se ha estabilizado.

El jueves 5 de abril de 2018 a la 1:53 p.m., David Ross [email protected] escribió:

@ hyst329 https://github.com/hyst329 Tenerlos como métodos limitaría
rangos a tipos de números, sin embargo. Realmente prefiero no tener una sintaxis para
rangos de números y otro para rangos de otras cosas.

Supongo que podríamos agregar un nuevo rasgo general al preludio para crear
rangos, pero eso todavía está al borde de un cambio radical para las cosas que tienen
métodos actuales hasta y hasta.

-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/rust-lang/rust/issues/28237#issuecomment-379021814 ,
o silenciar el hilo
https://github.com/notifications/unsubscribe-auth/AAC3nwBj-b985q1Ez0OHDEHkG6DWV_5nks5tlloZgaJpZM4F4LbW
.

Sí, hemos tenido más de 300 comentarios sobre este tema, y ​​el primer comentario dice:

no se deberían tener más discusiones sobre la sintaxis en este hilo . Cualquier propuesta diferente de sintaxis de rango exclusivo debe tener lugar en el foro del usuario o en el foro interno, después de haber leído todos los comentarios existentes y su justificación aquí. En particular, romper la compatibilidad con versiones anteriores no es un comienzo.

Voy a bloquear este problema por ahora, lo siento si me estoy pisando los dedos de los pies.

Creo que todo lo que abarca este tema está hecho. Vuelva a abrir y actualice la lista de verificación en el mensaje original del problema si hay algo más.

¿Fue útil esta página
0 / 5 - 0 calificaciones