sábado, 19 de novembro de 2011

Lisp - Arrays e loops

Usaremos nossa apostila (Ap.).

Arrays são criadas em Lisp pela função make-array (Ap. 12.1.1) e acessadas pela função aref (Ap. 12.1.2).

Há várias formas de loops em Lisp.  Nesta aula, focaremos apenas em duas delas: dolist e dotimes (Ap. 12.2).

Lisp - Funções para conjuntos

Usaremos nossa apostila (Ap.).

Lisp oferece funções para tratar listas como se fossem conjuntos.  Pode-se fazer união, interseção e várias outras operações de conjuntos.

Em relação a elementos repetidos, estas operações sempore retornam listas sem repetições quando recebem argumentos sem repetições.

sábado, 12 de novembro de 2011

Lisp - Algumas funções pré-definidas

Usaremos nossa apostila (Ap.).

Nesta aula, veremos algumas das principais funções pré-definidas (Ap. cap. 9).  A maioria delas se aplica a listas.

Assim, temos funções para ver se um elemento está numa lista, extrair elementos de listas (dado seu índice), retornar pedaços de listas, saber seu comprimento, revertê-las, construir listas, concatená-las, substituir elementos por outros em toda a estrutura, e até aplicar uma função a cada elemento da lista (retornando uma lista com os resultados).

segunda-feira, 7 de novembro de 2011

Lisp - Funções, macros, condicionais, predicados

Seguimos com a apostila (Ap.).

Nesta aula veremos algumas funções aritméticas (Ap. cap. 6).

A seguir, veremos a forma geral de definir funções e macros (Ap. cap. 7).

Para terminar, veremos em mais detalhe condicionais (Ap. 8.1 e 8.2) e predicados (Ap. 8.3).

Lisp - Recursão

Seguimos com nossa apostila (Ap.).

Veremos incialmente como escrever funções recursivas, com a ajuda do método do quadradão (Ap. 5.1).

A seguir, veremos como recursão pode substituir loops (Ap. 5.2), algo que fazemos também em Prolog.

quinta-feira, 3 de novembro de 2011

Lisp - Símbolos

Continuaremos a usar nossa apostila (Ap.).

De forma simplificadora, podemos dizer que os símbolos em Lisp são as variáveis.

Um símbolo pode ter um valor como dado e, independentemente, um valor como função (Ap. 4.1).  Veremos nesta aula como alterar estes valores (Ap. 4.2), e, no processo, falaremos sobre a avaliação de expressões em Lisp.

Por fim, veremos maneiras de inibir a avaliação, total ou percialmente (Ap. 4.3).

Lisp - Estrutura da linguagem

Continuaremos a usar nossa apostila (Ap.).

Um programa em Lisp consiste na definição de novas funções, para que possam ser usadas no contexto desejado.

Veremos nesta aula a estrutura básica de um programa em Lisp, incluindo a definição de funções (Ap. 3.1), o uso de condicionais (Ap. 3.2) e o uso de variáveis locais (Ap. 3.3).

domingo, 23 de outubro de 2011

Lisp - Elementos da linguagem

Acompanhe pela apostila (Ap.).  Nesta aula veremos:

Tipos existentes em Lisp (Ap. 2.1).

Tipos atômicos: números (Ap. 2.2), símbolos (Ap. 2.3) e strings.

Tipos não atômicos: pares-com-ponto, (Ap. 2.4), entre os quais estão as listas, e sua representação gráfica (Ap. 2.5).

Primeiras funções LISP: car, cdr, e cons (Ap. 2.6).

Coleta de lixo (Ap. 2.7).

sábado, 22 de outubro de 2011

Lisp - Introdução

Temos uma apostila (Ap.) para acompanhar as aulas da Lisp.  Nesta aula teremos:

Breve história de Lisp (Ap. cap. 1).

Alguns programas famosos: derivada simbólica (Ap. 1.1), psiquiatra (Ap. 1.2), médico (Ap. 1.3).

Por fim, algumas dicas sobre como usar um interpretador Lisp.

segunda-feira, 10 de outubro de 2011

Prolog - Gramáticas

Continuamos usando a apostila (Ap.).

Prolog é muito usada em processamento de linguagens naturais, onde aparece o problema da análise léxica de frases (Ap. 9.1).

É bastante simples codificar gramáticas livres de contexto em Prolog (Ap. 9.2), que conta com uma notação especial para este fim (Ap. 9.3).

Argumentos adicionais podem ser usados para resolver a questão dos plurais (Ap. 9.4), entre outras aplicações.

sábado, 1 de outubro de 2011

Prolog - Depuração

Seguiremos usando a apostila (Ap.).

Predicados trace, notrace, spy(P), nospy(P), debugging (Ap. 8.1).

Pontos de atenção: call, exit, redo, fail (Ap. 8.1).

Ações: w (write), c (creep), a (abort) e outras.  "Creep" também com espaço ou enter (Ap. 8.1).

Prolog - Predicados pré-definidos

Continuaremos a usar a nossa apostila (Ap.).

Veremos hoje alguns predicados pré-definidos da lingaugem Prolog (Ap. 7).

True, repeat (Ap. 7.1).

var(X), novar(X), atom(X), number(X), atomic(X) (Ap.7.2).

listing, listing(P), asserta(X), assertz(X), retract(X) (Ap. 7.3).

last(X, L), reverse(L, M), delete(X, L, M) (Ap. 7.4).

subset(X, Y), intersection(X, Y, Z), union(X, Y, Z) (Ap. 7.5).

X ..= L, random(N), findall(X, M, L), ; (Ap. 7.6).

sábado, 24 de setembro de 2011

Prolog - Entrada e saída

Continuamos a usar a apostila (Ap).

Prolog oferece predicados para a entrada e saída de termos (Ap. 6.1), e de caracteres (Ap. 6.2).  Os dispositivos para entrada e saída padrão são o teclado e a tela, respectivamente, mas podem ser trocados por arquivos (Ap. 6.3).

Veremos também como "consultar" arquivos, ou seja, carregar no banco de dados cláusulas de um arquivo de texto (Ap. 6.4).

Por fim, entrada e saída se relacionam com a definição de operadores: predicados que podme ser escritos de forma infixa ou posfixa (Ap. 6.5).

Prolog - Ressatisfação e corte

Continuamos usando a apostila (Ap).

Revisão de ressatisfação (backtracking) (Ap. 5, 5.1).

Introdução ao corte, um predicado extra-lógico (Ap. 5.2).

Usos do corte: indicar a cláusula correta, negação, limitar buscas (Ap. 5.3).

Cuidados com o corte: igualdade pode não mais ser equivalente a usar variáveis com o mesmo nome (Ap. 5.4).

domingo, 18 de setembro de 2011

Prolog - Introdução à recursão (com listas)

Continuamos usando a apostila (Ap).

Como listas têm tamanho arbitrário, é usual tratá-las com recursão.  O precidado member será nosso primeiro exemplo (Ap. 4.3).  Também veremos algumas dicas gerais sobre o uso de recursão em Prolog.

A seguir estudaremos um predicado muito importante em Prolog: append (Ap. 4.4).  Ele junta listas, mas, sendo em Prolog, também as separa (como veremos em aulas vindouras).

Por fim, aprenderemos a usar acumuladores, que, em geral, resultam em melhor performance para as nossas definições (Ap. 4.5).

Prolog - Estruturas e listas

Continuamos usando a apostila (Ap).

Estruturas em Prolog permitem representar árvores (Ap. 4.1).

Um tipo especial de estrutura --- as listas --- recebem atenção especial (Ap. 4.2).

domingo, 11 de setembro de 2011

Prolog - Sintaxe, unificação, aritmética

Continuamos seguindo a apostila (Ap).

Prolog só tem um tipo de dados: o termo.  Ele descreve dados e programas.  Seus subtipos são, constantes, variáveis e estruturas.  (Ap. 2.1 a 2.3)

Unificação é um dos conceitos mais importantes em Prolog. (Ap. 2.4)

Lidar com números é diferente em Prolog. O predicado is desempenha um papel fundamental. (Ap. 3)

Prolog - Fatos, regras, perguntas, variáveis

Usaremos muito o livro, ou sua tradução parcial na apostila (Ap.)

Usaremos também um interpretador para ver na prática como as coisas funcionam.

Um programa em Prolog consiste na descrição de um mundo próprio. Um universo paralelo. Prolog permite analisar as conclusões que podem ser tiradas desta descrição. (Ap. 1.2)

Fatos são afirmações incondicionais sobre o mundo. (Ap. 1.3)

Perguntas permitem entender o mundo criado. (Ap. 1.4)

Variáveis e conjunções aumentam nossa capacidade de perguntr. (Ap. 1.5 e 1.6)

Regras são afirmações sobre o mundo condicionadas a outros fatos e regras.  Uma regra pode valer por mil fatos! (Ap. 1.7)

segunda-feira, 29 de agosto de 2011

Java - Concorrência: threads e sincronização

Concorrência: editar textos, imprimir, ouvir música ... tudo ao mesmo tempo!

Processos e processos leves (threads)

Disparando uma thread: o método start.

Aguardando uma thread terminar: o método join.

Dando um tempo: o método Thread.sleep.  Ao contrário de start e join,  este método pode ser chamado sem referência a uma thread específica, pois é um método estático da classe Thread.

Aprenda como preparar seu código para receber e tratar interrupções.

Sincronização: evitando problemas de mais de uma thread mexendo na memória ao mesmo tempo.

Métodos sincronizados: cuidado com deadlock

Controle mais fino: comandos sincronizados

Ciclo de vida de uma thread

domingo, 21 de agosto de 2011

Java - Tratamento de exceções

Ao invés de encher seu programa de if's, considere exceções, que permitem manter o fluxo principal enxuto e claro, ao mesmo tempo que tratam das ocorrências excepcionais de maneira adequada. Java ajuda você a não esquecer nenhuma condição excepcional.

Tecnicamente, seu fluxo principal é cercado por um bloco try, que organiza o tratamento de exceções.  Você pode também delegar o tratamento a quem lhe chamou.

Algumas exceções não precisam ser capturadas ou tratadas.  Mas, entenda bem este mecanismo e aprenda a usá-lo a seu favor.

Em suma, exceções em Java trazem uma série de vantagens.

Hierarquia de exceções pré-definidas em Java.

Java - Classes Abstratas


Classes abstratas: são um meio-termo entre classes concretas e interfaces, pois geralmente alguns de seus métodos são concretos e outros são abstratos.  Não se pode criar objetos delas, mas servem para agrupar características comuns a suas subclasses.

Importante: o que caracteriza uma classe como abstrata é o uso da palavra reservada abstract em sua declaração.  Note porém que, se a classe não for abstrata e tiver um ou mais métodos abstratos, gerará um erro de complilação.

Métodos abstratos: métodos sem corpo, apenas com o cabeçalho, encerrado com ";".

Exemplo de uso:

Classes Rectangle, Line, Bezier, and Circle inherit from GraphicObject


Exemplo na hierarquia Java: AbstractList

domingo, 14 de agosto de 2011

Java - Interfaces

Interfaces são contratos entre quem vai implementar e quem vai usar uma determinada classe.

Em Java, interfaces são tipos válidos, assim como as classes, mas contêm apenas constantes, assinaturas de métodos e classes aninhadas.  Não podem ser instanciadas, mas podem ser implementadas e estendidas.

API = Application Program Interface

Interfaces têm o papel de fornecer a única forma (restrita) de herança múltipla em Java.  Uma classe pode herdar de uma só outra classe, mas pode implementar múltiplas interfaces.

Definição de uma interface:

public interface GroupedInterface
       extends Interface1, Interface2, Interface3 {

    // constant declarations
    
    // base of natural logarithms
    double E = 2.718282;
 
    // method signatures
    void doSomething (int i, double x);
    int doSomethingElse(String s);
}

Observe que uma interface pode estender várias outras. Todos os campos são implicitamente públicos, estáticos e finais.  Ou seja, constantes.

Implementação de uma interface: uso da palavra reservada implements. Ver exemplo de Relatable e uma implementação.  Observar casting.

Interfaces são tipos como outros quaisquer em Java. Podem ser usadas em parâmetros, por exemplo.  Apenas objetos de classes que implementem a interface podem ser usados como variáveis do tipo dela.

Estender uma interface pode ser uma boa alternativa a modificá-la, o que seria muito impactante negativamente.

Exemplo na hierarquia Java: a interface List é implementada por ArrayList e por LinkedList.

Java - Sobrecarga e Polimorfismo

Relembrando o conceito de assinatura de um método:  nome, número de parâmetros, ordem dos parâmteros e tipos dos parâmetros.  Em alguns contextos dentro do estudo de linguagens de programação, a assinatura também inclui o tipo do valor retornado, mas não no tutorial Java que estamos utilizando.

Em Java, não é possível definir métodos com mesma assinatura na mesma classe.  Porém, é possível definir métodos com mesma assinatura em classes derivadas.  Isto é um caso de Polimorfismo, ou seja, métodos com a mesma assinatura executando ações diferentes.

Métodos de instância podem ser redefinidos (overridden) por uma subclasse; métodos de classe podem ser escondidos (hidden) por uma subclasse.  A tabela abaixo serve de guia para entendermos melhor estes conceitos:

Definindo métodos com a mesma assinatura numa subclasse
Método de instância na superclasse Método de classe na superclasse
Método de instância na subclasse Redefinido Erro de compilação
Método estático na subclasse Erro de compilação Escondido

Com relação ao tipo de retorno, uma subclasse pode restringir o tipo de retorno (ou seja, usar um subtipo dele), mas não pode usar um tipo mais geral ou de outra parte da hierarquia de tipos.

Por outro lado, com relação ao encapsulamento, uma subclasse pode ser menos restritiva na permissão de acesso, mas não mais restritiva.

Note que é um erro de compilação usar a mesma assinatura para métodos de classe na superclasse e métodos de instância na subclasse, ou vice-versa.

A diferença entre redefinir e esconder é a seguinte: o método redefinido, quando chamado, determina o tipo da variável na hora da execução para escolher qual código executar, se o da classe filha ou o da classe mãe.  A isto se chama acoplamento dinâmico. Exemplo:


Arquivo: Animal.java

public class Animal {
    public static void testClassMethod() {
        System.out.println("The class method in Animal.");
    }
    public void testInstanceMethod() {
        System.out.println("The instance method in Animal.");
    }
}



Arquivo: Cat.java

public class Cat extends Animal {
    public static void testClassMethod() {
        System.out.println("The class method" + " in Cat.");
    }
    public void testInstanceMethod() {
        System.out.println("The instance method" + " in Cat.");
    }
   
    public static void main(String[] args) {
        // Método de classe chamado via classe
        Animal.testClassMethod();
        Cat.testClassMethod();
       
        // Cada macaco no seu galho
        Animal myAnimal = new Animal();
        Cat myCat = new Cat();

        // Método de classe chamado via instância (desencorajado)
        myAnimal.testClassMethod();
        myCat.testClassMethod();
       
        // Método de instância: escolhe em tempo de execução
        myAnimal.testInstanceMethod();
        myCat.testInstanceMethod();

        // Macaco no galho do outro
        myAnimal = myCat;     

        // Método de classe chamado via instância (desencorajado)
        myAnimal.testClassMethod();
        myCat.testClassMethod();

        // Método de instância: escolhe em tempo de execução
        myAnimal.testInstanceMethod();
        myCat.testInstanceMethod();
    }
}


Saída:

The class method in Animal.
The class method in Cat.
The class method in Animal.
The class method in Cat.
The instance method in Animal.
The instance method in Cat.
The class method in Animal.
The class method in Cat.
The instance method in Cat.
The instance method in Cat.


Anotação @Override

Sobrecarga (overloading) é quando métodos de uma mesma classe têm nomes iguais, mas assinaturas diferentes.

sexta-feira, 5 de agosto de 2011

Java - Herança

Herança: tem a haver com tipos e subtipos.  Subtipos herdam os membros da classe mãe.  Nota: construtores não são considerados membros, e portanto não são herdados.
Em Java, cada classe pode ter apenas uma classe mãe, embora acabe herdando membros não só da mãe, mas também indiretamente da avó, bisavó, etc. (se houver).
Isto cria uma hierarquia de classes em forma de árvore.  A raiz desta árvore é a classe pré-definida Object.

Exemplo:

class MountainBike extends Bicycle {

    // new fields and methods defining 
    // a mountain bike would go here

}

Nomenclatura: subclasse, classe derivada, clesse estendida. classe filha; superclasse, classe base, classe mãe.

Se sua classe é declarada sem mãe, Java a faz automaticamente filha de Object.

Apesar de herdar todos os membros das classes ancestrais, nem todos podem ser acessados.  Apenas membros os seguintes membros pode ser acessados numa subclasse:
  • public
  • protected da mãe
  • package-private, se a subclasse estiver no mesmo pacote da classe base
O que se pode fazer numa subclasse:
Com campos:
  • usar livremente os campos public e protected herdados, independentemente do pacote onde esteja; se estiver no mesmo pacote da mãe, pode tambem usar os campos package-private.
  • declarar um campo com o mesmo nome de um herdado, escondendo o herdado.
  • declarar novos campos que não estejam nas classes ancestrais.
Com métodos:
  • chamar livremente métodos public e protected herdados, independentemente do pacote onde esteja; se estiver no mesmo pacote da mãe, pode tambem usar os campos package-private.
  • escrever um novo método de instância com a mesma assinatura de um método herdado, redefinindo-o.
  • escrever um novo método de classe (static) com a mesma assinatura de um método herdado, escondendo-o.
  • declarar novos métodos que não estejam nas classes ancestrais.
  • escrever um construtor que chame um construtor da superclasse, seja explicitamente com a palavra reservada super, seja implicitamente.
Objetos de um certo tipo são também considerados objetos de qualquer supertipo deste tipo.  Java permite que seja usado um objeto de tipo X em qualquer parte do código onde se espera um objeto de tipo X ou de um tipo ancestral de X.

Por outro lado, o compilador não permite que seja usado um objeto de tipo X em lugares onde se espera algo de um tipo descendente de X, a não ser que se use casting.

MountainBike myBike = (MountainBike)obj;

Ao usar casting, o programador assume a responsabilidade de garantir que haverá um objeto do tipo adequado lá na hora da execução.  Por sua vez, o compilador insere código para verificar se isto realmente foi feito.  Existe o operador instanceof que nos diz se um dado objeto é ou não de uma dada classe:

if (obj instanceof MountainBike) {
    MountainBike myBike = (MountainBike)obj;
}

Reuso de código: muito do que precisamos já foi implementado por alguém.
É mais fácil aproveitar o que já existe, e apenas acrescentar o restante a uma classe existente. Exemplos na hierarquia de classes de Java.

Há duas formas de reuso: por herança e por agregação.  Use herança apenas quando realmente se tratar de um caso de especialização.  Caso contrário, considere agregação.  Exemplos: Pilha, Fila, ListaLigada.

Acoplamento dinâmico: o termo "acoplamento" refere-se ao modo como nomes de métodos são associados ao código que será executado para uma dada chamada.  Em Java, a novidade em relação a C é que esta decisão é postergada até o momento da execução do código, enquanto que em C o acoplamento é feito no momento da compilação.  Isto permite maior liberdade no desenvolvimento independente de partes de um grande sistema.

No tutorial, acoplamento dinâmico é chamado de virtual method invocation, na seção sobre polimorfismo.

Java - Encapsulamento

Acesso aos membros:

objeto.membro
objeto.membro(args)

Controlando acesso aos membros:
  • private: só a própria classe
  • public: todas acessam
  • package-private (sem modificador): só as do mesmo pacote
  • protected: só as subclasses (herdeiras) e as do mesmo pacote
Para classes, apenas as duas primeiras são permitidas.
Resumindo:

Modifier Class Package Subclass World
public Y Y Y Y
protected Y Y Y N
no modifier Y Y N N
private Y N N N

Dica: use o modificador mais restritivo que puder nas suas definições. Use public apenas para constantes.  Relemebrando, constantes são static e final; seus nomes são escritos em MAIUSCULAS_COM_UNDERSCORE.

final: não pode ser alterado.
No caso de métodos, não pode ser redefinido por subclasses.

static: compartilhado entre todos os objetos da classe.
No caso de métodos, são os únicos que podem acessar campos estáticos diretamente.  Acesso aos membros estáticos:

Classe.membro
Classe.membro(args)

Classes aninhadas: geralmente, as classes são declaradas no nível mais externo (top level).  No entanto, classes podem ser declaradas como membros de outras classes.  Estas classes têm acesso a todos os membros da classe onde estão, inclusive os privados.

quinta-feira, 4 de agosto de 2011

Java - Classes e Objetos

CADA ITEM TEM UM OU MAIS LINKS PARA O TUTORIAL JAVA

Objetos
Estado e compartamento (state and behaviour).
Estado = campos (fields)
Comportamento = métodos (methods), que são funções ou procedimentos.
Encaspulamento de dados: esconder campos, e permitir operação só através dos métodos.
Objeto controla como pode ser usado.  O código fica todo dentro dos objetos, na forma de métodos.  Vantagens:
  • Modularidade: objetos desenvolvidos e mantidos independentemente.
  • Reuso de código: se alguém já implementou um certo objeto, podemos usar.
  • Facilidade de substituição: é fácil trocar um objeto por outro com funcionalidade equivalente.

Variáveis
Tipos de variáveis em Java:
variáveis da instância (campos não estáticos)
variáveis da classe (campos estáticos)
variáveis locais
parâmetros
Variáveis que nunca mudam de valor: final.
(exemplo)

Campos e métodos são membros.
Convenções para nomes de membros: inicial minúscula, camel-case.
Boa prática: nomes de funções são sempre substantivos (o que retorna) e nomes de procedimentos são verbos (o que faz).

Classes
Tipos, ou modelos para objetos deste tipo.
Cada objeto é uma instância de uma classe.
Classes e suas subclasses formam uma hierarquia.
Convenções para nomes de membros: inicial maiúscula, camel-case.
(exemplos)

Como definir Métodos - 6 partes: modificador, tipo de retorno, nome, lista de parâmetros, exceções, corpo.
Assinatura: nome e parâmetros.Sobrecarga: mesmo nome, parâmetros diferentes (use com critério).
Construtores: métodos para inicializar objetos da classe
Sem tipo de retorno. Sobrecarga de construtores é comum.
Construtor default sem parâmetros.
Classe pai default: Object.

Mensagens ou chamadas
Parâmetros e argumentos.
Não é possível passar métodos como parâmetros.  Mas pode-se "simular" esta ação passando um objeto e chamando seus métodos.  Exemplo: sort.
Número variável de argumentos (simula um vetor).
Parâmetros que "encobrem" um campo: uso de this.
Tipos primitivos são sempre passados por valor.
Objetos e arrays são sempre passados por valor também, mas seus campos podem ser alterados dentro do método.

Tipos primitivos
Há 4 variedades de inteiros.
Todos são com sinal, representados em complemento de 2.
  • byte: inteiro de 8 bits.
  • short: inteiro de 16 bits.
  • int: inteiro de 32 bits.
  • long: inteiro de 64 bits.
Há duas variedades de números em ponto flutuante.
Todos seguem o padrão IEEE 754.
  • float: 32 bits.
  • double: 64 bits.
Além destes há:
  • boolean: apenas true ou false.
  • char: caractere Unicode de 16 bits.

Além destes, existe a classe String, e a linguagem Java dá suporte especial para ela: operador infixo +, por exemplo. Uma String é imutável, porém.

Valores default: campos são inicializados pelo compilador.  Variáveis locais, não.

A linguagem Java oferece literais para os tipos primitivos e para Strings.  Java 7: pode usar underscore ("_") em números.

Criando objetos (ponteiros, referências)
Declaração: determina o tipo (classe) do objeto.
Instanciação: efetivamente cria o objeto, através do operador new.
Inicialização: dá valores iniciais a seus campos (geralmente feita por um construtor).

Pacotes - espaços de nomes.
Implementados como diretórios (pastas).

Como compilar programas - IDE NetBeans
Pode-se usar Eclipse também, ou simplesmente a linha de comando.

Método main.  Tem que ser public static void.

Arrays sabem seu tamanho (.length).
Índices sempre começam de zero.
Declaração e criação.  Acesso.
Métodos pré-definidos: java.util.Arrays