4

Quelqu'un peut-il réécrire ce code pour faire la même chose, mais sans aucun avertissement du compilateur s'il vous plaît: -Comment puis-je correspondre à une signature de fonction sans obtenir les avertissements du compilateur d'effacement de type à Scala

object TestTypeErasure { 

    def main(args:Array[String]) { 

    def myFunction(myObject:Any):Boolean = { 
     true 
    } 

    val myVariable: (Any => Boolean) = myFunction 

    myVariable match { 
     case function:(Any => Boolean) => println("Match") 
    } 

    } 
} 

Mille thankyous

Keith

Mettre à jour !!!!. Désolé de faire un vrai hachage de ça. Sa première question sur le SO

Juste pour les gourous savent que je l'ai essayé quelque chose le long des lignes de cela aussi en vain: - (ne peut pas compiler)

object TestTypeErasure { 

    def doTest(parameter: Any) = { 
     parameter match { 
      case function:Function1[_, _] => function("Whatever") 
     } 
    } 

    def main(args:Array[String]) { 
    } 

} 

J'obtiens l'erreur: -

TestTypeErasure.scala:6: error: type mismatch; 
    found : java.lang.String("Whatever") 
    required: _ 
    case function:Function1[_, _] => function("Whatever") 
               ^
one error found 

Merci encore

Keith

Répondre

0
+0

Salut J'avais pris un coup d'oeil. J'ai essayé la meilleure réponse. La prochaine difficulté est que je veux appeler la fonction. Si je change le code pour appeler réellement la fonction comme ci-dessous, j'obtiens une erreur de compilation.Est-ce que quelqu'un sait comment je peux contourner ce objet TestTypeErasure { def DoTest (paramètre: Any) = { match paramètre { cas de fonction: Fonction1 [_, _] => fonction ("Whatever") } } def principaux (args: Array [String]) {} } Merci encore Keith – Keith

3

Vous pouvez capturer les informations de type avec Manifest. (T, R sont invariantes ici pour garder les choses simples.)

import scala.reflect._ 
def matchFunction[T,R](f: Function1[T,R], t : T)(implicit mt : Manifest[T], mr : Manifest[R]) = { 
    val result = if ((mt.erasure, mr.erasure) == (classOf[Any], classOf[Boolean])) "any, boolean " + f(t) 
    else if((mt.erasure, mr.erasure) == (classOf[Int], classOf[Int])) "int, int " + f(t) 
    else "Unknown " + f(t) 
    println(result) 
} 

scala>  matchFunction((x : Int) => x + 1, 1) 
int, int 2 

scala>  matchFunction((x : Any) => true, 1 : Any) 
any, boolean true 

scala>  matchFunction((x : Boolean) => ! x, false) 
Unknown 

Pour Scala 2.8, on peut utiliser des bornes de contexte, en supprimant les deux paramètres implicites:

import scala.reflect._ 
def matchFunction[T: Manifest,R : Manifest](f: Function1[T,R], t : T) = { 
    val mt = implicitly[Manifest[T]] 
    val mr = implicitly[Manifest[T]] 
    val result = if ((mt.erasure, mr.erasure) == (classOf[Any], classOf[Boolean])) "any, boolean " + f(t) 
    else if((mt.erasure, mr.erasure) == (classOf[Int], classOf[Int])) "int, int " + f(t) 
    else "Unknown " + f(t) 
    println(result) 
} 
+0

noter simplement que vous avez besoin Scala 2.8 pour cela. – retronym

+0

@retronym Non, cela fonctionne en 2.7.7. Le manifeste devrait être disponible depuis 2.7.2. –

0

Il existe une variété d'approches qui pourraient travail, dont aucun n'est aussi simple. Une option consiste à utiliser des manifestes, mais vous devez définir votre propre variante de correspondance qui était manifeste. Vous pouvez en savoir plus sur les manifestes here. Si vous devez souvent faire ce genre de chose, ce serait la bonne façon de procéder, bien que cette fonctionnalité soit toujours considérée comme expérimentale.

Une autre option, si votre utilisation est relativement légère, consiste à envelopper la fonction dans une classe qui n'est pas générique. Par exemple,

object Example { 
    def hasString(a:Any) = (a!=null && a.toString.length>0) 

    case class AnyImpliesBoolean(f: (Any) => Boolean) { } 
    implicit def callAIB(aib: AnyImpliesBoolean) = aib.f 

    def callWrapped(a: Any) { 
    a match { 
     case aib: AnyImpliesBoolean => println(aib("Check")) 
     case _ => println("(Nothing)") 
    } 
    } 

    def tryMe() { 
    val has = AnyImpliesBoolean(hasString _) 
    callWrapped(has) 
    callWrapped("foo") 
    callWrapped((s:String)=>true) 
    } 
} 

scala> Example.tryMe 
true 
(Nothing) 
(Nothing) 

Si vous envelopper plusieurs fonctions différentes, mais pas trop grand nombre d'entre eux, vous pouvez créer une classe de base WrappedFunction et ont des choses comme AnyImpliesBoolean étendent WrappedFunction. Cependant, une autre option consiste à ne pas passer les fonctions autour, mais à utiliser à la place la réflexion pour faire passer les méthodes java.lang.Methods. Les méthodes connaissent leurs types. Même avec de jolis emballages Scala, ça serait encore un peu maladroit (et ce n'est pas très performant).

(sous la direction d'ajouter le lien manifeste que je manquais.)