web-dev-qa-db-fra.com

pour les expressions par rapport à foreach dans Scala

Je me fraye un chemin Programmation en Scala , et bien que je sois tenté de voir les choses du point de vue de Python, je ne veux pas programmer "Python en Scala".

Je ne sais pas trop quoi faire en ce qui concerne le flux de contrôle: en Python, nous utilisons for x in some_iterable à mort, et nous l'aimons. Une construction très similaire existe dans Scala que Odersky appelle une expression for , probablement pour la distinguer de la Java for loop. En outre, Scala a un attribut foreach (je suppose que ce serait un attribut, je n'en sais pas assez sur Scala pour le nommer correctement) pour les types de données itérables. Il ne semble pas que je puisse utiliser foreach pour faire bien plus que d'appeler une fonction pour chaque élément du conteneur.

Cela me laisse avec quelques questions. Premièrement, les expressions sont des constructions importantes/fortement utilisées dans Scala comme elles sont en Python, et deuxièmement, quand dois-je utiliser foreach au lieu d'une expression for (autre que l'évidence) cas d'appel d'une fonction sur chaque élément d'un conteneur)?

J'espère que je ne suis pas terriblement ambigu ou trop large, mais j'essaie simplement de comprendre certaines des bases du design/langage dans Scala (ce qui semble très cool jusqu'à présent).

54
Rafe Kettler

python utilise for dans les compréhensions de liste et les expressions de générateur. Ce sont très similaires à l'expression scala for:

c'est python

>>> letters = ['a', 'b', 'c', 'd']
>>> ints = [0, 1, 2, 3]
>>> [l + str(i) for l in letters for i in ints if i % 2 == 0]
['a0', 'a2', 'b0', 'b2', 'c0', 'c2', 'd0', 'd2']

c'est scala

scala> val letters = List('a', 'b', 'c', 'd')
scala> val ints = List(0, 1, 2, 3)
scala> for (l <- letters; i <- ints if i % 2 == 0) yield l.toString + i
res0: List[Java.lang.String] = List(a0, a2, b0, b2, c0, c2, d0, d2)

Chaque construction peut prendre un certain nombre de générateurs/itérateurs, appliquer des expressions de filtres et produire une expression combinée. Dans python le (expr for v1 in gen1 if expr1 for v2 in gen2 if expr2) Est à peu près équivalent à:

for v1 in gen1:
  if expr1:
    for v2 in gen2:
      if expr2:
        yield expr

In scala for (v1 <- gen1 if expr1; v2 <- gen2 if expr2) yield expr est à peu près équivalent à:

gen1.withFilter(expr1).flatMap(v1 => gen2.withFilter(expr2).map(v2 => expr))

Si vous aimez la syntaxe python for x in xs, Vous aimerez probablement l'expression scala for).

Scala a quelques syntaxes et torsions de traduction supplémentaires. La syntaxe sage for peut être utilisée avec des accolades afin que vous puissiez mettre des instructions sur des lignes distinctes. Vous pouvez également effectuer des affectations de valeur.

val res = for {
    i <- 1 to 20; i2 = i*i
    j <- 1 to 20; j2 = j*j
    k <- 1 to 20; k2 = k*k
    if i2 + j2 == k2
  } yield (i, j, k)

v1 <- gen1 Effectue également une correspondance case v1 => gen1. S'il n'y a pas de correspondance, ces éléments sont ignorés de l'itération.

scala> val list = List(Some(1), None, Some(2))
scala> for (Some(i) <- list) yield i
res2: List[Int] = List(1, 2)

Je pense que for a une place importante dans la langue. Je peux dire du fait qu'il y a tout un chapitre (23) à ce sujet dans le livre que vous lisez!

59
huynhjl

Oui, Scala pour les compréhensions (comme ils sont communément connus) sont beaucoup utilisés, mais ils ne sont vraiment que du sucre syntaxique pour une combinaison particulière de méthodes, et beaucoup préfèrent appeler ces méthodes directement au lieu de en utilisant le sucre syntaxique.

Pour mieux comprendre Scala pour les compréhensions, veuillez vous référer à cette question . En particulier, vous verrez que for (x <- xs) f(x) est la même chose que xs.foreach(x => f(x)).

Maintenant, vous mentionnez que vous ne semblez pas très utile avec la méthode foreach, mais je soulignerai que presque toutes les méthodes des collections Scala sont (ou peuvent être ) implémenté avec seulement foreach. Voir la documentation de Traversable - toutes ses méthodes peuvent être implémentées avec seulement foreach.

Notez que yield de Scala ne ressemble pas à yield de Python - vous pouvez rechercher that question aussi.

25
Daniel C. Sobral

Avec son support pour l'itération, les filtres et la transformation imbriqués, je dirais que for de Scala est l'un des points forts du langage et très central. J'ai tendance à privilégier l'utilisation de foreach, map et filter.

3
Fabian Steeg

Le foreach est un style fonctionnel tandis que le for est un style impératif. Si vous avez déjà fait un LISP ou un schéma, vous connaissez déjà la programmation fonctionnelle. Si ce n'est pas le cas, cela peut être un peu déroutant au début. La première chose que je ferais serait de lire la syntaxe de fermeture, qui sont des fonctions anonymes que vous transmettez à des choses comme foreach. Une fois que vous comprenez que tout cela aura plus de sens.

3
JOTN

Les réponses à vos questions sont largement les suivantes:

Scala's For Comprehensions

rendement Scala

Pour résumer: c'est largement stylistique. Personnellement, je privilégie la méthodologie fonctionnelle, mais préfère la concision des compréhensions lors du traitement des boucles imbriquées.

3
Northover