2009-09-27 10 views
68

Où puis-je trouver une liste des fonctions «magiques» de Scala, telles que apply, unapply, update, +=, etc.?Liste des fonctions «magiques» de Scala

par magie-fonctions, je veux dire les fonctions qui sont utilisées par un peu de sucre syntaxique du compilateur, par exemple

o.update(x,y) <=> o(x) = y 

Je googlé pour une combinaison de scalamagic et synonymes de functions, mais je ne l'ai pas trouvé n'importe quoi.

Je ne suis pas intéressé par l'utilisation de fonctions magiques dans la bibliothèque standard, mais dans laquelle existent des fonctions magiques.

Répondre

71

Pour autant que je sais:

Getters/setters liés:

apply 
update 
identifier_= 

Recherche de motif:

unapply 
unapplySeq 

Pour-compréhensions:

map 
flatMap 
filter 
withFilter 
foreach 

opérateurs préfixés:

unary_+ 
unary_- 
unary_! 
unary_~ 

Au-delà, toute implicite de A à B. Scala sera également convertir A <op>= B en A = A <op> B, si l'ancien opérateur n'est pas définie, « op » n'est pas alphanumérique, et <op>= n'est pas !=, ==, <= ou >=.

Et je ne crois pas qu'il existe un seul endroit où tous les sucres syntactiques de Scala sont répertoriés.

+2

Vous voudrez peut-être ajouter le unary_! etc opérateurs qui ont été répertoriés dans l'un des autres messages, car cela ressemble à la réponse la plus exhaustive à la question ici :) – Calum

+1

... et vous l'avez fait, merci! – Calum

+1

Qu'est-ce que 'identifier_ ='? Je n'ai jamais vu ça. –

3

Ils sont définis dans la spécification de langage Scala. Pour autant que je sache, il n'y a que trois fonctions "magiques" comme vous l'avez mentionné.

Scalas Getter et Setter peuvent également se rapporter à votre « magique »:

scala> class Magic { 
|  private var x :Int = _ 
|  override def toString = "Magic(%d)".format(x) 
|  def member = x 
|  def member_=(m :Int){ x = m } 
| } 

defined class Magic 

scala> val m = new Magic 

m: Magic = Magic(0) 

scala> m.member 

res14: Int = 0 

scala> m.member = 100 

scala> m 

res15: Magic = Magic(100) 

scala> m.member += 99 

scala> m 

res17: Magic = Magic(199) 
+0

Si vous pouviez creuser pour moi une preuve de cette affirmation, vous serez répondre à ma question ;-) Je suppose que ce sera dans les spécifications, mais les trouver dans ce n'est pas un travail amusant. –

+2

Scala Langue Spécification: 6,15 missions ... Si x est une fonction sans paramètre défini dans un certain modèle, et le même modèle contient une fonction setter x_ = en tant que membre, alors l'affectation x = e est interprété comme l'invocation x _ = (e) de la fonction . De manière analogue, une affectation f .x = e à une fonction sans paramètre x est interprétée comme l'invocation f .x _ = (e). Une affectation f (args) = e avec une application de fonction à gauche de l'opérateur "=" est interprétée comme f .update (args, e), c'est-à-dire l'appel d'une fonction de mise à jour définie par f. – Eastsun

+0

I ment, preuve qu'il n'y en a plus. –

15

En plus de update et apply, il y a aussi un certain nombre d'opérateurs unaires (je crois) être considéré comme magique:

  • unary_+
  • unary_-
  • unary_!
  • unary_~

Ajoutez à cela les opérateurs infix réguliers/suffixe (qui peut être à peu près tout) et vous avez vous-même le package complet.

Vous devriez vraiment jeter un oeil à la spécification de langage Scala. C'est la seule source faisant autorité sur ce genre de choses. Ce n'est pas si difficile à lire (aussi longtemps que vous êtes à l'aise avec les grammaires contextuelles), et très facilement consultable. La seule chose qu'il ne spécifie pas bien est le support XML.

10

Désolé, ce n'est pas exactement la réponse à votre question, mais mon moment WTF préféré jusqu'à présent est @ comme opérateur d'assignation à l'intérieur du motif. Grâce à une copie de "Programming in Scala", j'ai découvert rapidement ce que c'était. En utilisant @ nous pouvons lier n'importe quelle partie d'un motif à une variable, et si la correspondance de motif réussit, la variable capturera la valeur du sous-motif. Voici l'exemple de programmation Scala (Section 15.2 - Variable Binding):

expr match { 
    case UnOp("abs", e @ UnOp("abs", _)) => e 
    case _ => 
} 

Si l'ensemble réussit match de motif, alors la partie qui correspondait à la UNOP ("ABS", _) partie est rendu disponible comme variable e.

Et here « s ce programmation Scala dit à ce sujet.

+0

Pouvez-vous partager avec nous ce que fait l'opérateur @? –

+0

Oui, juste édité ma réponse :-) – Yardena

2

Je vais aussi ajouter _* pour correspondance de motif sur un nombre arbitraire de paramètres comme

case x: A(_*) 

Et opérateur règle associativité, du livre Odersky-cuillère-Venners:

L'associativité d'un opérateur dans Scala est déterminée par son dernier caractère . Comme mentionné sur < ...>, toute méthode qui se termine dans un caractère ':' est invoquée sur son opérande droit, en passant dans l'opérande gauche . Les méthodes qui se terminent par un autre caractère sont l'autre . Ils sont invoqués sur leur opérande gauche, en passant dans l'opérande droit . Donc a * b donne un. * (B), mais a ::: b donne b.:::a).


Peut-être que nous devrions aussi mentionner désucrage syntaxique des pour les expressions qui se trouve here


et (bien sûr!), syntaxe alternative pour les paires

a -> b //converted to (a, b), where a and b are instances 

(comme correctement po imé out, celui-ci est juste une conversion implicite fait par une bibliothèque, il est donc probablement pas admissible, mais je trouve qu'il est un jeu de réflexion commune pour les nouveaux arrivants)


+1

IIRC '->' est juste une fonction de bibliothèque. –

2

Je voudrais ajouter qu'il ya aussi un trait "magique" -

Un trait de marqueur qui permet des invocations dynamiques.Les instances x de ce trait permettent des invocations de méthode x.meth(args) pour des noms de méthodes arbitraires meth et des listes d'arguments args ainsi que des accès de champ x.field pour des noms de champ arbitraires field.

Si un appel est pas pris en charge nativement par x (à savoir si le type de vérification échoue), il est réécrite selon les règles suivantes:

foo.method("blah")  ~~> foo.applyDynamic("method")("blah") 
foo.method(x = "blah") ~~> foo.applyDynamicNamed("method")(("x", "blah")) 
foo.method(x = 1, 2) ~~> foo.applyDynamicNamed("method")(("x", 1), ("", 2)) 
foo.field   ~~> foo.selectDynamic("field") 
foo.varia = 10  ~~> foo.updateDynamic("varia")(10) 
foo.arr(10) = 13 ~~> foo.selectDynamic("arr").update(10, 13) 
foo.arr(10)   ~~> foo.applyDynamic("arr")(10) 

Au Scala 2.10, la définition des sous-classes directes ou indirectes de ce trait n'est possible que si la dynamique des fonctions de langue est activée.

Alors vous pouvez faire des choses comme

import scala.language.dynamics 

object Dyn extends Dynamic { 
    def applyDynamic(name: String)(a1: Int, a2: String) { 
    println("Invoked " + name + " on (" + a1 + "," + a2 + ")"); 
    } 
} 

Dyn.foo(3, "x"); 
Dyn.bar(3, "y"); 
+0

Le lien ne fonctionne pas. Pouvez-vous mettre à jour? – Jus12

Questions connexes