2011-01-26 5 views
1

J'ai une partie du code d'un ami et j'essaie de le comprendre et de l'écrire d'une autre manière. « Gotowe » est une liste triée des éléments ("2011-12-22",-600.00)Scala Code - Je ne comprends pas

val wartosci = gotowe.foldLeft (List(initial_ballance)){ 
    case ((h::t), x) => (x._2 + h)::h::t 
    case _ => Nil 
    }.reverse 

C'est tout à fait correct, mais comment avec cette utilisation de foldLeft? (Je l'ai mis toutes les lignes supplémentaires nécessaires):

val max = wartosci.max 
val min = wartosci.min 
val wychylenie = if(math.abs(min)>max){math.abs(min)}else{max} 

    def scale(x: Double) = 
    (x/wychylenie) * 500 

    def point(x: Double) = 
    {val z:Int = (500 - x).toInt 
z} 

val (points, _) = wartosci.foldLeft(("", 1)){case ((a, i), h) => (a + " " + (i * 4) + "," + point(scale(h)), i + 1)} 

quand j'imprimer des points que j'ai une liste de valeurs, et je ne sais pas pourquoi quelque chose comme des paires de valeurs

+0

Cela ne semble pas avoir d'importance ici, mais pour être complet: "wartości" signifie "valeurs" et "gotowe" signifie "prêt". – Bolo

Répondre

5

Il y a deux concepts à l'œuvre, que nous allons examiner à son tour de travailler sur ce qui se passe:

  • foldLeft
  • modèle correspondant à

Examinons d'abord à la définition de foldLeft:

def foldLeft [B] (z: B) (f: (B, A) ⇒ B): B

applique un opérateur binaire à un commencer la valeur et tous les éléments de cette liste, en allant de gauche à droite.

Renvoie le résultat de l'insertion de op entre les éléments consécutifs de cette liste, en allant de gauche à droite avec la valeur de départ z à gauche: op (... op (z, x1), x2, ..., xn) où x1, ..., xn sont les éléments de cette liste.

Ainsi, dans votre exemple, nous prenons une liste de Tuple2 [String, Float] (ou quelque chose comme ça) et le pliage dans la valeur z, qui dans ce cas est une liste contenant un élément, initial_balance .

Maintenant, notre f dans ce cas est le code à l'intérieur des accolades. Il utilise la correspondance de modèle pour composer une fonction partielle de la paire (b,a) - où dans ce cas b est le 'résultat cumulatif' et a est l'élément suivant dans la liste. C'est le noeud de ce qu'un pli fait - il réduit la liste en une valeur, en utilisant des règles spécifiques régissant la façon d'ajouter chaque élément à la fois.

Qu'est-ce que la correspondance de motif/une fonction partielle? La correspondance de modèle est une technique très puissante pour conditionner et extraire des choses à partir de données d'entrée. Nous lui donnons quelque chose à rechercher - la partie case de l'expression - et lui dire comment y faire face après le =>. La puissance de ceci est que l'expression case ne correspond pas seulement, disons, à des nombres ou à des chaînes spécifiques comme l'instruction switch dans java, mais peut correspondre, par exemple, à des listes d'une certaine longueur, ou adresses email, ou tuples spécifiques. Plus encore, vous pouvez l'utiliser pour obtenir automatiquement certaines parties du match - le domaine de l'adresse e-mail, le troisième élément de la liste, etc.

Nous allons voir le premier motif:

case ((h::t), x) => (x._2 + h)::h::t

Le côté gauche (avant le =>) est utilisé pour correspondre à la valeur que nous recherchons et extraire les pièces spécifiques qui nous intéressent.Dans ce cas, nous recherchons un tuple où le premier élément est une liste composée d'une tête (h) et d'une queue (t), et le second élément est juste l'élément suivant de la liste. Le h::t est un modèle d'extracteur - il correspond à l'objet: :(h, t) qui construit un List en ajoutant h au List t existant.

Lorsque nous avons fait correspondre cela, nous suivons les instructions à la droite de la => pour plier x dans la valeur cumulée. Pour ce faire, nous prenons le côté droit du tuple date/valeur (._2), l'ajoutons à la dernière valeur de la liste (la tête), puis nous poussons en tête de la liste. Vous remarquerez qu'il utilise la même syntaxe que celle utilisée dans la correspondance de modèle - en utilisant :: pour ajouter des éléments à un List.

L'effet dans ce cas est de créer un total cumulé de ce qui se passe.

Le deuxième cas ne fait pas grand-chose - c'est un piège, mais comme il est utilisé dans un pli, il ne devrait jamais être appelé - nous allons toujours retourner quelque chose qui ressemble à ((h::t), x).

Enfin, nous inversons le tout! Donc, ce qui nous reste est une liste de soldes après chaque transaction, allant du plus ancien au plus jeune.

1

C'est assez simple. C'est juste la question de la mission. Vous avez ceci:

val (points, _) = wartosci.foldLeft(("", 1)){...} 

Qu'est-ce que l'intérieur {...} n'est pas pertinent. Le premier paramètre de foldLeft déterminera le type de son résultat. Puisque c'est ("", 1), il retournera un tuple (String, Int).

Maintenant, vous l'attribuez à (points, _). Une affectation comme celle-ci est également une correspondance de modèle. Il est comme vous avez écrit ceci:

var tmp: (String, Int) = _ 
val tmp: (String, Int) = wartosci.foldLeft(("", 1)){...} match { 
    case (x, y) => tmp = (x, y) 
} 
val points = tmp._1 

Ainsi, points ne se voit assigner la String.