73 votes

En Scala, que fait "view" ?

Plus précisément, je cherche à résoudre le problème 1.

http://pavelfatin.com/scala-for-project-euler/

Le code tel que listé est le suivant

val r = (1 until 1000).view.filter(n => n % 3 == 0 || n % 5 == 0).sum

Je peux tout suivre sauf "view". En fait, si j'enlève view, le code compile toujours et produit exactement la même réponse.

124voto

Kim Stebel Points 22873

View produit une collection paresseuse, de sorte que les appels à par ex. filter n'évaluent pas chaque élément de la collection. Les éléments ne sont évalués que lorsqu'ils sont explicitement accédés. Maintenant, sum accède à tous les éléments, mais avec view l'appel à filter ne crée pas un Vecteur complet. (Voir le commentaire de Steve)

Un bon exemple de l'utilisation de la vue serait :

scala> (1 to 1000000000).filter(_ % 2 == 0).take(10).toList
java.lang.OutOfMemoryError: GC overhead limit exceeded

Ici, Scala essaie de créer une collection avec 1000000000 pour ensuite accéder aux 10 premiers éléments. Mais avec la vue :

scala> (1 to 1000000000).view.filter(_ % 2 == 0).take(10).toList
res2: List[Int] = List(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)

25voto

Richard Inglis Points 3167

Je ne connais pas bien Scala, mais peut-être que cette page pourrait aider...

Il y a deux façons principales d'implémenter les transformateurs. L'une est stricte, c'est-à-dire qu'une nouvelle collection avec tous ses éléments est construite comme résultat du transformateur. L'autre est non stricte ou paresseuse, c'est-à-dire que l'on construit seulement un proxy pour la collection de résultat, et ses éléments sont construits seulement quand on les demande.

A voir est un type spécial de collection qui représente une collection de base, mais qui implémente tous les transformateurs paresseusement.

Donc il semble que le code fonctionnera toujours sans view mais vous pourriez, en théorie, faire un travail supplémentaire en construisant tous les éléments de votre collection dans la base de données de l'UE. strict plutôt que paresseux la mode.

9voto

Chema Points 2258

Lorsque l'on enchaîne plusieurs transformations sur une collection, on crée de nombreuses collections intermédiaires qui sont immédiatement jetées. Par exemple, dans le code suivant :

@ val myArray = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)
@ val myNewArray = myArray.map(x => x + 1).filter(x => x % 2 == 0).slice(1, 3)

myNewArray: Array[Int] = Array(4, 6)

La chaîne de .map .filter .slice finissent par traverser la collection trois fois, créant ainsi trois nouvelles nouvelles collections, mais seule la dernière collection finit par être stockée dans myNewArray et les autres sont rejetées.

myArray
1,2,3,4,5,6,7,8,9

map(x => x + 1)
2,3,4,5,6,7,8,9,10

filter(x => x % 2 == 0)
2,4,6,8,10

slice(1, 3)
myNewArray
4,6

Cette création et cette traversée de collections intermédiaires constituent un gaspillage. Dans les cas où vous avez de longues chaînes de qui deviennent un goulot d'étranglement au niveau des performances, vous pouvez utiliser la fonction .view méthode en même temps que .to à fusible les opérations ensemble :

@ val myNewArray = myArray.view.map(_ + 1).filter(_ % 2 == 0).slice(1, 3).to(Array)
myNewArray: Array[Int] = Array(4, 6)

Utilisation de .view avant le map/filter/slice de transformation reporte la traversée réelle et la création création d'une nouvelle collection jusqu'à plus tard, quand nous appelons .to pour le reconvertir en un type de collection concret :

myArray
1,2,3,4,5,6,7,8,9

view map filter slice to

myNewArray
4,6

Cela nous permet d'effectuer cette chaîne de map/filter/slice des transformations avec une seule traversée, et ne créer qu'une seule collection de sortie. Cela réduit la quantité de traitements inutiles et les mémoire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X