Serializable and AnyVal

I am looking for the correct signature of a method that accepts the func function and the arg argument, copies them over the network to the remote computer and returns the result. Currently, the signature looks like this:

def invokeRemote[A,B](address: String, func: A => B, arg: A): B 

The problem is that the method throws a NotSerializable exception if the arguments are not Serializable or one of the primitive Java types.

I came up with the following solution to catch this error at compile time ...

 type Func = (A => B) with Serializable def invokeRemote[A <: Serializable, B <: Serializable](address: String, func: Func, arg: A): B 

... but now it is no longer possible to pass arguments like AnyVal , such as Int , Float or Double , which do not explicitly implement Serializable.

What should the method signature look like so that it accepts only Serializable objects or objects of type AnyVal as an argument?

+6
source share
3 answers

You can use context binding implicit with a custom attribute and provide implicit conversions for AnyVal and Serializable for this trait.

 trait Ser[M] implicit def toSer1[T <: AnyVal]: Ser[T] = new Ser[T] {} implicit def toSer2[T <: java.io.Serializable]: Ser[T] = new Ser[T] {} def f[T: Ser](a:T): T = a f(1) // res2: Int = 1 f("123") // res3: java.lang.String = 123 f(new Object) // could not find implicit value for evidence parameter of type Ser[java.lang.Object] 

The compiler will look for an implicit type-based parameter, and since some of them are provided for T <: AnyVal and T <: java.io.Serializable , it will compile in this case.

You can stick to implicit definitions in the companion object for Ser so that they are available where necessary.

Then your signature will be:

 def invokeRemote[A:Ser, B:Ser](address: String, func: A => B, arg: A): B 
+9
source

Using Serializable as an argument type does not work in practice, because you can have Serializable instances that are not actually serializable:

 class NotSerializable(val s: String) // ArrayList inherits Serializable val list = new java.util.ArrayList[NotSerializable]() list.add(new NotSerializable("test")) // will fail at run time serialize(list) 

In addition, Scala collection features do not inherit Serializable (implementations are executed).

 def f(s: Serializable) { println(s) } // will fail to compile, because interface List does not inherit Serializable f(List("a", "b")) // will print true because list implementation is Serializable println(List("a", "b").isInstanceOf[Serializable]) 

Being Serializable is a run-time property and cannot be enforced only on types. Using Serializable as an argument type will not save you from Serialization errors at runtime. Everything you achieve will make your functions more complex, as you already experience with AnyVal (and this is just the tip of the iceberg).

+1
source

This may sound offtopic and weird, but I would suggest that you go around not java files as code, but, say, javascript code (possibly in its coffescript form) and use Rhino on the run side.

There are deep reasons for this, for example, typed lambdas for internal and untyped for sharing, but there is no theory yet.

0
source

Source: https://habr.com/ru/post/888113/


All Articles