I can't seem to create a SortedSet that also mixes in SynchronizedSet. The crux of the problem is SortedSet requires an implicit Ordering object.
val orderByIdThenName = Ordering[(Int, String)].on[Foo](foo => foo.id -> foo.name)
new mutable.TreeSet[Foo]()(orderByIdThenName) // <- Works fine and is Ordered
new mutable.HashSet[Foo] with mutable.SynchronizedSet[Foo] // <- Mixin works
new mutable.TreeSet[Foo]()(orderByCount) with mutable.SynchronizedSet[Foo] // Fail!
The last line gives an error "Object creation impossible, since member Ordering[A] in scala.collection.SortedSetLike is undefined.
Any suggestions?
This looks to be a bug in IntelliJ. I was able to reproduce the issue and see the error in the editor, but there are no errors or warnings on compiling.
Because there's no definition of orderByCount given, I'm assuming it's something like:
val orderByCount = Ordering[Int].on[Foo](_.count)
new mutable.TreeSet[Foo]()(orderByCount) with mutable.SynchronizedSet[Foo]
UPDATE:
Came up with a way to eliminate the error in IntelliJ by overriding ordering:
new mutable.TreeSet[Foo]()(orderByCount) with mutable.SynchronizedSet[Foo] {
implicit override val ordering: Ordering[Foo] = orderByCount
}
Related
I can't comprehend why the compiler allows for the current code.
I use phantom types to protect access to methods. Only under specific "states" should methods be allowed to be called.
In most scenarios, this invariant is indeed verified by the compilation. Sometimes however, the compiler just ignores the constraint imposed by the phantom type.
This feels like a major bug. What am I not understanding?
I tried to simplify the problem as much as possible. My use case is more complex:
class Door[State <: DoorState] private {
def doorKey: Int = 1
def open[Phatom >: State <: Closed.type]: Door[Open.type] = new Door[Open.type]
def close[Phatom >: State <: Open.type]: Door[Closed.type] = new Door[Closed.type]
}
object Door {
def applyOpenDoor: Door[Open.type] = new Door[Open.type]
def applyClosedDoor: Door[Closed.type] = new Door[Closed.type]
}
sealed trait DoorState
case object Closed extends DoorState
case object Open extends DoorState
Then
val aClosedDoor = Door.applyClosedDoor
val res1 = aClosedDoor.close // does not compile. Good!
val res2 = aClosedDoor.open.close.close // does not compile. Good!
println(aClosedDoor.open.close.close) // does not compile. Good!
println(aClosedDoor.open.close.close.doorKey) // does not compile. Good!
aClosedDoor.open.close.close.doorKey == 1 // does not compile. Good!
println(aClosedDoor.open.close.close.doorKey == 1) // compiles! WTF?
As you can see above, the client can close a closed door. In my library, the corresponding behaviour is throwing a runtime exception. (I was confident the exception was well protected and impossible to reach)
I have only been able to replicate this problem for expressions returning boolean and when this is the argument to a function (in the example, println)
I am not looking for alternative solutions as much as I am looking for an explanation as to how this can happen? Don't you agree this is a considerable flaw? Or maybe I am missing something?
Scala version: 2.13.5
Edit
After a discussion on gitter, I opened bug request # https://github.com/scala/bug
The problem does not seem to occur in scala 3.
Seems it is an bug related to usage of nullary method
def doorKey: Int = 1
if instead it is defined as nilary method
def doorKey(): Int = 1
then it works as expected
println(aClosedDoor.open.close.close.doorKey() == 1) // compiler error
I have 2 variables declared as follows,
implicit val decodeURL: Decoder[URL] = Decoder.decodeString.emapTry(s => Try(new URL(s))) // #1
implicit val decodeCompleted = Decoder[List[URL]].prepare(_.downField("completed")) // #2
Both lines compile and run.
However, if I annotate #2 with type i.e. implicit val decodeCompleted: Decoder[List[URL]] = Decoder[List[URL]].prepare(_.downField("completed")). It compiles and #2 will throw NullPointerException (NPE) during runtime.
How could this happen? I don't know if this is Circe or just plain Scala issue. Why #2 is different from #1? Thanks
The issue is that you are supposed to use implicits with annotation always.
Now, when you use them when they are not annotated you get into some sort on undefined/invalid behavior zone. That is why with unannotated happens sth like this:
I want to use Decoder[List[URL]]
there is no (annotated) Decoder[List[URL]] implicit in the scope
let's derive it normally (no need for generic.auto._ because the definition for that is in a companion object)
once derived you call on it .prepare(_.downField("completed"))
the final result is of type Decoder[List[URL]], so that is inferred type of decodeCompleted
Now, what happens if you annotate?
I want to use Decoder[List[URL]]
there is decodeCompleted declared as something that fulfills that definition
let use decodeCompleted value
but decodeCompleted wasn't initialized! in fact we are initializing it right now!
as a result you end up with decodeCompleted = null
This is virtually equal to:
val decodeCompleted = decodeCompleted
except that the layer of indirection get's in the way of discovering the absurdity of this by compiler. (If you replaced val with def you would end up with an infinite recursion and stack overflow):
# implicit val s: String = implicitly[String]
s: String = null
# implicit def s: String = implicitly[String]
defined function s
# s
java.lang.StackOverflowError
ammonite.$sess.cmd1$.s(cmd1.sc:1)
ammonite.$sess.cmd1$.s(cmd1.sc:1)
ammonite.$sess.cmd1$.s(cmd1.sc:1)
ammonite.$sess.cmd1$.s(cmd1.sc:1)
Yup, its messed up by compiler. You did nothing wrong and in a perfect world it would work.
Scala community mitigates that by distincting:
auto derivation - when you need implicit somewhere and it is automatically derived without you defining a variable for it
semiauto derivation - when you derive into a value, and make that value implicit
In the later case, you usually have some utilities like:
import io.circe.generic.semiauto._
implicit val decodeCompleted: Decoder[List[URL]] = deriveDecoder[List[URL]]
It works because it takes DerivedDecoder[A] implicit and then it extracts Decoder[A] from it, so you never end up with implicit val a: A = implicitly[A] scenario.
Indeed the problem is that you introduce a recursive val, like #MateuszKubuszok explained.
The most straightforward—although slightly ugly—workaround is:
implicit val decodeCompleted: Decoder[List[URL]] = {
val decodeCompleted = null
Decoder[List[URL]].prepare(_.downField("completed"))
}
By shadowing decodeCompleted in the right-hand side, implicit search will no longer consider it as a candidate inside that code block, because it can no longer be referenced.
In Scala what is the correct way to implement something like this that produces the error "forward reference extends over definition of value b"?
object a {
def main(args: Array[String]) {
val b: Map[Int, () => Int] = Map(5 -> { () => b.size })
println(b(5)())
}
}
Making b lazy works but that doesn't seem like the correct solution.
EDIT: The other question (What does "Forward reference extends over definition of value" mean in Scala?) is about a bug in Scala itself that where this error is reported incorrectly (or that is what the accepted answer suggests). This question is about what to do when this error is reported correctly. Also I supplied sample code.
Making b lazy seems like overkill because it changes the run-time behavior, when this is a compile-time problem that I assume could be fixed with a different declaration...
As mentioned in the comments, making b a def works too, which seems closer to the solution since def works for recursive functions, but that seems to be reevaluating it at run-time every time it is accessed.
scala> var a = 5
scala> def b = a
scala> a = 2
scala> b
res0: Int = 2
scala> a = 1
scala> b
res1: Int = 1
(with lazy it can be changed before it is accessed but is stored after that)
Both of these seem like run-time solutions to a compile-time problem, I'm looking for something analogous to letrec in Scala.
When you define a non-lazy val, you cannot refer to that val inside its definition. For that you either have to use a def or a lazy val.
This example code is based on Atmosphere classes, but if someone could give me some insights into what the error means in general, I think I can figure out any Atmosphere-specific solution...
val bc = BroadcasterFactory.getDefault().lookup(_broadcasterId)
bc.broadcast(message)
After the first line, bc should contain a handle to an object whose class definition includes the method broadcast() -- in fact, it contains several overloaded variations. However, the compiler chokes on the second line of code with the following: "value broadcast is not a member of Nothing"
Any ideas/suggestions on what would be causing this?
Thanks.
EDIT: signature for [BroadcasterFactor].lookup :
abstract Broadcaster lookup(Object id)
Note: 1) that is the signature version that I've used in the example, 2) it is the java Inteface signature - whereas the getDefault() hands back an instantiated object that implements that interface.
Solution: force type cast on value:
val bc: Broadcaster = BroadcasterFactory.getDefault().lookup(_broadcasterId)
Nothing is the type name. It's the subtype of all other types. You can't call methods from Nothing itself, you have to specify exact type ((bc: ExactType).broadcast(message)). Nothing has no instances. Method, that returns Nothing will, actually, never return value. It will throw an exception eventually.
Type inference
Definition of lookup:
abstract public <T extends Broadcaster> T lookup(Object id);
in scala this definition looks this way:
def lookup[T <: Broadcaster](Object id): T
There is not specified type parameter in lookup method. In this case compiler will infer this type parameter as the most specific type - Nothing:
scala> def test[T](i: Int): T = ???
test: [T](i: Int)T
scala> lazy val x = test(1)
x: Nothing = <lazy>
scala> lazy val x = test[String](1)
x: String = <lazy>
You could specify type parameter like this:
val bc = BroadcasterFactory.getDefault().lookup[Broadcaster](_broadcasterId)
Draft implementation
In development process lookup can be "implemented" like this:
def lookup(...) = ???
??? returns Nothing.
You should specify either result type of lookup method like this: def lookup(...): <TypeHere> = ... or type of bc: val bc: <TypeHere> =.
I'm trying to port my application to Scala 2.10.0-M2. I'm seeing some nice improvements with better warnings from compiler. But I also got bunch of errors, all related to me mapping from Enumeration.values.
I'll give you a simple example. I'd like to have an enumeration and then pre-create bunch of objects and build a map that uses enumeration values as keys and then some matching objects as values. For example:
object Phrase extends Enumeration {
type Phrase = Value
val PHRASE1 = Value("My phrase 1")
val PHRASE2 = Value("My phrase 2")
}
class Entity(text:String)
object Test {
val myMapWithPhrases = Phrase.values.map(p => (p -> new Entity(p.toString))).toMap
}
Now this used to work just fine on Scala 2.8 and 2.9. But 2.10.0-M2 gives me following warning:
[ERROR] common/Test.scala:21: error: diverging implicit expansion for type scala.collection.generic.CanBuildFrom[common.Phrase.ValueSet,(common.Phrase.Value, common.Entity),That]
[INFO] starting with method newCanBuildFrom in object SortedSet
[INFO] val myMapWithPhrases = Phrase.values.map(p => (p -> new Entity(p.toString))).toMap
^
What's causing this and how do you fix it?
It's basically a type mismatch error. You can work around it by first converting is to a list:
scala> Phrase.values.toList.map(p => (p, new Entity(p.toString))).toMap
res15: scala.collection.immutable.Map[Phrase.Value,Entity] = Map(My phrase 1 -> Entity#d0e999, My phrase 2 -> Entity#1987acd)
For more information, see the answers to What's a “diverging implicit expansion” scalac message mean? and What is a diverging implicit expansion error?
As you can see from your error, the ValueSet that holds the enums became a SortedSet at some point. It wants to produce a SortedSet on map, but can't sort on your Entity.
Something like this works with case class Entity:
implicit object orderingOfEntity extends Ordering[Entity] {
def compare(e1: Entity, e2: Entity) = e1.text compare e2.text
}