Elegir una sintaxis para las expresiones generadoras de listas [cerrado]
Pregunta
C # tiene funciones de generador que tienen una sintaxis como:
IEnumerable<int> GetNats(int max)
{
for (int i=0; i < max; ++i)
yield return i;
}
Una función que me interesa para mi lenguaje de programación (una simple programación orientada a objetos similar a Java, Scala, ActionScript y C #) son expresiones generadoras. Estos son esencialmente azúcares sintácticos para funciones de generador.
Mi candidato favorito actual es la siguiente sintaxis:
IEnumerable<int> nats =
witheach (i in range(0, 42))
yield i * 2;
La expresión range (0, 42)
es una función de generador integrada.
Entonces, mi pregunta es ¿qué sintaxis preferiría ver para las expresiones generadoras, en un lenguaje de tipo C # / Java / Scala / ActionScript, y por qué?
Algunos factores que pueden influir en las respuestas son que, como Scala y ActionScript, los tipos en mi idioma se declaran después del tipo. Por ejemplo:
var myVar : SomeType = initialValue;
También las funciones anónimas se ven así:
var myFunc = function(int x) {
return x + 1;
}
Aparte de eso, el resto de la sintaxis de mi lenguaje se parece a Java o C #. Mi idioma tiene una declaración foreach
que es muy similar a C #.
Solución
También hay un enfoque de Python's : no hay una sintaxis especial para los generadores; la presencia de un " rendimiento " declaración es todo lo que necesita. Se podría usar cualquier declaración que tome un bloque, aunque esperaría encontrar solo los bucles utilizados en la práctica:
IEnumerable<int> nats =
for (i in range(0,42))
yield i*2
String phrase = "I want to buy some cheese.";
IEnumerable<int> substrs =
for (i in 0 .. phrase.length)
for (j in i .. phrase.length+1)
yield phrase[i..j]
Aquí asumo que el punto final correcto no está incluido en un rango.
Para ser completamente honesto, cuando vi esto en Python, tuve que preguntarme: "¿a qué costo? "
Otros consejos
Echa un vistazo a lo que hace F #. Usted puede hacer
seq { seq-expr } // IEnumerable<T>, a.k.a. seq<T>
[ seq-expr ] // list<T>
[| seq-expr |] // array<T>
donde seq-expr es un formulario que incluye la mayoría de las construcciones de lenguaje junto con 'rendimiento'. Así por ejemplo puedes escribir
seq {
for i in 0..9 do
for j in someColl do
if i <> j then
yield i*j
}
El compilador F # traduce este código en una implementación de máquina de estado de IEnumerable (como lo hace C # para los bloques de iteradores).
Me gusta esta sintaxis porque significa, por ejemplo, puedes escribir exactamente el mismo código que escribirías para " hacer cosas imperativas ahora " ;, por ejemplo
for i in 0..9 do
for j in someColl do
if i <> j then
printfn "%d" i*j
pero envuelva ese código en seq {} y use 'rendimiento' y el código se convertirá en un IEnumerable perezoso en su lugar.
IEnumerable nats = 0...42 or for generators IEnumerable nats = yield 0...42