¿Cuál es la base matemática para valores de primera / segunda / tercera clase en lenguajes de programación?

19

Adicional

Acabo de encontrar dos preguntas relacionadas

/math//q/1759680/1281

/programming//a/2582804/156458


En lenguajes de programación, de la Pragmática del lenguaje de programación de Michael Scott

En general, se dice que un valor en un lenguaje de programación tiene un estado de primera clase si puede pasarse como un parámetro, devolverse desde una subrutina o asignarse a una variable. Los tipos simples como enteros y caracteres son valores de primera clase en la mayoría de los lenguajes de programación. Por el contrario, un valor de "segunda clase" puede pasarse como parámetro, pero no puede devolverse desde una subrutina o asignarse a una variable, y un valor de "tercera clase" ni siquiera puede pasarse como parámetro.

Las etiquetas son valores de tercera clase en la mayoría de los lenguajes de programación, pero valores de segunda clase en Algol. Las subrutinas muestran la mayor variación. Son valores de primera clase en todos los lenguajes de programación funcionales y en la mayoría de los lenguajes de script. También son valores de primera clase en C # y, con algunas restricciones, en varios otros lenguajes imperativos, incluidos Fortran, Modula-2 y -3, Ada 95, C y C ++. 11 Son valores de segunda clase en la mayoría de los otros idiomas imperativos, y valores de tercera clase en Ada 83.

  1. ¿Cuál es la base matemática para valores de primera / segunda / tercera clase en lenguajes de programación?

    La terminología me recuerda a la lógica de primer / segundo orden, pero ¿están relacionadas?

  2. Me parece que la diferencia entre ellos es en qué caso específico se puede usar un valor

    • pasado como un parámetro,
    • regresado de una subrutina, o
    • asignado a una variable.

    ¿Por qué son importantes los casos específicos, mientras que no se mencionan otros casos?

Gracias.

Tim
fuente
23
Clasificar valores en primera / segunda clase es tan infructuoso como clasificar idiomas en paradigmas. Todo lo que terminará con vagas generalizaciones que confunden la imagen. Este no es el enfoque correcto para comprender los lenguajes de programación. Lo importante es comprender la sintaxis, la estática y la dinámica del lenguaje, pero eso es demasiado grande para entrar en un comentario
gardenhead
3
Aparte: PL / I sería un ejemplo de etiquetas como de primera clase. En PL / I puede declarar variables escritas para etiquetar, asignarles ubicaciones de código y pasarlas. También puede pasarlos como parámetros e incluso crear matrices de ellos.
Theraot
@Theraot: Tal vez estoy saliendo conmigo mismo, pero ¿soy el único que tuvo que lidiar con GOTO asignados y calculados en FORTRAN? ¡Y no, no escribí el @ $%! código, estaba atascado reingenierándolo
jamesqf
@jamesqf Soy consciente de asignar etiquetas a FORTRAN y COBOL, no, no he usado eso. No estoy seguro de cómo clasificar las etiquetas allí. Sin embargo, por lo que leí (tengo los manuales) PL / I va más allá de eso, y estoy convencido de que las etiquetas son de primera clase allí.
Theraot

Respuestas:

45

No hay ninguno, y es bastante arbitrario.

La única distinción útil es entre primera clase y todas las demás. Cada caso que está en el "otro" grupo tiene su propio conjunto de reglas distintas en cada caso y agruparlos a todos simplemente no es muy útil. "Primera clase" significa "No tienes que buscar las reglas", esencialmente, y "otro" es "Tienes que aprender las reglas".

Por ejemplo, en C ++, las funciones individuales son valores de primera clase, siempre que no tengan estado. Los conjuntos de sobrecarga no lo son, pero las lambdas sí. En C #, las funciones son generalmente valores de primera clase, pero hay algunos casos incómodos que surgen cuando se trata de inferencia de tipos que evitan que sean en todos los casos.

DeadMG
fuente
10
+1, aunque en el contexto de un libro como Programming Language Pragmatics que compara una gran cantidad de construcciones en una gran cantidad de lenguajes, y analiza las similitudes, diferencias e implicaciones en profundidad, creo que este tipo de taquigrafía puede ser útil. (Simplemente no espere que otras personas entiendan que "segunda mano" y "tercera mano" significan cosas específicas.)
ruakh
(Uh, donde por "segunda mano" y "tercera mano" me refiero, por supuesto, a "segunda clase" y "tercera clase". :-P)
ruakh
3
Si desea comerciar con funciones de segunda mano, es mejor que lo haga en un idioma donde las funciones sean ciudadanos de primera clase. ^^
5gon12eder
@ 5gon12eder: "funciones de segunda mano" serían las que llama desde bibliotecas de terceros, ¿no?
jamesqf
11

Estoy de acuerdo con DeadMG, la distinción importante es entre primera clase y "todo lo demás". Sin embargo, hay una forma más familiar de clasificar la diferencia.

Los valores de primera clase son datos, los otros son código. (Hablando en términos generales: estoy seguro de que hay excepciones. Pero esta es una muy buena aproximación que se aplica a los idiomas del mundo real).

En algunos idiomas, puede tratar el código como datos. Los lenguajes funcionales son famosos por esto: algunos de ellos le permiten cambiar el código del programa mientras se ejecuta (la base de la programación genética ).

Los lenguajes como C y C ++ le permiten tomar la dirección de las funciones: aunque no puede modificarlas, puede pasar funciones como parámetros a otras funciones. C ++ también tiene el azúcar sintáctico de los functores . La idea es crear un objeto completo que, en la superficie, parezca comportarse como una función y pueda pasarse como si fueran datos. Lo que de otra manera es un valor de clase baja puede tratarse como un valor de primera clase.

Matemáticamente, creo que la mejor manera es pensar en el AST de un programa . Por lo general, cada token tiene un tipo específico que puede o no ser compatible con otros tipos. Piense en el valor l, el valor r y el otro desorden completo de tipos de valores en C ++ . Luego agregue las palabras clave, los símbolos que son funciones, etc. Algunos de estos pueden ser valores de primera, segunda o tercera clase dependiendo del idioma.

No estoy seguro de saber que la "clase" de valor es tan importante, excepto tal vez en un entorno académico. En el mundo real, lo importante es saber cómo puede pasar el código, tratándolo como datos: functores, lambdas / cierres, punteros de función, etc.


fuente
2
Un ejemplo de un valor sin código que no es de primera clase: Lua tiene una ..."variable" especial utilizada para denotar los parámetros de la función vararg. Puede usarlo en muchas expresiones como si fuera una lista de valores (como print(...)o local args = {...}) pero hay algunas cosas que no puede hacer con él, como referirse a él en un cierre ( function(...) return function() return ... end end).
Coronel Treinta y dos
8

La semántica de denominación proporciona una base matemática para describir cómo funcionan los valores y las variables en un lenguaje de programación. Se explicó tan bien en mi Licenciatura en Ciencias de la Computación que obtuve una calificación alta en el examen de Semántica Denotacional, luego olvidé la mayor parte y nunca tuve la necesidad de usarlo en una vida de 20 años como programador.

Puede optar por utilizar una base matemática bien definida, o puede utilizar una terminología informal como "estado de primera clase". Habría aprendido mucho más si el curso se basara en la Pragmática del lenguaje de programación de Scott, sin embargo, las matemáticas formales son necesarias para alguien que vaya a hacer un doctorado en diseño de lenguaje de programación.

Si lee la especificación para la mayoría de los lenguajes de programación, notará una falta disidente de semántica de denominación, sin embargo, la mayoría de los lenguajes bien diseñados tenían a alguien en el equipo experto en diseño de lenguaje de programación, por lo tanto, entiende bien la semántica de denominación.

Entonces, Michearl Scott usa una terminología informal que tiene alguna relación con las matemáticas formales, mientras presenta el tema de una manera que la mayoría de los programadores pueden beneficiarse. Su terminología no es utilizada por otras personas, por lo que no es útil para comunicarse, pero le brinda una buena base sobre las preguntas que debe hacer al ver un nuevo lenguaje de programación por primera vez.

Tenga en cuenta que Michael L. Scott es un investigador líder en Computer Sci, por lo que comprenderá y estará muy contento con las matemáticas formales, pero, como los mejores investigadores, tiene la habilidad de explicar la aplicación de la investigación al resto de nosotros.

Ian
fuente
Gracias. ¿Qué libros se usaron en tu clase? ¿Qué libros me recomiendan ahora? Soy un autodidacta
Tim
@Tim, ¡hice mi clase hace más de 20 años! Espero que el libro de Michearl Scott sea uno de los mejores y cubra más de lo que necesita a menos que haga una investigación a nivel de PHd.
Ian
3

No, la palabra "primero" en "primera clase" y en "primer orden" significan cosas diferentes.

Pero sí, los conceptos de "primera clase" y "primer orden" están relacionados. Ambos tratan de clasificar qué conceptos sobre los que un lenguaje puede describir el lenguaje también pueden abstraer.

Un concepto es de primera clase si los mecanismos de abstracción habituales de un lenguaje pueden abstraer sobre ese concepto.

Por ejemplo, el lenguaje de programación Java puede describir enteros, y todos los mecanismos habituales para abstraer sobre enteros (aceptarlos como parámetros de método, devolverlos como resultados de funciones, almacenarlos en estructuras de datos, ...) funcionan para enteros.

Un concepto es de primer orden si no puede usarse para abstraerse sobre sí mismo.

Por ejemplo, nuevamente en Java, podemos usar métodos para abstraer sobre ciertas cosas. Pero no podemos usar métodos para abstraer sobre métodos, porque un nombre de método no se puede pasar como parámetro de método. Esto es diferente en JavaScript, donde puede usar la notación de corchetes para acceder a una propiedad de un objeto por su nombre como una cadena, y puede abstraer sobre cadenas.

Un concepto es de segundo orden si puede usarse para abstraer sobre usos de primer orden de sí mismo, pero no sobre usos de segundo orden.

Por ejemplo, en Java, puede usar Generics para abstraer sobre tipos (como en class Foo<T> { public List<T> content; }). Sin embargo, no puede usar genéricos para abstraer sobre genéricos (como en class Bar<T> { public T<Int> content; }). Esto es diferente en Scala.

Un concepto es de tercer orden si puede usarse para abstraer sobre usos de primer orden y de segundo orden de sí mismo, pero no sobre usos de segundo orden.

Y así.

Finalmente, un concepto es de orden superior si puede usarse para abstraer sobre usos arbitrarios de sí mismo.

Resumen: si una característica de abstracción es de primera clase, también es de orden superior. Y si una característica de abstracción es de primer orden, no puede ser de primera clase.

Toxaris
fuente
1
Sin embargo, puedes hacerlo List<List>en Java. ¿Quizás puedas aclarar a qué te refieres con esa parte?
Polygnome
1
Buen punto. Es decir: class Foo<A> { A<Int> ... }. Es decir, me refiero a usar un parámetro de tipo genérico como una clase genérica. Entonces, Foo<List>instanciaría el A<Int>para List<Int>. En Java, eso no es posible. Intentaré editar esto en la respuesta más tarde.
Toxaris
De hecho, eso no es posible.
Polygnome
Ahora reemplacé el List<List>ejemplo engañoso . Gracias por señalar el problema, @Polygnome.
Toxaris
@Toxaris Creo que esto es solo una terminología idiosincrásica que usted mismo ha inventado. Un "concepto" no es de primer orden o de segundo orden, sino un cuantificador lógico.
Miles Rout
2

¿Cuál es la base matemática para valores de primera / segunda / tercera clase en lenguajes de programación?

Ninguno que yo sepa.

La terminología me recuerda a la lógica de primer / segundo orden, pero ¿están relacionadas?

Realmente no.

La "clase" de un elemento de lenguaje de programación es solo una forma abreviada de pensar sobre la pregunta ¿qué cosas desea manipular programáticamente el usuario de mi lenguaje ? Por ejemplo, C # le brinda un amplio conjunto de operaciones para manipular valores , un conjunto menos rico de formas de manipular tipos y ninguna operación que manipule etiquetas .

Sin embargo, su intuición de que hay una conexión aquí no está del todo equivocada. Se puede hacer una analogía desde la lógica de primer orden hasta la programación de procedimientos, y desde la lógica de orden superior hasta la programación funcional. La lógica de primer orden se trata de la manipulación lógica de los valores; La programación procesal se trata de la manipulación programática de valores. La lógica de orden superior se trata de la manipulación lógica de las declaraciones de lógica , la programación funcional se trata de la manipulación programática de las funciones .

¿Por qué son importantes los casos específicos, mientras que no se mencionan otros casos?

Tendría que pedirle al autor una respuesta definitiva.

No me obsesionaría demasiado con esta noción de "clase". No es una cosa formalmente definida. Es una forma abreviada que los diseñadores de lenguaje usan para hablar sobre qué tipo de cosas pueden manipularse mediante programación.

Eric Lippert
fuente
2

El "valor de primera clase", en este contexto, es la terminología estándar en la teoría del lenguaje de programación. Un valor de primera clase es algo que se puede manipular como valores normales en el lenguaje, algo que se puede calcular en tiempo de ejecución. Por supuesto, esa es una definición tautológica hasta que haya definido una semántica para el lenguaje, y luego un valor es lo que la semántica define como un valor. El objetivo del concepto es identificar lo que se puede manipular directamente, en lugar de solo acceder indirectamente.

Por ejemplo, en casi todos los lenguajes de programación, los enteros de máquina de un tamaño acotado (por ejemplo, enteros de 8 bits, enteros de 32 bits o enteros de 64 bits, etc.) son valores de primera clase. Puede almacenarlos en variables, pasarlos y devolverlos a funciones, etc. En la mayoría de los lenguajes, pero no en lenguajes de bajo nivel como ensamblado y C, las cadenas son valores de primera clase, pero en C no lo son, solo usted obtener punteros a las cuerdas. En C, las cadenas y las matrices no son valores de primera clase: por ejemplo, no puede pasar una matriz a una función, no puede asignar una matriz a una variable de matriz, etc. En C, las funciones no son valores de primera clase tampoco: no puede almacenar una función en una variable, solo un puntero a una función. Por el contrario, las cadenas y funciones son valores de primera clase en la mayoría de los lenguajes de programación de alto nivel: puede almacenarlos en una cadena, etc.

Un ejemplo de un concepto que no es de primera clase en muchos lenguajes de programación diseñados para ser compilados son los tipos. En un lenguaje como C o Java, los tipos viven en tiempo de compilación, no puede manipularlos usando construcciones de lenguaje. (Java también tiene un sistema de tipo dinámico basado en clases; las clases son valores de primera clase a través de la reflexión). Por el contrario, un lenguaje como Python tiene una typefunción que devuelve un valor que representa el tipo de su argumento.

La negación del "valor de primera clase" en la terminología estándar "no es un valor de primera clase". El término "valor de segunda clase" no se usa comúnmente, y "valor de tercera clase" aún menos. No esperes verlos fuera de este libro. No hay absolutamente ninguna base para definir "segundo" como "se puede pasar como parámetro" y "tercero" como "no se puede pasar como parámetro", no hay una escala de cosas que puedan numerarse de manera significativa. Muy pocos lenguajes hacen la diferencia entre los valores que se pueden pasar como parámetro a las funciones y los valores que se pueden asignar a las variables, por lo que no es útil definir un nombre para este concepto.

Gilles 'SO- deja de ser malvado'
fuente