Desenho de uma Linguagem de Programação
Como já está esboçado um esquema geral para representar programas, agora pode-se tratar da linguagem propriamente dita.
O que se pretende e/ou necessita numa linguagem de programação?
Em geral, numa linguagem de programação encontra-se:
- Expressões e Variáveis.
- Instruções e Sequências.
- Condicionais.
- Ciclos.
- Funções.
- Entrada/Saída.
Mais especificamente,
- Expressões e Variáveis. As expressões definem os valores que os programas processam e as variáveis "mantêm" esses valores para uso posterior.
Por exemplo, a instrução
a = 2 + (3 * 4)
emPython
define um certo valor que fica guardado na variávela
e que pode ser usado posteriormente, como ema % 2 == 0
.
- Instruções e Sequências. Um programa é uma sequência (ou bloco) de instruções. "Correr" um programa significar avançar uma instrução de cada vez ao longo dessa sequência.
São comuns certas convenções sobre as sequências que "efetivamente" definem um programa. Por exemplo, em
C
o programa é o bloco de instruções que está na funçãomain
e tudo o resto é "auxiliar".
- Condicionais. Um condicional permite certas condições ativarem e desativarem blocos de instruções.
A sintaxe mais comum dos condicionais é
if (C) A else B
com pequenas variantes conforme a linguagem.
- Ciclos. Um ciclo repete um certo bloco de instruções em função de uma condição.
Quando o número de repetições é conhecido de antemão é comum usar-se a sintaxe
for(i = 0; i < n; i++) A
para repetirn
vezes as instruções deA
.Quando as repetições estão dependentes de uma condição, a forma
while (C) A
, que testaC
e repeteA
enquanto a condiçãoC
for verdadeira, é comum.Também se usa a forma
do A while (C)
, que correA
pelo menos uma vez, antes de testarC
.
- Funções. As funções são uma forma simples de evitar repetição de código e de acrescentar instruções "novas" a uma linguagem de programação.
Se for necessário calcular
2 + 2
,2 + 3
,2 + 4
, ...,2 + 42
não se escrevem 40 instruções quase iguais. Define-se uma função que mantém a parte comum do código repetido e usa variáveis locais para os valores que variam. Sendo possível, a função pode ser evocada num ciclo.
Funções Anónimas. Formalmente, uma função não precisa de ter um nome. Nalgumas linguagens mais arcaicas, como o
C
, as funções anónimas (ou lambdas) não são suportadas diretamente. Com a maior disponibilidade do processamento de coleções têm ganho popularidade. Por exemplo, emJava
foi introduzido o operador->
, oJavascript
e oC#
têm o=>
, noPython
usam-se expressõeslambda
e noRust
a sintaxe é|var| instr
, etc. TL/DR: As funções anónimas são fixes.
- Entrada/Saída. Um programa, enquanto processador de informação precisa de canais de entrada e de saída de dados.
As formas mais simples de entrada e saída de dados pressupõem uma consola onde o utilizador digita e lê os dados que, respetivamente, dão entrada no, ou são escritos pelo, programa.
Lisp
O Lisp é uma das mais antigas, influentes e avançadas linguagens de programação.
Além disso, all the programming languages converge to Lisp e any sufficiently complicated program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.
Aspeto de um programa Lisp
(especificamente, Common Lisp):
(defun fib (x)
(if (< x 2)
1
(+ (fib (- x 1)) (fib (- x 2)))
)
)
(fib 6) ; resultado: 13
A "excecionalidade" do Lisp
está nas possibilidades que resultam da sua simplicidade. "Elegant weapons" significa que certas ideias muito simples são extremamente efetivas.
Por exemplo, (+ 41 1)
é uma lista com três elementos, uma expressão que vale 42
e
uma (instrução de) evocação da função +
.
-
Lisp
significa LISt Processor. Além dos tipos básicos (inteiros, doubles, strings) tem listas. Ao contrário dosarray
em muitas linguagens, uma lista doLisp
pode ter elementos de tipos diferentes. Por exemplo,(42 3.14 "fourty-two" ("sub" lista))
. -
No
Lisp
as instruções também são expressões. Isto é,(+ 2 (* 3 4))
é simultaneamente uma expressão (com valor 12) e uma instrução (neste caso, evocar a função"+"
).- Por exemplo, um condicional é
(if C A B)
e, comoC
,A
eB
são expressões, o valor do condicional é o valor do ramo que foi seguido.
- Por exemplo, um condicional é
-
A sintaxe segue fielmente a representação das árvores feita acima (as vírgulas são descartadas). Isto é: Um programa
Lisp
é a sua própria representação! É possível um programaLisp
ler, analisar e modificar o seu próprio código enquanto corre. Em particular, oLisp
é homoicónico.
No resto deste capítulo define-se uma linguagem de programação,
ALisP
, inspirada noLisp
. Além das propriedades acima, acresce ainda que a gramática para a sintaxe é extremamente simples e LL(1), o que permite implementar (quase) diretamente um analisador sintático.
Semântica Informal da ALisP
Uma antevisão da
ALisP
.
-
Variáveis e Expressões:
(set a (+ 30 12))
define a variávela
e dá-lhe o valor42
. A expressão completa também fica com esse valor. -
Instruções e Sequências:
(seq (set a (+ 40 10)) (set a (- a 8)))
executa as duas instruções. Fica com o mesmo valor que a última sub-expressão. -
Condicionais:
(if (== a 42) CERTO (> 0 1))
calcula o valor de(== a 42)
; Se forTrue
calcula e fica com o mesmo valor queCERTO
; Caso contrário calcula(> 0 1)
e fica com esse valor. -
Ciclos:
(while (< a 42) (set a (+ a 1)))
repete o "passo"(set a (+ a 1))
enquanto a condição(< a 42)
for verdadeira. Quando (se) termina fica com o valor do "passo". -
Funções (anónimas):
(fn (x) (== x 42))
define uma função anónima com argumentosx
e "corpo"(== x 42)
. A variávelx
está limitada ao "corpo" da função. Devolve o valor do "corpo" quandox
tem o valor com que a função é evocada. Por exemplo, em(seq (set dobro (fn (x) (* 2 x) )) (dobro 21) )
a evocação
(dobro 21)
define o valor dex
como21
e, portanto, a função devolve (surpresa!)42
. -
Entrada/Saída:
(read)
é uma forma especial. Tem o valor que o utilizador escrever na consola;(write 42)
esteve42
na consola. Tem o valor da expressão que é escrita.
Um programa ALisP
simples, que pergunta o nome do utilizador e o cumprimenta:
(seq
(write (What is your name?))
(set name (read))
(Hello name .)
)
Um defeito semântico da atual versão da
ALisP
é que os símbolos, como emWhat is your name?
são tratados comostring
, o que simplifica a implementação mas torna o código mais imprevisível. Por exemplo, o valor de(Hello name .)
varia conformename
é, ou não, uma variável e esse facto não pode ser deduzido olhando apenas para esta expressão.