I have defined a Result type like this:
sealed class BadResult {
data class Description(val description: String): BadResult()
data class Exception (val exception : Throwable): BadResult()
}
sealed class BadTree {
data class Leaf(val v: BadResult) : BadTree()
data class Fork(val l: BadTree, val r: BadTree) : BadTree()
}
sealed class Result<T> {
data class Good<T> (val good : T ) : Result<T>()
class Empty<T> : Result<T>()
data class Bad <T> (val badTree : BadTree ) : Result<T>()
}
fun <T> T.good() : Result<T> = Result.Good(this)
fun <T> empty() : Result<T> = Result.Empty()
fun <T> BadTree.bad() : Result<T> = Result.Bad<T>(this)
fun <T> String.bad() : Result<T> = BadTree.Leaf(BadResult.Description(this)).bad()
fun <T> Throwable.bad() : Result<T> = BadTree.Leaf(BadResult.Exception(this)).bad()
For this Result class I have defined the monadic bind:
infix fun <T, U> Result<T>.bind(uf: (T) -> Result<U>) : Result<U> {
return when(this) {
is Result.Good -> uf(this.good)
is Result.Empty -> empty()
is Result.Bad -> this.badTree.bad()
}
}
A very useful functional pattern is Applicative, if applied to Result this would allow me to invoke a function with arbritrary argument list if and only if all arguments are Good.
This is a technique that usually relies on partial application (aka currying) which AFAIK isn't supported out of the box in kotlin. I've seen some libraries try to do currying but it seems to me currying is not a commonly recognized idiom in kotlin.
What I ideally would like to write is something like this:
pure(::aFunctionThatTakes3Args) apply arg1 apply arg2 apply arg3
But I can't come up with how the signatures should look like.
I could make a lift function for each arity of the function but that quickly gets cumbersome.
lift(::aFunctionThatTakes3Args, arg1, arg2, arg3) // lift is overloaded for each arity
(This seems to be how funKTionale implements currying)
Any ideas welcome.
Related
Let's say I have the following Java class:
public class A {
public Result method1(Object o) {...}
public Result method2(Object o) {...}
...
public Result methodN(Object o) {...}
}
Then, in my Kotlin code:
fun myFunction(...) {
val a: A = ...
val parameter = ...
val result = a.method1(parameter) // what if i want methodX?
do more things with result
}
and I want to be able to choose which methodX will be called inside myFunction. in Java, I would pass A::method7 as an argument and call it. in Kotlin it doesn't compile. How should I solve it in Kotlin?
You can also pass the method reference in Kotlin (without needing the heavy hammer that is reflection):
fun myFunction(method: A.(Any) -> Result) {
val a: A = ...
val parameter = ...
val result = a.method(parameter)
do more things with result
}
myFunction(A::method1)
myFunction {/* do something in the context of A */}
This declares method as part of A, meaning you can call it with normal object.method() notation. It Just Works™ with the method reference syntax.
There's also another form that works with the same call syntax, but makes A more explicit:
fun myFunction(method: (A, Any) -> Result) { ... }
myFunction(A::method1)
myFunction {a, param -> /* do something with the object and parameter */}
You can actually do this exactly like you wanted to:
fun myFunction(kFunction: KFunction2<A, #ParameterName(name = "any") Any, Result>) {
val parameter = "string"
val result: Result = kFunction(A(), parameter)
//...
}
myFunction(A::method1)
myFunction(A::method2)
I'm porting a class from Java to Kotlin. This class declares hundreds of objects. Each object has a name property which is identical with the declared variable name of the object. Java reflection allows to use the declared name via reflection to set the object member name. Just saves one parameter in hundreds of constructors.
I try to do the same in Kotlin but can't figure out how to do the property setting. Here is some simplified test code:
import kotlin.reflect.full.companionObject
import kotlin.reflect.full.declaredMemberProperties
class MyTestObject() {
var name: String = "NotInitialized"
companion object {
val Anton = MyTestObject()
val Berta = MyTestObject()
val Caesar = MyTestObject()
}
}
fun main(args : Array<String>) {
println(MyTestObject.Anton.name) // name not yet initialized
// Initialize 'name' with the variable name of the object:
for (member in MyTestObject::class.companionObject!!.declaredMemberProperties) {
if (member.returnType.toString() == "myPackage.MyTestObject") {
println("$member: ${member.name}")
// Set 'name' property to 'member.name':
// ???
}
}
println(MyTestObject.Anton.name) // now with the initialized name
}
The ??? line is where I would like to get access to the name property of MyTestObject to set it to to member.name. I'm looking for a function similar to (member.toObject() as MyTestObject).name = member.name.
While kotlin-reflection strives to be type-safe, sometimes the type system and the inference logic are not enough to allow for the things like what you are trying to do in a type-safe way. So, you have to make unchecked casts, stating that your knowledge about the types is more than the compiler can infer.
In your case, it's enough to cast member so that you can pass the companion object instance into its .get(...) and use the result as a MyTestObject, replace the // ??? line with:
#Suppress("UNCHECKED_CAST")
(member as KProperty1<Any, MyTestObject>)
.get(MyTestObject::class.companionObject!!.objectInstance!!)
.name = member.name
If you can replace MyTestObject::class.companionObject!! with MyTestObject.Companion::class (i.e. your actual use case does not involve getting .companionObject from different classes), the unchecked cast is not needed, and you can replace the statement above with this:
(member.get(MyTestObject.Companion) as MyTestObject).name = member.name
As an alternative that does not require companion object reflection at all, you can do the same binding logic with the delegation. Implementing provideDelegate allows you to customize the logic of initializing the property, and that's where you can assign the names:
operator fun MyTestObject.provideDelegate(
thisRef: MyTestObject.Companion,
property: KProperty<*>
) = apply { name = property.name }
operator fun MyTestObject.getValue(
thisRef: MyTestObject.Companion,
property: KProperty<*>
) = this
Then declare your properties as
val Anton by MyTestObject()
val Berta by MyTestObject()
val Caesar by MyTestObject()
Here is the final test code based on hotkey's solution:
package myPackage
import kotlin.reflect.full.declaredMemberProperties
class MyTestObject() {
lateinit var name: String
companion object {
val Anton = MyTestObject()
val Berta = MyTestObject()
val Caesar = MyTestObject()
init {
for (member in MyTestObject.Companion::class.declaredMemberProperties) {
if (member.returnType.toString() == "myPackage.MyTestObject") {
(member.get(MyTestObject.Companion) as MyTestObject).name = member.name
}
}
}
}
}
fun main(args : Array<String>) {
println(MyTestObject.Anton.name)
println(MyTestObject.Caesar.name)
}
I want to print values of properties of my class.
fun print() {
val cl = this::class
cl.declaredMemberProperties.filter {it.visibility != KVisibility.PRIVATE}.forEach {
println("${it.name} = ${it.get(this)}")
}
}
When I try to build this code I get compiler error:
Error:(34, 40) Kotlin: Out-projected type 'KProperty1<out SomeClass, Any?>' prohibits the use of 'public abstract fun get(receiver: T): R defined in kotlin.reflect.KProperty1'
When I change this to class name SomeClass everything is fine
fun print() {
val cl = SomeClass::class
cl.declaredMemberProperties.filter {it.visibility != KVisibility.PRIVATE}.forEach {
println("${it.name} = ${it.get(this)}")
}
}
So the problem is that compiler changers type of this::class to KClass<out SomeClass> instead of using KClass<SomeClass>. Any idea why does it happen?
The reason for this difference is that, when you use the SomeClass::class reference, it is sure to be the class token representing SomeClass and not one of its possible derived classes, therefore it is KClass<SomeClass> without type projections.
But this::class written in a function of an open or abstract class or an extension function can return a class token of a derived class, therefore, to ensure type safety, the type is out-projected: KClass<out SomeClass> means that the actual type argument can be SomeClass or its subtype.
Example:
open class A {
fun f() {
println(this::class) // KClass<out A> because it can be KClass<B>
}
}
class B : A()
B().f()
Considering the following Scala snippet:
case class Foo(v1: String, v2: Int, v3: Any)
def inspect(p: Product) =
(0 until p.productArity).foreach(i => println(p.productElement(i)))
inspect(Foo("Moin", 77, null))
Does the invocation of inspect() here means that reflection is used (in whatever way)?
I'd like to somehow be able to access the fields of a case-class without having to explicitly refer to them, e.g. by foo.v1 and I'd favour a solution that does not require reflection since I expect that it entails some overhead.
No reflection will be used for the productElement. It's a compiler trick. Adding case before a class doesn't just create a companion object (with apply method and so on, see http://www.scala-lang.org/node/258), it also extends the class from the trait Product. The compiler creates implementations of the abstract methods productArity and productElement.
The output of scalac -print Foo.scala shows it:
... case class Foo extends java.lang.Object with ScalaObject with Product {
...
override def productArity(): Int = 3;
override def productElement(x$1: Int): java.lang.Object = {
<synthetic> val temp6: Int = x$1;
(temp6: Int) match {
case 0 => {
Foo.this.v1()
}
case 1 => {
scala.Int.box(Foo.this.v2())
}
case 2 => {
Foo.this.v3()
}
case _ => {
throw new java.lang.IndexOutOfBoundsException(scala.Int.box(x$1).toString())
}
}
};
...
}
If you want to access to the fields without reflection, you can use the method productElement from the trait Product
scala> case class Foo(v1: String, v2: Int, v3: Any)
defined class Foo
scala> val bar = Foo("Moin", 77, null)
bar: Foo = Foo(Moin,77,null)
scala> bar.productElement(0)
res4: Any = Moin
scala> bar.productElement(1)
res5: Any = 77
scala> bar.productElement(2)
res6: Any = null
In Scala, what's the best way to dynamically instantiate an object and invoke a method using reflection?
I would like to do Scala-equivalent of the following Java code:
Class class = Class.forName("Foo");
Object foo = class.newInstance();
Method method = class.getMethod("hello", null);
method.invoke(foo, null);
In the above code, both the class name and the method name are passed in dynamically. The above Java mechanism could probably be used for Foo and hello(), but the Scala types don't match one-to-one with that of Java. For example, a class may be declared implicitly for a singleton object. Also Scala method allows all sorts of symbols to be its name. Both are resolved by name mangling. See Interop Between Java and Scala.
Another issue seems to be the matching of parameters by resolving overloads and autoboxing, described in Reflection from Scala - Heaven and Hell.
There is an easier way to invoke method reflectively without resorting to calling Java reflection methods: use Structural Typing.
Just cast the object reference to a Structural Type which has the necessary method signature then call the method: no reflection necessary (of course, Scala is doing reflection underneath but we don't need to do it).
class Foo {
def hello(name: String): String = "Hello there, %s".format(name)
}
object FooMain {
def main(args: Array[String]) {
val foo = Class.forName("Foo").newInstance.asInstanceOf[{ def hello(name: String): String }]
println(foo.hello("Walter")) // prints "Hello there, Walter"
}
}
The answers by VonC and Walter Chang are quite good, so I'll just complement with one Scala 2.8 Experimental feature. In fact, I won't even bother to dress it up, I'll just copy the scaladoc.
object Invocation
extends AnyRef
A more convenient syntax for reflective
invocation. Example usage:
class Obj { private def foo(x: Int, y: String): Long = x + y.length }
You can call it reflectively one of
two ways:
import scala.reflect.Invocation._
(new Obj) o 'foo(5, "abc") // the 'o' method returns Any
val x: Long = (new Obj) oo 'foo(5, "abc") // the 'oo' method casts to expected type.
If you call the oo
method and do not give the type
inferencer enough help, it will most
likely infer Nothing, which will
result in a ClassCastException.
Author Paul Phillips
The instanciation part could use the Manifest: see this SO answer
experimental feature in Scala called manifests which are a way to get around a Java constraint regarding type erasure
class Test[T](implicit m : Manifest[T]) {
val testVal = m.erasure.newInstance().asInstanceOf[T]
}
With this version you still write
class Foo
val t = new Test[Foo]
However, if there's no no-arg constructor available you get a runtime exception instead of a static type error
scala> new Test[Set[String]]
java.lang.InstantiationException: scala.collection.immutable.Set
at java.lang.Class.newInstance0(Class.java:340)
So the true type safe solution would be using a Factory.
Note: as stated in this thread, Manifest is here to stay, but is for now "only use is to give access to the erasure of the type as a Class instance."
The only thing manifests give you now is the erasure of the static type of a parameter at the call site (contrary to getClass which give you the erasure of the dynamic type).
You can then get a method through reflection:
classOf[ClassName].getMethod("main", classOf[Array[String]])
and invoke it
scala> class A {
| def foo_=(foo: Boolean) = "bar"
| }
defined class A
scala>val a = new A
a: A = A#1f854bd
scala>a.getClass.getMethod(decode("foo_="),
classOf[Boolean]).invoke(a, java.lang.Boolean.TRUE)
res15: java.lang.Object = bar
In case you need to invoke a method of a Scala 2.10 object (not class) and you have the names of the method and object as Strings, you can do it like this:
package com.example.mytest
import scala.reflect.runtime.universe
class MyTest
object MyTest {
def target(i: Int) = println(i)
def invoker(objectName: String, methodName: String, arg: Any) = {
val runtimeMirror = universe.runtimeMirror(getClass.getClassLoader)
val moduleSymbol = runtimeMirror.moduleSymbol(
Class.forName(objectName))
val targetMethod = moduleSymbol.typeSignature
.members
.filter(x => x.isMethod && x.name.toString == methodName)
.head
.asMethod
runtimeMirror.reflect(runtimeMirror.reflectModule(moduleSymbol).instance)
.reflectMethod(targetMethod)(arg)
}
def main(args: Array[String]): Unit = {
invoker("com.example.mytest.MyTest$", "target", 5)
}
}
This prints 5 to standard output.
Further details in Scala Documentation.
Working up from #nedim's answer, here is a basis for a full answer,
main difference being here below we instantiate naive classes. This code does not handle the case of multiple constructors, and is by no means a full answer.
import scala.reflect.runtime.universe
case class Case(foo: Int) {
println("Case Case Instantiated")
}
class Class {
println("Class Instantiated")
}
object Inst {
def apply(className: String, arg: Any) = {
val runtimeMirror: universe.Mirror = universe.runtimeMirror(getClass.getClassLoader)
val classSymbol: universe.ClassSymbol = runtimeMirror.classSymbol(Class.forName(className))
val classMirror: universe.ClassMirror = runtimeMirror.reflectClass(classSymbol)
if (classSymbol.companion.toString() == "<none>") // TODO: use nicer method "hiding" in the api?
{
println(s"Info: $className has no companion object")
val constructors = classSymbol.typeSignature.members.filter(_.isConstructor).toList
if (constructors.length > 1) {
println(s"Info: $className has several constructors")
}
else {
val constructorMirror = classMirror.reflectConstructor(constructors.head.asMethod) // we can reuse it
constructorMirror()
}
}
else
{
val companionSymbol = classSymbol.companion
println(s"Info: $className has companion object $companionSymbol")
// TBD
}
}
}
object app extends App {
val c = Inst("Class", "")
val cc = Inst("Case", "")
}
Here is a build.sbt that would compile it:
lazy val reflection = (project in file("."))
.settings(
scalaVersion := "2.11.7",
libraryDependencies ++= Seq(
"org.scala-lang" % "scala-compiler" % scalaVersion.value % "provided",
"org.scala-lang" % "scala-library" % scalaVersion.value % "provided"
)
)