The Scala compiler compiles direct to Java byte code (or .NET CIL). Some of the features of Scala could be re-done in Java straightforwardly (e.g. simple for comprehensions, classes, translating anonymous/inner functionc etc). What are the features that cannot be translated that way?
That is presumably mostly of academic interest. More usefully, perhaps, what are the key features or idioms of Scala that YOU use that cannot be easily represented in Java?
Are there any the other way about? Things that can be done straightforwardly in Java that have no straightforward equivalent in Scala? Idioms in Java that don't translate?
This question, in my opinion, misses the point about by asking us to compare JVM languages by looking at their generated bytecode.
Scala compiles to Java-equivalent bytecode. That is, the bytecode could have been generated by code written in Java. Indeed you can even get scalac to output an intermediate form which looks a lot like Java.
All features like traits (via static forwarders), non-local returns (via exceptions), lazy values (via references) etc are all expressible by a Java program, although possibly in a most-ugly manner!
But what makes scala scala and not Java is what scalac can do for you, before the bytecode is generated. What scalac has going for it, as a statically typed language, is the ability to check a program for correctness, including type correctness (according to its type system) at compile time.
The major difference then between Java and scala (as of course Java is also statically typed), therefore, is scala's type system, which is capable of expressing programmatic relations which java-the-language's type system cannot.For example:
class Foo[M[_], A](m : M[A])
trait Bar[+A]
These concept, that M is a type parameter which itself has type parameters or that Bar is covariant, just do not exist in Java-land.
Traits are one thing that does not have an equivalent. Traits are Interfaces with code in them. You can copy the code to all classes that have a trait mixed in, but that is not the same thing.
Also I believe scala type system is more complete. While it will eventually map to the JVM types (actually suffer erasure). You can express some things in the Scala type system that may not be possible in Java (like variances).
I think, there is no equivalent for dynamically mix in some Traits. In Scala you can add at the time you're creating new objects some Traits, which are mixed in.
For example, we create one dog which is hungry and thirsty and one dog which is just hungry.
val hungryThirstyDog = new Dog with Hungry with Thirsty
val onlyHungryDog = new Dog with Hungry
I don't know an equivalent way to do this in Java. In Java, the inheritance is statically defined.
Implicit conversions don't have a straightforward equivalent in Java.
One feature of scala that I have found a good use for is type reification through Manifests. Since the JVM strips out all type information from generics, scala allows you to conserve this information in variables. This is something that Java reflection AFAIK can't handle, since there are no arguments to types in the bytecode.
The case I needed them was to pattern match on a type of List. This is, I had a VertexBuffer object which stored data on the GPU, that could be constructed from a List of floats or integers. The Manifest code looked approximately like this:
class VertexBuffer[T](data:List[T])(implicit m:Manifest[T]) {
m.toString.match {
case "float" => ...
case "int" => ...
}
}
This link links to a blog post with more information.
There are plenty of SO pages with more information too, like this one.
Three words: higher kinded types.
Your topic is not clear wehther you mean Java the JVM or Java the language. Given that Scala runs on the JVM, the q makes no sense, as we all know Scala runs on the JVM.
Scala has a "native" support for XML. You can build the XML, find elements, match directly in the Scala code.
Examples: http://programming-scala.labs.oreilly.com/ch10.html
Related
We can create a generic class in Java like this
public class MyClass<T> {
...
but, now that i'm translating a (very large) C++ code to Java, i need a class to be different from other depending on its size, like in this c++ code:
template<size_t size> class MyClass {
...
so every class is a different type, there static members are different, and members like "compare" can only be used with objects with the same size.
Is possible to do this in Java? if not, how would you handle this?
Sure, but it sucks.
You can model "counting' with a chain of recursive types. Inc<Inc<Inc<Integer>> could represent 3.
It is exceedingly awkward.
Java generics are not C++ templates. Java generics have a common base implementation and auto write some wrapping code to cast parameterized arguments to/from a common base in a thin wrapper.
C++ templates generate distinct types.
The design of C++ templates was to replace code generation and/or hand-rolled C code low level data structures. The goal was a template class could match or even exceed hand-written C versions (exceed because you can invest more engineering effort into the single template, and reuse it in 100s of spots).
Templates like std::function more closely approach Java generics. While the implementation is dissimilar, here it converts a myriad of types to one interface, hiding the casting from the end user. In C++ this technique is called type erasure, where std function "erases" all information about the stored callable except what it exposes. C++ type erasure does not require a common base class; Java does.
But because Java generics only supports one kind of type erssure, and C++ templates support not only more kinds of type erasure but also entitely different metaprogramming techniques that are alien to Java, replacing templates with Java generics is going to consistently run into problems. Only when the C++ use case happens to perfectly line up with the weaker Java generics does it work right.
(Note that, while weaker, Java generics make type erasure far easier, because they write a bunch of the casting code for you, and type check it. Weaker doesn't mean worse; it often means safer. But mechanically replacing a system with a weaker one often is doomed to failure.)
No, you can't use values as parameters instead of a generic type in Java. You should probably just take the size as a parameter in the constructor and implement safety checks taking the size into account.
In the "Kotlin for Java-Developers"-course by JetBrains (at Coursera) it is told, that Kotlin-code is compiled to byte-code directly. And that byte-code is then executed on the JVM.
But when I do:
var list = listOf<String>("A", "B", "C")
println(list::class) // => Prints "class java.util.Arrays$ArrayList"
Obviously the normal Java ArrayList is used underneath. So I confused ...
Is Kotlin just some "more modern" syntax thing, which uses Java underneath?
Practically some syntactic sugar, which is put on-top, so that one can write code in a nicier way. But underneath it's still the same old Java-thing.
Is Kotlin just some "more modern" syntax thing, which uses Java underneath?
No. You Kotlin source code >>is<< compiling to bytecodes.
But your code is using the listof Kotlin library function, and the implementation of that function is returning a value that is an instance of a Java class.
Why?
It was probably easier / quicker to implement it that way. (Based on the type of the list object, we can infer that listof is simply calling java.util.Arrays.asList(...).)
There is possibly no advantage in reimplementing it; e.g. no performance benefit.
There are possibly disadvantages; e.g. it is likely to cause problems for people who need their Kotlin code to be interoperable with Java which uses standard Java collection classes.
Since every class in java is a subclass of the Object, and variables in java are not objects themselves but instead are object references, why does java make type specification compulsory, when the Object type could be made implicit? The only time it seems necessary is when using the simple data types.
If a variable is of type Object, the compiler will not let you use the variable as any other type (unless you cast it).
This is called type safety.
For example:
Object str = "abc";
s.toUpppercase(); //Compiler error
Well. Java does it because.. this is how the language was defined.
this boils down to what was considered good practice when the language was designed (nearly 20 years ago), and also with complier ease of development.
Scala, a language which is closely related to Java (runs on the same JVM), does not require explicit type identifiers in most cases.
the downside is the scala compiler is much slower (for this among other reasons).
The answer is probably Java is an object oriented language used in large projects and created by reasonable company. Having such strong typing decrease amount of potential bugs, that you are able to remove on compilation level.
btw.
In the .NET product you have such thing as var x. But it can be used only locally in method body. But this is only a compiler sugar for developers. So Java is only a example of strong typed language.
Java is a strongly typed language. The types are needed to be able to compile code and validate types compatibility at compile time.
Weakly typed languages do not have types. For example when you say var x in JavaScript you just define variable. Then value of any type may be assigned there. This means that if for example your code has bug and you assign string to this variable and then try to divide this variable by 2 (y = x / 2) the script will just fail at runtime. Java will not allow you to compile such code.
There is the principle: the bug costs x during development, x*10 during QA and x*100 if it arrives to production. Compiler and strongly typed languages allow to decrease number of (stupid) bugs that arrive to QA and therefore make software development easier, faster and cheaper.
This question is inspired from Joel's "Making Wrong Code Look Wrong"
http://www.joelonsoftware.com/articles/Wrong.html
Sometimes you can use types to enforce semantics on objects beyond their interfaces. For example, the Java interface Serializable does not actually define methods, but the fact that an object implements Serializable says something about how it should be used.
Can we have UnsafeString and SafeString interfaces/subclasses in, say Java, that are used in much of the same way as Joel's Hungarian notation and Java's Serializable so that it doesn't just look bad--it doesn't compile?
Is this feasible in Java/C/C++ or are the type systems too weak or too dynamic?
Also, beyond input sanitization, what other security functions can be implemented in this manner?
The type system already enforces a huge number of such safety features. That is essentially what it's for.
For a very simple example, it prevents you from treating a float as an int. That's one aspect of safety -- it guarantees that the type you're working on are going to behave as expected. It guarantees that only string methods are called on a string. Assembly doesn't have that safeguard, for example.
It's also the job of the type system to ensure that you don't call private functions on a class. That's another safety feature.
Java's type system is too anemic to enforce a lot of interesting constraints effectively, but in many other languages (including C++), the type system can be used to enforce far more wide-ranging rules.
In C++, template metaprogramming gives you a lot of tools for prohibiting "bad" code. For example:
class myclass : boost::noncopyable {
...
};
enforces at compile-time that the class can not be copied. The following will produce compile errors:
myclass m;
myclass m2(m); // copy construction isn't allowed
myclass m3;
m3 = m; // assignment also not allowed
Likewise, we can ensure at compile-time that a template function only gets called on types which fulfill certain criteria (say, they must be random-access iterators, while bilinear ones aren't allowed, or they must be POD types, or they must not be any kind of integer type (char, short, int, long), but all other types should be legal.
A textbook example of template metaprogramming in C++ implements a library for computing physical units. It allows you to multiply a value of type "meter" with another value of the same type, and automatically determines that the result must be of type "square meter". Or divide a value of type "mile" with a value of type "hour" and get a unit of type "miles per hour".
Again, a safety feature that prevents you from getting your types mixed up and accidentally getting your units mixed up. You'll get a compile error if you compute a value and try to assign it to the wrong type. trying to divide, say, liters by meters^2 and assigning the result to a value of, say, kilograms, will result in a compile error.
Most of this requires some manual work to set up, certainly, but the language gives you the tools you need to basically build the type-checks you want. Some of this could be better supported directly in the language, but the more creative checks would have to be implemented manually in any case.
Yes you can do such thing. I don't know about Java, but in C++ it isn't customary and there is no support for this, so you have to do some manual work. It is customary in some other languages, Ada for example, which have the equivalent of a typedef which introduces a new type which can't be converted implicitly into the orignal one (this new type "inherits" some basic operations from the one it is created, so it stays usefull).
BTW, in general inheritance isn't a good way to introduce the new types, as even if there is no implicit conversion in one way, there is one in the other one.
You can do a certian amount of this out of the box in Ada. For example, you can make integer types that cannot implcitily interoperate with each other, and Ada enumerations are not compatible with any integer type. You can still convert between them, but you have to explicitly do it, which calls attention to what you are doing.
You could do the same with present-day C++, but you'd have to wrap all your integers and enums in classes, which is just way too much work for something that should be simple (or better yet, the default way of doing things).
I understand the next version of C++ is going to fix at least the enumeration issue.
In C++, I suppose you could use typedef to create a synonym for a primitive type. Your synonym could imply something about the content of that variable, replacing the function of the apps hungarian notation.
Intellisense will report the synonym you used during declaration, so if you don't like using actual hungarian, it does save you from scrolling about (or using Go To Definition).
I guess you are thinking of something along the lines of Perl's "tainting" analysis.
In Java, it should be possible to use custom annotations and an annotation processor to implement this. Not necessarily easy though.
You can't have a UnsafeString subclass of String in Java, since java.lang.String is final.
In general, you cannot provide any kind of security on the source level - if you want to protect against evil code, you must do that on the binary level (e.g. Java bytecode). That's why private/protected can't be used as a security mechanism in C++: it is possible to bypass that with pointer manipulations.
I've recently started learning Scala and was disappointed (but not surprised) that their generics are also implemented via type erasure.
My question is, is it possible for Scala to have reified generics, or would the JVM need to be changed in some way? If the JVM does need to be changed, what exactly would need to be changed?
No - it is not possible for Scala to run as Java-equivalent bytecode if that bytecode does not support reified generics.
When you ask "what is it that needs to be changed?", the answer is: the bytecode specification. Currently the bytecode does not allow for the parametrized type of a variable to be defined. It has been decided that as a modification to the bytecode to support reified generics would break backwards compatibility, that generics would have to be implemented via type erasure.
In order to get around this, Scala has used the power of its implicit mechanism to define a Manifest which can be imported in any scope to discover type information at runtime. Manifests are experimental and largely undocumented but they are coming as part of the library in 2.8. Here is another good resource on Scala reified generics / Manifests
Just to complement oxbow_lakes, there's a question on Stack Overflow about how to get around type erasure in Scala.
"implicit Manifest" is a Scala compiler trick and it does not make generics in Scala reified. The Scala compiler, when it sees a function with "implicit m: Manifest[A]" parameter and it knows the generic type of A at the call site, it will wrap the class of A and its generic type parameters into a Manifest and make it available inside the function. However, if it could not figure out the true type of A, then it has no way of creating a Manifest. In other words, Manifest has to be passed along the function calling chain if the inner function needs it.
scala> def typeName[A](a: A)(implicit m: reflect.Manifest[A]) = m.toString
typeName: [A](a: A)(implicit m: scala.reflect.Manifest[A])java.lang.String
scala> typeName(List(1))
res6: java.lang.String = scala.collection.immutable.List[int]
scala> def foo[A](a: A) = typeName(a)
<console>:5: error: could not find implicit value for parameter m:scala.reflect.Manifest[A].
def foo[A](a: A) = typeName(a)
^
scala> def foo[A](a: A)(implicit m: reflect.Manifest[A]) = typeName(a)
foo: [A](a: A)(implicit m: scala.reflect.Manifest[A])java.lang.String
scala> foo(Set("hello"))
res8: java.lang.String = scala.collection.immutable.Set[java.lang.String]
To complement oxbow_lakes answer: It is no possible and it seems it will never happen (at least soon).
The (refutable) reasons JVM will not support reified generics seems to be:
Lower performance.
It breaks backward compatibility. It can be solved duplicating and fixing a lot of libraries.
It can be implemented using manifests: The "solution" and the biggest impediment.
References:
Odersky comment in 2010: "I prefer a simpler VM architecture with type erasure"
In scala-internals list (Feb 2013) Grzegorz Kossakowski said:
You can easily benchmark it and see that performance impact is very
noticeable. Especially memory consumption increases a lot.
I believe the way to go is to have optional reification the way we
start to do in Scala with Manifests/TypeTags.
If you can and combine it with runtime specialization you can aim for
high performance and generic code. However, that's probably goal for
Scala 2.12 or 2.13.
Once scalac is a compiler, it has the potential of being able to embellish the generated code with whatever data structures are needed to implement reified generics.
What I mean is that scalac would have the ability to see...
// definition
class Klass[T] {
value : T
}
//calls
floats = Klass[float]
doubles = Klass[double]
... and "expand" to something like this:
// definition
class Klass_float {
value : float
}
class Klass_double {
value : double
}
// calls
floats = Klass_float
doubles = Klass_double
Edit
The point is: the compiler has the ability to create all necessary data structures which demonstrate to be necessary to provide additional type information at runtime. Once this type information is available, the Scala runtime would take advantage of it and could perform all type-aware operations we can imagine. It does not matter whether the JVM provides bytecode for reified generics or not. The work is not done by the JVM, but by the Scala library.
If you have already written a symbolic debugger (I did!), you know that you can basically 'dump' all information the compiler has at compile-time into the generated binary, adopting whatever data organization demonstrates to be more convenient for further processing. This is exactly the same idea: 'dump' all type information the Scala compiler has.
In a nutshell, I don't see why it could not be possible, does not matter whether the JVM provides native operations for reified generics or not. The JVM bytecode has nothing to do with reified generics. This sort of thing is a matter of language specification, compiler features and runtime library support.
Another edit
IBM X10 demonstrates the ability I'm talking of: it compiles X10 code onto Java code, leveraging reified generics onto Java platforms. As I mentioned before: it can be done (and IBM X10 did!) but this kind of feature involves language specification, compiler support (or compiler plugins) and enough support in runtime libraries. More info at: http://x10.sourceforge.net/documentation/papers/X10Workshop2012/slides/Takeuchi.pdf