2 votes

La défense implicite de Any to Function ajoute la méthode d'application aux classes.

Jetez un œil à ce qui suit et voyez si vous pouvez y trouver un sens :

Welcome to Scala version 2.8.1.final (Java HotSpot(TM) Client VM, Java 1.6.0_17).
Type in expressions to have them evaluated.
Type :help for more information.

scala> class A
defined class A

scala> val a = new A
a: A = A@1643e4b

scala> a.apply("foo")
<console>:8: error: value apply is not a member of A
       a.apply("foo")
         ^

Il semble tout à fait normal jusqu'ici. Mais ensuite nous ajoutons une conversion implicite.

scala> implicit def anyToFunc(any: Any) = { x: String => "bar" }
anyToFunc: (any: Any)(String) => java.lang.String

scala> a.apply("foo")
res1: java.lang.String = bar

Et soudain, A a un apply qui accepte un argument du même type que celui de la fonction que l'implicite retourne !

Inspectons-la un peu plus :

scala> class B { override def toString = "an instance of class B" }
defined class B

scala> implicit def anyToFunc(any: Any) = { x: String =>
     | println("any is " + any.toString)
     | println("x is " + x)
     | "bar" }
anyToFunc: (any: Any)(String) => java.lang.String

scala> val b = new B
b: B = an instance of class B

scala> b.apply("test")
any is an instance of class B
x is test
res8: java.lang.String = bar

S'agit-il d'une "fonction cachée" ? Si oui, à quoi sert-elle ?

5voto

sepp2k Points 157757

Vous appelez apply sur un objet de type A . A n'a pas de apply méthode. Toutefois, A est implicitement convertible en Function[String, String] qui a une apply méthode. Ainsi, la conversion implicite est appliquée et apply est appelé sur l'objet converti.

Il n'y a rien de magique ou de caché dans cette fonctionnalité. Si un objet ne possède pas la méthode que vous appelez, mais qu'il est implicitement convertible en une méthode qui la possède, il sera converti. C'est exactement à cela que servent les conversions implicites.

3voto

coubeatczech Points 2457

Toute fonction créée en scala est convertie en une classe avec la méthode apply. Alors le raccourci pour appeler apply est de l'omettre.

class A{
    val a = (x:String) => x * 2
}

compilez ceci et voyez, qu'il y a deux fichiers créés, A.class y A$$anonfun$1.class . Inspectez le fichier de classe avec javap et vous verrez ceci

Compiled from "Fun.scala"
public final class A$$anonfun$1 extends scala.runtime.AbstractFunction1 implements java.io.Serializable{
    public static final long serialVersionUID;
    public static {};
    public final java.lang.String apply(java.lang.String);
    public final java.lang.Object apply(java.lang.Object);
    public A$$anonfun$1(A);
}

La ligne importante est public final java.lang.String apply(java.lang.String); . Cela est appelé soit par a("string") o a.apply("string") .

Oui, vous pouvez convertir n'importe quoi en fonction avec implicit def mais ça n'a pas beaucoup de sens. Il est généralement utilisé dans différents cas : pimp my library

1voto

Submonoid Points 1817

Il ne s'agit pas tant d'une fonctionnalité cachée que du comportement attendu des définitions implicites et de la fonction apply méthode. D'un point de vue critique, la apply est une méthode spéciale qui est invoquée lorsque vous passez des arguments directement à un objet. Donc quand, dans votre exemple, vous faites ce qui suit :

b.apply("Test")

Cela équivaudrait à b("test") . Function définit les demandes afin que nous puissions faire des choses agréables comme :

val addOne = (b : Int) => b + 1
addOne(10)

Ainsi, lorsque vous essayez d'appeler apply sur une instance de B le compilateur vérifie d'abord si B a une méthode apply, puis cherche si une superclasse de B a une méthode apply, puis cherche un implicite vers quelque chose qui a une méthode apply . C'est le but des définitions implicites. Puisque Function1 a une méthode apply, la conversion implicite est appelée et la méthode apply de la fonction est également appelée.

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