I have a table column errorFixed of type TableColumn[Error, Boolean] inside a TableView[Error]. My Error class has a val fixed: Boolean which I try to put into this table column.
I tried
errorFixed.cellValueFactory = features =>
ReadOnlyBooleanWrapper(features.value.fixed)
but it fails with
type mismatch;
found : scalafx.beans.property.ReadOnlyBooleanWrapper
required: scalafx.beans.value.ObservableValue[Boolean,Boolean]
which I really don't understand as ObservableValue[Boolean,Boolean] is a supertype of ReadOnlyBooleanWrapper according to the documentation.
If I cast it myself using .asInstanceOf[ObservableValue[Boolean, Boolean]] it seems to work. What is going on here?
Gist with stripped down project to reproduce
Short answer is: instead of
errorFixed.cellValueFactory = features =>
ReadOnlyBooleanWrapper(features.value.fixed)
you should use
errorFixed.cellValueFactory = features =>
ObjectProperty[Boolean](features.value.fixed)
or ReadOnlyObjectWrapper[Boolean].
A brief version of long answer: there are certain "frictions" between Scala and Java when working with primitive Java types, like boolean or int. This inconvenience shows up in property binding in ScalaFX. Not everything is inherited in an intuitive way. In this case
ReadOnlyBooleanWrapper
is a subclass of
ObservableValue[scala.Boolean, java.lang.Boolean]
but scala.Boolean is not a subclass of java.lang.Boolean which internally, in ScalaFX this leads to complications. Interesting thing is that the casting .asInstanceOf[ObservableValue[scala.Boolean, scala.Boolean]] works, though type parameters do not match at compile time.
Thanks for positing a full code example (gist) this really helps in clarifying the question.
Related
I want to use sttp library with guice(with scalaguice wrapper) in my app. But seems it is not so easy to correctly bind things like SttpBackend[Try, Nothing]
SttpBackend.scala
Try[_] and Try[AnyRef] show some other errors, but still have no idea how it should be done correctly
the error I got:
kinds of the type arguments (scala.util.Try) do not conform to the expected kinds of the type parameters (type T).
[error] scala.util.Try's type parameters do not match type T's expected parameters:
[error] class Try has one type parameter, but type T has none
[error] bind[SttpBackend[Try, Nothing]].toProvider[SttpBackendProvider]
[error] ` ^
SttpBackendProvider looks like:
def get: SttpBackend[Try, Nothing] = TryHttpURLConnectionBackend(opts)
complete example in scastie
interesting that version scalaguice 4.1.0 show this error, but latest 4.2.2 shows error inside it with converting Nothing to JavaType
I believe you hit two different bugs in the Scala-Guice one of which is not fixed yet (and probably even not submitted yet).
To describe those issues I need a fast intro into how Guice and Scala-Guice work. Essentially what Guice do is have a mapping from type onto the factory method for an object of that type. To support some advanced features types are mapped onto some internal "keys" representation and then for each "key" Guice builds a way to construct a corresponding object. Also it is important that generics in Java are implemented using type erasure. That's why when you write something like:
bind(classOf[SttpBackend[Try, Nothing]]).toProvider(classOf[SttpBackendProvider])
in raw-Guice, the "key" actually becomes something like "com.softwaremill.sttp.SttpBackend". Luckily Guice developers have thought about this issue with generics and introduced TypeLiteral[T] so you can convey the information about generics.
Scala type system is more reach than in Java and it has some better reflection support from the compiler. Scala-Guice exploits it to map Scala-types on those more detailed keys automatically. Unfortunately it doesn't always work perfectly.
The first issue is the result of the facts that the type SttpBackend is defined as
trait SttpBackend[R[_], -S]
so it uses it expects its first parameter to be a type constructor; and that originally Scala-Guice used the scala.reflect.Manifest infrastructure. AFAIU such higher-kind types are not representable as Manifest and this is what the error in your question really says.
Luckily Scala has added a new scala.reflect.runtime.universe.TypeTag infrastructure to tackle this issue in a better and more consistent way and the Scala-Guice migrated to its usage. That's why with the newer version of Scala-Guice the compiler error goes away. Unfortunately there is another bug in the Scala-Guice that makes the code fail in runtime and it is a lack of handling of the Nothing Scala type. You see, the Nothing type is a kind of fake one on the JVM. It is one of the things where the Scala type system is more reach than the Java one. There is no direct mapping for Nothing in the JVM world. Luckily there is no way to create any value of the type Nothing. Unfortunately you still can create a classOf[Nothing]. The Scala-to-JVM compiler handles it by using an artificial scala.runtime.Nothing$. It is not a part of the public API, it is implementation details of specifically Scala over JVM. Anyway this means that the Nothing type needs additional handling when converting into the Guice TypeLiteral and there is none. There is for Any the cousin of Nothing but not for Nothing (see the usage of the anyType in TypeConversions.scala).
So there are really two workarounds:
Use raw Java-based syntax for Guice instead of the nice Scala-Guice one:
bind(new TypeLiteral[SttpBackend[Try, Nothing]]() {})
.toInstance(sttpBackend) // or to whatever
See online demo based on your example.
Patch the TypeConversions.scala in the Scala-Guice as in:
private[scalaguice] object TypeConversions {
private val mirror = runtimeMirror(getClass.getClassLoader)
private val anyType = typeOf[Any]
private val nothingType = typeOf[Nothing] // added
...
def scalaTypeToJavaType(scalaType: ScalaType): JavaType = {
scalaType.dealias match {
case `anyType` => classOf[java.lang.Object]
case `nothingType` => classOf[scala.runtime.Nothing$] //added
...
I tried it locally and it seems to fix your example. I didn't do any extensive tests so it might have broken something else.
As an overview, I am trying to dynamically create a constructor for a case class from a Cassandra Java Row using reflection to find the primary constructor for the case class, and then trying to extract the values from the Cassandra Row.
Specifically, I want to support an Option in a case class as being an optional field in the Row, such that
case class Person(name: String, age: Option[Int])
will successfully populate if the Row has a name and an age, or just the name (and fill in a None for age).
To this end, I followed this very helpful blog post that achieves a similar objective between Case Classes and Maps.
However, I seem to be stuck trying to consolidate the dynamic nature of reflectively extracting types from the Case Class and the compile-time nature of quasiquotes. As an example:
I have a type fieldType which could be a native type or an Option of a native type. If it is an Option, I want to pass returnType.typeArgs.head to my quasiquote construction, so that it can extract the parameterized type from the Row, and if it is not an Option, I will just pass returnType.
if (fieldType <:< typeOf[Option[_]])
q"r.getAs[${returnType.typeArgs.head}]($fieldName)"
else
q"r.as[$returnType]($fieldName)"
(assuming r is a Cassandra Row and as and getAs exist for this Row)
When I try to compile this, I get an error saying that it does not know how to deal with doing r.as[Option[String]]. This makes conceptual sense to me because there is no way the compiler would know which way the runtime comparison will resolve and so needs to check both cases.
So how might I go about making this type check? If I could maybe compare the types fieldType and typeOf[Option[_]] within the quasiquote, it might stop complaining, but I can't figure out how to compare types in a quasiquote, and I'm not sure it's even possible. If I could extract the parameterized type of the Option within the quasiquote, it might stop complaining, but I could not figure that out either.
Sorry, I am very new to Scala and this stuff is, at the moment, very confusing and esoteric to me. If you want to look more closely at what I am doing, I have a repo: https://github.com/thurstonsand/scala-cass/blob/master/src/main/scala/com/weather/scalacass/ScalaCass.scala
where the interesting part is ScalaCass.CaseClassRealizer, and I am testing it in CaseClassUnitTests.
I found help from #liff on the gitter scala/scala page.
Apparently, I was finding my fieldType incorrectly.
I was doing: val fieldType = tpe.decl(encodedName).typeSignature where I should have been doing val fieldType = field.infoIn(tpe). Will update once I know what this difference means.
The following snippet returns true as expected:
import scala.reflect.runtime.universe._
typeOf[Seq[Int]] <:< typeOf[Traversable[Int]]
This snippet does not however:
val s = Seq[Int](1,2,3)
val m = runtimeMirror(this.getClass.getClassLoader)
val t = m.reflect(s).symbol.typeSignature
t <:< typeOf[Seq[Int]]
I'm sure that I'm just missing something obvious, but I have been on the REPL for a couple of hours and haven't worked it out. Any suggestions would be much appreciated. Thanks in advance.
1) typeOf[...] preserves the exact Scala type from Java erasure, however, obj.getClass (and consequently m.reflect(obj), which uses getClass under the covers) does not. Consequently, the best runtime reflection can get from reflecting on s without extra compile-time efforts is Seq[_] (which will fail the subtyping test). If you need to remember the exact Scala type of something for runtime, use type tags (just like typeOf does) or macros (just like type tags do).
2) .symbol.typeSignature isn't going to work, because that's ClassInfoType (i.e. a type, which encapsulates a list of parents and members of a class type). Class info types work great for inspecting members (probably also for base classes and maybe for a few more things as well, but I'm not sure off the top of my head), but not so great for everything else. You'd want to go for something like .symbol.asType.toType, which would return a TypeRef (i.e. in our case scala.collection.immutable.:: - note the lack of any type arguments here!). Unfortunately that'd still not work out of the box because of erasure as described in #1.
You don't need reflection to ascertain that a given value conforms to a given statically known type. There are two ways (at least) to do so:
if (someValue.isInstanceOf[SomeType])
...
else
...
or
someValue match {
case st: SomeType => ...
case _ =>
}
Given a java class with two methods (taken from mockito):
OngoingStubbing<T> thenReturn(T value);
OngoingStubbing<T> thenReturn(T value, T... values);
If I invoke from scala with
....thenReturn("something")
I get an error:
Description Resource Path Location Type
ambiguous reference to overloaded definition, both method thenReturn in trait OngoingStubbing of type (x$1: java.lang.Object, x$2: <repeated...>[java.lang.Object])org.mockito.stubbing.OngoingStubbing[java.lang.Object] and method thenReturn in trait OngoingStubbing of type (x$1: java.lang.Object)org.mockito.stubbing.OngoingStubbing[java.lang.Object] match argument types (java.lang.String)
And I cannot figure out how to fix this.
This is a known Scala-Java interoperability problem, though it's unfortunately not in the FAQ. Here's the Scala ticket describing the problem. Essentially, both methods are applicable when you give a single argument, and the Scala compiler currently doesn't have any heuristic to decide which one is "more specific". Alexey Romanov's approach to always use the varargs version is a good workaround:
thenReturn("something", Nil: _*)
There is also a question running into a similar problem with JCommander. One of the answers there gives a clever workaround using structural types. This approach will use reflection behind the scenes, so you may or may not want to go that direction. For your use case, it would look something like:
type useSingleArgVersion = { def thenReturn(value: AnyRef): OngoingStubbing }
(...).asInstanceOf[useSingleArgVersion].thenReturn("something")
Finally, there is a similar question running into a similar problem with mokito. It doesn't really provide any workarounds, but it does describe the problem in a bit more detail, if you're interested in the reason this happens.
If calling the vararg version is acceptable,
thenReturn("something", Nil: _*)
Can't think of a way to call the method without varargs right now.
These answers are all to the wrong question. The difference is subtle, but this is not the same issue as the one in the linked ticket. That one does require unreasonable gymnastics to call the non-varargs method. For this one, the following is enough.
thenReturn[String]("something")
Or, if you didn't want to do that for some reason, you don't need the type alias and the cast. You can use a structural type ascription directly.
(this: { def thenReturn[T](s: T): OngoingStubbing[T] }).thenReturn("something")
The issue here is type inference at the intersection of overloading and polymorphism - one method is more specific, but scalac doesn't figure out which. The issue in SI-2991 is genuine ambiguity due to an interaction between overloading and tuple conversion - neither is more specific.
Assuming others will find this question when having the overloaded method value thenReturn with alternatives error, I want to share my solution as well.
Instead of
when(field.getValue(isA(classOf[Record]))).thenReturn(value)
I use
doReturn(value).when(field).getValue(isA(classOf[Record]))
which resolves the disambiguity in my case.
The workaround is quite easy:
OngoingStubbing<T> thenReturn(T value);
OngoingStubbing<T> thenReturn(T value1, T valu2, T... values);
There is no "varargs must be non empty" feature.
I tried Steve's solution and got a huge compiler error including:
scala.tools.nsc.symtab.Types$TypeError: type mismatch;
found : scala.reflect.Manifest[Nothing]
required: scala.reflect.ClassManifest[B]
Note: Nothing <: B, but trait ClassManifest is invariant in type T.
You may wish to investigate a wildcard type such as `_ <: B`. (SLS 3.2.10)
I was able to make it work with something like:
thenReturn("something", Seq.empty[Object]: _*)
I want to come out a way to define a new method in some existing class in scala.
For example, I think the asInstanceOf[T] method has too long a name, I want to replace it with as[T].
A straight forward approach can be:
class WrappedAny(val a: Any) {
def as[T] = a.asInstanceOf[T]
}
implicit def wrappingAny(a: Any): WrappedAny = new WrappedAny(a)
Is there a more natural way with less code?
Also, a strange thing happens when I try this:
scala> class A
defined class A
scala> implicit def toA(x: Any): A = x
toA: (x: Any)A
scala> toA(1)
And the console hang. It seems that toA(Any) should not pass the type checking phase, and it can't when it's not implicit. And putting all the code into a external source code can produce the same problem. How did this happen? Is it a bug of the compiler(version 2.8.0)?
There's nothing technically wrong with your approach to pimping Any, although I think it's generally ill-advised. Likewise, there's a reason asInstanceOf and isInstanceOf are so verbosely named; it's to discourage you from using them! There's almost certainly a better, statically type-safe way to do whatever you're trying to do.
Regarding the example which causes your console to hang: the declared type of toA is Any => A, yet you've defined its result as x, which has type Any, not A. How can this possibly compile? Well, remember that when an apparent type error occurs, the compiler looks around for any available implicit conversions to resolve the problem. In this case, it needs an implicit conversion Any => A... and finds one: toA! So the reason toA type checks is because the compiler is implicitly redefining it as:
implicit def toA(x: Any): A = toA(x)
... which of course results in infinite recursion when you try to use it.
In your second example you are passing Any to a function that must return A. However it never returns A but the same Any you passed in. The compiler then tries to apply the implicit conversion which in turn does not return an A but Any, and so on.
If you define toA as not being implicit you get:
scala> def toA(x: Any): A = x
<console>:6: error: type mismatch;
found : Any
required: A
def toA(x: Any): A = x
^
As it happens, this has been discussed on Scala lists before. The pimp my class pattern is indeed a bit verbose for what it does, and, perhaps, there might be a way to clean the syntax without introducing new keywords.
The bit about new keywords is that one of Scala goals is to make the language scalable through libraries, instead of turning the language into a giant quilt of ideas that passed someone's criteria for "useful enough to add to the language" and, at the same time, making other ideas impossible because they weren't deemed useful and/or common enough.
Anyway, nothing so far has come up, and I haven't heard that there is any work in progress towards that goal. You are welcome to join the community through its mailing lists and contribute to its development.