In some method I would like to force parameters to be named. The reason being autogenerated code for which the order of parameters is unspecified (and will remain that way).
The closest I can get is
private val _forceNamed: Object = new Object()
def doSomething(forceNamed: Object = _forceNamed, arg1: String, arg2: String, ...): Unit = {
if (forceNamed != _forceNamed) {
throw Exception(something)
}
// actually do stuff
}
However this only fails at runtime, whereas something failing at compile time would be much nicer.
If you want to close the loophole of being able to pass in null, you can use a value class as a guard.
scala> :paste
// Entering paste mode (ctrl-D to finish)
class Foo {
import Foo._
def foo(x: Bar = bar, a: String, b: String) = println(a + b)
}
object Foo {
private[Foo] class Bar(val i: Int) extends AnyVal
private val bar = new Bar(42)
}
// Exiting paste mode, now interpreting.
defined class Foo
defined object Foo
scala> val f = new Foo
f: Foo = Foo#4a4f9c58
scala> f.foo(null, "", "")
<console>:13: error: type mismatch;
found : Null(null)
required: Foo.Bar
f.foo(null, "", "")
^
We have this in our code base for this purpose:
object `(Please use explicitly named arguments)`
def foo(
`(Please use explicitly named arguments)`:
`(Please use explicitly named arguments)`.type =
`(Please use explicitly named arguments)`,
namedArg1: Int,
namedArg2: String,
...
) = ...
Something like this maybe:
class Foo {
class Bar private[Foo]()
private val bar = new Bar
def foo(x: Bar= bar, a: String, b: String) = println(a + b)
}
What a great idea.
It looks like hygiene issues with default args prohibit singleton types.
$ scala
Welcome to Scala 2.12.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_111).
Type in expressions for evaluation. Or try :help.
scala> private val x = new Object ; def f(foo: x.type = x, i: Int) = i
<console>:11: error: private value x escapes its defining scope as part of type x.type
private val x = new Object ; def f(foo: x.type = x, i: Int) = i
^
scala> val x = new Object ; def f(foo: x.type = (x: x.type), i: Int) = i
x: Object = java.lang.Object#1e54cb33
f: (foo: x.type, i: Int)Int
scala> f(i = 42)
<console>:13: error: type mismatch;
found : Object
required: x.type
f(i = 42)
^
or no, this looks OK:
private[this] val x: Object = new java.lang.Object();
<stable> <accessor> def x: Object = $iw.this.x;
def f(foo: x.type = $iw.this.x, i: Int): Int = i;
<synthetic> def f$default$1: x.type = $iw.this.x
or is the problem the assignment to the default value?
but you can't do this:
scala> val x: x.type = new Object
<console>:36: error: recursive value x needs type
val x: x.type = new Object
^
I guess this works because you don't have to tell it that x is x.type:
scala> object x
defined object x
scala> def f(y: x.type = x, i: Int) = i
f: (y: x.type, i: Int)Int
scala> f(i = 42)
res2: Int = 42
That still allows explicitly providing x, which could be obfuscated.
I'm too scared to investigate why this fails:
scala> object x$$ ; def f(y: x$$.type = x$$, i: Int) = i
defined object x$$
f: (y: .type, i: Int)Int
scala> f(i = 42)
res0: Int = 42
scala> f(x$$, 42) // or x$$$
<console>:13: error: not found: value x$$
f(x$$, 42)
^
But that suggests that even though the object is public, access to it is somehow crippled by name mangling.
Welcome to Scala 2.12.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_102).
Type in expressions for evaluation. Or try :help.
scala> type `(Please use explicitly named arguments)` = Nothing
defined type alias $u0028Please$u0020use$u0020explicitly$u0020named$u0020arguments$u0029
scala> def foo(`(Please use explicitly named arguments)`: => `(Please use explicitly named arguments)` = ???, i: Int, j: Int) = i + j
foo: ((Please use explicitly named arguments): => (Please use explicitly named arguments), i: Int, j: Int)Int
scala> foo(null, 1, 4)
<console>:13: error: type mismatch;
found : Null(null)
required: (Please use explicitly named arguments)
(which expands to) Nothing
foo(null, 1, 4)
^
scala> foo(i = 1, j = 4)
res1: Int = 5
Related
I'm using a ConcurrentHashMap in Scala and I would like to use the computeIfAbsent() method but can't figure out the syntax for the second argument. Can someone show me what would be the proper syntax?
When running the following code
val data = new ConcurrentHashMap[String, LongAdder]
data.computeIfAbsent("bob", k: String => new LongAdder()).increment()
I'm getting the following error
Type mismatch, expected: Function[_ >: String, _ <: LongAdder], actual: (String) => Any
Thanking you in advance
Francis
The problem is that you're using java.util.concurrent.ConcurrentHashMap, which accepts java.util.function.Function as a parameter for computeIfAbsent() instead of scala.Function1 which you pass to it.
Since scala doesn't support lambda conversion for functional interfaces as Java does (at least not without the -Xexperimental flag), you can solve this by implementing a java.util.function.Function explicitly:
val data = new ConcurrentHashMap[String, LongAdder]
val adderSupplier = new java.util.function.Function[String, LongAdder]() {
override def apply(t: String): LongAdder = new LongAdder()
}
data.computeIfAbsent("bob", adderSupplier).increment()
Alternatively, if you need this more often, you may write a utility conversion function or even an implicit conversion:
object FunctionConverter {
implicit def scalaFunctionToJava[From, To](function: (From) => To): java.util.function.Function[From, To] = {
new java.util.function.Function[From, To] {
override def apply(input: From): To = function(input)
}
}
}
import FunctionConverter._
val data = new ConcurrentHashMap[String, LongAdder]()
data.computeIfAbsent("bob", (k: String) => new LongAdder()) // <- implicit conversion applied here
If you enable -Xexperimental flag you can use scala anonymous function notation for this:
scala> val data = new java.util.concurrent.ConcurrentHashMap[String, Int]
data: java.util.concurrent.ConcurrentHashMap[String,Int] = {}
scala> data.computeIfAbsent("bob", _.size)
res0: Int = 3
Note that you still can't pass regular scala Function
scala> val f: String => Int = _.size
f: String => Int = <function1>
scala> data.computeIfAbsent("bob", f)
<console>:13: error: type mismatch;
found : String => Int
required: java.util.function.Function[_ >: String, _ <: Int]
data.computeIfAbsent("bob", f)
^
But eta-expansion will work
scala> def a(s: String): Int = s.size
a: (s: String)Int
scala> data.computeIfAbsent("bob", a)
res3: Int = 3
So, basically, what I want to do is:
object WithoutWrap {
def f[T: ClassTag](x: String): T = {
println("Class of T is really… " ++ implicitly[ClassTag[T]].toString)
??? : T
}
def y: Int = f("abc")
def z: Int = f[Int]("abc")
}
In both cases I’d like the inferred T to be Int. Let’s run this:
scala> WithoutWrap.y
Class of T is really… Nothing
scala.NotImplementedError: an implementation is missing
scala> WithoutWrap.z
Class of T is really… Int
scala.NotImplementedError: an implementation is missing
Unfortunately it’s Nothing in the first case.
However, if we return the T wrapped in something,
object WithWrap {
trait Wrap[T]
def f[T: ClassTag](x: String): Wrap[T] = {
println("Class of T is really… " ++ implicitly[ClassTag[T]].toString)
??? : Wrap[T]
}
def y: Wrap[Int] = f("abc")
def z: Wrap[Int] = f[Int]("abc")
}
… the T is inferred correctly in both cases:
scala> WithWrap.y
Class of T is really… Int
scala.NotImplementedError: an implementation is missing
scala> WithWrap.z
Class of T is really… Int
scala.NotImplementedError: an implementation is missing
How to get Int in both cases without wrapping?
Depending on what you're trying to accomplish, overload resolution is sensitive to expected type:
scala> case class A(s: String) ; case class B(s: String)
defined class A
defined class B
scala> :pa
// Entering paste mode (ctrl-D to finish)
object X {
def f(s: String): A = A(s)
def f(s: String)(implicit d: DummyImplicit): B = B(s)
}
// Exiting paste mode, now interpreting.
defined object X
scala> val x: A = X f "hi"
x: A = A(hi)
scala> val y: B = X f "hi"
y: B = B(hi)
I would like to ask how to achieve the following in Scala. Consider
scala> case class C(i:Int)
defined class C
scala> val c = C(1)
c: C = C(1)
Given a field of interest, in this case
scala> val fname = "i"
fname: String = i
we would like to retrieve the original value and type of field i in c.
A first, naive, attempt included the following,
scala> val f = c.getClass.getDeclaredField(fname)
f: java.lang.reflect.Field = private final int C.i
scala> f.setAccessible(true)
scala> f.getType
res3: Class[_] = int
However,
scala> val a:Int = f.get(c)
<console>:11: error: type mismatch;
found : Object
required: Int
val a:Int = f.get(c)
^
Put another way, how to fetch the Int value for i in c (*)
scala> :type -v case class C(i:Int)
// Type signature
AnyRef
with Product
with Serializable {
val i: Int <----------------------- (*)
private[this] val i: Int
def <init>(i: Int): C
def copy(i: Int): C
...
and for not necessarily Int type, consider field j in D,
scala> case class C(i:Int)
defined class C
scala> case class D(j:C)
defined class D
scala> :type -v case class D(j:C)
// Type signature
AnyRef
with Product
with Serializable {
val j: C
private[this] val j: C
def <init>(j: C): D
def copy(j: C): D
...
Thanks very much...
In Summary
Given
scala> f.get(c)
res1: Object = 1
and
scala> f.getType
res3: Class[_] = int
how to get
val a = 1
where a is of type Int, and knowing the type only from f.getType.
The static type of f.get(c) is Object, because it can be any class and any field. However, at the runtime it will return an Integer (the Java wrapper class for Int). You can cast it by using
f.get(c).asInstanceOf[Int]
or
f.getInt(c)
if you know in advance that you are calling for an Int field. If you don't, you can pattern match:
f.get(c) match {
case i: Integer => ...
case l: java.lang.Long => ...
case s: String => ...
// etc.
}
// actually compiles to same code, but avoids the need to use boxed classes
(f.get(c): Any) match {
case i: Int => ...
case l: Long => ...
case s: String => ...
// etc.
}
Note that the taken branch depends on the actual value of the field, not on its type; e.g. for val f: Any = "" the case s: String branch will be taken.
Or you can use f.getType to get its type and make your logic depend on that.
Is it possible to get the type of a type field after creating an object ?
I would like to do something like this:
scala> class A { type T = String }
defined class A
scala> val a = new A
a: A = A#591171
scala> a.T
<console>:13: error: value T is not a member of A
a.T
^
The last
What do you want to do with the type? You can use a type projection in various ways with the class's type (without an instance):
scala> class A { type T = String }
defined class A
scala> val x: A#T = "test"
x: java.lang.String = test
scala> def f(b: A#T) = b
f: (a: java.lang.String)java.lang.String
Or if you enable -Ydependent-method-types, you can get the type member from the instance:
scala> val a = new A
a: A = A#6a3de2df
scala> val x: a.T = "test"
x: a.T = test
scala> def f(b: a.T) = b
f: (b: a.T)a.T
Scala's reflection API prior to 2.10 doesn't really model types in any clean way, so if you want to "get the type" in some other sense, you're probably out of luck.
One way is with reflection (since 2.10M4):
// with static types
scala> class A { type T = String }
defined class A
scala> import reflect.runtime.{universe => u}
import reflect.runtime.{universe=>u}
scala> val t = u.typeOf[A]
t: reflect.runtime.universe.Type = A
scala> val types = t.declarations.filter(_.isType)
types: Iterable[reflect.runtime.universe.Symbol] = SynchronizedOps(type T)
scala> types.toList.head.typeSignature
res9: reflect.runtime.universe.Type = String
// with instances
scala> val a = new A
a: A = A#68d7c870
scala> import reflect.runtime.{currentMirror => m}
import reflect.runtime.{currentMirror=>m}
scala> m.reflect(a).symbol.asType // same type as t
res20: reflect.runtime.universe.Type = A
After having discovered that currying multi parameter-groups method is possible, I am trying to get a partially applied function which requires implicit parameters.
It seams not possible to do so. If not could you explain me why ?
scala> def sum(a: Int)(implicit b: Int): Int = { a+b }
sum: (a: Int)(implicit b: Int)Int
scala> sum(3)(4)
res12: Int = 7
scala> val partFunc2 = sum _
<console>:8: error: could not find implicit value for parameter b: Int
val partFunc2 = sum _
^
I use a singleton object to create this partially applied function and I want to use it in a scope where the implicit int is defined.
That is because you don't have an implicit Int in scope. See:
scala> def foo(x: Int)(implicit y: Int) = x + y
foo: (x: Int)(implicit y: Int)Int
scala> foo _
<console>:9: error: could not find implicit value for parameter y: Int
foo _
^
scala> implicit val b = 2
b: Int = 2
scala> foo _
res1: Int => Int = <function1>
The implicit gets replaced with a real value by the compiler. If you curry the method the result is a function and functions can't have implicit parameters, so the compiler has to insert the value at the time you curry the method.
edit:
For your use case, why don't you try something like:
object Foo {
def partialSum(implicit x: Int) = sum(3)(x)
}
scala> object MySingleton {
| def sum(a: Int)(implicit b: Int): Int = { a+b }
|
|
| def caller(a: Int) = {
| implicit val b = 3; // This allows you to define the partial below
| def pf = sum _ // and call sum()() without repeating the arg list.
| pf.apply(a)
| }
| }
defined module MySingleton
scala> MySingleton.caller(10)
res10: Int = 13