Question

C # a des fonctions génératrices dont la syntaxe est la suivante:

IEnumerable<int> GetNats(int max)
{
   for (int i=0; i < max; ++i)
      yield return i;
}

Une fonctionnalité qui m'intéresse pour mon langage de programmation (une programmation orientée objet simple, similaire à Java, Scala, ActionScript et C #) est une expression de générateur. Ce sont essentiellement des sucres syntaxiques pour les fonctions génératrices.

Mon candidat actuel favori est la syntaxe suivante:

IEnumerable<int> nats = 
  witheach (i in range(0, 42)) 
     yield i * 2; 

L'expression range (0, 42) est une fonction génératrice intégrée.

Donc, ma question est la suivante: quelle syntaxe préférez-vous voir pour les expressions de générateur, dans un langage de type C # / Java / Scala / ActionScript, et pourquoi?

Certains facteurs susceptibles d’influencer les réponses sont que, comme Scala et ActionScript, les types de mon langage sont déclarés après le type. Par exemple:

var myVar : SomeType = initialValue;

Les fonctions anonymes ressemblent à ceci:

var myFunc = function(int x) { 
  return x + 1; 
}

À part cela, le reste de la syntaxe de mon langage ressemble à Java ou à C #. Ma langue a une instruction foreach qui est très similaire à C #.

Était-ce utile?

La solution

Il existe également une approche de Python - aucune syntaxe spéciale pour les générateurs; la présence d'un "rendement" la déclaration est tout ce qu'il faut. Toutes les instructions qui prennent un bloc peuvent être utilisées, même si je n’espérerais trouver que des boucles utilisées dans la pratique:

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]

Ici, je suppose que le bon point de terminaison n'est pas inclus dans une plage.

Pour être tout à fait honnête, quand j'ai vu cela en Python, je me suis demandé: "à quel prix?"

Autres conseils

Découvrez ce que fait F #. Vous pouvez faire

seq { seq-expr }    // IEnumerable<T>, a.k.a. seq<T>
[ seq-expr ]        // list<T>
[| seq-expr |]      // array<T>

où seq-expr est une forme qui inclut la plupart des constructions de langage avec "rendement". Donc, par exemple vous pouvez écrire

seq {
    for i in 0..9 do
        for j in someColl do
            if i <> j then
                yield i*j
}

Le compilateur F # traduit ce code en une implémentation de machine à état de IEnumerable (comme C # le fait pour les blocs itérateurs).

J'aime cette syntaxe car elle signifie par exemple vous pouvez écrire exactement le même code que celui auquel vous écririez "faire des choses impératives maintenant", par exemple.

    for i in 0..9 do
        for j in someColl do
            if i <> j then
                printfn "%d" i*j

mais enveloppez ce code dans seq {} et utilisez 'rendement' et le code devient un IEnumerable paresseux.

IEnumerable nats = 0...42

or for generators 

IEnumerable nats = yield 0...42
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top