2011-01-01 24 views
12

Desde que escuché sobre la inferencia de tipos (en Haskell), viví con la impresión de que Java es exactamente lo contrario, es decir, no tiene ninguna inferencia de tipo. Recientemente, tuve un momento increíble y me di cuenta de que Java emplea la inferencia de tipo en su implementación de genéricos.Tipo de inferencia en Java (à la C#)

Luego, leí dos artículos de Gilad Bracha (una de las personas detrás de la implementación de genéricos en Java, por lo que yo entiendo). El primer documento es un tutorial about generics (PDF), en el que dice explícitamente que el compilador inferirá el argumento de tipo real utilizado para reemplazar el parámetro de tipo de formato. Entonces, hay inferencia de tipo en Java, pero ¿por qué solo para los genéricos, por qué no algo como la palabra clave var de C#? Y esta es mi pregunta para ti.

¿Por qué Java no tiene más inferencias de tipo integradas en el compilador?

Voy a sugerir una respuesta, y esto está relacionado con el segundo documento que leí, Pluggable Type Systems (PDF). Parece, Gilad Bracha cree que la parte de inferencia no debe ser parte del compilador, pero una característica IDE o similar (sección 4, párrafo 6 en el documento mencionado anteriormente):

Un mejor enfoque de ingeniería es implementar la inferencia de tipo como una herramienta independiente , disponible en el IDE. Los programadores que encuentran que ingresar el tipo de anotaciones tediosas pueden invocar un inferencer bajo demanda.

¿Qué opinas?

+0

Es interesante utilizar la palabra clave ** var ** como ejemplo: cuando se usa con tipos anónimos de C#, proporciona un claro ejemplo de inferencia de tipo que sería imposible sin incluir en el compilador. –

+0

@Kirk - No veo cómo la inferencia de tipo para 'var' tendría que hornearse en el compilador. Muchos lenguajes dinámicos le permiten hacer algo como los tipos anónimos de C# (por ejemplo, JavaScript). El sistema de tipo conectable tendría acceso al código fuente, por lo que podría inferir algo así como un tipo anónimo ... (y verificar la estructura del mismo, porque no tiene un nombre) –

+1

@Tomas, Javascript no está tipeado estáticamente ni un lenguaje compilado por lo que su comparación está fuera de lugar. –

Respuesta

2

Bueno, creo que es la inferencia de tipos en Java para históricos razones sobre todo: como corresponde a un lenguaje con fuertes limitaciones heredadas, mejoras Java se hacen con precaución & de forma incremental (como muestra JCP, aunque algunos improvements de inferencia de tipo se administran a go through). Con los genéricos, el GJ aplicación de larga data se evaluó a fondo antes de su inclusión en Java 5.

Antes de la liberación de Java 5, no había ninguna inferencia de tipos en Java. (...) Cuando se introdujeron los genéricos (...) en Java 5, el lenguaje retuvo este requisito para variables, métodos y asignaciones. Pero la introducción de métodos polimórficos (parametrizados por tipo) dictaba que (i) el programador proporciona los argumentos de tipo de método en cada sitio de llamada de método polimórfico o (ii) el lenguaje admite la inferencia de argumentos de tipo de método. Para evitar crear una carga administrativa adicional para los programadores, los diseñadores de Java 5 eligieron realizar una inferencia de tipo para determinar los argumentos de tipo para las llamadas al método polimórfico. (source)

Pero eso no significa que exista una cultura fuerte para la inferencia de tipo dominante en Java. Según the spec:

Tenga en cuenta también que la inferencia de tipo no afecta a la solidez de ninguna manera. Si los tipos inferidos son absurdos, la invocación arrojará un error de tipo. El algoritmo de inferencia de tipo debe verse como una heurística, diseñada para funcionar bien en la práctica. Si no puede inferir el resultado deseado, se pueden usar parámetros de tipo explícitos en su lugar.

yo creo más la inferencia de tipos para Java sería una gran ayuda (Scala es ya un very interesting improvement en esa dirección). En mi humilde opinión, tipo de inferencia hace que el ciclo de retroalimentación con el verificador de tipos sea menos mecánico, mientras que es igual que el sonido, lo que le permite escribir menos tipos, pero haciendo que usted marque con la misma cantidad.Dado que un beneficio importante de los tipos es dirigir el proceso mental de búsqueda de programa ("letting you write within the space of well-typed programs, rather than in the space of ascii turds"), esta comodidad en la interacción con el verificador de tipos parece invaluable: tiene que tener un verificador de tipos que verifica que piensa en bien tipado términos y lo entrena para que lo haga, en lugar de hacer que lo tenga en cuenta en cada línea.

Ahora, la etapa en la que debe ocurrir la inferencia de tipo es otra cuestión. Creo que querer tener "inferencias" separadas de las preocupaciones de legado de las respuestas de tiempo de ejecución: evita requerir un algoritmo de inferencia de tipo que siempre sea compatible con versiones anteriores. Pero la clave se convierte entonces en lo que parecen sus bibliotecas estándar/principales: ¿la fuente que publica & intercambia con otros anotados o no?

Si bien es cierto que una fuente con anotaciones puede, valiosamente, comprobarse con un tipo cualquiera que sea la potencia de su motor de inferencia, aún así querría un tipo inferencer en el compilador, porque no es solo que no quiero a escribaList<CacheDecoratorFactory> cacheDecoratorFactories = new ArrayList<CacheDecoratorFactory>();, es que no deseo leer. Tampoco quiero tratar con eso cuando refactorice una fuente preexistente, para el caso. Yo necesito un tipo "ocultador" borrar anotaciones antes de interactuar con la fuente, pero si el motor del tipo de inferencia es no completa, el problema de la cuales anotaciones para borrar, y asegurar el borrado seguido del tipo de reconstrucción es biyectiva se vuelve espinoso (especialmente si su motor de inferencia no devuelve un principal type) ... Si tenemos que resolver un problema espinoso de todos modos, ¿por qué no hacerlo un algoritmo de inferencia de tipo bueno, y tan completo como sea posible? Mi corazonada es que pasado un cierto nivel de calidad (particularmente en la generalidad de los tipos devueltos), las preocupaciones heredadas comenzarían a desvanecerse.

+0

Me gusta mucho esta respuesta. Muy documentado también +1 –

1

Este es un tema interesante y muy interesante, más relacionado con la investigación que con la programación actual (es decir, actual).

Lo primero es lo primero. Acerca de var en Java, en realidad no hay razón para implementarlo, ya tienen la "tecnología". Los genéricos, sin embargo, están solo en el lado del compilador del sistema, esto significa que en su tiempo de ejecución, la VM solo está utilizando referencias a Object, y se emiten adecuadamente debido al código inyectado por el compilador (nuevamente en tiempo de compilación). En C#, sin embargo, los genéricos viven después del tiempo de compilación.

En segundo lugar, sobre ese papel (muy interesante) de Bracha, probablemente debería echarle un vistazo a nuestro proyecto StaDyn, un C# 'como el lenguaje de programación. El sistema de tipo es en realidad conectable, es decir, puede usarlo como en C# simple, o no usarlo en absoluto, y experimentar un lenguaje totalmente dinámico.

http://www.reflection.uniovi.es/stadyn/

+1

De hecho, sé que los genéricos se implementan utilizando borrado de tipos en Java (y creo que esto tiene que ver con la opinión de Gilad Bracha de que el sistema de tipos debe estar separado del tiempo de ejecución del lenguaje, también visto en este video: http: // bit.ly/eSVcQm, donde dice que prefiere borrado de tipo). Pero no entiendo por qué no habría ninguna razón para apoyar algo en vivo 'var'. Para mí, al menos, es más fácil leer y escribir cosas que no se ven como 'List cacheDecoratorFactories = new ArrayList ();' –

+0

Claro. Tal vez no estaba claro: ESTOY de acuerdo. – Baltasarq

+0

Inferencia de tipo variable La declaración var de ala C# no es un "tema de investigación" y realmente no hay duda de que es relevante para la programación real. Salva a los desarrolladores de declaraciones excesivamente detalladas que pueden saturar el código, una gran cantidad de tipeo adicional, y puede hacer que el código de refactorización sea más fácil cuando hay menos declaraciones explícitas de tipo que necesitan ser modificadas. Se podría implementar con bastante facilidad y no requeriría cambios de JVM. Realmente no entiendo por qué no ha encontrado su camino en el lenguaje por ahora. –

2

El tipo de inferencia está disponible en IntelliJ, posiblemente otros IDE también. Puede escribir una expresión (o usar una existente) y seleccionar "Introducir campo/Variable local/Constante", etc., y le dará algunas opciones de tipo inferidas y algunos nombres sugeridos. Si la expresión aparece más de una vez, le da la opción de reemplazar todas las instancias. p.ej. decir que tengo una cadena que quiero convertir en un parámetro

myMethod(); 

public void myMethod() { 
    "/tmp/20101112/data.file" 
} 

selecciono la parte de fecha y < ctrl> + < Alt> + P y sugiere un tipo int para agregar como un parámetro. Insertará esta fecha en todas las personas que llaman.

myMethod(20101112); 

public void myMethod(int date) { 
    "/tmp/"+date+"/data.file" 
} 

I coloque "new FileInputStream (" al principio e introduzca una variable local.< ctrl> + < Alt> + V

FileInputStream fileInputStream = new FileInputStream("/tmp/"+date+"/data.file"); 

Se destaca que este puede lanzar una excepción que puedo automático fijar un número de maneras. Selecciono < alt> + < enter> y agrego la excepción a la cláusula throws del método.

myMethod(20101112); 

public void myMethod(int date) throws FileNotFoundException { 
    FileInputStream fileInputStream = new FileInputStream("/tmp/"+date+"/data.file"); 

en mi humilde opinión, tiene mucho más sentido que el IDE haga el trabajo, ya que puede hacer mucho más interactiva que el compilador y se puede ver de forma explícita lo que se convierten en sus tipos.

+1

Me encantaría que IntelliJ pueda ocultar tipos con texto 'colapsado' que diga 'var'. Al hacer clic en 'var' se expandiría la declaración. Eso haría que el código se vea más como el código C# en ese sentido. –

2

Esto no es realmente una respuesta, pero en una nota lateral, es posible que desee examinar el lenguaje D. Se le permite escribir código como este:

int*[6]*[wstring][]*[string]*[] myVar; 
auto myVar2 = new typeof(myVar[0])[100]; // equivalent to: new int*[6]*[wstring][]*[string]*[]*[string]*[100] 

Básicamente, es la inferencia manual + auto-inferencia, y que le permite escribir código muy genérico que es más difícil escribir con otros idiomas. (Este ejemplo no es muy realista, pero ilustra el punto.)

+0

Lo mismo se admitirá en la próxima versión del estándar C++. Misma sintaxis – Baltasarq

+0

Sabía que 'auto' sería compatible, pero no tenía idea de' typeof() '; ¡Gracias por compartir eso! Solo curiosidad, ¿también es posible encontrar el tipo de uno de los padres de un objeto en C++ 0x? – Mehrdad

+0

¿Está buscando typeid (obj) ?: http://www.cplusplus.com/doc/tutorial/typecasting/ – Baltasarq

Cuestiones relacionadas