The Scala API lists something called Abstract Value Members under some classes and traits. What are these things and how do they differ from what the API lists as Concrete Values Members?
An abstract value has a name and a type but no value. This value has to be provided by a concrete val definition in a subclass. In contrast, concrete value members do have a name, type and value defined. It is as simple as that. Scala' abstraction mechanisms are more general than Java's.
I think it is covered in the link provided by #I.K. http://www.artima.com/pins1ed/abstract-members.html
Abstract Value Members are simple abstract members, i.e. members that don't have a value. Note that they are NOT necessarily vals but defs are included as well.
Related
According to Adaic, an interface in Ada is defined as
a "tagged type with no components and no concrete operations". It can be used for multiple inheritance.
In contrast, an abstract type is a tagged type intended for use as an ancestor of other types, but which is not allowed to have objects of its own.
Is the essential difference between both just the multiple inheritance feature of the interface? Can the types otherwise be used interchangeably?
An interface cannot have any components, and all operations for one must be abstract. An abstract tagged type may have components and may have non-abstract operations.
A concrete type may extend multiple interfaces, but may only extend a single tagged type.
"IMHO, Interfaces are worthless."
Randy Brukardt, ARG member and ARM editor
Does below construct makes any sense? Are any benefits of using it?
final case class Id(uuid: UUID) extends AnyVal
As I understand above construct, Id doesn't have to be instantiated in some scenarios described here. But I have some doubts because I didn't find any example with AnyRef as a parameter.
Yes, this example makes sense. Extending AnyVal is useful when you want specific semantics for a type, but don't want to pay the additional allocation cost that come along with it. For example, say you have a typeclass instance for outputting string representation of values, like Show[A], and you want to give specific semantics to UUID, but there already exists an instance of Show[UUID] in scope which you can't control, this is when wrapping a type and introducing an implicit typeclass for it can be useful.
Do note that AnyVal may end up allocating instances of the wrapper class in specific cases as mentioned in this documentation:
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.
In Java, Object is the base class, which is extended by all other classes. What is the equivalent base class in Scala?
Not so fast! ;)
The question seems somewhat ill-posed, because primitive types do not extend from Object in Java. Therefore, Java simply isn't like Scala. The base class of all reference types (what corresponds to classes that subclass Object in Java) is actually AnyRef, not Any.
Indeed, Scala Tour page about unified types states:
AnyRef represents reference types. All non-value types are defined as reference types. Every user-defined type in Scala is a subtype of AnyRef. If Scala is used in the context of a Java runtime environment, AnyRef corresponds to java.lang.Object.
The base class of all types (Any) and the base class of all reference types (AnyRef) are two separate concepts.
I got the answer. It is of type Any.
http://joelabrahamsson.com/learning-scala-part-eight-scalas-type-hierarchy-and-object-equality/
I'm reading through the Swift documentation about type methods and type properties, and I cannot for the life of me figure out why it says this particular thing (in bold):
Within the body of a type method, the implicit self property refers to
the type itself, rather than an instance of that type. For
structures and enumerations, this means that you can use self to
disambiguate between type properties and type method parameters, just
as you do for instance properties and instance method parameters.
More generally, any unqualified method and property names that you use
within the body of a type method will refer to other type-level
methods and properties. A type method can call another type method
with the other method’s name, without needing to prefix it with the
type name. Similarly, type methods on structures and enumerations
can access type properties by using the type property’s name without a
type name prefix.
So, why is this pointing out structures and enumerations being able to do these things when, as far as I know, you can do these things with any kind of type methods/parameters (i.e. classes as well)? It makes me think I'm missing something.
The page in the documentation I'm looking at is here: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Methods.html
Apparently I wasn't the only one with this question. I'm not sure how I didn't see this post before: https://softwareengineering.stackexchange.com/questions/276962/static-properties-and-implicit-self-property-in-structures-and-enumerations-vs
When I compile:
object Test extends App {
implicit def pimp[V](xs: Seq[V]) = new {
def dummy(x: V) = x
}
}
I get:
$ fsc -d aoeu go.scala
go.scala:3: error: Parameter type in structural refinement may not refer to an abstract type defined outside that refinement
def dummy(x: V) = x
^
one error found
Why?
(Scala: "Parameter type in structural refinement may not refer to an abstract type defined outside that refinement" doesn't really answer this.)
It's disallowed by the spec. See 3.2.7 Compound Types.
Within a method declaration in a structural refinement, the type of any value parameter may only refer to type parameters or abstract types that are contained inside the refinement. That is, it must refer either to a type parameter of the method
itself, or to a type definition within the refinement. This restriction does not apply
to the function’s result type.
Before Bug 1906 was fixed, the compiler would have compiled this and you'd have gotten a method not found at runtime. This was fixed in revision 19442 and this is why you get this wonderful message.
The question is then, why is this not allowed?
Here is very detailed explanation from Gilles Dubochet from the scala mailing list back in 2007. It roughly boils down to the fact that structural types use reflection and the compiler does not know how to look up the method to call if it uses a type defined outside the refinement (the compiler does not know ahead of time how to fill the second parameter of getMethod in p.getClass.getMethod("pimp", Array(?))
But go look at the post, it will answer your question and some more.
Edit:
Hello list.
I try to define structural types with abstract datatype in function
parameter. ... Any reason?
I have heard about two questions concerning the structural typing
extension of Scala 2.6 lately, and I would like to answer them here.
Why did we change Scala's native values (“int”, etc.) boxing scheme
to Java's (“java.lang.Integer”).
Why is the restriction on parameters for structurally defined
methods (“Parameter type in structural refinement may not refer
to abstract type defined outside that same refinement”) required.
Before I can answer these two questions, I need to speak about the
implementation of structural types.
The JVM's type system is very basic (and corresponds to Java 1.4). That
means that many types that can be represented in Scala cannot be
represented in the VM. Path dependant types (“x.y.A”), singleton types
(“a.type”), compound types (“A with B”) or abstract types are all types
that cannot be represented in the JVM's type system.
To be able to compile to JVM bytecode, the Scala compilers changes the
Scala types of the program to their “erasure” (see section 3.6 of the
reference). Erased types can be represented in the VM's type system and
define a type discipline on the program that is equivalent to that of
the program typed with Scala types (saving some casts), although less
precise. As a side note, the fact that types are erased in the VM
explains why operations on the dynamic representation of types (pattern
matching on types) are very restricted with respect to Scala's type
system.
Until now all type constructs in Scala could be erased in some way.
This isn't true for structural types. The simple structural type “{ def
x: Int }” can't be erased to “Object” as the VM would not allow
accessing the “x” field. Using an interface “interface X { int x{}; }”
as the erased type won't work either because any instance bound by a
value of this type would have to implement that interface which cannot
be done in presence of separate compilation. Indeed (bear with me) any
class that contains a member of the same name than a member defined in
a structural type anywhere would have to implement the corresponding
interface. Unfortunately this class may be defined even before the
structural type is known to exist.
Instead, any reference to a structurally defined member is implemented
as a reflective call, completely bypassing the VM's type system. For
example def f(p: { def x(q: Int): Int }) = p.x(4) will be rewritten
to something like:
def f(p: Object) = p.getClass.getMethod("x", Array(Int)).invoke(p, Array(4))
And now the answers.
“invoke” will use boxed (“java.lang.Integer”) values whenever the
invoked method uses native values (“int”). That means that the above
call must really look like “...invoke(p, Array(new
java.lang.Integer(4))).intValue”.
Integer values in a Scala program are already often boxed (to allow the
“Any” type) and it would be wasteful to unbox them from Scala's own
boxing scheme to rebox them immediately as java.lang.Integer.
Worst still, when a reflective call has the “Any” return type,
what should be done when a java.lang.Integer is returned? The called
method may either be returning an “int” (in which case it should be
unboxed and reboxed as a Scala box) or it may be returning a
java.lang.Integer that should be left untouched.
Instead we decided to change Scala's own boxing scheme to Java's. The
two previous problems then simply disappear. Some performance-related
optimisations we had with Scala's boxing scheme (pre-calculate the
boxed form of the most common numbers) were easy to use with Java
boxing too. In the end, using Java boxing was even a bit faster than
our own scheme.
“getMethod”'s second parameter is an array with the types of the
parameters of the (structurally defined) method to lookup — for
selecting which method to get when the name is overloaded. This is the
one place where exact, static types are needed in the process of
translating a structural member call. Usually, exploitable static types
for a method's parameter are provided with the structural type
definition. In the example above, the parameter type of “x” is known to
be “Int”, which allows looking it up.
Parameter types defined as abstract types where the abstract type is
defined inside the scope of the structural refinement are no problem
either:
def f(p: { def x[T](t: T): Int }) = p.xInt
In this example we know that any instance passed to “f” as “p” will
define “x[T](t: T)” which is necessarily erased to “x(t: Object)”. The
lookup is then correctly done on the erased type:
def f(p: Object) = p.getClass.getMethod("x", Array(Object)).invoke(p,
Array(new java.lang.Integer(4)))
But if an abstract type from outside the structural refinement's scope
is used to define a parameter of a structural method, everything breaks:
def f[T](p: { def x(t: T): Int }, t: T) = p.x(t)
When “f” is called, “T” can be instantiated to any type, for example:
f[Int]({ def x(t: Int) = t }, 4)
f[Any]({ def x(t: Any) = 5 }, 4)
The lookup for the first case would have to be “getMethod("x",
Array(int))” and for the second “getMethod("x", Array(Object))”, and
there is no way to know which one to generate in the body of
“f”: “p.x(t)”.
To allow defining a unique “getMethod” call inside “f”'s body for
any instantiation of “T” would require any object passed to “f” as the
“p” parameter to have the type of “t” erased to “Any”. This would be a
transformation where the type of a class' members depend on how
instances of this class are used in the program. And this is something
we definitely don't want to do (and can't be done with separate
compilation).
Alternatively, if Scala supported run-time types one could use them to
solve this problem. Maybe one day ...
But for now, using abstract types for structural method's parameter
types is simply forbidden.
Sincerely,
Gilles.
Discovered the problem shortly after posting this: I have to define a named class instead of using an anonymous class. (Still would love to hear a better explanation of the reasoning though.)
object Test extends App {
case class G[V](xs: Seq[V]) {
def dummy(x: V) = x
}
implicit def pimp[V](xs: Seq[V]) = G(xs)
}
works.