2012-04-21 22 views
17

Tengo curiosidad por las diferencias entre la inferencia tipo de Scala y C++ 11. ¿En qué situaciones tengo que especificar los tipos en un idioma pero no en el otro? Una diferencia parece ser el tipo de retorno de funciones que siempre debe especificarse en C++ 11, aunque decltype y la nueva sintaxis de función con un tipo de retorno posterior permiten especificar un tipo inferido.¿Cuáles son las diferencias entre la inferencia tipo de Scala y C++ 11?

Respuesta

10

C++ no puede deducir dichas funciones anónimas:

// 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 

mientras que Scala puede:

def somefunc(v: Vector[Int]) = v.map(x => x +1) 

* no estoy seguro de que he tratado correctamente con sintaxis de C++ Code, no insultar idioma , pero es realmente críptico. Si cometí un error, corrígeme, por favor

+3

Estás comparando una llamada a un método en un vector con una función. Un método Scala equivalente debería verse como 'map (v, x => x + 1)' (con un método apropiado de 'mapa'). En este caso, la inferencia de Scala falla también. Sin embargo, esto funcionará: 'map (v) (x => x + 1)'. – Debilski

+0

@Debilski también, si hablamos de comparación exacta: la versión de Scala crea una nueva colección (y acepta el vector por valor), mientras que la versión de C++ actualiza el vector en su lugar. –

+1

Pero el punto aquí son las diferencias en la inferencia de tipo, no cómo funcionan las colecciones. Creo que es perfectamente posible contrastar la inferencia de tipo, es solo su ejemplo el que da una impresión equivocada. – Debilski

9

En esencia, la inferencia en C++ es simplista en comparación con los adultos.

Lenguajes funcionales generalmente algo cerca de Hindley/Milner que está muy cerca de resolver un sistema de ecuaciones y permite tener incógnitas en ambos lados de la guía.

Por el contrario, C++ esperan a ser capaz de saber el tipo de cualquier interior expresión y de que deducir el tipo de la expresión externa. Es un estrictamente una forma de inferencia, lo que significa que:

auto x = foo(1, 2); 

funciona como se espera, siempre y cuando hay un foo aceptar enteros y devolviendo no nula. Sin embargo, como se demuestra por om-nom-nom:

foo(1, [](auto x) { ++x; }); 

no va a funcionar, porque no se puede ir hacia atrás y utilice el tipo de foo pretendida para deducir el tipo de la lambda.

La razón detrás de esto es que C++ usa sobrecargas de funciones, lo que significa que podrían existir varias definiciones de foo, y usted realmente necesita saber los tipos de argumentos para elegir la correcta. Dado que, en general, la expresión anterior sería indecidible, está prohibido incluso en casos limitados, se podría haber evitado el futuro mantenimiento infierno y la gente nunca sabe cuándo o no se puede utilizar.

+4

Con el fin de contrastar C++ 11 y Scala: Scala también sobrecarga el método (y tampoco usa Hindley-Milner). – Debilski

+0

@Debilski: Ah, interesante. Pensé que Scala estaba más cerca de Haskell. Supongo que eso es lo que obtengo de la lectura superficial. Gracias por llamarlo. –

+0

@MatthieuM. Scala tiene subtipado, lo que hace que su sistema de tipos sea más poderoso, pero en consecuencia hace que sus habilidades de inferencia sean más débiles. (Haskell no tiene subtipado, a menos que cuente las restricciones de superclase en las clases de tipos) –

Cuestiones relacionadas