Saltar para o conteúdo

APL (linguagem de programação)

Origem: Wikipédia, a enciclopédia livre.
 Nota: Para Este artigo é sobre a linguagem de programação, para outros usos, veja APL (desambiguação).
APL
Surgido em 1962
Criado por Kenneth Iverson
Estilo de tipagem dinâmica
Principais implementações IBM APL2
Influenciada por Notação matemática
Influenciou A+, J, K, MATLAB, FP[1], entre outras

APL é uma linguagem de programação destinada a operações matemáticas.

Ela nasceu do trabalho do professor de matemática canadense Kenneth Iverson. A linguagem APL foi formalmente definida e introduzida por Iverson em seu livro A Programming Language, de 1962.[2][3] Sua proposta original era a de produzir uma nova notação matemática, menos sujeita às ambiguidades da notação convencional. Segundo Iverson, foi projetada com o objetivo de ser matematicamente concisa, simples, precisa e executável.

Na década de 1960, trabalhando na IBM em conjunto com Adin Falkoff, ambos produziram a primeira versão de APL, de 1966, quando um interpretador da linguagem ficou disponível.[4]

APL tem diversos dialetos, mas há uma versão internacional padronizada pela ISO/IEC 13751:2001.[5][6] Outra referência importante é APL2 Programming: Language Reference, da IBM.[7]

O Conjunto de Caracteres APL

[editar | editar código-fonte]
Por limitações técnicas, alguns navegadores podem não mostrar alguns caracteres especiais deste artigo.

Uma das principais características de APL é o uso de um conjunto especial de caracteres que incluem algumas letras gregas (⍴ − rho, ⍳ − iota…), símbolos matemáticos convencionais (o sinal × de vezes, o ÷ de dividido…) e alguns símbolos especialmente inventados (como ⍋ e ⍟). Este fato sempre limitou a disseminação da linguagem. Até o advento das interfaces gráficas (Windows, por exemplo), exigia-se um hardware especial para programar em APL.

A linguagem APL recebeu muitas críticas pelo fato de usar este conjunto de caracteres não padronizado. Tal número de caracteres adicionais pode levar a um grau de complexidade alto resultando em uma baixa legibilidade. Por outro lado, o conjunto adicional de caracteres dá a linguagem uma elegância e a tornam concisa, o que é mais difícil de se conseguir em linguagens com um conjunto de caracteres reduzido.

A dificuldade criada pelos caracteres especiais de APL foi um dos motivos para que, ao conceber a linguagem J no início dos anos 1990, Kenneth E. Iverson (criador de APL), decidisse nela usar apenas caracteres convencionais ASCII.[8]

Este (abaixo) é um subconjunto da lista de caracteres APL usados pelo interpretador GNU APL, gerado pelo comando ,¨7 32⍴32↓⎕AV .[nota 1]

  ! "  $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
 @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _
 ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ 
 ¥           μ  ¡            λ   £   
   χ                  </small>       -->    == Galeria de imagens ==
   ] 

   <!--         ⍝ ⍲ ⍴ ⍱ ⌽ ⊖ ○ ∨ ⍳ ⍉ ∈ ∩ ⌿ ⍀ ≥ ≤ ≠ × ÷ ⍙ ∘ ⍵ ⍫ ⍋ ⍒ ¯ ¨ ␚

Unicode e fontes

[editar | editar código-fonte]

O padrão Unicode contém os símbolos especiais de APL (pontos de código U+2336 a U+237A e U+2395) no bloco Miscellaneous Technical.[9][10]

Algumas fontes tipográficas[11] que incluem os símbolos requeridos por APL conforme o padrão Unicode são:

Símbolos APL e Layouts de Teclado

[editar | editar código-fonte]
Esquema de teclado com mapeamento de símbolos APL básicos. Notar diversas associações com as letras de cada tecla, por semelhança visual (a; w; e; L; o; i) ou por inicial da função ou do símbolo (base; |módulo ou magnitude; potência; ~til; ).
Esquema de teclado com símbolos de APL2. Inclui letras maiúsculas sublinhadas, entre outros símbolos.

Para solucionar o problema da falta de caracteres especiais nos conjuntos padrão (como o ASCII, por exemplo), alguns interpretadores APL têm mapeamentos ou conjuntos de teclas simultâneas para a entrada destes. Uma das associações que se procurou fazer, para facilitar a busca, é relacionar os símbolos com as suas respectivas letras iniciais como no caso do símbolo de interrogação '?' em cima da letra 'Q' (Em inglês question mark) ou o símbolo '' em cima da letra 'G' (Em inglês: gradient).

As figuras ao lado ilustram dois exemplos de teclados com os símbolos APL e APL2.

Configuração de teclado em X Window System (GNU/Linux e outros sistemas)

[editar | editar código-fonte]

Em sistemas GNU/Linux com X Window System, pode-se ativar o layout apl com o programa setxkbmap. No exemplo a seguir, definem-se os layouts Brasil(ABNT2) e APL(Dyalog), de modo que a tecla Caps_Lock passa a ativar o modo APL enquanto estiver pressionada (o comportamento normal dessa tecla passa a Alt+Caps_Lock).[17][18]

setxkbmap -query
setxkbmap -layout br,apl -variant abnt2,dyalog -option grp:caps_switch
setxkbmap -query

Elementos da linguagem

[editar | editar código-fonte]

Iverson descrevia a linguagem APL usando termos das linguagens naturais, como, por exemplo:[19]

Vetorização

[editar | editar código-fonte]

O tipo principal de estrutura de dados de APL é o arranjo ou array, com zero, uma ou mais dimensões. Tipicamente, as operações aplicam-se tanto a escalares (sem dimensão) quanto a vetores (uma dimensão), matrizes (duas dimensões) e arranjos multidimensionais (com qualquer número de dimensões suportado pela implementação). Dessa forma, dispensam-se laços explícitos na maioria dos casos. O funcionamento é similar ao do MATLAB, cuja linguagem teve em APL um de seus modelos.[20][21]

Veja-se o exemplo de sessão interativa abaixo, em que as instruções da pessoa operadora estão recuadas por 6 espaços, e as respostas do programa começam na margem esquerda.

      1 2 3 + 4 5 6     ⍝ Somas dos elementos correspondentes de dois vetores
5 7 9
      3 × 1 2 3         ⍝ Multiplicação de um escalar por um vetor
3 6 9
      2 × 4 - 1         ⍝ APL interpreta-se da direita para a esquerda
6
      2 × (4 - 1)
6
      (2 × 4) - 1
7
      X  1 2 3 1000    ⍝ X é um vetor com 4 elementos
      X                 ⍝ Mostra X
1 2 3 1000
      Y   (1 2 3 4) (1.1 2.2 3.3 4.4)
      Y                 ⍝ Y é uma matriz 2×4
1   2   3   4
1.1 2.2 3.3 4.4
      +/X               ⍝ Soma as linhas de X
1006
      +Y               ⍝ Soma as colunas de Y
2.1 4.2 6.3 8.4
      Z   10          ⍝ Z é um vetor de índices com 10 elementos
      Z                 ⍝ Mostra Z
1 2 3 4 5 6 7 8 9 10
      M  X∘.×Z         ⍝ Multiplica todos os elementos de X e Z
      M
   1    2    3    4    5    6    7    8    9    10
   2    4    6    8   10   12   14   16   18    20
   3    6    9   12   15   18   21   24   27    30
1000 2000 3000 4000 5000 6000 7000 8000 9000 10000
      M  ⍴⍴M          ⍝ Tamanho (⍴) e número de dimensões (⍴⍴) de M
4 10
2

Ambivalência dos símbolos

[editar | editar código-fonte]

Em APL, cada um dos símbolos pode ter duas funções a ele associadas. Segundo Kenneth Iverson, o motivo para isso é representar um grande número de funções através de um pequeno vocabulário de símbolos:

Uma economia significativa de símbolos, em oposição a economia de funções, é atingida ao se permitir que cada símbolo represente tanto uma função unária [i.e., uma função de um argumento] quanto uma função binária, da mesma maneira como o sinal de menos é comumente usado para ambas subtração e negação. Podendo as duas funções serem relacionadas entre si, como no caso do sinal de menos, a memorização dos símbolos fica facilitada.[22]

Por exemplo, o símbolo (iota), na forma unária (prefixa), é um gerador de índices. Ele gera uma sequência de números inteiros em ordem ascendente, conforme o número à sua direita. Já na forma binária, o operador é infixo (sintaxe X⍳E), e sua função é localizar o índice da primeira ocorrência do elemento E em X:

      ⍝ iota unário
       10               ⍝  expressão
1 2 3 4 5 6 7 8 9 10     ⍝  resultado

      ⍝ iota binário
      'anaconda'  'n'    ⍝  primeira ocorrência de 'n' em 'anaconda'?
2                         ⍝  resultado: segunda letra
      'paladar'  'apl'   ⍝  primeira ocorrência das letras 'a', 'p' e 'l' em 'paladar'?
2 1 3                     ⍝  resultado: 'a':2, 'p':1, 'l':3

Outros exemplos:

      ⍝  ⍴ (rô) infixo "formata" o arg. da direita com as dimensões dadas à esquerda.
      2 3  1 2 3 'a' 'b' 'c'    ⍝  gera matriz com 2 linhas e 3 colunas:
1 2 3
a b c
      (3 4  1)    ⍝  gera matriz com 3 linhas e 4 colunas com o número 1:
1 1 1 1
1 1 1 1
1 1 1 1
      ⍝  ⍴ unário retorna o "formato" (dimensões) do argumento à sua direita:
       (3 4  1)
3 4

e

      ⍝  ⌈ unário é a função teto (arredonda para cima)
       1.1
2
      ⍝  ⌊ unário é a função piso (arredonda para baixo)
       1.1
1
      ⍝  na forma binária, ⌈ e ⌊ retornam resp. o máximo e o mínimo dos argumentos:
      2  3
3
      2  3
2

Ordem de avaliação de expressões

[editar | editar código-fonte]

Em APL, as expressões são avaliadas da direita para a esquerda, e todas as funções têm a mesma precedência. Parênteses podem ser necessários para determinar a prioridade de avaliação:

      2 × 2 + 2 × 3 + 2
24
      (2 × (2 + (2 × (3 + 2))))
24
      (2 × 2) + (2 × 3) + 2
12

“Advérbios”

[editar | editar código-fonte]

O operador permuta os operandos de uma função binária:

      4 ÷ 2
2
      4 ÷ 2    ⍝  equivale a 2÷4
0.5

Quando o operando esquerdo é omitido, usa o operando direito em seu lugar:

      2 × 2
4
      × 2    ⍝  equivale a 2×2
4

/ e intercalam a função entre os elementos do arranjo, retornando o resultado final (tal como o operador reduce em LISP):

      +/ 1 2 3    ⍝  equivale a 1+2+3
6
      -/ 1 2 3 4  ⍝  equivale a 1-(2-(3-4))
¯2
      M  2 3  1 2
      M
1 2 1
2 1 2
      + / M         ⍝  em matrizes, / opera ao longo das linhas (linha por linha)
4 5
      +  M         ⍝  em matrizes, ⌿ opera ao longo das colunas (coluna por coluna)
3 3 3

\ e atuam de maneira similar, mas incluem os resultados parciais:

      +\ 1 2 3
1 2 6
      -\ 1 2 3 4
1 ¯1 2 ¯2
      M  2 3  1 2
      M
1 2 1
2 1 2
      + \ M         ⍝  em matrizes, \ opera ao longo das linhas
1 3 4
2 3 5
      +  M         ⍝  em matrizes, ⍀ opera ao longo das colunas
1 2 1
3 3 3

Estruturas de controle de fluxo

[editar | editar código-fonte]

Exceto em alguns dialetos, APL não contém instruções como if, if/else, switch/case, for, repeat. O controle do fluxo de execução é feito através de saltos (branching = ramificação)[23] e chamadas de funções.

Ramificações () são permitidas apenas dentro da definição de funções, através de uma instrução do tipo → NUMLINHA ou → (CONDICAO)/NUMLINHA. O código → 0 (escape) termina a execução da função. Laços raramente são necessários, por a linguagem ser especialmente projetada para o tratamento de arranjos (arrays). Assim, o principal uso de é para execução condicional.

Outra forma de execução condicional pode ser obtida com o operador (execute), que avalia uma cadeia de caracteres como uma instrução em APL:

      X  1
      (X>0)/ '2+5'
7
      ⍎∊(1 0=(X>0)) / '⎕ ← ''X é maior que zero.'''  '⎕ ← ''X não é maior que zero.'''
X é maior que zero.

      X  0
      (X>0)/ '2+5'   ⍝  (Nada é executado.)
      ⍎∊(1 0=(X>0)) / '⎕ ← ''X é maior que zero.'''  '⎕ ← ''X não é maior que zero.'''
X não é maior que zero.

Organização do código

[editar | editar código-fonte]

Para escrever programas em APL de maneira estruturada, sugere-se[24] evitar ramificações e laços,[25] e, quando não for possível evitá-los, organizar o código em blocos delimitados por rótulos (B#: ... E#:, BE:), imitando-se a sintaxe begin ... end das linguagens de programação estruturada.

Alguns exemplos:

If

B1:  (CONDICAO)/1+E3
  ...
E3: ...

While

B3:  (CONDICAO)/1+E3
  ...
E3: B3

Ciclo em uma linha (⎕LC é o número da linha atual do código-fonte)

BE:  (CONDICAO)/1+⎕LC  ...ação...  ⎕LC

Switch/Case

B2:  ((CASO=TRESCASOS)/B2a,B2b,B2c) , 1+E2
 B2a: ...
1+E2
 B2b: ...
1+E2
 B2c: ...
E2: ...

Uso de ramificações e ciclos

[editar | editar código-fonte]

Gary Bergquist faz uma análise aprofundada de ramificações e ciclos em APL no capítulo 2 (Branching and Looping) de APL − Advanced Techniques and Utilities. São abordados critérios como velocidade de execução, requerimento de memória, legibilidade, limitações e compatibilidade.[26]

Bergquist recomenda:

  • Evitar ciclos em APL quando possível (p.16);
  • Quando ciclos forem necessários, devem ter apenas o mínimo possível de código (p.16);
  • Todavia, não perder tempo buscando obsessivamente um algoritmo sem ciclos, a não ser que haja motivos suficientes para tal (p.18−19).

Há também no livro de Bergquist (p.8−9) a sugestão de se criarem as funções como IF ("se") e UNLESS ("a menos que", "a não ser que"), para facilitar a legibilidade do código, permitindo-se assim as construções:

 CALC IF X>5        ⍝  Alternativa a →(X>5)/CALC      ⍝   IF     ← {⍵/⍺}
 CALC UNLESS X5    ⍝  Alternativa a →(X≤5)↓CALC      ⍝   UNLESS ← {⍵↓⍺}

Expressões idiomáticas

[editar | editar código-fonte]

Ao estudar os processos de leitura e escrita de programas em APL, Alan J. Perlis e Spencer Rugaber notaram que certas expressões se repetiam em diversos contextos. Tais expressões são chamadas em inglês de idioms (expressões idiomáticas). Uma vez aprendidas, essas expressões passam a ser reconhecidas como uma unidade, dispensando a necessidade de se analizá-las caracter por caracter. Por isso, os autores defendem que expressões idiomáticas em APL devem ser ensinadas desde o início da experiência com essa linguagem.[27][19][28]

Na introdução de APL2 IDIOMS Library, Stan Cason destaca que a utilidade das coleções de expressões idiomáticas não se limita apenas em acelerar o processo de aprendizagem de APL por iniciantes. Essas coleções também servem como fonte de consulta para programadores experientes nessa linguagem, que podem não se recordar de um algoritmo que não tenham utilizado recentemente.[29]

Exemplos:

P  ? N                ⍝ Permutação aleatória com N elementos
((,C='¯')/,C)'-'       ⍝ Substitui '¯' por '-' em arranjo de caracteres
VV  (C' ')  C        ⍝ Particiona cadeia de caracteres em lista de palavras
C  1 ' ',¨VV         ⍝ Junta lista de palavras em única cadeia de caracteres
R  G×○÷180             ⍝ Converte graus em radianos
G  R×180÷○1            ⍝ Converte radianos em graus
M  ∘.=  N            ⍝ Matriz identidade N×N
N  +/X∘.=M             ⍝ Número de ocorrências de cada elemento de X em M
B  (N2)  D           ⍝ Converte de decimal para binário, usando N bits
(I F)  0 1  N         ⍝ Extrai partes inteira e fracionária do número não-negativo N
(I F)  (×N)×0 1⊤|N     ⍝ Extrai partes inteira e fracionária com sinal

Exemplos de código

[editar | editar código-fonte]

Função Fatorial

[editar | editar código-fonte]

Este código é apenas para exemplo, pois APL já contém em si a função fatorial (!).

Versão longa, usando recursão:

     Z  FATORIAL N          ⍝  Define função de nome FATORIAL, que usa o parâmetro N, e que retorna Z.
[1]    (N > 0) / REC         ⍝  Se N for maior que zero, salta para linha de rótulo REC.
[2]    0, Z1                ⍝  Senão, atribui 1 a Z e termina a função (que retorna Z).
[3]  REC:  ZN×FATORIAL(N-1)  ⍝  Calcula Z (que é então retornado como resultado).
    

Versão curta, usando vetor com N elementos:

 Y  FATORIAL N
  Y  ×/ N

Exemplo usando função direta (GNU APL):

 FATORIAL  { ×/ }

Soma dos Elementos de um Vetor

[editar | editar código-fonte]

O somatório de um vetor é expresso por +/:

   V  7 12 3
   +/ V
   ⍝ (retorna 22)

Função SV (versão longa, irrealista):

     SOMA  SV VETOR
[1]   SOMA  0
[2]   I  1
[3] VOLTA:  (I > VETOR) / SAI
[4]   SOMA  SOMA + VETOR[I]
[5]   I  I + 1
[6]  VOLTA
[7] SAI:
    

Versão curta:

SV  {+/}    ⍝ define função ''inline''
SV 1 2 5 6    ⍝ executa-a com o vetor [1, 2, 5, 6] (deve retornar 14)

Soma dos Elementos de um Vetor e Calculo da média sem loop

[editar | editar código-fonte]
VETOR  10    ⍝  inteiros de 1 a 10
SOMA  +/VETOR
MEDIA  SOMA ÷ VETOR

Média dos elementos de um vetor

[editar | editar código-fonte]

Este código computa a média aritmética dos elementos de um vetor, inseridos via teclado em tempo de execução. O vetor é armazenado na variável x. A função unária ⍴x retorna o número de elementos de x, pelo qual é dividida a soma dos elementos (+/x). Os parênteses são necessários porque APL é interpretada da direita para a esquerda.

 (+/x)÷⍴x

As versões seguintes produzem o mesmo resultado, mas não utilizam nenhuma variável explícita.

 ÷/+/⍪⊃1 0
 ÷/+1 0
 ÷/+∘.1 0

Algoritmo de Trabb Pardo-Knuth

[editar | editar código-fonte]
Ver artigo principal: Algoritmo de Trabb Pardo-Knuth
LIM  400 ⍝ Limite
F  {( (|)÷2 ) + 5×3} ⍝ Função
  'Insira 11 números separados por espaços' ⍝ Solicita entrada
A  11 ⍝ Obtém 11 números
A  A   ⍝ Reverte sequência
A  F¨A  ⍝ Aplica função
((A>LIM)/A)   'Muito grande!' ⍝ Alerta se resultado for maior que o limite
   A                         ⍝ Imprime resultado (11 linhas)

Esta é uma versão compacta, que usa apenas uma variável (A):

'Insira 11 números separados por espaços'
A{((|)÷2)+5×3}¨11  ((A>400)/A)'Muito grande!'  A

Implementações

[editar | editar código-fonte]

Notas

  1. Para melhor legibilidade, Cerquilha (#), Espaço, Espaço não quebrável e Delete estão substituídos pelos caracteres , , e . Outros caracteres de controle foram omitidos.
  2. A inversão dos símbolos e parece ser reflexo de convenções contraditórias, que acarretaram inclusive em erros no padrão Unicode. Ver: The Naming of Tack Symbols.

Referências

  1. The Conception, Evolution, and Application of Functional Programming Languages Arquivado em 11 de março de 2016, no Wayback Machine. Paul Hudak, 1989
  2. Iverson, Kenneth (1962). A Programming Language. [S.l.: s.n.] 
  3. TUCKER Jr., Allen B. (1986). Programming Languages 2ª ed. New York: McGraw-Hill. 590 páginas. ISBN 0-07-065416-6 
  4. [1] Arquivado em 5 de julho de 2018, no Wayback Machine. HUI, Roger, ed. (September 2010), APL Quotations and Anecdotes.
    «The workspace "1 cleanspace" was saved at 1966-11-27 22.53.58 UTC.»
  5. [2] ISO/IEC 13751:2001 Information technology -- Programming languages, their environments and system software interfaces -- Programming language Extended APL.
  6. [3]
  7. [4] IBM APL2 Programming: Language Reference.
  8. [5] K.E. Iverson. A Personal View of APL.
  9. [6] Unicode − Miscellaneous Technical.
  10. [7] FileFormat.info − Font Support for Unicode Block 'Miscellaneous Technical'.
  11. a b c [8] APL Wiki. APL Characters. Acesso em 7Jul2018.
  12. [9] DejaVu Fonts.
  13. a b [10] Projeto GNU − Free Font.
  14. [11] Quivira Font.
  15. [12] Font Library − Rursus Compact Mono Font.
  16. [13] Font Library − Symbola.
  17. [14]
  18. [15]
  19. a b [16] Kenneth E. Iverson. A Dictionary of APL. 1987. Acesso em 6Jul2018.
  20. [17] H. James de St. Germain. Vectorized (or Array) Operations. University of Utah.
  21. Moler, Cleve. «The Growth of MATLAB» (PDF). Arquivado do original (PDF) em 11 de Abril de 2009 
  22. [18] [19] IVERSON, Kenneth. Notation as a Tool of Thought. 1979. (1979 Turing Award Lecture).
    [Há também uma versão com postscript, de 1986: iverson.pdf.]
  23. [20] Brad Miller, David Ranum, Jeffrey Elkner, Peter Wentworth, Allen B. Downey, Chris Meyers & Dario Mitchell. Como Pensar Como um Cientista da Computação ­­− Decisões e Seleção. (Tradução do livro “How to Think Like a Computer Scientist: Interactive Version”, de Brad Miller e David Ranum). Acesso em 6Jul2018.
  24. Ver p.10−11 de [21] van BATENBURG, BONNEMA, van GELDROP, van LOON & SMOOR. ASWI programming standards for APL programs (v.2, 16/12/2004). Acesso em 6Jul2018.
  25. Ver Looping Is Rarely Needed, p.352 de [22] APL2 Programming.
  26. BERGQUIST, Gary A. APL − Advanced Techniques and Utilities. [23] (Arquivado pelo Software Preservation Group).
  27. [24] PERLIS & RUGABER. The APL idiom list. 1977. Acesso em 6Jul2018.
  28. [25] APL Wiki. The FinnAPL Idiom Library. Acesso em 6Jul2018.
  29. CASON, Stan. APL2 IDIOMS Library − IBM − Endicott, NY.
  • IVERSON, Kenneth E. (1962). A Programming Language. New York: John Wiley and Sons. 286 páginas. ISBN 0-47143014-5 
  • TUCKER Jr., Allen B. (1986). Programming Languages 2ª ed. New York: McGraw-Hill. 590 páginas. ISBN 0-07-065416-6 
  • ZIMMERMANN, Carlos Jorge (1981). Processamento Interativo: a Linguagem de Programação APL. Rio de Janeiro: LTC. ISBN 85-216-0138-7