What is the meaning of <% in Scala?
The context I see it in is an abstract class declaration that I am trying to extend. This is the important part of the class:
abstract class Index[Res <% Result[Res]] {
def results (term: String) : List[Res] ...
This is the header of the Result trait:
trait Result[T] extends Any {
I was able to successfully create a class that extends Result. For simplification here, I will use this header:
class Sample extends Result[Int] {
I want results in my class (extending Index) to return type List[Sample]. I tried a few different definitions, but I always get a similar error:
No implicit view available from [type] to Result[type]
where type is whatever type I used to extend Index, i.e. :
class SampleIndex extends Index[Sample]
I think my problem comes from my misunderstanding of the <% in the definition of the abstract class. Any idea how to fix this?
It's a view bound. check more info here
Related
I have an abstract class Model from which I create case classes:
abstract class Model
case class User(.) extends Model
an abstract class Table taking such a Model as type parameter, used in one of its default concrete methods:
abstract class Table[M <: Model] {
def parser = SomeExternalBuilder[M]
}
The meaning is rather simple: "Give every instance of Table a default parser based on its own class".
The problem is that SomeExternalBuilder will only accept a case class as argument ("case class expected: M"), so it does not compile.
Can I make Table take only case classes as type parameter?
I have seen a few answers providing a missing copy method (ref1, ref2), so I tried this:
trait Model[T] {
def copy: T
}
abstract class Table[M <: Model[M]]
but now case class User extends Model[User] and must overwrite copy too, every function creating a Model takes a type parameter, and honestly the code quickly starts being atrocious, all that for that single line in Table.
Is there no better way than copying that def parser line in every child's body?
Edit: N.B. The real function is def parser: anorm.Macro.namedParser[M] from the "anorm" library for Play.
Edit: Source of the type check by this macro: https://github.com/playframework/anorm/blob/0a1b19055ba3e3749044ad8a54a6b2326235f7c8/core/src/main/scala/anorm/Macro.scala#L117
The problem is that SomeExternalBuilder will only accept a case class as argument ("case class expected: M"), so it does not compile.
I don't think you can ever get such a message from Scala compiler itself, which means that SomeExternalBuilder.apply is a macro. It requires a specific case class in order to know its fields, so that it doesn't matter if you could limit M to be a case class (which you can't): it still wouldn't accept a type parameter.
What you can do is create a macro annotation, so that when you write e.g.
#HasModel
class SomeTable extends Table[SomeModel] {
...
}
the val parser = namedParser[SomeModel] is generated automatically.
Alternately, write #HasModel[SomeModel] class SomeTable { ... } and generate extends Table[SomeModel] as well.
It wouldn't be hard (as macros go), but you still need to annotate each class extending Table.
Not fool proof solution but worth a try
case classes extend Product and Serialisable. Constraint Product with Serialisable will help you get some type safety. M can be any class which extends Product with Serialisable. But Product is extended by case class mostly
abstract class Table[M <: (Product with Serializable)] {
def parser = SomeExternalBuilder[M]
}
I have in my project objects that represent IDs.
Let's say it is ChairId, TableId, LampId. I want them all to inherit from GenericId. And I want to be able to call def f(x: GenericId) = x.id
I want them to hold only single id: String so I would like to make them extend AnyVal.
Also I would like for each type to provide function generate which would generate my specific ID i.e. I would like to type something like ChairId.generate()
I have typed this:
sealed abstract class GenericId(val id: String)
final case class ChairId(override val id: String) extends GenericId(id)
final case class TableId(override val id: String) extends GenericId(id
And I though if GenericId would inherit from AnyVal that would work but so far no luck ;/ I also tried making GenericId a trait and make case classes extend AnyVal with GenericId but also won't compile :/
Another thing with TableId.generate() I can provide companion object just with function generate and that basically solve my problem but I wondered if there is possibility to solve that without defining companion object? (i.e. through implicits somehow)
// edit
regarding comment to provide code which doesn't compile(and I would like to):
sealed abstract class AbstractId(val id: String) extends AnyVal
final case class CatId(override val id: String) extends AbstractId(id)
final case class DogId(override val id: String) extends AbstractId(id)
Value classes cannot work this way for a couple of reasons.
First, from the documentation, value classes cannot be extended by any other class, so AbstractId cannot extend AnyVal. (Limitation #7)
scala> abstract class AbstractId(val id: String) extends AnyVal
<console>:10: error: `abstract' modifier cannot be used with value classes
abstract class AbstractId(val id: String) extends AnyVal
^
Second, even if you make AbstractId a trait, and define the other ids like this:
final case class DogId(val id: String) extends AnyVal with AbstractId
.. the usage of the value class wouldn't fit your case, because the class itself would still get allocated. See the allocation summary:
A value class is actually instantiated when:
a value class is treated as another type.
a value class is assigned to an array.
doing runtime type tests, such as pattern matching.
Some quotes from the value classes SIP that are likely to clarify your doubts:
Value classes...
...must have only a primary constructor with exactly one public, val
parameter whose type is not a value class.
... cannot be extended by another class.
As per 1. it can not be abstract; per 2. your encoding doesn't work.
There is another caveat:
A value class can only extend universal traits and cannot be extended
itself. A universal trait is a trait that extends Any, only has defs
as members, and does no initialization. Universal traits allow basic
inheritance of methods for value classes, but they incur the overhead
of allocation.
With all that in mind, based on your last snippet, this might work:
sealed trait AbstractId extends Any { def id: String }
final case class CatId(id: String) extends AnyVal with AbstractId
final case class DogId(id: String) extends AnyVal with AbstractId
But keep in mind the allocation only occurs if you want to use CatId and DogId as an AbstractId. For better understanding I recommend reading the SIP.
I ran into an interesting scenario in Scala. It seems then I have a base trait that defines other traits, the implementation cannot find the base trait not matter what.
I created this base trait simple for convenience that I don't need to redefined these traits on every implementation. Do anyone know why this doesn't work?
object Base {
trait Create
trait Delete
}
trait BaseTrait {
trait Create extends Base.Create
trait Delete extends Base.Delete
}
object Implementation extends BaseTrait
object Something {
class SomeClass extends Implementation.Create //The trait is not defined.
}
Update:
The question has been cleared up a bit so that its more precise. The solution as #BrianHsu pointed out is that trait cannot be inherited.
This block of code is fine:
object Base {
trait Event
trait Command
}
The following block will run into to trouble:
trait BaseTrait {
trait Event extends Event
trait Command extends Command
}
But Scala compiler says it very clearly.
test.scala:7: error: illegal cyclic reference involving trait Event
trait Event extends Event
^
test.scala:8: error: illegal cyclic reference involving trait Command
trait Command extends Command
Of course you cannot do this, just like you could not do the following in Java:
class HelloWorld extends HelloWorld
You have to specify that what you extend is actually Base.Event / Base.Command, so it will only work if you write it as:
trait BaseTrait {
trait Event extends Base.Event
trait Command extends Base.Command
}
Another problem in your code it the last Something object, it does not make sense at all:
object Something {
Implementation.Event
Implementation.Commannd
}
So compiler give you a clear error message:
test.scala:14: error: value Event is not a member of object Implementation
Implementation.Event
^
test.scala:15: error: value Commannd is not a member of object Implementation
Implementation.Commannd
It's quite obvious, an trait in Scala is much like interface in Java, you should not use it as it is a field.
I have a trait that's implemented by a large number of classes, and I'd like to use the names of the classes that implement this trait at runtime, but with as much code centralized as possible.
Specifically, in my code, I'm using tokens to represent classes to be initialized at runtime. The tokens carry configuration, and the actual class is instantiated as needed via the token, combined with run-time information. For linking with resources outside of my app, I want to be able to access the name of the class for which a token is defined. See the example:
trait Token[Cls] {
val className = ???
// Example generic method depending on final class name
def printClassName = println(className)
}
case class ClassA(t: ClassAToken, runtimeContext: String) {
// a bunch of other code
}
object ClassA {
case class ClassAToken(configParam: String) extends Token[ClassA]
}
So, I'm trying to implement className. Ideally, I can pull this information once at compile time. How can I do this, while keeping boilerplate code out of ClassA? Although, if I can drop the type parameter and get the name of the class implementing the Token trait at runtime, that's great too.
Due to Type Erasure Cls is not available on runtime anymore. To get the informations at runtime, you need to use a TypeTag (in your case a ClassTag).
Your code could look like this:
import scala.reflect._
trait Token[Cls] {
def className(implicit ct: ClassTag[Cls]) = ct.runtimeClass.getName
// Example generic method depending on final class name
def printClassName(implicit ct: ClassTag[Cls]) = println(className)
}
case class ClassA(t: ClassAToken, runtimeContext: String) {
// a bunch of other code
}
object ClassA {
case class ClassAToken(configParam: String) extends Token[ClassA]
}
or if it is possible for you to let Token be an class, you could use the ClassTag context bounds:
import scala.reflect._
class Token[Cls: ClassTag] {
def className = classTag[Cls].runtimeClass.getName
// Example generic method depending on final class name
def printClassName = println(className)
}
case class ClassA(t: ClassAToken, runtimeContext: String) {
// a bunch of other code
}
object ClassA {
case class ClassAToken(configParam: String) extends Token[ClassA]
}
For more informations on TypeTags/ClassTags see Scala: What is a TypeTag and how do I use it?
I would like to automatically weave the definition of a new function say introduced by an extending trait Ext into an abstract class A:
class Base {
abstract class A
class B extends A
case class C extends A
}
trait Ext extends Base {
trait A extends super.A {
def say = "hello"
}
}
object Test extends Base with Ext {
val b = new B
b.say
}
However, I obtain the following error:
<console>:12: error: value say is not a member of Test.B
b.say
Any way of doing it?
It seems you are trying to use virtual classes, which is a feature not available in Scala.
Once A and B are defined they can't be redefined (like method overriding).
abstract class A
class B extends A
On the other hand, given your example, your objective could be achieved by a simple mixin. Here it is with few rewrites:
class Base {
abstract class A
class B extends A
case class C extends A
}
trait Ext extends Base {
trait CanSay extends A {
def say = "hello"
}
}
object Test extends Base with Ext {
val b = new B with CanSay
def apply = b.say
}
Test.apply
No sure it will really help, but at least will help you understand what is going on.
Okay, as I said in a comment, it's not entirely clear what you're trying to do here, so I can't really try to suggest ways to do it. However, the approach you're using at the moment will not work.
Consider the class Hierarchy in this situation. At the base, we have A, which is then subclassed with B (in Base) and with Ext.A. These are not related save by their shared supertype, so you'll never find a say method on an instance of B.
The confusion possibly arises through the use of the word abstract. An abstract modifier on a class (even an inner class) does not make it an abstract member of the parent class, but denotes that it itself may have abstract members. There are ways of giving a class an abstract class member - through type parameters or type members. Unfortunately, you cannot derive from these AFAIK.