There is no any images today, except maybe one. I particularly have a little brainstorming and maybe somebody would be interested too. Let’s try to scarcely touch the Scala type inference on small practical example.
In the Scala code snippets below I will provide a three methods with a short explanation in terms of the Scala type inference.
The first one is pretty straightforward, we’re defining some trivial logic and eventually Scala compiler (and interpreter, of course) will infer our return method type as Int, thus, there is no need to declare it explicitly. Here we go:
//------------------------------------------------------------------------------------------- // 1. A simple one //------------------------------------------------------------------------------------------- def max2(x: Int, y: Int) = if (x > y) x else y
If we’ll define this method in the Scala interpreter and will make a call of the method by passing an Integer parameters, we’ll get something like this:
scala> def max2(x: Int, y: Int) = if (x > y) x else y max2: (x: Int, y: Int)Int scala> max2(23,145) res0: Int = 145
Pretty easy. Our return type is Int, as mentioned above. By going further, the second method is simply a side effect of the method call and return type of the method always would be a Unit (a void in Java):
//------------------------------------------------------------------------------------------- // 2. Side effect of the useless method call //------------------------------------------------------------------------------------------- def greet() = println("Hello, world!")
Declaring and running in the Scala interpreter:
scala> def greet() = println("Hello, world!") greet: ()Unit scala> greet() Hello, world!
Hence, this method is pretty useless for us, but it shows how Scala compiler infers return types.
And the last one is an interesting thing… A type annotation must follow every function parameter, preceded by a colon, because the Scala compiler (and interpreter) does not infer function parameter types. A one interesting example initially was mentioned by Andrey Breslav (and maybe by somebody else, I don’t know), that makes a surprising revelation about Scala type inference. To not digress from a context and to be abridged, here is the example that deserve to think about:
//------------------------------------------------------------------------------------------- // 3. Interesting //------------------------------------------------------------------------------------------- class InferTest { def foo_bar[T](x: T): T = x val b = foo_bar() }
Just stopping by and try to think at this point. As already mentioned, Scala does not infer a function parameter types. Therefore, we’re trying to make a call without a parameter declaration and the question is: is this code will compile and if yes, then what is the type of ‘b’ ? Is it will be a Unit type, since we’re making a call of the method without a parameter (probably a Unit type) ? What do you think?
Your mind would be hamble fast as you’ll see a result. I’ll try to make it step by step. Firstly, let’s define a function in the Scala interpreter and make a method call with a String type:
scala> def foo_bar[T](x: T): T = x foo_bar: [T](x: T)T scala> foo_bar("Wow cool!") res2: java.lang.String = Wow cool!
Secondly, let’s make the same, but by passing Integer type instead:
scala> foo_bar(9955) res3: Int = 9955
Surprisingly very simple. A tension on both cortex hemispheres will grow up dramatically, when we’ll try to make a compulsive method call without a passing through any parameters. Ready?:
scala> foo_bar() scala>
I was very astonished by seeing this result! It is even not a Unit type, it’s a type of nothing, a black hole. But, we can make a call.
Conclusion
As a corollary, you might see, that a confine of type safeness is slightly blurred for now and could even cause a sleep deprivation in some cases. Scala type safeness and complexity are still becoming to be a point of contention ever since. However, it does not mean, that you should expunge this wonderful language from your toolbox, instead you must to be aware of. I am wholeheartedly wish you not be trapped in such situations, but who knows…
Don’t know how are you, but me slightly suffering from a finger and mental fatigue at the end of this post. So, that’s enough for today!
The Scala interpreter with the “:type” command can help resolve this puzzle. Here’s what I get:
————————————–
scala> def f[T](x: T): T = x
f: [T](x: T)T
scala> :type f()
Unit
scala> :type ()
Unit
———————————
It turns out that () is the single instance of type Unit, and when you pass it to f, it’s also what you get back. The Scala interpreter doesn’t print out (), leading to the confusion.
It’s not only a confusion, it’s weird behavior from the design perspective. We may not only make a method call without passing any parameters to our previously declared method, but moreover Scala interpreter doesn’t provide any feedback and not throwing an exception in such case. Frankly, slightly misleading. Maybe this is a “feedback” from the Scala feature – each method is object and each operation is actually a method.
Thank you for your note and explanation! Good to know this.
“I was very astonished by seeing this result! It is even not a Unit type, it’s a type of nothing, a black hole. But, we can make a call.”
Really? Which version do you use? In every Scala version I tried, foo_bar() is Unit and not Nothing, as easily seen by assigning it to a value:
val foo = foo_bar()
foo: Unit = ()
@Steve you absolutely right. When we’re assigning a result from this method call to a value, it prints out a type of ‘()’ operation (a Unit type, as expressed by Kipton Barros above), but I guess not a type of our method. It’s still weird, that we can make a call of the method without passing through any parameters. I thought about this and I guess, that Scala interpreter in such case don’t actually calling our method, but instead assigning a type of the ‘()’ operation. Maybe, it would be right to throw an exception instead and don’t provide a confusion? => http://min.us/ll4KVS
I think what’s happening is that the scala interpreter is able to parse the ‘no param’ call because scala doesn’t require you to use parens on method calls. For example, instead of
foo_bar(“Wow cool!”)
you could have written
foo_bar “Wow cool!”
instead. So when you write
foo_bar()
the interpreter parses this as if you had written
foo_bar ()
which is equivalent to
foo_bar(())
where — as Kipton and Steve explained — () is the sole instance of type Unit, which in turn determines the return type.
@Christopher And this only adds to the confusion, more and more and more. This should be more clear, simple and non opaque. Some things in Scala much easier than ever, but some of them are very messy.
Nothing is ideal and we shouldn’t fight for the idealism. So, can live with that. Maybe in the next releases and after new investigations, such things would be more transparent. I love Scala, whatever.
PS: sorry, that I didn’t approve your comment as fast as possible. He just falls down into a spam somehow… Both of them…
Just occasionally found a simple explanation on this terms.
The Nothing type has no instances. It is occasionally useful for generic constructs. For example, the empty list Nil has type
List[Nothing], which is a subtype of List[T] for any T.The Nothing type is not at all the same as void in Java or C++. In Scala, void is represented by the Unit type, the type with the sole value ().
Also, Unit is not a supertype of any other type. However, the compiler still allows any value to be replaced by a (). Consider:
def printAny(x: Any) { println(x) }def printUnit(x: Unit) { println(x) }
printAny("Hello") // Prints Hello
printUnit("Hello")
// Replaces "Hello" with () and calls printUnit(()), which prints ()
With havin so much content do you ever run into any issues of plagorism or copyright infringement? My site has a lot of unique content I’ve either written myself or outsourced but it seems a lot of it is popping it up all over the web without my authorization. Do you know any ways to help stop content from being ripped off? I’d definitely appreciate it.
@property_man I don’t care about license. It should to be copyleft in any fashion. Humans’ knowledge and evolution are more important, than your own self-gratification. If you want to protect something – just keep it in private and don’t tell anybody.