2009-09-06 5 views
19

Quand j'ai commencé à regarder Scala, j'ai aimé le look for-comprehensions. Ils semblaient être un peu comme les boucles foreach auxquelles j'étais habitué depuis Java 5, mais avec des restrictions fonctionnelles et beaucoup de gentillesse syntaxique douce.Compréhensions de Scala: caractéristique vitale ou sucre syntaxique?

Mais comme je l'ai absorbé le style Scala, je trouve que chaque fois que je pouvais utiliser un pour-comprension J'utilise map, flatMap, filter, reduce et foreach à la place. L'intention du code me semble plus claire, avec moins de surprises cachées potentielles, et elles sont généralement plus courtes. Pour autant que je sache, car les compréhensions sont toujours compilées dans ces méthodes de toute façon, alors je me demande: à quoi servent-elles réellement? Ai-je manqué une revalorisation fonctionnelle (ce ne serait pas la première fois)? Est-ce que les compréhensions font quelque chose que les autres caractéristiques ne peuvent pas faire, ou seraient au moins beaucoup plus maladroites? Est-ce qu'ils brillent sous un cas d'utilisation particulier? Est-ce vraiment juste une question de goût personnel?

+2

Ceci est presque un double de http://stackoverflow.com/questions/1052476/can-someone-explain-scalas-yield. Cette question se demandait ce que «rendement» a fait, celui-ci se demande quel est son but. Les réponses sont à peu près les mêmes. –

Répondre

13

Veuillez vous reporter au this question. La réponse courte est que pour-les compréhensions peuvent être plus lisibles. En particulier, si vous avez plusieurs générateurs imbriqués, la portée réelle de ce que vous faites devient plus claire, et vous n'avez pas besoin d'énormes retraits.

10

pour-les compréhensions sont du sucre syntaxique, mais cela ne signifie pas qu'elles ne sont pas vitales. Ils sont généralement plus concis que leur forme développée, ce qui est bien, mais peut-être plus important encore, ils aident les programmeurs de langages impératifs à utiliser des constructions fonctionnelles. Quand j'ai commencé avec Scala, j'ai beaucoup utilisé les compréhensions for- cées, parce qu'elles m'étaient familières. Puis j'ai presque arrêté complètement, parce que j'avais l'impression que l'utilisation des méthodes sous-jacentes était plus explicite et donc plus claire. Maintenant, je suis de retour à l'utilisation pour les compréhensions parce que je pense qu'ils expriment mieux l'intention de ce que je fais plutôt que les moyens de le faire.

3

Vous avez raison. La for-compréhension est le sucre syntaxique. Je crois que les méthodes sous-jacentes sont plus succinctes et plus faciles à lire, une fois que vous y êtes habitué.

Comparez les déclarations équivalentes:

1. for (i <- 1 to 100; if (i % 3 == 0)) yield Math.pow(i, 2) 
2. (1 to 100).filter(_ % 3 == 0).map(Math.pow(_, 2)) 

À mon avis, l'ajout du point-virgule # 1 détourne l'attention de sens que ce soit une seule instruction enchaînée. Il y a aussi un sens que i est un var (est-ce 1, ou est-ce 99, ou quelque chose entre deux?) Qui porte atteinte à un style autrement fonctionnel.

L'option 2 est plus évidemment une chaîne d'appels de méthode sur des objets. Chaque maillon de la chaîne énonce clairement sa responsabilité. Il n'y a pas de variables intermédiaires. Peut-être pour des raisons de compréhension sont inclus comme une commodité pour les développeurs en transition de Java. Peu importe, ce qui est choisi est une question de style et de préférence.

+0

"une fois que vous êtes habitué à eux" - exactement. Une fois que j'ai compris les monades, je suis passé aux méthodes sous-jacentes. Le pour la compréhension était un lien utile avant cela. –

+1

Vous n'avez besoin d'aucun point-virgule dans 1: 'for (i <- 1 à 100 if (i% 3 == 0)) donne Math.pow (i, 2)'. De plus, vous pouvez remplacer les parenthèses par des accolades pour activer l'inférence par points-virgules. – Blaisorblade

+0

Merci @Blaisorblade Je me demande si le point-virgule était nécessaire en 2009. – Synesso

11

Un autre grand usage de la compréhension for-est pour DSL interne. ScalaQL est un excellent exemple de cela. Il peut transformer cette

val underAge = for { 
    p <- Person 
    c <- Company 
    if p.company is c 
    if p.age < 14 
} yield p 

dans ce

SELECT p.* FROM people p JOIN companies c ON p.company_id = c.id WHERE p.age < 14 

et beaucoup plus.

+0

@Erik Cela a fonctionné quand je l'ai essayé. C'est un lien vers un fichier PDF. Si vous ne pouvez toujours pas télécharger le fichier, il suffit de le google: ScalaQL: requêtes de base de données de langue intégrée pour Scala par Daniel Spiewak et Tian Zhao –

+0

Downvoted: la question réelle est de savoir s'il y a un avantage de for-comprehensions sur leur désugaring - et vous pouvez écrire ce code aussi sous forme désucrée. ScalaQuery est un meilleur exemple, car il dispose d'une implémentation de qualité de production disponible. Ce document laisse entrevoir trop de détails importants à recommander. – Blaisorblade

5

Dans certains cas, pour que les compréhensions puissent mieux exprimer l'intention, alors quand ils le font, utilisez-les.

Notez également qu'avec pour des compréhensions, vous obtenez modèle correspondant gratuitement. Par exemple, sur une carte itérer est beaucoup plus simple avec pour la compréhension:

for ((key, value) <- map) println (key + "-->" + value)

qu'avec foreach:

map foreach { case (key, value) => println (key + "-->" + value) }

Questions connexes