2009-03-14 18 views
23

Al intentar hacer algo bastante avanzado en C# (como algún tipo de truco), se plantea el concepto de "primera clase".¿Qué es una construcción de programación de primera clase?

Por ejemplo, un método es una construcción de programación de primera clase porque puedes hacer xyz con ella (xyz no es lo que hace el método, pero lo que un método en general te da, no recuerdo qué era xyz ahora) , pero en .NET 1.1 los delegados no pudieron pasar a los métodos porque no eran construcciones de programación de primera clase (leo algo en esta línea).

¿Qué es exactamente una construcción de programación de primera clase?

Gracias

Respuesta

21

sospecho que no encontrará una definición formal Apparently Jörg W Mittag found one :)

Dado que la definición formal, el resto de mi respuesta es simplemente mi comprensión de la misma en el momento. Si cualquiera que use el término "constructo de primera clase" significa exactamente lo mismo es una cuestión diferente, por supuesto.

La manera de determinar si algo es una "primera clase" construir o no es preguntarse a sí mismo algo como esto:

es la característica apoyado y integrado completamente con el resto de el idioma o ¿hay una gran cantidad de restricciones innecesarias que dan la impresión de que sólo ha sido "atornillados" posiblemente para hacer frente a solo un caso uso particular sin tener en cuenta otras áreas donde la construcción podría ser realmente útil si hubiera sido más completamente "parte del lenguaje "?

Como se puede ver, se trata de un área gris clara :)

delegados en C# son un buen ejemplo, en realidad. En C# 1 usted podría pasar delegados a los métodos, y había muchas maneras en que eran bien integrados en el idioma (cosas como conversiones disponibles, manejo de eventos, + = y - = traducir a Delegate.Combine/Retirar). Yo diría que fueron construcciones de primera clase. Sin embargo, eso no contradice el hecho de que los delegados han ganado tremendamente de C# 2 y 3, con métodos anónimos, conversiones de grupos de métodos implícitos, expresiones lambda y covarianza. Son discutiblemente más de una construcción de primera clase ahora ... y aunque diría que eran de "primera clase" en C# 1, pude ver por qué alguien podría estar en desacuerdo.

Un caso similar podría hacerse para IEnumerable. En C# 1.0, era compatible con foreach pero el bucle foreach no eliminaría el IEnumerator al final. Esta parte se corrigió en C# 1.2, pero todavía había compatibilidad con el idioma para que consumíaIEnumerable s, sin crearlos. C# 2.0 proporciona bloques de iteradores, lo que hace que sea trivial implementar IEnumerable (y su equivalente genérico). ¿Significa eso que el concepto de una secuencia iterable no era una construcción de "primera clase" en C# 1.0? Debatable, básicamente ...

+1

Gran explicación (y para todos los demás). Ciertamente es una zona gris :) – dotnetdev

+1

¿La respuesta de Jörg no proporciona una definición formal? –

+1

@Rich: Parece que no lo había visto. Editaré cuando tenga oportunidad. –

7

¿Qué es exactamente una construcción de programación de primera clase?

Algo es una primera clase de construcción de si el lenguaje que soporta de una manera que es análoga a otros tipos de objetos.

Por ejemplo, en C++, las funciones no se considerarían construcciones de primera clase: puede hacer otros tipos de objetos en tiempo de ejecución, pero no puede instanciar nuevas funciones. Por el contrario, en C# 3 y posterior, las funciones probablemente se considerarían construcciones de primera clase con la introducción de lambdas/funciones anónimas.

Como en muchas otras cosas, esta es, naturalmente, una definición subjetiva. Wikipedia tiene a good summary para obtener ejemplos más concretos, al igual que C2.

+0

A partir de C++ 0x, esto es ligeramente diferente ahora. –

+0

Si C++ 0x alguna vez se convierte en un estándar real, puede decir "es". Hasta entonces es "puede terminar siendo". :) – cHao

0

Mi comprensión de una construcción de programación de primera clase es que significa que puede hacer cosa, cualquiera que sea, de la mejor manera posible sin tener que hacer dos o tres cosas más, o combinar dos o otros tres conceptos.

Por lo tanto, Java no tiene soporte de cierre de primera clase. Sin embargo, podemos simularlo creando una clase (usando otro concepto) que admita casi todas las cosas para las que utiliza cierres y luego crear instancias de esa clase (otro concepto) o extender esa clase de forma anónima (otro concepto más)

Lo mismo con 'funciones'. En Java no puede tener funciones, pero puede tener métodos estáticos, que son un concepto similar pero diferente.

Uno (no yo) también podría argumentar que el soporte de genéricos de Java no es de primera clase, porque es un hack de biblioteca y no está realmente "en" el lenguaje. Esto significa que algunas de las cosas que puede hacer en C# con genéricos no pueden hacerlo en Java.

36

La noción de "first-class citizen" or "first-class element" en un lenguaje de programación fue introducida por el informático británico Christopher Strachey en la década de 1960 en el contexto de funciones de primera clase. La formulación más famosa de este principio es, probablemente, en Structure and Interpretation of Computer Programs por Gerald Jay Sussman y Harry Abelson:

  • Se pueden mencionar por variables.
  • Se pueden pasar como argumentos para los procedimientos.
  • Se pueden devolver como resultado de los procedimientos.
  • Se pueden incluir en las estructuras de datos.

Básicamente, significa que puede hacer con este elemento del lenguaje de programación todo lo que puede hacer con todos los demás elementos en el lenguaje de programación.

0

¿Qué es exactamente una construcción de programación de primera clase?

Respuesta simple: es algo que admite todas las operaciones estándar que proporciona el lenguaje.En un lenguaje orientado a objetos, los constructos de primera clase son, como era de esperar, los objetos. Resulta que en tales idiomas a menudo, por razones de eficiencia o legado, ciudadanos de segunda clase, generalmente los tipos de datos primitivos, que no son objetos adecuados, y para los que no se pueden hacer ciertas cosas.

Por ejemplo, en Java un punto es un objeto completo. Se puede declarar un

List<Point> plist;

y luego poner los puntos en ella. Un int no es un objeto completo. Hay ciertas cosas que no puede hacer con una subclase int, por ejemplo, o invocar métodos en ella, aparte de algunos operadores predefinidos. Tampoco se puede almacenar en un

List<int> intlist;

Java tiene una salida para este problema, ya que hay un tipo "caja", Entero, que es un objeto de pleno derecho. Puede declarar un List<Integer>, por ejemplo. Sin embargo, usar un Entero es mucho menos eficiente que con un "int". Java proporciona boxeo automático y unboxing (es decir, conversión) del tipo Integer a int y viceversa en contextos en los que se requiere uno u otro, para ayudar al programador a combinar lo mejor de ambos mundos.

Tener dos tipos - entero e int - para un número entero es confuso, y algo así como un truco. Se me dice que una versión temprana de Java no tenía primitivos y todos sus tipos eran objetos de pleno derecho. Eso resultó ser demasiado lento para su uso previsto (¡Java temprana resultó ser lenta de todos modos, por supuesto!), Por lo que se agregaron algunas primitivas que no respaldaban la semántica propia del objeto.

en .NET 1.1 no se pudieron pasar los delegados a los métodos porque no eran construcciones de programación de primera clase (he leído algo en este sentido).

No sé nada de .NET, pero parece que usted tiene la idea. Tiene razón: si los delegados no pueden pasar a métodos como cualquier otro objeto estándar, no son construcciones de programación de primera clase.

Cuestiones relacionadas