2010-11-09 24 views
4

Quelqu'un d'autre pense-t-il que les itérateurs sont courts quand vous voulez prendre part à une séquence morceau par morceau? Peut-être devrais-je juste commencer à écrire mon code en F # (tout le monde sait si F # utilise l'évaluation paresseuse) mais je me suis retrouvé à vouloir un moyen de tirer une séquence d'une manière très distincte.Choses amusantes à faire avec les générateurs et les séquences

par exemple.

// string.Split implemented as a generator, with lazy evaluation 
var it = "a,b,c".GetSplit(',').GetEnumerator(); 
it.MoveNext(); 
var a = it.Current; 
it.MoveNext(); 
it.MoveNext(); 
var c = it.Current; 

Cela fonctionne, mais je ne l'aime pas, c'est moche. Alors je peux faire ça?

var it = "a,b,c".GetSplit(','); 
string a; 
var c = it.Yield(out a).Skip(1).First(); 

C'est mieux. Mais je me demande s'il y a une autre façon de généraliser la même sémantique, peut-être que c'est assez bon. Habituellement, je fais de l'analyse de chaînes intégrée, c'est à ce moment-là que ça sort.

Il y a aussi le cas où je souhaite consommer une séquence jusqu'à un point spécifique, puis fondamentalement, la fourchonner (ou la cloner, c'est mieux). Comme si

var s = "abc"; 
IEnumerable<string> a; 
var b = s.Skip(1).Fork(out a); 
var s2 = new string(a.ToArray()); // "bc" 
var s3 = new string(b.ToArray()); // "bc" 

Ce dernier, pourrait ne pas être utile que dans un premier temps, je trouve qu'il résout les problèmes plutôt commodément backtracking.

Ma question est de savoir si nous en avons besoin? ou existe-t-il déjà d'une certaine manière et je l'ai juste raté?

+0

"quelqu'un sait si F # utilise une évaluation paresseuse" - pas par défaut. Les séquences F # sont paresseuses comme en C# (elles sont aussi 'IEnumerable'). F # a des fonctions lambda (encore une fois, comme C#) et du sucre syntaxique pour des valeurs évaluées paresseusement (qui se compilent à une fonction en dessous). –

+0

Dans quel but? Avoir la syntaxe/méthodes etc est * bien * - mais à moins que vous connaissiez un cas d'utilisation raisonnable valable ... pourquoi s'embêter? Re the fork - "Push LINQ" (MiscUtil) peut vous intéresser. –

+0

Stimules intellectuels? Amuse-moi ... parfois j'aime juste faire des recherches. Je dois payer Push LINQ. –

Répondre

1

Les séquences fonctionnent normalement bien dans ce qu'elles font, c'est-à-dire qu'elles fournissent une interface simple qui génère un flux de valeurs à la demande. Si vous avez des demandes plus complexes, vous pouvez utiliser une interface plus puissante. Par exemple, vos exemples de chaînes semblent pouvoir être écrits en tant qu'analyseur: c'est-à-dire, une fonction qui consomme une séquence de caractères d'un flux et utilise l'état interne pour garder une trace de son emplacement dans le flux.

+0

Vous savez, ce que je voudrais vraiment. Je voudrais quelque chose comme Boost Spirit, la programmation meta et la surcharge de l'opérateur pour créer essentiellement un DSL C++ qui peut être utilisé pour consommer une entrée de chaîne. C'est incroyablement compilateur intensif et ralentit beaucoup la compilation de votre programme, mais cela fonctionne et c'est plutôt cool d'avoir quelque chose de puissant construit sur le langage C++. Fondamentalement parlant, il consomme toujours des flux de caractères, mais à ce niveau, il est vraiment difficile de décrire une fonction de haut niveau. Ce qui est un peu ce que j'essaie de faire ici. –

+0

Je n'ai jamais vu un framework de parser pour C# que j'ai aimé. Vous avez mentionné F #; là vous avez 'fslex' /' fsyacc' (partie du PowerPack) ou la bibliothèque 'FParsec'. –

+0

Vraiment? Vous savez, le langage de programmation des fonctions a toujours eu cela en faveur. Peut-être que je devrais rouler des analyseurs en F # mais les consommer en C# ... c'est logique. –