2016-11-13 2 views
2

Ich versuche, über die Konstruktoren einer bestimmten Klasse mit Reflektion zu iterieren. Das Problem ist, dass ich etwas zu jedem Element machen muss und dann nur diejenigen zurückgeben muss, die mit einem Prädikat übereinstimmen. der folgende Code wirft AusnahmeScala flatMap über getConstructors-Methode (Reflexion)

classOf[String].getConstructors.flatMap(x=> doSomething(x); if(predicate(x)) Some(x) else None) 

Die Ausnahme:

argument expression's type is not compatible with formal parameter type; 
found : java.lang.reflect.Constructor[_] => Iterable[java.lang.reflect.Constructor[?0(in value $anonfun)]] forSome { type ?0(in value $anonfun) } 
required: java.lang.reflect.Constructor[_] => scala.collection.GenTraversableOnce[?B] 

Ich bin nicht sicher, ob dies mit für das Verständnis getan werden kann, weil ich etwas für jedes Element tun müssen, rufen Sie (nicht nur für die diejenigen, die das Prädikat) gilt:

for{ 
    x <- c.getConsturctors 
    //doSomething(x) ?? 
    if predicate(x) 
}yield{ 
    //doSomething(x) - only for the ones that holds the predicate 
    x 
} 

Aufruf c.getMethods funktioniert so etwas hat es ich vermute, mit dem Rückgabetyp (Array [Methoden] vs Array [Constructor [_]]) zu tun ... ?

Antwort:

flatMap - Alexey Romanov

für das Verständnis beantworten (mit Hilfe von Pamu):

for{ 
    x <- c.getConsturctors 
    _ = doSomething(x) 
    if predicate(x) 
}yield x 
+0

Benötigen Sie weitere Informationen über 'doSomething' und' Prädikat' um zu sagen, was genau falsch ist – pamu

+0

Es ist nicht wirklich wichtig, sagen DoSomething druckt x und Prädikat gibt nur zurück –

Antwort

1

Aufgrund Einzelheiten Typinferenz Implementierung endet Scala oben mit Iterable[java.lang.reflect.Constructor[A]] forSome { type A } wo Sie Iterable[java.lang.reflect.Constructor[A] forSome { type A }] (oder kürzer, Iterable[java.lang.reflect.Constructor[_]]) wollen. Anmerkungen versehen die Art funktionieren sollte:

c.getConstructors.flatMap { x => 
    doSomething(x) 
    (if (predicate(x)) Some(x) else None): Option[Constructor[_]] 
} 

aber ich muss zugeben, ich nicht sehen, warum das Problem entsteht.

+0

ya Ich denke, es hat etwas mit implicits zu tun .. immer noch interessant zu wissen, ob jemand weiß warum ... –

1

Verwenden collect statt flatMap und dann Some Rückkehr None

classOf[String].getConstructors.toList 
    .collect { case elem if predicate(elem) => doSomething(elem) } 

Mit flatMap

classOf[String].getConstructors.toList.flatMap { elem => 
    doSomething(elem); 
    if (predicate(elem)) { 
    List(elem) 
    } else List() 
} 

Verwendung für Verständnis

for { 
elem <- classOf[String].getConstructors.toList 
_ = doSomething(elem) 
val result = if (predicate(elem) List(elem) else List() 
} yield result 
+0

es funktioniert (aber das sollte innerhalb der case-Klausel sein So wird bei jeder Iteration unabhängig vom Ergebnis des Prädikats etwas aufgerufen. Jedenfalls suche ich nach einer Möglichkeit, das Problem mit FlatMap oder zum Verständnis zu lösen. –

+0

In Bezug auf die Flatmap- Ich will nicht Liste aber Option. Das for ist nützlich, aber ich würde das ändern zu: ... if (Prädikat (elem))} yield elem –

+0

"Ich will nicht Liste, aber Option" Option wird sowieso von der implizit in eine Liste konvertiert, um die erwartete zu erfüllen Art. –

Verwandte Themen