270 votes

Différence entre méthode et fonction dans Scala

J'ai lu Scala Functions (partie d'une autre tournée de Scala ). Dans ce post, il a déclaré:

Les méthodes et les fonctions ne sont pas la même chose

Mais il n'a rien expliqué à ce sujet. Qu'est-ce qu'il essayait de dire?

247voto

Daniel C. Sobral Points 159554

Jim a eu ce assez bien couvert dans son billet de blog, mais je vais poster un briefing ici pour référence.

Tout d'abord, voyons ce que la Scala de Spécification de nous le dire. Le chapitre 3 (types) de nous dire à propos des Types de Fonction (3.2.9) et les Types de Méthode (3.3.1). Le chapitre 4 (la base de déclarations) parle de la Déclaration de la Valeur et des Définitions (4.1), la Déclaration de la Variable et Définitions (4.2) et les Fonctions Déclarations et les Définitions (4.6). Le chapitre 6 (expressions) parle de Fonctions Anonymes (6.23) et la Méthode des Valeurs de (6.7). Curieusement, les valeurs de la fonction est parlé une fois sur 3.2.9, et pas ailleurs.

Un Type de Fonction est (en gros) un type de la forme (T1, ..., Tn) => U, qui est une abréviation pour le caractère FunctionN dans la bibliothèque standard. Les Fonctions anonymes et Méthode les Valeurs ont la fonction des types et des types de fonction peut être utilisé comme une partie de la valeur de la variable et la fonction déclarations et les définitions. En fait, il peut être une partie d'un type de méthode.

Un Type de Méthode est un non-type de la valeur. Cela signifie qu'il est sans valeur - aucun objet, aucune instance n' - avec un type de méthode. Comme mentionné ci-dessus, une Méthode de la Valeur a un Type de Fonction. Un type de méthode est une def déclaration - tout sur un def à l'exception de son corps.

Les Déclarations de valeur et les Définitions et les Déclarations de Variables et Définitions sont val et var des déclarations, y compris à la fois le type et la valeur - qui peut être, respectivement, en Fonction du Type et de Fonctions Anonymes ou de la Méthode des Valeurs. Notez que, sur la JVM, ces (méthode de valeurs) sont mis en œuvre avec ce que Java appelle "méthodes".

Une Déclaration de Fonction est un def déclaration, y compris le type et le corps. Le type de partie est le Type de Méthode, et le corps est une expression ou d'un bloc. C'est également mise en œuvre sur la JVM avec ce que Java appelle "méthodes".

Enfin, une Fonction Anonyme est une instance d'un Type de Fonction (c'est à dire une instance de la trait FunctionN), et une Méthode de la Valeur est la même chose! La distinction est que la Méthode de la Valeur est créée à partir de méthodes, soit par postfixing un trait de soulignement (m _ est une méthode de la valeur correspondant à la "déclaration de fonction" (def) m), ou par un processus appelé eta-extension, qui est comme une automatique en fonte à partir de la méthode de la fonction.

C'est ce que les spécifications dire, permettez-moi de mettre cela en place-avant: nous n'utilisons pas ce vocabulaire! Elle conduit à trop de confusion entre les soi-disant "déclaration de fonction", qui est une partie du programme (chapitre 4 -- base des déclarations) et "fonction anonyme", qui est une expression, et "type de fonction", qui est, un type -- un trait.

La terminologie ci-dessous, et utilisé par des Scala programmeurs, fait un changement de la terminologie du cahier des charges: au lieu de dire une déclaration de fonction, nous disons méthode. Ou même de la déclaration de la méthode. Nous notons en outre que les déclarations de valeur et les déclarations de variables sont également des méthodes pour des raisons pratiques.

Donc, compte tenu de la modification ci-dessus dans la terminologie, voici une explication pratique de la distinction.

Une fonction est un objet qui contient l'un de l' FunctionX traits, tels que l' Function0, Function1, Function2, etc. Il peut être notamment PartialFunction , ce qui s'étend Function1.

Nous allons voir le type de signature pour l'un de ces traits:

trait Function2[-T1, -T2, +R] extends AnyRef

Ce trait a une méthode abstraite (il a quelques méthodes concrètes en tant que bien):

def apply(v1: T1, v2: T2): R

Et que nous disent tous qu'il y a à savoir sur le sujet. Une fonction a un apply méthode qui reçoit les N paramètres de types T1, T2, ..., TN, et renvoie à quelque chose de type R. Il est contre-variante sur les paramètres qu'il reçoit, et co-variante sur le résultat.

La variance signifie qu'un Function1[Seq[T], String] est un sous-type d' Function1[List[T], AnyRef]. Étant un sous-type signifie qu'il peut être utilisé à la place de . On peut facilement voir que si je vais l'appeler f(List(1, 2, 3)) et s'attendre à un AnyRef de retour, l'un des deux types ci-dessus serait de travailler.

Maintenant, quelle est la similitude d'une méthode et d'une fonction? Eh bien, si f est une fonction et m est une méthode locale de la portée, alors que les deux peuvent être appelés comme ceci:

val o1 = f(List(1, 2, 3))
val o2 = m(List(1, 2, 3))

Ces appels sont en fait différents, parce que le premier est juste un sucre syntaxique. Scala augmente à:

val o1 = f.apply(List(1, 2, 3))

Ce qui, bien sûr, est un appel de méthode sur l'objet" f. Les fonctions ont également d'autres sucres syntaxiques à son avantage: la fonction littéraux (deux d'entre eux, en fait) et (T1, T2) => R type de signatures. Par exemple:

val f = (l: List[Int]) => l mkString ""
val g: (AnyVal) => String = {
  case i: Int => "Int"
  case d: Double => "Double"
  case o => "Other"
}

Une autre similitude entre une méthode et une fonction, c'est que l'ancien peut être facilement convertie en celle-ci:

val f = m _

Scala étendra que, en supposant m type (List[Int])AnyRef (Scala 2.7):

val f = new AnyRef with Function1[List[Int], AnyRef] {
  def apply(x$1: List[Int]) = this.m(x$1)
}

Sur Scala 2.8, il utilise un AbstractFunction1 classe de réduire la taille des classes.

D'avis que l'on ne peut pas convertir dans l'autre sens -- à partir d'une fonction à une méthode.

Méthodes, cependant, ont un grand avantage (enfin, deux, ils peuvent être un peu plus rapide): ils peuvent recevoir des paramètres de type. Par exemple, f ci-dessus peuvent nécessairement spécifier le type d' List il reçoit (List[Int] dans l'exemple), m pouvez paramétrer:

def m[T](l: List[T]): String = l mkString ""

Je pense que cela couvre à peu près tout, mais je vais être heureux de compléter cela avec des réponses à toutes les questions qui peuvent rester.

70voto

Ben Lings Points 11395

Une grande différence pratique entre une méthode et une fonction est ce que return signifie. return ne renvoie jamais qu'une méthode. Par exemple:

 scala> val f = () => { return "test" }
<console>:4: error: return outside method definition
       val f = () => { return "test" }
                       ^
 

Le retour d'une fonction définie dans une méthode effectue un retour non local:

 scala> def f: String = {                 
     |    val g = () => { return "test" }
     | g()                               
     | "not this"
     | }
f: String

scala> f
res4: String = test
 

Considérant que le retour d'une méthode locale ne renvoie que de cette méthode.

 scala> def f2: String = {         
     | def g(): String = { return "test" }
     | g()
     | "is this"
     | }
f2: String

scala> f2
res5: String = is this
 

43voto

jamlhet Points 26

fonction Une fonction peut être appelée avec une liste d'arguments pour produire un résultat. Une fonction est une liste de paramètres, d'un corps et d'un type de résultat. Les fonctions membres d'une classe, d'un trait de caractère, ou un objet singleton sont appelées méthodes. Fonctions définies à l'intérieur d'autres fonctions sont appelées les fonctions locales. Fonctions avec le type de résultat de l'Unité sont appelés les procédures. Les fonctions anonymes dans le code source sont appelés des littéraux de fonction. Au moment de l'exécution, en fonction des littéraux sont instanciés dans des objets appelés les valeurs de la fonction.

La programmation Scala Deuxième Édition. Martin Odersky - Lex Cuillère - Bill Venners

32voto

anish Points 919

Disons que vous avez une Liste

scala> val x =List.range(10,20)
x: List[Int] = List(10, 11, 12, 13, 14, 15, 16, 17, 18, 19)

Définir une Méthode

scala> def m1(i:Int)=i+2
m1: (i: Int)Int

Définir une Fonction

scala> (i:Int)=>i+2
res0: Int => Int = <function1>

scala> x.map((x)=>x+2)
res2: List[Int] = List(12, 13, 14, 15, 16, 17, 18, 19, 20, 21)

Méthode D'Accepter L'Argument

scala> m1(2)
res3: Int = 4

La définition de Fonction avec val

scala> val p =(i:Int)=>i+2
p: Int => Int = <function1>

Argumnet de fonction est Facultative

 scala> p(2)
    res4: Int = 4

scala> p
res5: Int => Int = <function1>

Argument à la Méthode est Mandoatory

scala> m1
<console>:9: error: missing arguments for method m1;
follow this method with `_' if you want to treat it as a partially applied function

Vérifiez les points suivants Tutoriel qui explique en passant les différences avec les autres exemples comme autre exemple de diff avec la Méthode Vs Fonction à l'Aide de la fonction en tant que Variables, la création de la fonction que la fonction renvoyée

13voto

eptx Points 410

Les fonctions ne prennent pas en charge les paramètres par défaut. Les méthodes font. La conversion d'une méthode en une fonction perd les paramètres par défaut. (Scala 2.8.1)

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