Adicionado
Acabei de encontrar duas perguntas relacionadas
/programming//a/2582804/156458
Em linguagens de programação, da Programming Language Pragmatics de Michael Scott
Em geral, é dito que um valor em uma linguagem de programação tem status de primeira classe se puder ser passado como parâmetro, retornado de uma sub-rotina ou atribuído a uma variável. Tipos simples, como números inteiros e caracteres, são valores de primeira classe na maioria das linguagens de programação. Por outro lado, um valor de "segunda classe" pode ser passado como parâmetro, mas não retornado de uma sub-rotina ou atribuído a uma variável, e um valor de "terceira classe" nem mesmo pode ser passado como parâmetro.
Os rótulos são valores de terceira classe na maioria das linguagens de programação, mas valores de segunda classe em Algol. As sub-rotinas exibem a maior variação. Eles são valores de primeira classe em todas as linguagens de programação funcionais e na maioria das linguagens de script. Eles também são valores de primeira classe em C # e, com algumas restrições, em várias outras linguagens imperativas, incluindo Fortran, Modula-2 e -3, Ada 95, C e C ++. 11 São valores de segunda classe na maioria das outras línguas imperativas e valores de terceira classe em Ada 83.
Qual é a base matemática para os valores de primeira / segunda / terceira classe em linguagens de programação?
A terminologia me lembra a lógica de primeira / segunda ordem, mas elas estão relacionadas?
Parece-me que a diferença entre eles é que caso específico um valor pode ser usado
- passado como parâmetro,
- retornado de uma sub-rotina, ou
- atribuído a uma variável.
Por que os casos específicos são importantes, enquanto outros não são mencionados?
Obrigado.
Respostas:
Não existe, e é bastante arbitrário.
A única distinção útil é entre primeira classe e todas as outras. Todos os casos que estão no "outro" colchete têm seu próprio conjunto distinto de regras em cada caso e agrupá-los todos juntos não é muito útil. "Primeira classe" significa "Você não precisa procurar as regras", essencialmente, e "outro" é "Você tem que aprender as regras".
Por exemplo, em C ++, funções individuais são valores de primeira classe, desde que não tenham estado. Conjuntos de sobrecarga não são, mas lambdas. Em C #, as funções geralmente são valores de primeira classe, mas há alguns casos estranhos que surgem ao lidar com inferência de tipo que os impedem de existir em todos os casos.
fonte
Eu concordo com DeadMG, a distinção importante é entre primeira classe e "tudo o resto". No entanto, existe uma maneira mais familiar de classificar a diferença.
Os valores de primeira classe são dados, os outros são código. (grosso modo: tenho certeza de que há exceções. Mas essa é realmente uma boa aproximação para os idiomas do mundo real.)
Em alguns idiomas, você pode tratar o código como dados. As linguagens funcionais são famosas por isso: algumas permitem alterar o código do programa enquanto ele está sendo executado (a base da programação genética ).
Idiomas como C e C ++ permitem que você tome o endereço das funções: embora não possa modificá-las, você pode passar funções como parâmetros para outras funções. O C ++ também possui o açúcar sintático dos functores . A idéia é criar um objeto inteiro que, na superfície, pareça se comportar como uma função e possa ser transmitido como se fossem dados. Caso contrário, uma classe de valor inferior pode ser tratada como um valor de primeira classe.
Matematicamente, acho que a melhor maneira é pensar no AST de um programa . Normalmente, cada token possui um tipo específico que pode ou não ser compatível com outros tipos. Pense em valor l, valor r e a outra confusão de tipos de valor em C ++ . Em seguida, adicione as palavras-chave, símbolos que são funções etc. Alguns deles podem ser valores de primeira, segunda ou terceira classe, dependendo do idioma.
Não tenho certeza de que a "classe" de valor seja tão importante, exceto talvez em um ambiente acadêmico. No mundo real, o importante é saber como você pode transmitir o código, tratando-o como dados: functors, lambdas / closures, ponteiros de função, etc.
fonte
...
"variável" especial usada para indicar parâmetros de função vararg. Você pode usá-lo em várias expressões como se fosse uma lista de valores (comoprint(...)
oulocal args = {...}
), mas há algumas coisas que você não pode fazer com ela, como referir-se a ela em um fechamento (function(...) return function() return ... end end
).A Semântica Denotacional fornece uma base matemática para descrever como valores e variáveis funcionam em uma linguagem de programação. Foi tão bem explicado no meu diploma de ciência da computação que obtive uma nota máxima no exame Denotational Semantics, depois esqueci a maioria e nunca tive a necessidade de usá-lo em 20 anos como programador.
Você pode optar por usar uma base matematicamente bem definida, ou pode usar terminologia informal como “status de primeira classe”. Eu teria aprendido muito mais se o curso fosse baseado na Pragmática da Linguagem de Programação de Scott, no entanto, a matemática formal é necessária para alguém que fará um doutorado em design de linguagem de programação.
Se você ler a especificação para a maioria das linguagens de programação, notará uma falta dissidente de semântica denotacional; no entanto, as linguagens mais bem projetadas tinham alguém na equipe especialista em design de linguagem de programação, portanto, entende bem a semântica denotacional.
Então Michearl Scott usa terminologia informal que tem alguma relação com a matemática formal, enquanto apresenta o assunto de uma maneira que a maioria dos programadores pode se beneficiar. Sua terminologia não é usada por outras pessoas, portanto não é útil para a comunicação, mas fornece uma boa base para as perguntas que você deve fazer ao ver uma nova linguagem de programação pela primeira vez.
Observe que Michael L. Scott é um pesquisador líder em Computer Sci; portanto, entenderá e ficará muito feliz usando a matemática formal, mas, como os melhores pesquisadores, ele é especialista em explicar a aplicação da pesquisa para o resto de nós.
fonte
Não, a palavra "primeiro" em "primeira classe" e "primeira ordem" significa coisas diferentes.
Mas sim, os conceitos de "primeira classe" e "primeira ordem" estão relacionados. Ambos são sobre a classificação de quais conceitos que uma linguagem pode descrever a linguagem também podem abstrair.
Um conceito é de primeira classe se os mecanismos de abstração usuais de uma linguagem puderem abstrair esse conceito.
Por exemplo, a linguagem de programação Java pode descrever números inteiros, e todos os mecanismos usuais para abstrair sobre números inteiros (aceitando-os como parâmetros de método, retornando-os como resultados de funções, armazenando-os em estruturas de dados, ...) funcionam para números inteiros.
Um conceito é de primeira ordem se não puder ser usado para abstrair sobre si mesmo.
Por exemplo, novamente em Java, podemos usar métodos para abstrair sobre certas coisas. Mas não podemos usar métodos para abstrair sobre métodos, porque um nome de método não pode ser passado como parâmetro de método. Isso é diferente no JavaScript, onde você pode usar a notação de colchete para acessar uma propriedade de um objeto pelo nome como uma sequência e pode abstrair sobre sequências.
Um conceito é de segunda ordem se puder ser usado para abstrair sobre os usos de primeira ordem em si, mas não sobre os usos de segunda ordem.
Por exemplo, em Java, você pode usar Genéricos para abstrair sobre tipos (como em
class Foo<T> { public List<T> content; }
). No entanto, você não pode usar genéricos para abstrair sobre genéricos (como emclass Bar<T> { public T<Int> content; }
). Isso é diferente em Scala.Um conceito é de terceira ordem se puder ser usado para abstrair sobre os usos de primeira e segunda ordem de si mesmo, mas não sobre os usos de segunda ordem.
E assim por diante.
Finalmente, um conceito é de ordem superior se puder ser usado para abstrair sobre usos arbitrários de si mesmo.
Resumo: Se um recurso de abstração é de primeira classe, também é de ordem superior. E se um recurso de abstração é de primeira ordem, não pode ser de primeira classe.
fonte
List<List>
em Java, no entanto. Talvez você possa esclarecer o que você quer dizer com essa parte?class Foo<A> { A<Int> ... }
. Ou seja, pretendo usar um parâmetro de tipo genérico como uma classe genérica. Em seguida,Foo<List>
instanciaria oA<Int>
paraList<Int>
. Em Java, isso não é possível. Vou tentar editar isso na resposta mais tarde.List<List>
exemplo enganoso . Obrigado por apontar o problema, @Polygnome.Nada que eu saiba.
Na verdade não.
A "classe" de um elemento da linguagem de programação é apenas uma maneira abreviada de pensar sobre a pergunta que coisas o usuário da minha linguagem deseja manipular programaticamente ? Por exemplo, o C # oferece um rico conjunto de operações para manipular valores , um conjunto menos rico de maneiras de manipular tipos e nenhuma operação que manipula rótulos .
No entanto, sua intuição de que existe uma conexão aqui não é totalmente equivocada. Existe uma analogia a ser feita da lógica de primeira ordem à programação procedural e da lógica de ordem superior à programação funcional. A lógica de primeira ordem trata da manipulação lógica de valores; programação procedural trata de manipulação programática de valores. A lógica de ordem superior refere-se à manipulação lógica de declarações da lógica , a programação funcional trata da manipulação programática de funções .
Você teria que pedir ao autor uma resposta definitiva.
Eu não ficaria muito preocupado com essa noção de "classe". Não é uma coisa formalmente definida. É um atalho que os designers de linguagem usam para falar sobre que tipos de coisas podem ser manipuladas programaticamente.
fonte
"Valor de primeira classe", neste contexto, é uma terminologia padrão na teoria da linguagem de programação. Um valor de primeira classe é algo que pode ser manipulado como valores normais na linguagem, algo que pode ser calculado em tempo de execução. Obviamente, essa é uma definição tautológica até que você defina uma semântica para a linguagem e, em seguida, um valor seja o que a semântica definir como valor. O objetivo do conceito é identificar o que pode ser manipulado diretamente, em vez de apenas acessado indiretamente.
Por exemplo, em quase todas as linguagens de programação, números inteiros de máquinas de tamanho limitado (por exemplo, números inteiros de 8 bits, números inteiros de 32 bits ou números inteiros de 64 bits, etc.) são valores de primeira classe. Você pode armazená-los em variáveis, passá-los e retorná-los às funções, etc. Na maioria dos idiomas, mas não nos idiomas de baixo nível, como assembly e C, as strings são valores de primeira classe - mas em C, eles não são, você só obter ponteiros para seqüências de caracteres. Em C, strings e matrizes não são valores de primeira classe: por exemplo, você não pode passar um array para uma função, não pode atribuir um array a uma variável de array, etc. Em C, funções não são valores de primeira classe ou: você não pode armazenar uma função em uma variável, apenas um ponteiro para uma função. Por outro lado, strings e funções são valores de primeira classe na maioria das linguagens de programação de alto nível: você pode armazená-los em uma string, etc.
Um exemplo de um conceito que não é de primeira classe em muitas linguagens de programação projetadas para serem compiladas são os tipos. Em uma linguagem como C ou Java, os tipos vivem em tempo de compilação, você não pode manipulá-los usando construções de linguagem. (Java também possui um sistema de tipo dinâmico baseado em classes; classes são valores de primeira classe por meio de reflexão.) Por outro lado, uma linguagem como Python tem uma
type
função que retorna um valor que representa o tipo de seu argumento.A negação do "valor de primeira classe" na terminologia padrão "não é um valor de primeira classe". O termo "valor de segunda classe" não é comumente usado e "valor de terceira classe" ainda menos. Não espere vê-los fora deste livro. Não existe absolutamente nenhuma base para definir "segundo" como "pode ser passado como parâmetro" e "terceiro" como "não pode ser passado como parâmetro", não há escala de coisas que possam ser numeradas de maneira significativa. Pouquíssimos idiomas fazem a diferença entre valores que podem ser passados como parâmetro para funções e valores que podem ser atribuídos a variáveis, portanto, não é útil definir um nome para esse conceito.
fonte