I'm curious what the differences between the type inference of Scala and C++11 are. In which situations do I have to specify the types in one language but not in the other? One difference seems to be the return type of functions which always have to be specified in C++11, although decltype
and the new function syntax with a trailing return type allow to specify a inferred type.
The Scala compiler can infer the types of expressions automatically from contextual information. Therefore, we need not declare the types explicitly. This feature is commonly referred to as type inference. It helps reduce the verbosity of our code, making it more concise and readable.
Scala has a built-in type inference mechanism.
Scala compiler can automatically infer types of each variable declared. If the value of a variable is declared in double-quotes it will automatically be inferred as String. Also, the compiler can infer any value in a single quote is inferred as Char.
When we declare a variable in C, it is necessary that a type is explicitly associated to it (e.g., int or double ). This is a distinction to languages that feature a so-called type inference, where programmers are freed from the need of annotating types.
C++ cannot infer such anonymous functions:
// this wont work*
void somefunc(std::vector<int>& v)
{
std::for_each(v.begin(), v.end(), [](auto &x) { x++; });
}
// /\
// ------ I want this to be infered
whereas Scala can:
def somefunc(v: Vector[Int]) = v.map(x => x +1)
*not sure that I've dealt correctly with C++ code syntax, I don't insult language, but it's really cryptic. If I've made a mistake, correct me, please
In essence, C++ inference is simplistic compared to the grown ups.
Functional languages generally something close to Hindley/Milner which is pretty close to solving an equation systems and allow to have unknowns on both sides of the fence.
On the contrary, C++ expect to be able to know the type of any inner expression and from that deduce the type of the outer expression. It's a strictly one way inference, meaning that:
auto x = foo(1, 2);
works as expected as long as there is a foo
accepting integers and returning non-void. However, as demonstrated by om-nom-nom:
foo(1, [](auto x) { ++x; });
Will not work, because you cannot go backward and use the purported type of foo
to deduce the type of the lambda.
The reason behind is that C++ uses overloads of functions, meaning that several definitions of foo
could exist, and you actually need to know the types of the arguments to elect the right one. Since in general the above expression would be undecidable, it is forbidden even in limited cases it could have been allowed to avoid future maintenance hell and people never knowing when or not it can be used.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With