2. Quem é o Instrutor?
2
Marcelo Tomio Hama:
- Líder Técnico de Eng. de TI - ID & Auth (Itaú Unibanco)
- Prof. Docente Universitário (Fac. Metropolitanas Unidas)
Titulações:
- Bacharel em Ciência da Computação - Univ. Estadual Paulista;
- Mestre em Computação - Univ. Federal do Rio Grande do Sul;
- MBA - Fundação Instituto de Administração.
Experiência Profissional:
- 2006 ~ 2010: Depto de inf. Anglo Prudentino, Ministério da
Educação;
- 2010 ~ 2014: Start-ups e Inovação;
- 2014 ~ 2016: Núcleo de Informação do .BR;
- 2016 ~ 2018: Mercado Livre & Mercado Pago LatAm;
- 2018 ~ Atual: Itaú Unibanco.
3. Aulas e Cronograma
3
Aula Tema
1 Fundamentos de Linguagem de Programação
2 Evolução das Principais Linguagens de Programação - Parte I
3 Evolução das Principais Linguagens de Programação - Parte II
4 Aspectos Sintáticos e Semântico Básicos de Linguagens de Programação - Parte I
5 Aspectos Sintáticos e Semântico Básicos de Linguagens de Programação - Parte II
6 Paradigma Estruturado vs Paradigma Orientado a Objeto
7 Paradigma Funcional - Conceitos
8 Paradigma Funcional - Aplicações
9 Estudo Comparativo
10 Paradigma Lógico
11 Paradigma Concorrente - Conceitos
12 Paradigma Concorrente - Aplicações
13 Novos Paradigmas de Linguagens de Programação
14 Integração de Conhecimento
15 Integração de Conhecimento
16 Integração de Conhecimento
4. Bibliografia
4
Básica
● SEBESTA,Robert W. Conceitos de Linguagens de Programação, 9a edição, 2011. ISBN: 9788577808625
[recurso eletrônico, Biblioteca Virtual];
● AHO, Alfred V., LAM, Mônica S., SETHI, Ravi, ULLMAN, Jeffrey D., Compiladores: Princípios, Técnicas e
Ferramentas [recurso eletrônico, Biblioteca Virtual]. São Paulo: Pearson Addison-Wesley, 2008;
● NOOMAN, R.; TUCKER, A. B. Linguagens de Programação - Princípios e Paradigmas - 2a Ed. Mcgraw-hill
Interamericana. 2009. [recurso eletrônico, Biblioteca Virtual].
Complementar
● MULTI-LEVEL MODEL ACCESS IN WEB SYSTEMS USING ASPECT-ORIENTED PROGRAMMING. By:
Francisco, Maxwell Queiroz; de Oliveira Vasconcelos, Felype Nery; da Silva Andrade, Richardson Bruno;
Ferreira, Aida Araújo. Revista Brasileira de Administração Científica. ago2012, Vol. 3 Issue 2, p57-70. 14p.
Language: Portuguese. DOI: 10.6008/ESS2179-684X.2012.002.0004. [Base de dados: Academic Search
Premier];
● JOQUE, J. The Invention of the Object: Object Orientation and the Philosophical Development of Programming
Languages. Philosophy & Technology. 29, 4, 335-356, Dec. 2016. ISSN: 22105433. [Base de dados: Ebesco]
● New Paradigms for Computing, New Paradigms for Thinking. Disponível em:
https://web.media.mit.edu/~mres/papers/new_paradigms/new_paradigms.html;
● MYERS, BA; PANE, JF; KO, A. NATURAL PROGRAMMING LANGUAGES AND ENVIRONMENTS.
Communications of the ACM. 47, 9, 47-52, Sept. 2004. ISSN: 00010782. [Base de dados: Ebesco];
● HARRISON, W; ADRANGI, B. The Role of Programming Language in Estimating Software Development Costs.
Journal of Management Information Systems. 3, 3, 101-110, 1986. ISSN: 07421222. [Base de dados: Ebesco].
5. Para Começarmos...
5
Dentro do seu conhecimento atual:
O que é Paradigma de Linguagens de
Programação e qual a sua importância?
Elabore suas idéias para discutirmos
em nossa próxima aula
6. AULA 1
Fundamentos de Linguagens de
Programação
6
Paradigmas de Linguagens de
Programação
8. Linguagens de Programação
8
Desde quando elas existem?
Porque existem várias delas?
Para quais tarefas as usamos?
O que é importante haver nelas?
Nós as compreendemos facilmente?
Em que tipos de computadores as usamos?
9. Linguagens de Programação
9
Desde quando elas existem?
Plankalkül (primeira linguagem em 1942) / Fortran (uso comercial em 1956)
Porque existem várias delas?
Para quais tarefas as usamos?
O que é importante haver nelas?
Nós as compreendemos facilmente?
Em que tipos de computadores as usamos?
10. Linguagens de Programação
10
Desde quando elas existem?
Plankalkül (primeira linguagem em 1942) / Fortran (uso comercial em 1956)
Porque existem várias delas?
Diferentes problemas precisam de diferentes abstrações e paradigmas
Para quais tarefas as usamos?
O que é importante haver nelas?
Nós as compreendemos facilmente?
Em que tipos de computadores as usamos?
11. Linguagens de Programação
11
Desde quando elas existem?
Plankalkül (primeira linguagem em 1942) / Fortran (uso comercial em 1956)
Porque existem várias delas?
Diferentes problemas precisam de diferentes abstrações e paradigmas
Para quais tarefas as usamos?
Aplicações científicas e empresariais, Inteligência Artificial, software para web
O que é importante haver nelas?
Nós as compreendemos facilmente?
Em que tipos de computadores as usamos?
12. Linguagens de Programação
12
Desde quando elas existem?
Plankalkül (primeira linguagem em 1942) / Fortran (uso comercial em 1956)
Porque existem várias delas?
Diferentes problemas precisam de diferentes abstrações e paradigmas
Para quais tarefas as usamos?
Aplicações científicas e empresariais, Inteligência Artificial, software para web
O que é importante haver nelas?
Legibilidade, redigibilidade, expressividade, confiabilidade, custo
Nós as compreendemos facilmente?
Em que tipos de computadores as usamos?
13. Linguagens de Programação
13
Desde quando elas existem?
Plankalkül (primeira linguagem em 1942) / Fortran (uso comercial em 1956)
Porque existem várias delas?
Diferentes problemas precisam de diferentes abstrações e paradigmas
Para quais tarefas as usamos?
Aplicações científicas e empresariais, Inteligência Artificial, software para web
O que é importante haver nelas?
Legibilidade, redigibilidade, expressividade, confiabilidade, custo
Nós as compreendemos facilmente?
Depende de: paradigma, nível de abstração, conhecimento do programador
Em que tipos de computadores as usamos?
14. Linguagens de Programação
14
Desde quando elas existem?
Plankalkül (primeira linguagem em 1942) / Fortran (uso comercial em 1956)
Porque existem várias delas?
Diferentes problemas precisam de diferentes abstrações e paradigmas
Para quais tarefas as usamos?
Aplicações científicas e empresariais, Inteligência Artificial, software para web
O que é importante haver nelas?
Legibilidade, redigibilidade, expressividade, confiabilidade, custo
Nós as compreendemos facilmente?
Depende de: paradigma, nível de abstração, conhecimento do programador
Em que tipos de computadores as usamos?
Mainframes, Desktops, Smartphones, Embarcados, IoT
15. Motivações para Estudar Linguagens de Programação
15
Aumento da capacidade de expressão de ideias
Embasamento para escolher linguagens mais adequadas
Aumento da habilidade em aprender outras linguagens
Melhor entendimento da importância da implementação
Melhor uso das linguagens já conhecidas
Avanço geral da computação
Entender como compará-las
16. Como comparar? Quais Critérios?
16
Legibilidade: facilidade de entendimento da linguagem,
melhorando sua manutenção e diminuindo custo e tempo
para atualizações.
Redigibilidade: facilidade de escrita de uma linguagem,
aumentando a velocidade da programação.
Confiabilidade: facilidade de adequação à especificação
geral do programa implementado, minimizando chances de
ambiguidades e falhas.
Custo: Sofre influência dos critérios anteriores e mais
outros: portabilidade, generalidade, documentação, etc.
17. Legibilidade
17
Simplicidade
Impactada pelo número de construções básicas e palavras-chave,
multiplicidade de recursos, sobrecarga de operadores
Dois exemplos de não-simplicidade: Em ObjectiveC, o operador caracter "-" (menos) possui a função
de indicar um método de instância além de ser operador matemático. Em Java temos o operador
ternário para testes booleanos.
18. Legibilidade
18
Ortogonalidade
Indica o quanto as estruturas, operadores e tipos de uma linguagem podem ser
combinados entre si, gerando mais possibilidades de construções.
Exemplo de ortogonalidade: Em Assembl o operador MOV pode receber tanto registradores quanto
variáveis ou ainda constantes. Contra-exemplo de ortogonalidade: Em C uma função pode retornar
uma struct mas não um vetor (apenas o ponteiro dele).
19. Legibilidade
19
Tipagem de Dados
Os tipos devem ser claros e representativos, cada qual tendo a semântica
adequada para os dados que representam.
Exemplo de tipagem ruim: o PHP é uma linguagem de baixa tipagem que, apesar de flexível, faz com
que seja mais difícil prever e tratar inconsistências. Uma variável pode assumir qualquer valor.
Outro exemplo: suponha uma linguagem em que o tipo booleano não exista. Como poderíamos fazer
para representar uma flag de sistema?
20. Legibilidade
20
Projeto de Sintaxe
Determina as regras léxicas e sintáticas da gramática da linguagem.
Em ADA os laços são finalizados usando a mesma palavra-chave de início, deixando claro qual tipo
de laço está sendo fechado. Usar "}" (chaves) para fechar laços não deixam isso claro.
Problemas: Em Fortran95, as palavras Do e End são nomes válidos de
variáveis. Em C, a palavra static tem semântica que depende do contexto.
Dentro de método (criada em compilação) ou fora dos métodos (uso local).
21. Redigibilidade
21
Suporte para Abstrações
É a combinação equilibrada entre simplicidade e ortogonalidade.
As construções básicas fornecem ferramentas para o programador. Mas um
grande número de construções faz com que nem todas elas sejam conhecidas,
abrindo possibilidade para usos incorretos ou não intencionais.
A ortogonalidade permite combinar recursos e dar mais poder para a
linguagem. Mas a ortogonalidade excessiva pode causar uma sintaxe aberta
demais, tornando difícil que compiladores detectem problemas sintáticos.
22. Redigibilidade
22
Expressividade
Quanto mais expressiva é a linguagem, menos código é necessário.
Exemplo de diferentes expressividades, com laços FOR em C e Assembly.
Em ADA os laços são finalizados usando a mesma palavra-chave de início,
deixando claro qual tipo de laço está sendo fechado. Usar "}" (chaves) para
fechar laços não deixam isso claro.
Em C, podemos incrementar variáveis através do operador "++".
Ao invés de V=V+1, podemos escrever V++.
23. Confiabilidade
23
Verificação de Tipos
A verificação de tipos, em tempo de compilação e/ou execução, aumenta a
confiabilidade de que o programa está livre de inconsistências.
Contra-Exemplo: a versão inicial da linguagem C não tinha verificação do tipo
do parâmetro nas funções. Uma função com parâmetro INT poderia ser
chamada com um parâmetro do tipo FLOAT. Esse tipo de construção pode
ocasionar falhas difíceis de serem detectadas.
Exemplo de declaração de função em C.
24. Confiabilidade
24
Tratamento de Exceções
Identificar e tratar exceções em tempo de execução reduz a ocorrência de
falhas e aumenta a confiabilidade do programa executado.
Construção TRY/CATCH existente em Java
25. Confiabilidade
25
Apelidos Restritos
Apelidos são referências ou nomes para um mesmo endereço de memória. A
existência destas construções aumenta a flexibilidade da programação mas
pode ocasionar falhas de difícil identificação.
A linguagem C implementa ponteiros. Essa ferramenta pode, por vezes, ser perigosa.
Alterar o valor referenciado por um ponteiro altera o valor referenciado por outros ponteiros a esta
mesma referência.
26. Custo
26
Treinamento Técnico
Os custos da mão de obra operacional
Escrita dos Programas
Os custos da escrita do programa impactados pela legibilidade e redigibilidade
Compilação dos Programas
Os custos para compilar os programas (tempo e recursos)
Execução dos Programas
Os custos para executar os programas, tais como verificações ou velocidade
Sistema Implementado
Os custos e interoperabilidades do hardware necessário
Confiabilidade
Os custos para mitigar possíveis falhas dos programas
Manutenibilidade
Os custos para dar manutenções
27. Critérios para Avaliar Linguagens
27
Há 4 critérios para avaliarmos:
- Facilidade de leitura Há Trade-offs! A melhora
- Facilidade de escrita de algumas características
- Confiabilidade implica na piora de outras
- Custo
Característica que
impactam os critérios
Legibilidade Redigibilidade Confiabilidade
Simplicidade X X X
Ortogonalidade X X X
Tipagem de Dados X X X
Projeto da Sintaxe X X X
Suporte para Abstração X X
Expressividade X X
Verificação de Tipos X
Tratamento de Exceções X
Apelidos Restritos X
28. Influências e Categorias das Linguagens
28
Programação Imperativa (Arquitetura von Neumann)
Praticamente todos os computadores digitais construídos desde 1940 são
influenciados pela arquitetura de von Neumann, sendo o paradigma imperativo
uma característica das linguagens usadas.
- Variáveis modelam endereços de memória;
- Atribuições e operações de envio de dados;
- Ciclos de computação pela CPU;
- Enfatiza a mudança de estados das variáveis e os algoritmos.
Programação Funcional
Em contraste ao paradigma imperativo, há o paradigma funcional em que a
ênfase da programação é dada às funções e suas sentenças.
Exemplo de uma função que retorna 12, em linguagem Scheme:
((lambda (x) (+ x x)) (* 3 4))
29. Influências e Categorias das Linguagens
29
Programação Lógica
Na programação lógica implementa-se um conjunto pré-definido de regras as
quais são assumidas como verdades. A computação é realizada através de
"queries" a este conjunto de regras.
Prolog é uma das principais linguagens lógicas:
rei(arthur)
acesa(luz) :- ligado(interruptor)
?- rei(arthur)
yes.
Programação Orientada
Objetos do mundo real são modelados em classes, possuindo propriedades
específicas tais como herança, polimorfismo, abstração, e encapsulamento.
Exemplo da propriedade da herança:
Professor e alunos herdam propriedades em comum de Pessoa,
e especificam propriedades adicionais inerentes de cada um.
30. Métodos de Implementação
30
Em geral, as linguagens de
programação são implementadas em
compiladores, que possuem
componentes para análises léxicas e
análises sintáticas para produzirem
códigos intermediários que serão
verificados semanticamente.
Opcionalmente, é possível incluir
otimizações para que o código criado
seja mais eficiente.
Ao final, o código intermediário é
traduzido para a linguagem de
máquina que será executada com os
devidos parâmetros de entrada.
31. Ambientes de Programação
31
São ambientes criados para a escrita de programas. Possuem uma série de
ferramentas destinadas a ajudar na leitura, escrita, confiabilidade, e custo das
linguagens.
32. Exercícios em Sala
32
Em grupos de 4 a 6 alunos:
Escolha 3 linguagens de programação de seu conhecimento e compare-as
segundo os critérios estudados:
- simplicidade,
- ortogonalidade,
- tipagem de dados,
- projeto de sintaxe,
- suporte para abstração,
- expressividade,
- verificação de tipos,
- tratamento de exceções,
- apelidos restritos.
Na comparação, construa uma tabela com cada critério, dando uma nota de 1
(baixo/ruim) a 5 (alto/bom) para cada critério e exemplificando com exemplo de
código.
33. Exercícios para casa
33
1. Você acredita que nossa capacidade de abstração é influenciada por
nosso domínio de linguagens? Defenda sua opinião.
2. Cite alguns dos recursos de linguagens de programação específicas
que você conhece cujo objetivo seja um mistério para você.
3. Que argumentos você pode dar a favor da ideia de uma única
linguagem para todos os domínios de programação?
4. Que argumentos você pode dar contra a ideia de uma única
linguagem para todos os domínios de programação?
5. Nomeie e explique outro critério pelo qual as linguagens podem ser
julgadas (além dos discutidos neste capítulo).
6. Que sentença comum das linguagens de programação, em sua
opinião, é mais prejudicial à legibilidade?
34. AULA 2
Evolução das Principais Linguagens
de Programação - Parte I
34
Paradigmas de Linguagens de
Programação
35. Você acredita que nossa capacidade de abstração é influenciada por nosso domínio de
linguagens? Defenda sua opinião.
35
37. Qual o Motivo de Várias Linguagens?
37
Para termos diferentes formas de se escrever a mesma
solução, dado o contexto em que o problema está definido.
Pedindo socorro, de diferentes formas:
Socorro! Help!
助けて!
. . . _ _ _ . . .
Mayday
Na programação
de computadores o
conceito é similar:
dependendo do
problema a ser
resolvido, escrever
a mesma solução
de outra maneira
pode ser melhor!
38. Como as Coisas Começaram...
38
Programar computadores nem sempre foi uma tarefa prática. Ainda hoje, é
uma tarefa complexa, mas antigamente as coisas eram muito piores!
39. A Primeira Linguagem de Programação: Plankakul
39
Em 1945, Plankakul foi definida na tese de doutorado do
alemão Konrad Zuse. Sua publicação ocorreu só em 1972;
Junto com sua definição, foram fornecidos exemplos de
programas para diversos tipos de problemas;
Plankakul significa "cálculo de programas";
Jamais foi implementada para uso computacional. Menção
meramente a caráter de estudo;
Marco histórico: Plankakul é a primeira linguagem de
programação.
40. A Primeira Linguagem de Programação: Plankakul
40
Plankakul (Zuse, 1945): Hello World
41. A Primeira Linguagem de Programação: Plankakul
41
Plankakul (Zuse, 1945): Hello World
[m x sig] Array de sinais
[W] Wiederholungsplan (repetir plano)
[->] Implikation (condição se)
[=>] Atribuição
- Linguagem relativamente completa e com muitas funcionalidades;
- Notação complexa para implementação;
- Elaborada de forma isolada, no cenário de conflito da guerra;
- Complemento: http://www.thecorememory.com/Zuse_Plan_Kalkul.pdf
43. Linguagem de Montagem & Pseudocódigos
43
Entre 1940 e 1950 os computadores eram lentos, caros, e limitados. A
programação era feita através de códigos de máquina (sequer haviam nomes
para as instruções). Uma instrução inserida no meio do programa invalidava o
programa do ponto de inserção em diante por conta do endereçamento
absoluto. Tais problemas incentivaram a seguintes iniciativas:
Shortcode: criada por John Mauchly em 1949, visava a simplificação da
programação. Usava um interpretador ao invés de ser convertida para
linguagem de máquina.
Speedcoding: John Backus o criou para o IBM 701 em 1954, visando o
suporte para ponto-flutuante.
Compilação UNIVAC: Entre 1951 e 1953, Grace Hopper e sua equipe
desenvolvem uma série de sistemas (A-0, A-1, e A-2) para otimizar a
compilação de programas para o UNIVAC.
44. Assembly - Hello World!
44
section .text ;section declaration
;we must export the entry point to the ELF linker or
global _start ;loader. They conventionally recognize _start as their
;entry point. Use ld -e foo to override the default.
_start:
;write our string to stdout
mov edx,len ;third argument: message length
mov ecx,msg ;second argument: pointer to message to write
mov ebx,1 ;first argument: file handle (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel and exit
mov ebx,0 ;first syscall argument: exit code
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data ;section declaration
msg db "Hello, world!",0xa ;our dear string
len equ $ - msg ;length of our dear string
IDE Online: https://www.jdoodle.com/compile-assembler-nasm-online/
Documentação: https://docs.oracle.com/cd/E19253-01/817-5477/817-5477.pdf
45. Fortran (FORmula TRANslation)
45
Cenário: computadores com memórias limitadas, lentos e não-confiáveis.
Computação para uso científico. Inexistência de maneiras efetivas de
programação. Velocidade de código como objetivo principal;
Em 1954, o IBM 704 (hardware com suporte a ponto-flutuante) permite o
desenvolvimento do Fortran;
Fortran I foi publicada pela IBM em 1957, e incluía formatação de
entrada/saída, nomes de variáveis em até 6 caracteres, sub-rotinas, e
sentenças IF e DO;
Ao longo de sua evolução teve as versões I, II, III, IV, 77, 90, 95, 2003, e 2008;
Os projetistas não imaginaram que Fortrans seria usado em computadores que
não fossem da IBM;
Marco histórico: é a primeira linguagem amplamente usada e implementada.
46. Fortran (FORmula TRANslation) - Fatorial Recursivo
46
program factorial_example
integer :: factorial,n
n = 5
write(*,"('Factorial of ',i3,' = ',i7)") n,factorial(n)
end program factorial_example
recursive function factorial( n ) result( f )
integer f
integer, intent( in ) :: n
if ( n <= 0 ) then
f = 1
else
f = n * factorial( n-1 )
end if
end function factorial
IDE Online: https://www.jdoodle.com/execute-fortran-online/
Documentação: https://www.fortran90.org/
Exemplo: Hello World!
47. LISP (LISt Processing)
47
Cenário: em 1950, houve crescente interesse no processamento de listas: IA,
process. de linguagem, modelagem de informação, e provas de teoremas;
O conceito de processar listas foi criado por Allen Newell, J.C. Shaw, e Herbert
Simon, com a linguagem IPL (Information Processing Language), mas não
vingou por conta da baixa popularidade e à máquina de implementação;
Em 1958, John McCarthy e Marvin Minsky iniciam o desenvolvimento de LISP.
LISP pura tem 2 tipos de dados: átomos e listas. Exemplo: (A (B C) (E (F G)));
A sintaxe de (A B C) é "função A aplicada aos parâmetros B e C). Atribuições e
variáveis não são necessários, e laços podem ser definidos com recursão;
Scheme (1970): dialeto LISP com funções como entidades de primeira classe);
Common Lisp: dialeto LISP com portabilidade e suporte a outros dialetos LISP;
Marco histórico: é a primeira linguagem do Paradigma Funcional.
48. LISP (LISt Processing) - Fatorial Recursivo
48
(defun factorial (n)
(if (zerop n) 1 (* n (factorial (1- n)))))
(format t "~D! is ~D" 6 (factorial 6))
IDE Online: https://www.jdoodle.com/execute-clisp-online/
Documentação: https://lisp-lang.org/
Exemplo: Hello World!
(format t "Hello, World!")
49. Algol (ALGOrithmic Language)
49
Cenário: com a disseminação das linguagens, programas começaram a ser de
difícil compartilhamento. Ainda, tais linguagens cresciam em torno de
arquiteturas específicas (Univac e IBM 700);
Em 1957 uma petição é enviada à ACM (Association of Computing Machinery),
para desenvolver uma linguagem universal. A GAMM (Sociedade de
Matemática e Mecânica Aplicada) trabalhava na Europa em seu próprio projeto
de linguagem universal, e une-se à ACM, para um trabalho conjunto.
Próxima do padrão matemático, programas legíveis com poucas explicações,
algoritmos descritível para publicações, e traduzível em código de máquina;
Teve o formalismo da notação BNF e influência de Fortran. Influenciou C,
Pascal, Ada, C++, Java, e C#. Fracassou em ser usada de forma majoritária,
tanto na ACM/EUA quanto na GAMM/Europa;
Marco histórico: é a primeira linguagem independente de máquina e sem dono.
50. Algol (ALGOrithmic Language) - Fatorial Recursivo
50
PROC factorial = (INT n) LONG LONG INT:
CASE n+1 IN
1,1,2,6,24,120,720 # a brief lookup #
OUT
n*factorial(n-1)
ESAC
;
INT k = 5;
print(( "Factorial of ", k, " is "));
print(("",whole(factorial(5),0)))
IDE Online: https://www.tutorialspoint.com/execute_algol_online.php
Documentação: https://jmvdveer.home.xs4all.nl/learning-algol-68-genie.pdf
Exemplo: Hello World!
print("Hello world!")
51. Cobol
51
Cenário: Em 1959, o estado da computação para negócios era similar ao da
computação para ciência e havia a necessidade de uma linguagem que tivesse
foco em registros;
Em 1955, Grace Hopper havia proposto o Flow-Matic, uma linguagem para uso
comercial, com sintaxe semelhante ao inglês. Flow-Matic viria a ser uma das
principais influências para o Cobol;
Em 1959, houve a primeira reunião formal no Pentágono para a definição de
uma linguagem comercial universal, que deveria ser semelhante ao inglês e
fácil de programar;
Cobol existe ainda hoje devido ao seu sucesso em atender os requisitos que
se propunha. É, porém, pouco difundida pois seu nicho de aplicação é restrito
a poucas empresas;
Marco histórico: Cobol é a primeira linguagem comercial universal.
52. Cobol - Fatorial Recursivo
52
IDENTIFICATION DIVISION.
PROGRAM-ID. RECURSE1 IS RECURSIVE.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 N PIC 9(05) VALUE 5.
01 WS-FACTOR PIC 9(05).
LOCAL-STORAGE SECTION.
01 LS-NUM PIC 9(05).
PROCEDURE DIVISION.
00000-MAIN.
MOVE N TO LS-NUM.
IF N = 0
MOVE 1 TO WS-FACTOR
ELSE
SUBTRACT 1 FROM N
CALL 'RECURSE1'
COMPUTE WS-FACTOR = WS-FACTOR * LS-NUM
END-IF.
DISPLAY 'FACTORIAL OF ' LS-NUM ' IS ' WS-FACTOR.
00000-EXIT.
GOBACK.
IDE Online: https://www.jdoodle.com/execute-cobol-online/
Documentação: Cobol Language Reference
Exemplo: Hello World!
IDENTIFICATION DIVISION.
PROGRAM-ID. HELLO.
PROCEDURE DIVISION.
DISPLAY 'Hello World!'.
GOBACK.
END PROGRAM HELLO.
53. Basic (Beginner's All-purpose Symbolic Instruction Code)
53
Cenário: Programar era uma tarefa complexa para leigos em informática. Em
1960, John Kemeny e Thomas Kurtz projetam a primeira versão do Basic
usável por estudantes de humanas e engenharias;
A linguagem deveria ser fácil de aprender e usar, prazerosa e amigável,
eficiente e ágil, permitir acessos livres e privados, e considerar o tempo do
programador mais importante que o do computador;
Apesar de fácil de usar, era uma linguagem bastante limitada. Não havia
maneira de um programa em execução receber dados de entrada;
Em 1990, Basic ressurgiu e influenciou linguagens posteriores como o Visual
Basic (criação de GUI's com Basic) e o VB.NET;
Marco histórico: Basic foi a primeira linguagem criada para usuários comuns e
programável em computadores com terminais remotos.
54. Basic - Fatorial Recursivo
54
FUNCTION factorial (n AS Integer) AS Integer
IF n < 2 THEN
factorial = 1
ELSE
factorial = n * factorial(n-1)
END IF
END FUNCTION
print "Fatorial de 5! = ";factorial(5)
IDE Online: https://www.jdoodle.com/execute-freebasic-online/
Documentação: Basic Language Reference
Exemplo: Hello World!
print "Hello World!"
55. PL/I (Programming Language One)
55
Cenário: O mundo da programação se dividia em dois mundos: científico e de
negócios. Cada um com seus problemas específicos, suas linguagens, e suas
estruturas necessárias. Fortran e Cobol figuravam nestes dois mundos;
Em 1963, percebe-se que estes dois mundo estavam ficando mais próximos;
PL/I incluía os principais recursos do Fortran (pontos flutuantes e compilação
separada por dados globais), Algo 60 (recursão e estrutura de blocos), e Cobol
60 (estruturas de dados, entrada/saída, e funcionalidades para relatórios);
PL/I era, no entanto, complexa e com recursos demais. Havia ainda muitos
recursos deficientes (i.e. ponteiros, exceções, e concorrência);
Marco histórico: PL/I realiza uma "integração" com os principais recursos de
linguagens de programação da época.
56. PL/I (Programming Language One) - Fatorial Recursivo
56
factorial: procedure (N) returns (fixed decimal (30));
declare N fixed binary nonassignable;
declare i fixed decimal (10);
declare F fixed decimal (30);
if N < 0 then signal error;
F = 1;
do i = 2 to N;
F = F * i;
end;
return (F);
end factorial;
Material Complementar: https://www.whoishostingthis.com/resources/pl-i/
Exemplo: Hello World!
HelloWorld: proc options (main);
put skip list("Hello World!");
end HelloWorld;
57. Outras Linguagens
57
APL e Snobol: Em 1960, APL foi projetada para descrever arquiteturas de
computador tendo um grande número de operadores. Snobol veio no mesmo
ano, para trabalhar com padrões de cadeias em editores de texto;
Marco histórico: APL e Snobol inauguraram o dinamismo de tipagem e de
alocação de memória.
Simula 67: Em 1964, Simula foi implementada para atender as necessidades
de simulação de sistemas. Simula é uma extensão de Algol 60, e adicionou o
conceito de classe.
Marco histórico: Simula traz as primeiras ideias de abstração de dados que,
posteriormente, seria a base para a orientação a objetos.
58. Árvore Genealógica (Linguagens de Programação)
58
Assista ao vídeo Linguagens Populares:
https://www.youtube.com/watch?v=Og847HVwRSI
60. Exercícios em Sala
60
Para cada uma das linguagens: Assembly, Fortran, Lisp, Algol, Cobol, e
Basic, execute as seguintes tarefas:
1. Implemente o pseudocódigo:
x = 10
enquanto x > 0 faça
x = x - 1
fim-enquanto
2. Em um quadro/planilha, compare as implementações quanto a :
a. Número de linhas de código
b. Número de palavras-chave utilizadas
c. Quantidade de caracteres do código
d. Tempo de execução do código (use uma IDE)
e. Memória usada (use uma IDE)
3. Elabore um relatório para ser entregue até o final desta aula.
61. Exercícios para casa
61
1. Que características Ruby tem em comum com Smalltalk?
2. Em que linguagem de programação Cobol foi baseada?
3. Por quê Basic foi uma linguagem importante no início dos anos 1980?
4. Assista a vídeo-aula disponível em:
https://www.youtube.com/watch?v=EefVmQ2wPlM
E elabore 1 pergunta para trazer na próxima aula.
62. AULA 3
Evolução das Principais Linguagens
de Programação - Parte II
62
Paradigmas de Linguagens de
Programação
63. Prática em Laboratório
63
Individual ou em duplas
Estudaremos e analisaremos cada uma das seguintes linguagens:
Pascal/Delphi, C, Prolog, Ada, Smalltalk, C++,
Objective-C, Java, Perl, JavaScript, PHP,
Python, Ruby, Lua, .NET C#, XSLT e JSP
Ao final da análise da dada linguagem, escolha uma das tarefas abaixo para
implementar uma função/método:
Cálculo de fatorial
Ordenação Bubble-Sort
Ordenação Quick-Sort
Leitura de entrada
Escrita em disco
Operação aritmética qualquer
Compilador Online: https://www.jdoodle.com/ Códigos: https://rosettacode.org/
64. Cenário: Algol 68 foi fonte de muitas ideias, como os tipos de dados definidos
pelos usuários (ampla ortogonalidade) e os vetores dinâmicos. Algumas
dessas características foram implementadas em seus descendentes;
Em 1971 Niklaus Wirth disponibiliza o Pascal, que trazia recursos de Algol
(ortogonalidade e seleção múltipla com case) e Cobol/PL/I (registros).
Com sua simplicidade e expressividade, Pascal era usada principalmente no
ensino da programação. Posteriormente, houve a adição de POO a Pascal, e a
linguagem passou a se chamar Delphi;
A linguagem C descende das linguagens CPL, BCPL, B, e Algo 68. Foi
projetada para ser usada na programação de sistemas, e publicada em 1978
por Kernighan e Ritchie.
C teve maior popularidade nos anos 80, quando um compilador C foi
introduzido no sistema operacional UNIX.
Descendentes de Algol: Pascal/Delphi e C
64
65. Prática em Laboratório
65
Individual ou em duplas
Estudaremos e analisaremos cada uma das seguintes linguagens:
Pascal/Delphi, C, Prolog, Ada, Smalltalk, C++,
Objective-C, Java, Perl, JavaScript, PHP,
Python, Ruby, Lua, .NET C#, XSLT e JSP
Ao final da análise da dada linguagem, escolha uma das tarefas abaixo para
implementar uma função/método:
Cálculo de fatorial
Ordenação Bubble-Sort
Ordenação Quick-Sort
Leitura de entrada
Escrita em disco
Operação aritmética qualquer
Compilador Online: https://www.jdoodle.com/ Códigos: https://rosettacode.org/
66. Prolog (PROgramming LOGic)
66
Cenário: Em 1970, Alain Colmerauer e Phillipe Roussel desenvolvem o projeto
fundamental de Prolog na Univ. de Edimbugo;
A programação lógica é não-procedural e usa o cálculo de predicados onde
são disponibilizadas informações de relevância para que a computação de
conclusões seja inferida;
Programas em Prolog consistem em coleções de sentenças (fatos e regras),
que podem vir a ser complexas. Um uso comum de Prolog é como base de
dados inteligente.
Nos anos 1980, um pequeno grupo de cientistas acreditava que a
programação lógica seria uma alternativa para escapar dos problemas da
programação imperativa (complexidade e quantidade de código). Esta crença
não se mostrou verdade até o momento e alguns dos motivos são a questão
da eficiência e o limitado escopo de aplicação do paradigma lógico.
67. Prática em Laboratório
67
Individual ou em duplas
Estudaremos e analisaremos cada uma das seguintes linguagens:
Pascal/Delphi, C, Prolog, Ada, Smalltalk, C++,
Objective-C, Java, Perl, JavaScript, PHP,
Python, Ruby, Lua, .NET C#, XSLT e JSP
Ao final da análise da dada linguagem, escolha uma das tarefas abaixo para
implementar uma função/método:
Cálculo de fatorial
Ordenação Bubble-Sort
Ordenação Quick-Sort
Leitura de entrada
Escrita em disco
Operação aritmética qualquer
Compilador Online: https://www.jdoodle.com/ Códigos: https://rosettacode.org/
68. Ada
68
Cenário: Em 1974, o Departamento de Defesa dos EUA usavam aplicações
majoritariamente executadas em sistemas eram embarcados, de diferentes
fabricantes, e não padronizados. O projeto de Ada foi proposto para padronizar
as tecnologias e permitir reuso de software;
Em 1975 o High-Order Language Working Group (HOLWG) é criado para criar
Ada. O HOLWG era composto por representantes de todas as esferas militares
americanas e representantes da Grã-Bretanha, França, e Alemanha Ocidental;
Houve uma série de atualizações das especificações: Strawman e
Woodenman (1975), Tinman (1976), Ironman (1977), Steelman (1978), e
Stoneman (1980). Ada trouxe uma amplo conjunto de ferramentas como
encapsulamento de dados, tipos genéricos, tratamento de exceções, e
concorrência;
O projeto Ada é considerado o mais caro e de maior esforço da história das
linguagens de programação.
69. Prática em Laboratório
69
Individual ou em duplas
Estudaremos e analisaremos cada uma das seguintes linguagens:
Pascal/Delphi, C, Prolog, Ada, Smalltalk, C++,
Objective-C, Java, Perl, JavaScript, PHP,
Python, Ruby, Lua, .NET C#, XSLT e JSP
Ao final da análise da dada linguagem, escolha uma das tarefas abaixo para
implementar uma função/método:
Cálculo de fatorial
Ordenação Bubble-Sort
Ordenação Quick-Sort
Leitura de entrada
Escrita em disco
Operação aritmética qualquer
Compilador Online: https://www.jdoodle.com/ Códigos: https://rosettacode.org/
70. Smalltalk
70
Cenário: Em 1960, Alan Kay desenvolve tese de doutorado que viria a ser a
base para o Smalltalk. Kay previu que computadores seriam usados por
pessoas comuns cada vez mais, e que uma interface homem-máquina de fácil
usabilidade deveria ser necessária;
Smalltalk tem suas raízes no sistema Dynabook, baseado na linguagem Flex
(que por sua vez, era baseada em Simula 67). Dynabook abstraia uma mesa
de trabalho com diversos papéis;
Smalltalk é a primeira linguagem com suporte completo para orientação a
objetos. O mundo Smalltalk é definido por objetos, e a computação usa sempre
o mesmo conceito: mensagens de objetos para objetos;
Smalltalk traz grandes evoluções para a computação como as interfaces
gráficas para os usuários e a orientação a objetos.
71. Prática em Laboratório
71
Individual ou em duplas
Estudaremos e analisaremos cada uma das seguintes linguagens:
Pascal/Delphi, C, Prolog, Ada, Smalltalk, C++,
Objective-C, Java, Perl, JavaScript, PHP,
Python, Ruby, Lua, .NET C#, XSLT e JSP
Ao final da análise da dada linguagem, escolha uma das tarefas abaixo para
implementar uma função/método:
Cálculo de fatorial
Ordenação Bubble-Sort
Ordenação Quick-Sort
Leitura de entrada
Escrita em disco
Operação aritmética qualquer
Compilador Online: https://www.jdoodle.com/ Códigos: https://rosettacode.org/
72. POO Imperativa: C++, Objective-C, e Java
72
Cenário: As ideias do paradigma da Orientação a Objetos trouxeram
importantes avanços na abstração da computação que motivaram esforços
para adicionar funcionalidades da POO para as linguagens imperativas;
C++
- C tem seu primeiro passo rumo a C++ em 1980 (Bjarne Stroustrup) com a
verificação de tipos e a conversão de parâmetros em funções e classes, controle de
acessos a componentes herdados, construtores/destrutores, e classes amigas. Este
projeto foi chamado de C com Classe.
- Em 1984 a linguagem recebeu a funcionalidade dos métodos virtuais, e passou a se
chamar C++. Em 1985 é feita a primeira implementação (release 1.0) com C++: o
sistema Cfront, que transformava programas C++ em C. Em 1989 é lançado o
release 2.0, com heranças múltiplas e classes abstratas. Em 1990 é lançado o
release 3.0, com templates e tratamento de exceções;
- Há grande número de compiladores e (quase sempre) compatibilidade com C. Os
pontos negativos de C++ são sua complexidade e menor confiabilidade.
73. POO Imperativa: C++, Objective-C, e Java
73
Objective-C
- Projetada Brad Cox e Tom Love no início dos anos 80, é uma linguagem híbrida de
C (imperativismo) com Smalltalk (POO);
- Foi a linguagem oficial da NeXT (empresa comprada pela Apple), que foi usada
para escrever o MAC OS X.
Java
- Em 1990, a Sun Microsystems observou a necessidade de uma linguagem para
embarcados eletrônicos (eletrodomésticos, TVs, etc), com confiabilidade satisfatória
para evitar custos com recalls;
- Foi considerado usar C ou C++. Mas C não tinha POO (uma necessidade), e C++
foi considerada complexa e extensa demais. Ainda, ambas foram consideradas ter
pouca confiabilidade;
- Os eletrodomésticos com suporte a Java não chegaram a ser comercializados.
Mas, após a World Wide Web comerçar a ser amplamente usada, observou-se a
aplicabilidade de Java para construir aplicações web.
74. Prática em Laboratório
74
Individual ou em duplas
Estudaremos e analisaremos cada uma das seguintes linguagens:
Pascal/Delphi, C, Prolog, Ada, Smalltalk, C++,
Objective-C, Java, Perl, JavaScript, PHP,
Python, Ruby, Lua, .NET C#, XSLT e JSP
Ao final da análise da dada linguagem, escolha uma das tarefas abaixo para
implementar uma função/método:
Cálculo de fatorial
Ordenação Bubble-Sort
Ordenação Quick-Sort
Leitura de entrada
Escrita em disco
Operação aritmética qualquer
Compilador Online: https://www.jdoodle.com/ Códigos: https://rosettacode.org/
75. Scripting: Perl, Lua, JavaScript, PHP, Python, e Ruby
75
Cenário: Linguagens de script evoluíram muito nas últimas décadas. As
primeiras eram usadas para chamar subprogramas e realizar funções
utilitárias;
Perl
- Perl foi criada por Larry Wall e era inicialmente uma combinação de shell e awk.
Muito similar a uma linguagem imperativa, é compilada e aplicada a uma variedade
de problemas computacionais;
- Inicialmente, Perl era usada como utilitário de arquivos de texto no ambiente UNIX,
e foi amplamente incorporada na World Wide Web como linguagem de interface de
gateway. Hoje em dia, tem se tornado raro vê-la, pois vem sendo substituída por
outras linguagens.
Lua
- Projetada em 1990 por Roberto Ierusalimschy, Waldemar Celes, e Luis Henrique de
Figueiredo. É uma linguagem pequena e de paradigmas procedurais e funcionais.
76. Scripting: Perl, Lua, JavaScript, PHP, Python, e Ruby
76
JavaScript
- Criada por Brendam Eich, JavaScript foi lançada em 1995 tendo antes sido
chamada de LiveScript e Mocha. Foi criada tendo em vista a necessidade de
dinamização de conteúdos HTML, que é estática por si apenas;
- Apesar do nome, JavaScript relaciona-se com Java apenas na sintaxe similar. Java
tem tipagem forte e suporte completo a POO, ferramentas ausentes em JavaScript;
- Programar em JavaScript é programar para navegadores. O código é embarcado
juntamente com o HTML e interpretado pelo navegador. Em geral, é usado para
validar campos de entrada antes de serem enviados ao servidor.
PHP
- PHP (PHP: Hypertext Preprocessor) foi criada por Rasmus Lerdorf em 1994, e seu
objetivo inicial era ser uma ferramenta de rastreamento de visitantes a sites;
- É uma linguagem de scripting do lado do servidor que gera código HTML. Há
suporte a POO com classes (sem classes abstratas ou interfaces).
77. Scripting: Perl, Lua, JavaScript, PHP, Python, e Ruby
77
Python
- Projeto inicial criado por Guido van Rossum em 1990. É usada praticamente para
as mesmas tarefas que Perl: administração de sistemas, programação para a web,
e outras tarefas de pequena a média complexidade;
- Possui suporte a POO, verificação de tipos, tipagem dinâmica, tratamento de
exceções, redes, tuplas (listas e dicionários), e concorrência. Por possuir múltiplas
ferramentas e ser extensível, é usada hoje tanto em aplicações web como
processamentos de dados e informações.
Ruby
- Criada no início dos anos 1990 por Yukihiko Matsumoto, que estava insatisfeito com
os suportes a POO de Perl e Python. Ruby é, portanto, uma linguagem puramente
orientada a objetos: a computação é feita por objetos que enviam mensagens;
- Classes, objetos, métodos, e tipagem, são todos dinâmicos em Ruby. Um objeto
pode ter um método adicionado dinamicamente, em tempo de execução, e não há a
necessidade de declarar variáveis.
78. Prática em Laboratório
78
Individual ou em duplas
Estudaremos e analisaremos cada uma das seguintes linguagens:
Pascal/Delphi, C, Prolog, Ada, Smalltalk, C++,
Objective-C, Java, Perl, JavaScript, PHP,
Python, Ruby, Lua, .NET C#, XSLT e JSP
Ao final da análise da dada linguagem, escolha uma das tarefas abaixo para
implementar uma função/método:
Cálculo de fatorial
Ordenação Bubble-Sort
Ordenação Quick-Sort
Leitura de entrada
Escrita em disco
Operação aritmética qualquer
Compilador Online: https://www.jdoodle.com/ Códigos: https://rosettacode.org/
79. Outras Linguagens: .NET C#, XSLT, e JSP
79
C#
- Incorpora ideias de C++, Java, Delphi e Visual Basic. Foi criada para ser uma
linguagem de desenvolvimento baseada em componentes para o .NET e mescla
diversas funcionalidades de Java e C++;
XSLT (eXtensible Stylesheet Language for Transformation)
- XSLT é uma linguagem híbrida de marcação/programação definida pelo World Wide
Web Consortium (W3C – Consórcio Web) no fim dos anos 1990;
- Especifica a forma como documentos XML (a serem convertidos e exibidos via
HTML) devem ser apresentados, bem como adicionar ou esconder conteúdos. Tem
aplicação similar ao CSS.
JSP (Java Server Page)
- JSP é uma coleção de tecnologias projetadas para oferecer suporte a do- cumentos
Web dinâmicos e fornecer outras necessidades de processamento para
documentos Web;
- Tem por objetivo criar Java Servlets a partir de códigos Java e HTML.
80. Prática em Laboratório
80
Individual ou em duplas
Estudaremos e analisaremos cada uma das seguintes linguagens:
Pascal/Delphi, C, Prolog, Ada, Smalltalk, C++,
Objective-C, Java, Perl, JavaScript, PHP,
Python, Ruby, Lua, .NET C#, XSLT e JSP
Ao final da análise da dada linguagem, escolha uma das tarefas abaixo para
implementar uma função/método:
Cálculo de fatorial
Ordenação Bubble-Sort
Ordenação Quick-Sort
Leitura de entrada
Escrita em disco
Operação aritmética qualquer
Compilador Online: https://www.jdoodle.com/ Códigos: https://rosettacode.org/
81. Exercícios em Laboratório
81
1. Para entender o valor dos registros em uma linguagem de programação,
escreva um pequeno programa em uma linguagem baseada em C que use um
vetor de estruturas que armazenem informações de estudantes, incluindo o
nome, a ida- de, a média das notas como um ponto-flutuante e o nível do
estudante em uma cadeia (por exemplo, “calouro” etc.). Escreva também o
mesmo programa na mesma linguagem sem usar tais estruturas.
2. Para entender o valor da recursão em uma linguagem de programação,
escreva um programa que implemente o algoritmo quicksort, primeiro usando
recursão e então sem usar recursão.
3. Para entender o valor dos laços de iteração de contagem, escreva um
programa que implemente multiplicação de matrizes usando construções de
repetição ba- seadas em contagem. Então, escreva o mesmo programa
usando apenas laços de repetição lógicos – por exemplo, laços while.
82. Exercícios para casa
82
1. Cite 2 características que tornaram C menos segura que pascal.
2. Que característica de Java é mais evidente em Javascript?
3. Que estrutura de dados Python usa em vez de vetores?
84. Motivações
84
Diferenciar a Sintaxe da Semântica
Apesar de ocuparem-se de diferentes campos da análise de uma linguagem, a
sintaxe e semântica estão fortemente relacionadas.
Entender como as linguagens de programação são projetadas
Uma linguagem é um conjunto de regras léxicas, sintáticas, e semânticas, que
estabelecem o conjunto de lexemas e como estes se relacionam e criam
significados.
Agregar conhecimento para comparar diferentes paradigmas
Conhecendo as regras sintáticas e semânticas e como estas definem a
construção das linguagens de programação nos dá mais ferramentas para
analisar e comparar seus paradigmas.
Quais as nossas motivações para estudar a sintaxe
e a semântica das linguagens de programação?
85. Contexto Histórico
85
ALGOL 60 e ALGOL 68 foram as primeiras linguagens a serem definidas por
meio de descrições formais. E em ambos os casos, houveram dificuldades no
entendimento inicial;
Um dos problemas em se descrever a sintaxe e a semântica: muitas pessoas
podem usar as linguagens e é preciso que as regras sintáticas e semânticas
sejam claras para todos;
Descrever a sintaxe é mais simples que descrever a semântica. A sintaxe
precisa "apenas" de um conjunto de regras gramaticais, enquanto que a
semântica necessita de interpretação de quem projeta, lê, e implementa;
Para propósitos de discussão, a sintaxe e a semântica são separadas, mas
existe uma relação muito forte entre ambas. Em uma linguagem bem
projetada, a aparência de uma sentença deve sugerir o que ela realiza.
86. Conceitos
86
Sintaxe
- Do grego súntaksis, (ordenação, disposição, arranjo)
- Estuda a estrutura e as regras gramaticais de uma linguagem
Grande aeroporto
adjetivo substantivo
Semântica
- Do grego semantikos (significativo, sinal, marcado)
- Estuda o significado das sentenças de uma linguagem
- O significado é mais complexo e pode depender do contexto
Grande
aeroporto
Grande
aeroporto
Grande
aeroporto
Há regras que definem como as palavras devem
estar estruturalmente organizadas para que o texto
esteja de acordo com a linguagem.
87. Conceitos
87
Sintaxe
- Do grego súntaksis, (ordenação, disposição, arranjo)
- Estuda a estrutura e as regras gramaticais de uma linguagem
Em Java, a sintaxe do laço while define que a palavra chave deve ser seguida de
uma expressão condicional entre parênteses, e de um bloco de instruções:
while (<expr>) { <instruction>; }
Semântica
- Do grego semantikos (significativo, sinal, marcado)
- Estuda o significado das sentenças de uma linguagem
- O significado é mais complexo e pode depender do contexto
Em Java, a semântica do laço while é:
Enquanto a condicional for verdadeira, execute o bloco de instruções
88. Semântica em Linguagens de Programação
88
Semântica em Linguagens de Programação
- São implementadas conforme uma metodologia escolhida
- Devem considerar a finalidade da linguagem de programação
Tipos de Semânticas
- Operacional: Descreve o significado de um programa pela execução de
suas instruções em uma máquina real ou simulada;
- Axiomática: Baseada em lógica (cálculo de predicados)
- Denotacional: Objetos do programa são definidos por entidades
matemáticas e funções recursivas de mapeamento
Motivações para Descrever a Semântica
- Saber precisamente o que as instruções de uma linguagem fazem;
- As provas de exatidão do programa recorrem a descrição formal da
semântica da linguagem.
89. Sintaxe em Linguagens de Programação
89
Sintaxe em Linguagens de Programação
- É definida/construída pelos projetistas da linguagem
- É seguida/obedecida pelos programadores da linguagem
Tipos de Gramáticas (Noam Chomsky, 1959)
90. Sintaxe em Linguagens de Programação
90
Regras de Produção das Gramáticas de
Chomsky
L A linguagem
N Conjunto de símbolos não-terminais
Σ Conjunto de símbolos terminais
P Conjunto de regras derivativas α -> β
S Símbolo inicial (S ∈ N)
ε Símbolo vazio
Gramáticas de Interesse
- Livres de Contexto (ex: analisadores
sintáticos, BNF)
- Regulares (ex: expressões regulares,
analisadores léxicos)
Regular (Tipo 3)
A -> wB
A -> Bw
A -> w
A -> ε
Onde w ∈ Σ* e A,B ∈ N
Livre de Contexto (Tipo 2)
A -> α
Onde α ∈ (Σ U N)*
Sensível a Contexto (Tipo 1)
u -> W
Onde u ∈ (Σ U N)* e W ∈ (Σ U N)*
e com |u| ≤ |W|
Irrestrita (Tipo 0)
u -> W
Onde u ∈ (Σ U N)* e W ∈ (Σ U N)*
91. Sintaxe em Linguagens de Programação
91
Terminologias Importantes
- Linguagem: conjunto de sentenças;
- Sentença: cadeia de caracteres de
um determinado alfabeto;
- Lexema: unidade básica de uma
construção sintática;
* if while
+ var 255
- Token: categoria de um lexema;
identificador
operador
keyword
LEXEMA TOKEN
index identificador
= atribuidor
2 literal_inteiro
* operador
count identificador
+ operador
17 literal_inteiro
; fecha_instrucao
Por exemplo, suponha:
index = 2 * count +17;
Neste exemplo, os lexemas e
tokens são:
92. Existem 2 possíveis abordagens para definir uma linguagem:
- Reconhecimento: suponha uma linguagem L com um alfabeto S de
caracteres. Para definir formalmente L cria-se um dispositivo R que lê as
cadeias de caracteres do alfabeto S. Assim, R poderá indicar se uma
linguagem é ou não aceita, sendo portanto uma descrição de L. O
reconhecedor não deve prever todas as possíveis combinações de
construções, mas sim dizer se um programa de computador em específico
é escrito em linguagem L.
- Geração: Um gerador é um dispositivo que gera sentenças de uma
linguagem L. Apesar de mais legível, as construções não são muito úteis
aos programadores, visto que podem ser usadas apenas em modo de
tentativa e erro.
O Problema Geral da Descrição da Sintaxe
92
93. Suponha a linguagem L, com um alfabeto S = {a, e, i, o, u}. Como regra de
construção dos lexemas, há apenas a restrição de que os símbolos do alfabeto
S não se repetem em uma sentença. Usando uma linguagem de programação
do seu domínio:
1. Construa um reconhecedor para L, que retorne TRUE ou FALSE para uma
determinada sentença, indicando se tal sentença pertence à L. Faça testes
com as sentenças "aeiou", "aeaea", e "abcde".
2. Construa um gerador para L, que retorne o conjunto de todos os lexemas da
linguagem L. Exiba tem tela este conjunto.
Prática em Laboratório (individual, 15 minutos)
93
94. Métodos Formais para Descrever Sintaxe
94
Contexto Histórico
Em 1950, Noam Chomsky e John Backus desenvolvem, separadamente,
formalismos para descrever gramáticas.
Chomsky descreve 4 tipos de gramáticas, das quais 2 foram úteis para
aplicações nas linguagens de programação:
Regulares: aplicável ao tokens
Livres de Contexto: aplicável a sintaxe das linguagens
John Backus, em trabalhos para o projeto ALGOL 58, descreve uma
formalização para as linguagens de programação que, posteriormente, é
modificada por Peter Naur para a descrição de ALGOL 60. Esta revisão final é
conhecida como Backus-Naur Form (BNF).
A BNF é a formalização atual para descrição de linguagens de programação,
sendo assim uma meta-linguagem.
95. Backus-Naur Form - Fundamentos
95
Abstrações de Linguagens de Programação
Uma abstração é uma construção básica de uma linguagem de programação.
O lado esquerdo (left-hand-side) é a abstração, e o direito (right-hand-side) é
sua definição composta por um misto de lexemas, tokens, e outras abstrações.
Exemplos de Abstrações:
Atribuição
<assign> -> <var>=<expression>
Sentença IF de Java
<if_stmt> -> if ( <logic_expr> ) <stmt>
| if ( <logic_expr> ) <stmt> else <stmt>
Lista
<ident_list> -> identifier | identifier, <ident_list>
96. Backus-Naur Form - Derivações
96
Derivação
Em uma gramática, as sentenças de uma linguagem são geradas por meio de
uma sequência de aplicações de regras (derivações), que se inicia através do
símbolo inicial. Uma derivação é uma regra do tipo α -> β, que substitui α por β.
Exemplo de uma gramática de uma pequena linguagem:
<program> -> begin <stmt_list> end
<stmt_list> -> <stmt>
| <stmt> ; <stmt_list>
<stmt> -> <var> = <expression>
<var> -> A | B | C
<expression> -> <var> + <var>
| <var> - <var>
| <var>
Você seria capaz de
escrever um programa
na linguagem definida
por esta gramática?
97. Backus-Naur Form - Derivações
97
Considere a gramática para descrever uma sentença de atribuição simples:
<assign> -> <id> = <expr>
<id> -> A | B | C
<expr> -> <id> + <expr>
| <id> * <expr>
| (<expr>)
| <id>
A sentença A = B * (A + C) é gerada pela seguinte derivação:
<assign> -> <id> = <expr>
-> A = <expr>
-> A = <id> * <expr>
-> A = B * <expr>
-> A = B * (<expr>)
-> A = B * (<id> + <expr>)
-> A = B * (A + <expr>)
-> A = B * (A + <id>)
-> A = B * (A + C)
98. Backus-Naur Form - Árvores Sintáticas
98
Um atraente recurso das gramáticas é que elas descrevem naturalmente a
estrutura hierárquica estática das sentenças das linguagens que definem.
<assign> -> <id> = <expr>
<id> -> A | B | C
<expr> -> <id> + <expr>
| <id> * <expr>
| (<expr>)
| <id>
Na figura a direita, uma árvore de
análise sintática para a sentença
A = B * (A + C)
99. Backus-Naur Form - Ambiguidade
99
Considere a Gramática Ambígua
<assign> -> <id> = <expr>
<id> -> A | B | C
<expr> -> <expr> + <expr> | <expr> * <expr> | (<expr>) | <id>
Uma gramática é dita
ambígua se ela gera
uma forma sentencial
para a qual existem
duas ou mais árvores
de análise sintática.
Devem haver regras
para implementar:
- Precedências
- Associatividades
100. Exercício em Sala
100
Observe a seguinte implementação (Java) do comando if-else:
if (flagX == true) metodoA();
if (flagY == true) metodoB();
else metodoC();
Implemente uma gramática em BNF para o comando if-else que
consiga remover a ambiguidade do else.
101. Exercício para Casa
101
1. Explique a diferença entre Sintaxe e Semântica.
2. Elabore a BNF das seguintes sentenças:
a. Laço for de Java
b. Laço while de Java
c. Declaração de método de Java
3. Mostre que a seguinte gramática é ambígua:
<prog> -> <inst>
<inst> -> <inst> + <inst> | <id>
<id> -> A | B | C
[prog [inst [id a][|[inst [id b]]+[inst [id c]]]]]
[prog [inst [|[inst [id a]]+[inst [id b]]] [id c]]]
Gerador de árvore sintática: http://mshang.ca/syntree/
104. Semântica
104
public void print() {
System.out.println("5");
}
public void print() {
System.out.println("10");
}
Em contra-parte à Sintaxe que se dedica a validar as regras de
construção de uma linguagem, a Semântica se dedica a validar
a linguagem (o código implementado faz realmente o que se
propõem a fazer?)
Exemplo:
Qual método em Java imprime o valor 10? Todos eles compilam (sintaxe ok).
public void print() {
//System.out.println("10");
}
public void print() {
/*System.out.println("10");*/
}
105. Semântica
105
Gramáticas livres de contexto não podem descrever toda a
sintaxe de linguagens de programação. Inclusive, algumas
regras são impossíveis de serem definidas.
Alguns cenários:
- Definição de compatibilidade de tipos: variáveis INT podem
ser atribuídas a variáveis FLOAT, mas o inverso não é
permitido;
- Declaração prévia de variáveis antes de seus usos;
- Declarações de rotinas deve ter nomes correspondentes na
tag de início e na tag de fim.
106. Semântica
106
Gramáticas livres de contexto não podem descrever toda a
sintaxe de linguagens de programação. Inclusive, algumas
regras são impossíveis de serem definidas.
(aumento inviável do tamanho da gramática)
int x = 5;
float y = 10.5 * x;
(não é possível de ser definida pela BNF)
int a;
a = 10;
(não é possível de ser definida pela BNF)
procedure A_Test (A, B: in Integer; C: out Integer) is
begin C := A + B;
end A_Test;
107. Gramática de Atributos
107
Gramáticas de atributos incorporam informações semânticas nas
parse trees. A idéia da gramática de atributos é criar predicados
qualificadores para as abstrações.
Exemplo: Para o caso da conformidade de tags de procedures
da linguagem ADA:
Regra Sintática:
<def_proc> → procedure <nome_do_proc>[1]
<corpo_do_proc>
end <nome_do_proc>[2]
Regra Semântica:
<nome_do_proc>[1].string == <nome_do_proc>[2].string
108. Gramática de Atributos
108
Gramáticas de atributos incorporam informações semânticas nas
parse trees. A idéia da gramática de atributos é criar predicados
qualificadores para as abstrações.
Para o caso da verificação de compatibilidade de tipos, na
gramática de atributos há dois tipos de atributos para os não
terminais:
- Sintetizados (actual_type): armazena o tipo atual de uma
expressão ou variável;
- Herdados (expected_type): armazena o tipo inteiro ou real,
que é esperado para uma expressão.
109. Gramática de Atributos
109
Regra semântica simples, para a compatibilidade de tipos:
A função look-up
retorna o tipo de
uma variável.
110. Gramática de Atributos
110
Regra semântica simples, para a compatibilidade de tipos:
Árvore com gramática de atributos A = A + B, com A do tipo real e B do tipo int
111. Gramática de Atributos
111
Têm sido utilizadas em diversas aplicações, como:
- Descrições completas da sintaxe e da semântica de
linguagens de programação;
- Como a definição formal de uma linguagem (geração de
compiladores);
- Sistemas de processamento de linguagens naturais.
Dificuldades
- Torna a gramática/BNF complexa e grande;
- Dificuldade de leitura e escritas das gramáticas;
112. Exercícios em Sala
112
Utilizando o exemplo das tags de procedures da linguagem
ADA, defina as regras sintáticas e semânticas para formalizar
declarações de funções iniciando-se com
func <nome_da_função>:<tipo>
e terminarem seu bloco com
end_func <nome_da_função>
113. Semântica Estática VS Semântica Dinâmica
113
A semântica estática é aquela onde a análise necessária para
verificar especificações semânticas podem ser feitas no código
em tempo de compilação;
A semântica dinâmica, por outro lado, analisa e verifica a
semântica em tempo de execução, de acordo com os contextos
específicos da computação, operação, e máquina.
- Não são triviais. São complexas, e não há um padrão aceito;
- Há 3 metodologias formais:
- Operacional: menos formal, mais granular, pesada
implementação, baseada em estados da máquina;
- Denotacional: baseada em mapeamento matemático;
- Axiomática: baseada em axiomas e provas de asserção.
114. Semântica Operacional
114
Descreve o significado de um programa pela execução de suas
instruções em uma máquina, seja ela real ou simulada. As
mudanças no estado da máquina (memória, registradores, etc)
irão definir o significado da instrução. É implementada através
de máquinas virtuais ou linguagens intermediárias.
Instrução C:
for (expr1; expr2; expr3) { ... }
Semântica Operacional:
expr1; loop: if expr2 = 0 goto out
…
expr3
goto loop
out:...
Se usada informalmente,
é muito boa.
Complexa, se usada
formalmente
115. Semântica Axiomática
115
Baseada em cálculo de predicados, axiomas ou regras de
inferência (asserções) são definidas para cada tipo de instrução
na linguagem permitindo transformações de expressões para
outras expressões.
Condições:
- Pré-condição: Uma asserção que precede imediatamente uma instrução
de programa e descreve as variáveis dela nesse ponto;
- Pós-condição: Uma asserção que segue imediatamente a uma instrução e
descreve as novas restrições a essas variáveis (e possivelmente a outras)
depois da execução da instrução.
Exemplo:
soma = 2*x + 1 {soma >1}
possível pré-condição: {x > 10}
pós-condição
É difícil criar axiomas para
todas as instruções
Boa para executar provas
de exatidão de programas
116. Semântica Denotacional
116
A idéia baseia-se no fato de que há maneiras rigorosas de
manipular objetos matemáticos, mas não construções de
linguagens de programação. Define-se uma função que mapeia
instâncias das entidades da linguagem em instâncias dos
correspondentes objetos matemáticos.
Exemplo - Representação de números binários:
<num_bin> → 0 | 1 | <num_bin> 0 | <num_bin> 1
A função Mbin mapeia os objetos sintáticos com decimais
Mbin(‘0’) = 0
Mbin(‘1’) = 1
Mbin(<num_bin> ‘0’) = 2 * Mbin(<num_bin>)
Mbin(<num_bin> ‘1’) = 2 * Mbin(<num_bin>) + 1
Pode ser usada na
geração automática
de compiladores
Complexa, pouco
usada em linguagens
117. Exercícios para Casa
117
1. Pesquise e traga um exemplo de implementação (não citado
neste slide/aula) para cada um dos itens abaixo:
- Gramática de atributos
- Semântica Operacional
- Semântica Denotacional
- Semântica Axiomática
2. Quais as diferenças identificadas por você nos itens do
exercício anterior?
119. Abstrações Estruturais
119
Para um programa de computador, é suficiente que ele atenda aos
requisitos funcionais?
Não! Existem outros
requisitos importantes:
Manutenção: software não
estraga, mas se deteriora;
Portabilidade: aplicações
precisam executar em
diferentes sistemas;
Legibilidade: pessoas
devem ser treinadas para
entender o programa.
Analogia: As técnicas
para se construir uma
casa não são suficientes
para um prédio.
120. Evolução da Estrutura dos Programas
120
Início da programação até os anos 70
Programação Imperativa
Ênfase na modificação de valores em endereços de memória.
Até o final da década de 90
Programação Estruturada
Ênfase na estrutura do código, sem "pulos" ou
redirecionamentos arbitrários.
A partir da década de 90
Programação Orientada a Objetos
Ênfase na abstração e reuso de código.
122. Programação Imperativa
122
Arquitetura von Neumann Tanto os dados como os
programas são armazenados
na mesma memória, e a CPU,
que executa realmente as
instruções, é separada da
memória. Dessa forma,
instruções e dados devem ser
transportados, ou transmitidos,
da memória para a CPU. Os
resultados das operações
realizadas na CPU devem ser
devolvidos para a memória.
123. Programação Imperativa
123
imperare, do latim "comandar".
O paradigma imperativo é o mais antigo de todos os
paradigmas. Se baseia no funcionamento do computador, ou
seja, é influenciado pela arquitetura (von Neumann).
Execução sequencial baseada em comandos e em memória de
dados alteráveis, similar à maneira pela qual computadores
executam os programas a nível de linguagem de máquina.
O paradigma imperativo foi predominante, pois tais linguagens
são mais fáceis de traduzir para uma forma adequada para
execução na máquina.
124. Programação Imperativa
124
Conceitos-chave da Programação Imperativa:
- Variáveis: As variáveis mantém o estado de um programa
imperativo e são associadas com localizações de memória
que correspondem a um endereço e um valor de
armazenamento.
- Atribuições: O comando de atribuição introduz uma
dependência de ordem no programa: o valor de uma variável
é diferente antes e depois de um comando de atribuição.
- Sequência: O resultado do processamento de um programa
depende da ordem na qual os comandos são escritos e
executados, ou seja, da sequência na qual os comandos
estão escritos.
Linguagens Imperativas: Fortran, Cobol, Basic, Pascal, C e Ada.
126. Exercício em Sala
126
Utilizando uma linguagem imperativa, escreva um programa que
calcule a soma 1 + 2 + 3 + 4 + … + 50, sem usar laços FOR,
WHILE, ou DO-WHILE. Sugestão: use C com goto.
#include<stdio.h>
int main() {
int x=1;
int sum=0;
loop:
if (x<=50) {
sum=sum+x;
x=x+1;
goto loop;
} else {
printf("Sum = %i", sum);
}
}
Compilador online: https://www.jdoodle.com/
Exemplos de código: https://rosettacode.org/
127. Evolução da Estrutura dos Programas
127
Início da programação até os anos 70
Programação Imperativa
Ênfase na modificação de valores em endereços de memória.
Até o final da década de 90
Programação Estruturada
Ênfase na estrutura do código, sem "pulos" ou
redirecionamentos arbitrários.
A partir da década de 90
Programação Orientada a Objetos
Ênfase na abstração e reuso de código.
128. Programação Estruturada
128
A programação estrutura impõe uma disciplina rígida de
programação que faz uso de três controles para a construção da
lógica de um programa:
- Sequência: define que as instruções do programa são executadas
sequencialmente, de cima para baixo, linha a linha, e de forma
sequencial
- Seleção: permite que o fluxo de execução das instruções seja
executado de acordo com uma condição lógica avaliada
- Repetição: permite que uma ou um grupo de instruções seja
executado repetidamente de acordo com condições lógicas
Com as 3 estruturas de controle é possível construir programas
sem o uso de desvios incondicionais. Os comandos de desvio
incondicional, como o goto, não foram totalmente abolidos mas
seu uso deve ser evitado sempre que possível.
130. Checkpoint de Conhecimento
130
Vamos assistir ao vídeo "Paradigma Estruturado" de um
trabalho dos alunos da Unicamp:
https://www.youtube.com/watch?v=gHYs4YKUI6U
Exercício Mental (10 minutos)
Explique com suas palavras, a analogia encontrada entre o jogo
Tetris e o Paradigma Estruturado. Desenhe um fluxograma do
jogo arcade Tetris levando em consideração as instruções,
pontos de decisão, e laços de repetição.
131. Evolução da Estrutura dos Programas
131
Início da programação até os anos 70
Programação Imperativa
Ênfase na modificação de valores em endereços de memória.
Até o final da década de 90
Programação Estruturada
Ênfase na estrutura do código, sem "pulos" ou
redirecionamentos arbitrários.
A partir da década de 90
Programação Orientada a Objetos
Ênfase na abstração e reuso de código.
132. POO - Programação Orientada a Objetos
132
Simula 67: Em 1964, Simula foi implementada para atender as
necessidades de simulação de sistemas. Simula é uma extensão de
Algol 60, e adicionou o conceito de classe.
Smalltalk: É a primeira linguagem com suporte completo para
orientação a objetos. O mundo Smalltalk é definido por objetos, e a
computação usa sempre o mesmo conceito: mensagens de objetos
para objetos;
Transcript show: 'Hello World'.
Recursos-Chaves da POO:
Tipos abstratos, Herança, e Vinculação Dinâmica.
133. POO - Programação Orientada a Objetos
133
As 3 características da POO:
Tipos Abstratos: A abstração a tipos de dados abre a
possibilidade para a criação de classes e objetos, com os quais
o encapsulamento pode ser definido. Deve ser possível criar
diferentes tipos de dados por meio de propriedades e funções.
Herança: Um recurso central das linguagens Orientadas a
Objetos, onde o reuso de propriedades e funções é a principal
funcionalidade dos tipos da linguagem.
Vinculação Dinâmica: Abre possibilidade para o polimorfismo,
em que diferentes métodos com um mesmo nome podem ser
invocados dinamicamente.
134. POO - Tipos Abstratos
134
Conceito e Introdução
Uma abstração é uma visão ou representação de uma entidade
que inclui apenas os atributos mais significativos. De um modo
geral, a abstração permite que alguém colete exemplares de
entidades em grupos nos quais seus atributos comuns não
precisam ser considerados. É uma meta-representação das
entidades de dados e processos.
Questões de Projeto para Tipos Abstratos
Recurso para definir tipos de dados abstratos em uma
linguagem, devendo fornecer uma unidade sintática que envolva
a declaração do tipo e os protótipos dos subprogramas
(representação). Há também a questão da parametrização ou
não dos tipos abstratos (parametrização).
135. POO - Tipos Abstratos
135
Tipos de Dados Abstratos Parametrizados
Em geral, é conveniente a parametrização de tipos de dados
abstratos. Por exemplo, ao definirmos um tipo de dados abstrato
para uma pilha, podemos parametrizar o tipo das entidades que
serão empilhadas.
List<Carro> carros;
carros = new ArrayList<Carro>();
Construções e Nomeações de Encapsulamento
É a forma com a qual os programas podem ser reutilizados sem
necessidade de recompilação, por motivos de reuso simples ou
por motivos de limitação de tamanho do programa. Ex: pacotes
(Java) ou namespaces (C++).
136. POO - Herança
136
Dada a contínua diminuição do custo de hardware, cada vez
mais a produtividade dos desenvolvedores de software era
cobrada. Evidenciou-se a necessidade de reuso de código.
Tipos Abstratos foram fortes candidatos para reuso. Mas
existiam alguns problemas:
- Necessário conhecimento da implementação;
- Quase sempre necessário modificar o código;
- Quase sempre necessário atualizar códigos que os usam.
A Herança visa oferecer a solução para o reuso:
- Permite reusar tipos abstratos;
- Permite alterar e/ou adicionar novas entidades;
- Define estrutura de hierarquia entre as classes.
137. POO - Herança
137
Conceitos da Herança:
Classe: são os tipos abstratos da POO;
Objeto: instâncias dos tipos abstratos;
Classe Derivada ou Subclasse: classe definida por meio de herança de
outra classe;
Classe Pai ou Superclasse: classe da qual uma nova classe deriva;
Métodos: subprogramas que definem as operações em objetos;
Mensagens: chamadas a métodos;
Protocolo ou Interface de Mensagens: coleção completa de métodos
de um objeto;
Métodos e Variáveis de Instância: conjunto de métodos e variáveis de
um objeto, cada qual tendo seus próprios valores;
Métodos e Variáveis de Classe: conjunto de métodos e variáveis de
classe, registrados de forma única para tal classe.
138. POO - Herança
138
Subclasses e superclasses podem diferenciar-se quando:
- A superclasse define propriedades e métodos privados;
- A subclasse pode adicionar membros àqueles herdados;
- A subclasse pode sobrescrever métodos herdados.
Multiplicidade:
A herança pode ser simples (há apenas 1 superclasse) ou
múltipla (mais de 1 superclasse).
Desvantagens: interdependências entre classes e suas
hierarquias. A alteração em uma superclasse acaba afetando
todos os seus descendentes.
139. POO - Vinculação Dinâmica
139
Permite que diferentes vinculações a métodos ou operadores sejam
referenciados pelas mensagens, em tempo de compilação/execução.
O propósito para a vinculação dinâmica é permitir que os sistemas de
software sejam melhor estendidos durante o desenvolvimento e a
manutenção.
Polimorfismo: funcionalidade dada pela vinculação dinâmica.
140. POO - Questões de Projeto para Linguagens
140
Exclusividade de objetos: todas as entidades devem ser objetos?
Subclasses como subtipos: classes derivadas são superclasses?
Verificação de tipos e polimorfismo: quando verificar vinculações?
Herança simples vs Herança múltipla: benefícios / complexidades
Alocação e liberação de objetos: onde/como/quando alocar/liberar?
Vinculação estática e dinâmica: como linkar mensagens a métodos
Classes aninhadas: como deve ser a visibilidade de recursos?
Inicialização de objetos: como e com quais valores inicializar?
141. Suporte para POO - Visão de Cada Linguagem
141
Questões de
Projeto
Smalltalk C++ Objective-C Java C# Ruby
Exclusividade de
Objetos
Todos os dados são
objetos.
Tipos primitivos, mais
objetos.
Tipos primitivos, mais
objetos.
Tipos primitivos, mais
objetos.
Tipos primitivos, mais
objetos.
Todos os dados são
objetos.
Subclasses como
Subtipos
Podem ser, e
normalmente são.
Podem ser, e
normalmente são, se
a derivação for
pública.
Podem ser, e
normalmente são.
Podem ser, e
normalmente são.
Podem ser, e
normalmente são.
Nenhuma classe é um
subtipo.
Herança Simples e
Múltipla
Somente simples. Ambas. Somente simples.
Mas alguns feitos com
protocolos.
Somente simples.
Mas alguns feitos com
interfaces.
Somente simples.
Mas alguns feitos com
interfaces.
Somente simples.
Mas alguns feitos com
módulos.
Alocação e
Liberação de
Objetos
Toda alocação é feita
em memória.
Alocação explícita, e
liberação implícita.
Os objetos podem ser
estáticos, dinâmicos
de pilha, ou dinâmicos
em memória.
Alocação e liberação
são explícitas.
Toda alocação é feita
em memória.
Alocação explícita, e
liberação implícita.
Toda alocação é feita
em memória.
Alocação explícita, e
liberação implícita.
Toda alocação é feita
em memória.
Alocação explícita, e
liberação implícita.
Toda alocação é feita
em memória.
Alocação explícita, e
liberação implícita.
Vinculação
Estática e
Dinâmica
Todas as vinculações
de método são
dinâmicas.
A vinculação de
método pode ser
estática ou dinâmica.
A vinculação de
método pode ser
estática ou dinâmica.
A vinculação de
método pode ser
estática ou dinâmica.
A vinculação de
método pode ser
estática ou dinâmica.
Todas as vinculações
de método são
dinâmicas.
Classes Aninhadas Não. Sim. Não. Sim. Sim. Sim.
Inicialização Construtores
chamados
explicitamente.
Construtores
chamados
implicitamente.
Construtores
chamados
explicitamente.
Construtores
chamados
implicitamente.
Construtores
chamados
implicitamente.
Construtores
chamados
implicitamente.
142. Construções Orientadas a Objeto
142
Armazenamento de Dados de Instâncias
Em C++ as classes são definidas como extensões dos registros
de C (structs). As formas de armazenamento destas estruturas
chamam-se Registros de Instância de Classe (RIC). Tais
estruturas operam de forma estática, tornando-as tão eficientes
quanto acessar campos de registros.
Vinculação Dinâmica de Chamadas a Métodos
Métodos em uma classe estaticamente vinculados não precisam
se envolver no RIC para a classe, mas vinculações dinâmicas
precisam ter entradas na estrutura, que podem ser ponteiros
para o código do método. A desvantagem é que cada instância
precisa armazenar ponteiros para todos os métodos vinculados
dinamicamente.
143. Reflexão
143
O Que É Reflexão?
É uma forma de vinculação dinâmica tardia, onde as chamadas
a métodos podem ser feitas fora da estrutura hierárquica de
herança do código chamador. Isso torna a linguagem muito mais
flexível, permitindo que tipos e comportamentos possam ser
modificados dinamicamente em tempo de execução.
Reflexão em Java
Implementado com import java.lang.reflect;
https://www.geeksforgeeks.org/reflection-in-java/
Reflexão em C#
Implementado com using System.Reflection;
https://docs.microsoft.com/pt-br/dotnet/csharp/programming-guide/concepts/reflection
144. Exercício em Sala
144
Utilizando uma linguagem orientada a objetos de sua
escolha, implemente classes e subclasses para a seguinte
estrutura hierárquica:
145. Exercício para Casa
145
1. Assista a cada um dos vídeos a seguir:
○ https://www.youtube.com/watch?v=ngeAfwrEALg&t=7s
○ https://www.youtube.com/watch?v=_yQcmjRLJEc
○ https://www.youtube.com/watch?v=JDSglOBvhw8
2. Elabore um pequeno texto, com um resumo de cada um dos
vídeos assistidos.
146. AULAS 7 e 8
Paradigma Funcional
Conceitos e Aplicações
146
Paradigmas de Linguagens de
Programação
147. Introdução
147
Linguagens imperativas sempre foram as mais utilizadas e mais conhecidas
devido à ênfase na arquitetura Von Neumann.
Mas...
John Backus (1978): Linguagens puramente funcionais são superiores às
linguagens imperativas:
- Maior legibilidade
- Maior confiabilidade
- Maior propensão a estarem corretos
- Não possuem estados durante suas execuções
- Candidatos às provas matemáticas formais
- Significado das expressões independente de contexto
148. Motivações
148
Legibilidade e redigibilidade: Linguagens imperativas são mais complexas que
linguagens funcionais. Necessidade de lidar com variáveis no imperativismo;
Descrição Semântica: Linguagens imperativas precisam ter sua semântica
traduzida para a funcional e depois convertida de volta. Ainda, há o fator do
efeito colateral dos contextos imperativos;
Produtividade: Programas 10% menores em paradigmas funcionais com
relação ao paradigma imperativo. No imperativismo, há a necessidade de
linhas adicionais para processar e inicializar variáveis;
Execução: Programas em linguagens funcionais são, em geral, mais lentos
que seus correspondentes em linguagens imperativas (~2x mais tempo);
Concorrência: O projeto da concorrência é mais complexo em linguagens
imperativas, uma vez que é necessário gerenciar recursos em paralelo.
149. O Efeito Colateral do Contexto Imperativo
149
O paradigma imperativo possui efeitos colaterais relacionados ao contexto
semântico. Pelo fato da computação ser em torno de variáveis que armazenam
estados, um mesma mesma função pode gerar diferentes resultados e
comportamentos. Isso aumenta a complexidade das funções e diminui a
confiabilidade da implementação.
Exemplo onde uma mesma função pode retornar valores diferentes:
int a = 1; // atribuição em algum momento antes da chamada da função
public int funcao(int b) {
return a + b;
} // retorna 1 quando b = 0
int a = 2; // atribuição em algum momento antes da chamada da função
public int funcao(int b) {
return a + b;
} // retorna 2 quando b = 0
150. Conceitos: Funções Matemáticas
150
Uma função matemática é um mapeamento de um conjunto (domínio) para
outro (imagem);
Definição geral: um nome, um vetor de parâmetros, e uma expressão de
mapeamento: cubo(x) ≡ x * x * x;
O parâmetro de entrada e a saída mapeada de uma função são vetores e
podem ter múltiplos elementos.
Uma função y = f(x), com domínio no conjunto A e imagem no conjunto B.
151. Conceitos: Funções Matemáticas
151
Notação Lambda: Em 1941, Alonzo Church separa as tarefas de definir e
nomear as funções, criando a notação λ. Lambda para calcular o cubo de 2:
(λ(x)x*x*x)(2)
Ordem de Função: Define o grau de aninhamento entre múltiplas funções.
h = f ° g ≡ h(x) = f(g(x))
Laços de Repetição: Criados através de recursividade.
f(x): x = 0 → 1 ; x ≠ 0 → f(x - 1) + 1
Apply-to-All: Forma funcional α que recebe uma função como parâmetro e
aplica-a para múltiplas entradas.
Se h(x) = x*x, então α(h,(2,3,4)) resulta em (4,9,16)
152. Programação Funcional
152
No imperativismo, sentenças são calculadas e atribuídas a endereços de
memória, os quais mantém estados que podem ser diferentes para diferentes
contextos. Em contrapartida, no paradigma funcional, o objetivo é imitar a
lógica da matemática, a qual é independente de contextos. Testes são mais
simples de serem realizados em funções, uma vez que apenas a lógica precisa
ser verificada, produzindo códigos menores e mais fáceis de se ler e entender.
// fatorial em linguagem C
int factorial(int n) {
int result = 1;
for (int i = 1; i <= n; ++i) {
result *= i;
}
return result;
}
-- fatorial em linguagem Haskell
factorial n = product [1..n]
// quicksort em linguagem C
… mais de 20 linhas de código!
-- quicksort em linguagem Haskell
qsort [] = []
qsort (x:xs) =
qsort (filter (<x) xs)
++ [x] ++
qsort (filter (>x) xs)
153. Programação Funcional
153
Estudo de caso: Quicksort em Haskell:
-- quicksort em linguagem Haskell (https://www.jdoodle.com/)
qsort [] = []
qsort (x:xs) = qsort (filter (<x) xs) ++ [x] ++ qsort (filter (>x) xs)
main :: IO ()
main = do
print(qsort [5,2,6,8,4,7,0,1,3])
● Há duas definições para a qsort, uma para tratar a lista vazia [] e outra
para tratar listas com cabeça x e cauda xs;
● Uma lista pode ser escrita enumerando os seus elementos separados por
vírgula e colocados entre colchetes;
● A função filter seleciona os elementos de uma lista que satisfazem uma
determinada propriedade;
● (<x) e (>x) são funções que verificam se o seu argumento é menor ou
maior, respectivamente, do que x;
● O operador ++ concatena duas listas.
154. Suporte para Programação Funcional
154
Linguagens Imperativas
Linguagens imperativas normalmente fornecem suporte limitado para o
paradigma funcional. Um exemplo é a notação lambda:
parâmetros(s) => expressão
Algumas linguagens imperativas que implementam λ:
- Javascript var anon = function (a, b) { return a + b };
- Java Factory factory = chars -> new String(chars);
- Python x = lambda a : a + 10
- Ruby times_two = ->(x) { x * 2 }
- C# var squared = numbers.Select(x => x * x);
Havendo mais de um parâmetro, os mesmos devem vir entre parênteses.
Algumas Linguagens do Paradigma Funcional
Lisp, Haskell, Scheme, ML, OCaml, F#, Elixir, e Erlang.
155. Programação em Haskell
155
Haskell: linguagem puramente do Paradigma Funcional.
Quem usa Haskell? Eis algumas empresas:
- Bank of America: implementação de serviços;
- Facebook: manipulação da base de código PHP;
- Google: infra-estrutura interna de TI;
- NVIDIA: ferramentas usadas internamente;
- Qualcomm, Inc: geração de interfaces de programação para Lua;
- The New York Times: processamento de imagens
- Mais casos em: https://wiki.haskell.org/Haskell_in_industry
Características de Haskell: Programas concisos, tipagem estática, sistema de
tipos de ampla variedade, tipos e funções recursivas, funções de ordem
superior, linguagem pura (declarativa).
Contexto Histórico: Cálculo Lambda (1930), LISP (1950), ISWIM (1960), FP e
ML (1970), Miranda (1970~1980), Haskell (1987~2003).
156. Características de Haskell
156
Tipos estáticos e inferidos: podem ser identificados, mas não alterados;
Ausência de Estado e Imutabilidade: funções são escritas como expressões
matemáticas, e as variáveis assumem valores finais;
Referência Transparente: qualquer função ou rotina, independente de como ou
de quantas vezes for chamada, sempre retornará o mesmo valor para os
mesmos parâmetros. Isso permite:
- Que o compilador faça processamentos adicionais;
- Uma melhor dedução de valores, e até mesmo prova dos mesmos;
- A construção de funções mais complexas por composição de outras;
Avaliação Preguiçosa: não computa funções e operações se não houver
instrução para mostrar resultados, simplificando estruturas de dados infinitas.
Exemplo: seja a função addOne que toma uma lista e adiciona 1 para cada elemento.
Para a chamada addOne(addOne([1,2,3,4])), temos
Imperativa: computa addOne para todos os elementos antes de chamar novamente;
Preguiçosa: computa addOne para cada elemento, até o final das re-chamadas.
159. Funções em Haskell
159
BNF resumido de definição de função Haskell:
<funcao> -> <id_nome> <parametros> = <sentencas>
<parametros> -><var> <parametros> | <var>
<id_nome> -> <id>
-- mapeamento do tipo da função
addOne :: Int -> Int
-- declaração da função
addOne x = x + 1
Recursividade:
Implementada através da definição
de parada e de recursão:
fatorial :: Int -> Int
fatorial 0 = 1
fatorial x = x * fatorial(x-1)
Apply-to-All:
-- Fatorial com apply-to-all
module Main where
import Text.Printf
factorial :: Integer -> Integer
factorial 0 = 1
factorial n = n * factorial (n - 1)
line x = printf "%d! = %dn" x $ factorial x
main = mapM_ line [0..5]
Pattern Matching:
Realiza pesquisa por
padrões de informação:
truco :: String -> String
truco "4paus" = "zap"
print(truco "4paus")
160. Listas em Haskell
160
Guardas:
Testa uma ou mais propriedades, aferindo V ou F (similar ao switch/case).
calculoImc :: (RealFloat x) => x -> String
calculoImc imc
|imc <= 18.5 = "abaixo do peso"
|imc <= 25.0 = "peso normal"
|imc <= 30.0 = "acima do peso"
|otherwise = "obesidade"
Listas:
Estruturas de dados homogêneas, definidas
por colchetes "[" e "]", cujos elementos são
separados por vírgulas.
Exemplo:
lista1 = [1,2,3,4,5,6,7,8,9,0]
lista2 = [[1,2,3],[9,8,7],[1.0,2.0,3.0]]
Operadores de Listas:
++ concatena
: adiciona no início
!! selecionar por índice
Exemplo:
list1 = [1,2,3,4] ++ [9,10,11,12]
161. Listas em Haskell
161
Operações com Listas
head obtém o primeiro elemento
tail obtém a lista inteira, com exceção do primeiro elemento
last obtém o último elemento
init obtém a lista inteira, com exceção do último elemento
length retorna o tamanho de uma lista
null verifica se a lista está vazia
reverse retorna o inverso da lista
take retorna, a partir do início, um número desejado de elementos da lista
drop retira, a partir do início, um número desejado de elementos da lista
maximum retorna o maior elemento da lista
minimum retorna o menor elemento da lista
sum retorna a soma dos elementos da lista
product retorna o produto dos elementos da lista
elem verifica se um elemento está na lista
replicate replica uma quantia um determinado elemento da lista em outra lista
Ranges
list1 = [1...100] cria uma lista com todos o números entre 1 e 100
162. Exercícios em Sala
162
Acesse o compilador online: https://www.jdoodle.com/ e implemente os
seguintes algoritmos com a linguagem Haskell:
1. Verifique se um número é primo;
2. Verifique se um número é palíndromo (igual ao seu reverso literal);
3. Função fibonacci até a n-ésima iteração, dado n como parâmetro;
4. Função somaPa que calcula a soma Sn de uma progressão aritmética,
dados a1, r, e n como parâmetros.
Referência Haskell: https://wiki.haskell.org/wikiupload/b/b2/QuickReference.pdf
163. Tuplas em Haskell
163
Tuplas:
Estruturas de dados heterogêneas, definidas
por parênteses "(" e ")", separados por vírgulas.
Exemplo:
tupla1 = (1,2,3,'a','b','c')
tupla2 = ("nome1", 1)
Operações de Listas:
fst seleciona o 1o elemento
snd seleciona o 2o elemento
Exemplo:
print(fst ("nome1", 1))
print(snd ("nome1", 1))
Obs: fst e snd são definidos para tuplas de aridade 2. Exemplo de fst para aridade 3:
fst3 :: (a, b, c) -> a
fst3 (x, _, _) = x
Operadores:
É possível usar ==, /=, >, <,
>=, <=
Exemplo:
main :: IO ()
main = do
let
t1 = ("nome1",1)
t2 = ("nome2",2)
t3 = ("nome3",3)
print(t1 == t2)
print(t2 /= t3)
164. Clojure
Criada em 2007 por Rich Hickey, é uma linguagem de programação funcional
recente e poderosa, influenciada por Lisp, Prolog, ML, Haskell, e Erlang. É
basicamente um dialeto de Lisp, executável em JVM.
Exemplo: Quicksort em Clojure
(ns clojure.examples.hello
(:gen-class))
(defn qsort [[pivot & xs]]
(when pivot
(let [smaller #(< % pivot)]
(lazy-cat (qsort (filter smaller xs))
[pivot]
(qsort (remove smaller xs))))))
(println (qsort [5,2,7,0,4,3]))
(qsort [5,2,7,0,4,3])
164
Características:
- Tipagem dinâmica (há esforços
para migrar para a estática);
- Estruturas de dados imutáveis;
- Sintaxe bastante similar ao do
Haskell;
- Empresas que usam: Wallmart,
Puppet Lab, Nubank.
166. Exercício para Casa
166
1. Assista a cada um dos vídeos a seguir:
a. https://www.youtube.com/watch?v=JDSglOBvhw8
b. https://www.youtube.com/watch?v=BxbHGPivjdc
c. https://www.infoq.com/br/presentations/usando-programacao-funcional-agora/
d. https://www.alura.com.br/conteudo/clojure-introducao-a-programacao-funcional
2. Elabore um pequeno texto, com um resumo de cada um dos
vídeos assistidos.
168. Introdução
168
O paradigma lógico é uma abordagem baseada na expressão de
programas em uma forma de lógica simbólica, com o uso de
inferências para computar resultados.
INFERÊNCIA => Derivar conclusões a partir de premissas conhecidas
Programas lógicos são declarativos:
- São coleções de fatos e regras;
- A computação é feita através de consultas a estes fatos;
- Trazem conclusões por meio de inferências das regras.
[FATO]
Choveu
[REGRA]
Se chove => Há trânsito
[CONSULTA]
Há trânsito?
[RESULTADO]
Sim!
169. Introdução
169
Cálculo de Predicados
FATO: Como devemos modelar e representar conhecimento?
Sócrates é humano.
homem(socrates)
REGRA: De que forma tratamos as inferência e como construímos as
regras para as derivações?
Todo humano é mortal.
∀X[homem(X) → mortal(X)]
CONSULTA: Como devem ser feitas as "queries" para nosso sistema?
Logo, Sócrates é mortal.
mortal(socrates)
170. Cálculo de Predicados
170
Proposição: Sentença lógica que pode ou não ser verdadeira,
consistindo de objetos e seus relacionamentos. Exemplos:
P1: O carro é vermelho vermelho(carro) 1-tupla
P2: O aluno gosta de estudar gosta(aluno,estudar) 2-tupla
Lógica Simbólica: Usada para 3 necessidades da lógica formal.
- Expressar proposições;
- Expressar relacionamentos entre proposições;
- Descrever como novas proposições podem ser inferidas a partir de
outras.
Cálculo de Predicados
Lógica simbólica usada
na programação lógica.
172. Cálculo de Predicados
172
Alguns exemplos:
∀X.(man(X) ⊃ human(X))
Para todo X, se X é um homem então ele é um humano
∃X.(mother(mary, X) ∩ man(X))
Existe um homem X cuja mãe é Mary
∀X.(human(X) ⊃ smart(X))
Para todo X, se X é um humano então ele é inteligente
∀X.((woman(X) ∪ man(X)) ⊃ ¬robot(X))
Para todo X, se X é um homem ou uma mulher então X não é um robô.
173. Forma Clausal
173
Assim como outras linguagens, as lógicas são melhores em sua forma
simples, e isso significa que a redundância deve ser minimizada.
Existem muitas maneiras de definir proposições com o mesmo
significado. Em um sistema automatizado é um problema sério.
A forma clausal é a padronização para evitar redundâncias e tem a
seguinte sintaxe geral:
B1 ∪ B2 ∪ … ∪ Bn ⊂ A1 ∩ A2 ∩ … ∩ Am
Se todos os As são verdadeiros, então ao menos um B é verdadeiro.
- Quantificadores existenciais não são necessários;
- Quantificadores universais são implícitos em atômicos;
- Apenas conjunção e disjunção são necessários;
- Conjunções aparecem à esquerda e disjunções à direita.
Nilsson (1971): Toda proposição é conversível para a forma clausal.
174. Exercícios em Sala
174
Converta as seguintes frases (português) para suas formas clausais:
1. Se Roberto gosta de peixe e se uma truta é um peixe, então Roberto
gosta de trutas.
gosta(Roberto,truta) ⊂ gosta(Roberto,peixe) ∩ peixe(truta)
2. Se Duda é o pai de Roberto e Denise é a mãe de Roberto e Geraldo
é o avô de Roberto, então ou Geraldo é o pai de Duda ou Geraldo é o
pai de Denise.
pai(Geraldo,Duda) ∪ pai(Geraldo,Denise) ⊂ pai(Duda,Roberto)
∩ mae(Denise,Roberto) ∩ avo(Geraldo,Roberto)
175. Cálculo de Predicados e Provas de Teoremas
175
Um uso de coleções de proposições é determinar se quaisquer fatos
interessantes ou úteis podem ser inferidos a partir delas. Isso é
exatamente análogo ao trabalho dos matemáticos, que buscam
descobrir novos teoremas que podem ser inferidos a partir de axiomas
e teoremas conhecidos.
No início da ciência da computação (1950~1960) havia interesse na
automatização dos processos de prova de teoremas. A resolução,
desenvolvida para ser aplicada nas formas clausais, é uma regra de
inferência que permite às proposições inferidas serem computadas a
partir de dadas proposições.
Suponha: P1 ⊂ P2; Q1 ⊂ Q2; P1 ≡ Q2
Sendo P1 equivalente a Q2, podemos escrever: T ⊂ P2; Q1 ⊂ T
Que por transitividade é: Q1 ⊂ T ⊂ P2 ou seja, Q1 ⊂ P2
176. Cálculo de Predicados e Provas de Teoremas
176
Assim, o processo de inferir essa proposição a partir das duas
proposições originais é chamado de resolução. Como outro exemplo,
considere as duas proposições:
older(joanne, jake) ⊂ mother(joanne, jake)
wiser(joanne, jake) ⊂ older(joanne, jake)
A partir dessas proposições, as seguintes proposições podem ser
construídas usando resolução:
wiser(joanne, jake) ⊂ mother(joanne, jake)
Proposições dadas:
- Se Joanne é mãe de Jake então Joanne é mais velha que Jake
- Se Joanne é mais velha que Jake então Joanne é mais sábia que Jake
Resolução:
- Se Joanne é mãe de Jake então Joanne é mais sábia que Jake
177. Panorama da Programação Lógica
177
Lógica: Ciência do pensamento correto e consistente.
Personalidades importantes na história da Lógica:
- Boole (1815 a 1864): Diversas contribuições para a lógica e para a
matemática, como a Álgebra Booleana;
- De Morgan (1806 a 1871): Reforma da lógica, que efetivamente
trouxe o renascimento dos estudos de lógica que começaram na
primeira metade do século XIX;
- Frege (1879): Criação de um sistema de representação simbólica
para representar formalmente a estrutura dos enunciados e suas
relações, e a contribuição para a implementação do cálculo dos
predicados.
Vamos assistir a este vídeo:
https://www.youtube.com/watch?v=ozMbmBp3onE
178. A Linguagem Prolog
178
Prolog: PROgramming LOGic
- Desenvolvida a partir do teorema da lógica
- Primeira implementação por Alain Colmerauer em 1972
- Semântica próxima da especificação lógica
Sintaxe Geral
- Nomes de relacionamentos e objetos começam com caixa baixa;
- Variáveis iniciam com caixa alta;
- A relação é escrita primeiramente. Objetos são escritos entre parênteses,
separando-se por vírgulas;
- O caractere de parada "." deve vir no final de cada fato;
- Conjunções (E) devem ser separadas por ",";
- Disjunções (OU) devem ser separadas por ";";
- Regras
- Especificam em quais condições a tupla satisfaz os predicados;
- Iniciam com ":-" e terminam com ".";
- A construção básica é chamada de átomo;