segunda-feira, 23 de abril de 2012

3 - Listas em AutoLisp (list) - PARTE 2 - Funções: length, cons, append, subst

Olá Pessoal, neste post irei continuar falando sobre funções que manipulam listas. No post passado, falei como criar listas e como obter um elemento de uma posição da lista. Neste post, irei falar como adicionar elementos numa lista existente, como trocar elementos e como saber a quantidade de elementos numa lista qualquer.


Quantidade de elementos em uma lista

Através da função length seguido pelo nome da lista, podemos descobrir quantos elementos existem nesta lista. OBS: cada sub lista é considerada um elemento da lista.
Exemplos:
- (length (list))
   retorna 0
- (length (list 1 2 3))
   retorna 3
- criando uma lista na variável a1: (setq a1 (list "teste" (list (list 1 2 3) 10)))
   criada a lista: ("teste" ((1 2 3) 10))
   verificando o tamanho da lista contida em a1: (length a1)
   retorna 2



Adicionando elementos em uma lista existente

1 - Função CONS

A função cons permite adicionar um átomo ou uma sub lista como um novo elemento de uma lista. A sua sintaxe é a seguinte: (cons NovoItem ListaA), onde NovoItem é um átomo ou uma lista, e ListaA é a lista no qual receberá o novo elemento. OBS: só é possível adicionar um novo elemento de cada vez na lista, e este elemento será posicionado na primeira posição da lista existente.
Exemplos:
- adicionando o átomo 15 na lista (5 10): (cons 15 (list 5 10))
   retorna a nova lista: (15 5 10)
- adicionando a sub lista (1 2) na lista (3 4): (cons (list 1 2) (list 3 4))
   retorna a lista: ((1 2) 3 4)
- adicionando o átomo "teste" na lista vazia (): (cons "teste" (list))
  retorna a lista: ("teste")

OBS2: a função cons também é utilizada para construirmos um tipo de lista especial (list association) que contém 2 pares (o primeiro elemento funciona como um cabeçalho e o segundo elemento é associado a este cabeçalho). Este tipo de estrutura é muito utilizado em entidades do AutoCAD, quando se manipula em AutoLISP. Num post futuro irei falar sobre este tipo de estrutura.


2 - Função APPEND

A função append, é um pouco parecida com a função cons, porém a forma que ela funciona é um pouco diferente. Nesta função, o objetivo é anexar alguma lista numa outra lista. A sintaxe da função é a seguinte: (append (lista1) (lista2) (lista3) ... ) , assim pode-se  juntar N-listas em uma única lista.
Exemplos:
- juntando a lista (10 20) com a lista (30 40): (append (list 10 20) (list 30 40))
  retorna a lista: (10 20 30 40)
- criando uma lista na variável teste: (setq teste (list 1 2 3))
  anexando no ínicio da lista teste, os elementos -1 e 0: (append (list -1 0) teste)
  retorna a lista: (-1 0 1 2 3)
- anexando no final da lista ("abc" "def") a sub lista ("123" "456"): (append (list "abc" "def") (list (list "123" "456")))
  retorna a lista: ("abc" "def" ("123" "456"))



Substituindo elementos em uma lista

Utilizando a função subst, podemos trocar um elemento de uma lista por outro. A sintaxe da função é a seguinte: (subst NovoElemento VelhoElemento Lista) , onde NovoElemento pode ser um átomo ou uma lista e VelhoElemento deve ser um item existente na Lista. OBS: caso o velho elemento definido não exista dentro da Lista, então nada será substituído, e será retornado a lista original. E se existir mais de uma vez o velho elemento, então todos estes elementos repetidos serão trocados pelo novo elemento na lista
Exemplos:
- substituindo o átomo "dois" pelo átomo 2 na lista (1 "dois" 3): (subst 2 "dois" (list 1 "dois" 3))
 retorna: (1 2 3)
- substituindo o átomo 1 pelo átomo "troca" na lista (1 1 2 1 3 1 4): (subst "troca" 1 (list 1 1 2 1 3 1 4))
  retorna: ("troca" "troca" 2 "troca" 3 "troca" 4)
- troca cada átomo 1 por 10 na lista (10 20 30): (subst 10 1 (list 10 20 30))
  retorna a mesma lista, pois não houve troca: (10 20 30)
- substituindo a sub lista (1 2) pelo átomo 12 na lista ((1 2) 3 4): (subst 12 (list 1 2) (list (list 1 2) 3 4))
  retorna a lista: (12 3 4)
- utilizando a função subst em conjunto com a função nth; Dado a variável teste, que contém a lista  (1 2 3 4), substituir o segundo elemento da lista por "num2":
  criando a lista: (setq teste (list 1 2 3 4))
  substituindo o segundo elemento da lista: (subst "num2" (nth 1 teste) teste)
  retorna a lista: (1 "num2" 3 4)



Bom, assim termino esta pequena introdução sobre listas. Vocês devem ter notado, que não falei, de nenhuma função que deleta itens de forma direta da lista. Isto devido ao simples fato de que não existe (ou eu não conheço?), mas o leitor não precisa ficar assustado, pois existe funções em ActiveX, que permitem fazer esta operação comum. Como considero o assunto sobre ActiveX, um pouco mais avançado, não irei falar sobre estas funções neste momento.

No próximo post, eu irei falar sobre operadores de comparação e operadores lógicos, para introduzir o assunto do post seguinte, que é funções de repetição. Até lá, pessoal!

2 - Listas em AutoLisp (list) - PARTE 1 - Funções: list, car, cdr e nth

Olá Pessoal, neste post eu irei falar sobre a manipulação de listas no AutoLisp, que pode-se dizer que é a estrutura mais importante que existe em lisp, isto fica mais evidente com o fato de LISP significar LISt Processing (processamento de listas).

Neste post, eu irei focar na manipulação de listas através dos comandos básicos presentes na linguagem. Num post futuro, irei falar dos comandos para manipulação de listas, utilizando o ActiveX, que é uma expansão do Visual Lisp, que amplia em muito o AutoLisp.



CRIANDO LISTAS


Para criar uma lista, usamos a palavra chave list, seguido dos itens no qual se deseja adicionar a lista. Estes itens podem ser de qualquer tipo, números, strings, outras listas (sub listas), ou uma mistura de várias coisas.
Exemplos:
- criando uma lista com os números 1, 2 e 3: (list 1 2 3) 
   retorna: (1 2 3)
- criando uma lista com as strings "Autolisp" e "Brasil": (list "Autolisp" "Brasil")
   retorna: ("Autolisp" "Brasil")
- criando uma lista que contém as duas listas dos exemplos anteriores: (list (list 1 2 3) (list "Autolisp" "Brasil"))
  retorna: ((1 2 3) ("Autolisp" "Brasil"))

O caractere ' nos permite substituir a palavra chave list em alguns casos, na verdade este caractere é equivalente ao comando quota do AutoLisp, que não entrarei em detalhes.
Exemplo do uso do caractere ' , onde queremos criar uma lista com os seguintes itens: o número 1, uma sub lista com os números 2 e 3, e o número 4:
(list 1 '(2 3) 4)
retorna: (1 (2 3) 4)

Exemplo que não funciona com o caractere ' :
('( 1 2 3)) (NÃO FUNCIONA)

Para fazer o exemplo anterior funcionar, podemos associar a lista em uma variável qualquer, assim podemos utilizar do caractere ' , como mostrado no exemplo abaixo:
(setq variavel '( 1 2 3))
que retorna a lista: (1 2 3)



RECUPERANDO ELEMENTOS DA LISTA

1 - FUNÇÕES CAR E CDR
Uma maneira de recuperar os elementos de uma lista, é utilizando as funções car e cdr. A função car, recupera sempre o primeiro elemento de uma lista, que pode ser um átomo ou uma sub lista, ou seja, qualquer coisa que esteja como primeiro item da lista.
Exemplos, utilizando a função car:
- Exemplo 1: Temos a seguinte lista: (10 20 30 40)
                      Utilizando da função car: (car (list 10 20 30 40))
                      Obtemos o átomo: 10
- Exemplo 2: Temos a váriavel listaObjetos com os itens "autolisp", 30, 3.14
                      Criando a lista: (setq listaObjetos (list "autolisp" 30 3.14))
                      Lista gerada: ("autolisp" 30 3.14)
                      Utilizando da função car: (car listaObjetos)
                      Obtemos o átomo: "autolisp"
- Exemplo 3: Temos uma lista com uma sub lista contendo os números 1, 2 e 3, e uma outra sub lista contendo os números 4, 5 e 6.
                       Utilizando da função car: (car (list (list 1 2 3) (list 4 5 6)))
                       Obtemos a lista: (1 2 3)


A função cdr, recupera todos os itens da lista, exceto o primeiro. Utilizando os mesmo exemplos anteriores, temos:

Exemplos, utilizando a função cdr:
- Exemplo 1: Temos a seguinte lista: (10 20 30 40)
                      Utilizando da função cdr: (cdr (list 10 20 30 40))
                      Obtemos a lista: (20 30 40)
- Exemplo 2: Temos a váriavel listaObjetos com os itens "autolisp", 30, 3.14
                      Criando a lista: (setq listaObjetos (list "autolisp" 30 3.14))
                      Lista gerada: ("autolisp" 30 3.14)
                      Utilizando da função cdr: (cdr listaObjetos)
                      Obtemos a lista: (30 3.14)
- Exemplo 3: Temos uma lista com uma sub lista contendo os números 1, 2 e 3, e uma outra sub lista contendo os números 4, 5 e 6.
                       Utilizando da função cdr: (cdr (list (list 1 2 3) (list 4 5 6)))
                       Obtemos uma lista com um único item, que é uma sub lista: ((4 5 6))


Para obtermos por exemplo o segundo item da lista, precisamos utilizarmos a função cdr, que retorna a lista sem o primeiro item seguido da função car, como mostrado abaixo para a seguinte lista (10 20 30 40 50):
(setq lista (list 10 20 30 40 50))
(setq novaLista (cdr lista))
(setq novaNovaLista (car novaLista))

Recuperar os itens desta forma é bem ineficiente, pois se tivermos que recuperar o quarto item, temos que invocar três vezes a função cdr e por fim a função car. Felizmente, lisp permite concatenar as funções cdr e car, assim para o caso anterior, podemos usar a função cadddr, que pode ser lida de trás para frente, onde cada "d" significa uma execução da função cdr, e cada "a" significa a execução da função car.

Abaixo temos uma listagem de funções permitidas com a junção das funções car com cdr, lembrando que a chamada das funções car e cdr é feita de trás para frente nestas funções:

caar cadr cdar cddr caaar caadr cadar caddr cdaar cdadr cddar cdddr caaaar caaadr caadar caaddr cadaar cadadr caddar cadddr cdaaar cdaadr cdadar cdaddr cddaar cddadr cdddar cddddr


Infelizmente, nem sempre temos uma função que desejamos, quando vamos obter um item, por exemplo para pegar o quinto item da lista (10 20 30 40 50), temos que executar quatro vezes a função cdr, seguido de uma execução da função car. Não existe a função caddddr em lisp, então temos que mesclar as funções disponíveis para se conseguir o efeito desejado.


2 - FUNÇÃO NTH

Através da função nth, podemos acessar de forma mais direta elementos da lista. Sabendo-se qual a posição do elemento na lista, a função nth é usada da seguinte forma: (nth x listaA) , onde x é a posição do elemento na lista e listaA é a lista no qual está efetuando a operação. OBS: a primeira posição da lista é sempre 0, e a última posição da lista é o número de elementos menos um.

Exemplos, utilizando a função nth:
- Exemplo 1: Temos a seguinte lista: (10 20 30 40)
                     Utilizando da função nth, queremos obter o terceiro elemento da lista: (nth 2 (list 10 20 30 40))
                     Obtemos o átomo: 30
- Exemplo 2: Temos a váriavel listaObjetos com os itens "autolisp", 30, 3.14
                      Criando a lista: (setq listaObjetos (list "autolisp" 30 3.14))
                      Lista gerada: ("autolisp" 30 3.14)
                    Utilizando da função nth, queremos obter o primeiro elemento da lista: (nth 0 listaObjetos)
                      Obtemos o átomo: "autolisp"
- Exemplo 3: Temos uma lista com uma sub lista contendo os números 1, 2 e 3, e uma outra sub lista contendo os números 4, 5 e 6.
                    Utilizando da função nth, queremos obter o segundo elemento da lista: (nth 1 (list (list 1 2 3) (list 4 5 6)))
                    Obtemos a sub lista: (4 5 6)




OBSERVAÇÕES:

- Quando tenta-se obter um elemento inexistente de uma lista, como por exemplo uma lista com 3 elementos, tenta-se acessar o quinto elemento, é obtido o valor nil;
- Um erro é obtido em situações no qual é aplicados as funções car, cdr ou nth, em elementos que não são listas;



No próximo post, irei continuar falando de outras funções que manipulam listas.

segunda-feira, 16 de abril de 2012

1 - Introdução ao AutoLISP

Um pouco de história

O AutoLISP é um dialeto da antiga linguagem LISP. A linguagem LISP foi concebida por John McCarthy em 1958, e o seu nome vem de LISt Processing, pois a lista é a estrutura de dados fundamental da linguagem. 
LISP é a segunda mais antiga linguagem de programação de alto nível criada, perdendo apenar para a linguagem FORTRAN.
O principal paradigma de programação de LISP é a programação funcional, e além disso a linguagem não é compilada, e sim interpretada, ou seja, existe um programa instalado chamado interpretador, que executa o código fonte, para em seguida ser executado pelo sistema operacional ou processador.

O AutoLISP foi criado especificamente para ser utilizado com o programa AutoCAD da Autodesk. E ele foi introduzido no AutoCAD em 1986 na versão 2.18. Atualmente o interpretador e o ambiente de programação, vem junto com o AutoCAD, exceto nas versões do AutoCAD LT.



Tipos de dados básicos

Na linguagem AutoLisp, existe praticamente dois tipos de dados fundamentais: o átomo e a lista. 
O átomo pode ser numérico ou alfanumérico. Além disso, existem dois tipos de átomos especiais muito usados, o nil e o T. O nil representa o valor nulo e ao mesmo tempo uma lista vazia, o T representa o símbolo verdadeiro (true).
A lista é a associação de átomos ou outras listas representandos entre parêntesis.


Expressões

- Cada instrução deve iniciar sempre com um abre parêntesis "(" e terminar com um fecha parêntesis ")";

- O AutoLisp utiliza a notação infixa quando efetuamos uma expressão matemática, isto é, primeiramente vem o operador seguidos dos operandos.
Exemplo: 10 + 20 + 30 + 40
Em AutoLisp, você escreveria assim: 
(+ 10 20 30 40)

- Qualquer coisa avaliada em AutoLisp retorna um valor como resultado;



Declarando variáveis

Para declarar uma variável, utilizamos a palavra chave setq seguida de um nome válido para a variável e seguida de um átomo ou uma expressão.
Exemplos:
- declarando uma variável chamada teste com o valor 10: (setq teste 10) 
- declarando uma variável chamada conta com o resultado da expressão 10 * 2: (setq conta (* 10 2))
- declarando uma variável chamada valor com o valor nil (nulo): (setq valor nil)
- declarando uma variável chamada lista com uma lista com os inteiros 1, 2 e 3: (setq lista (list 1 2 3))



Executando código AutoLisp pela linha de comando do AutoCAD


A execução de comandos AutoLisp pela linha de comando do AutoCAD é muito útil para realizar pequenos testes. Para isso, digite na linha de comando a expressão ou função desejada e aperte ENTER. O resultado da avaliação do interpretador é retornado na linha de comando para o usuário. OBS: não esqueça de sempre utilizar dos parêntesis ao iniciar uma expressão.


Carregando programas AutoLisp no AutoCAD

Entre na opção Load Application, presente no menu Tools no modo do AutoCAD Classic. Se você estiver utilizado as ribbons ao invés do menu clássico, vá na aba Manage, e em Applications, clique em Load Application. Outra maneira de chegar até está tela, é digitando na linha de comando o comando appload (ou simplesmente "ap"), seguido de um ENTER.
Na tela que se segue, navegue até o diretório e clique no arquivo desejado a ser carregado, e em seguida clique no botão Load. OBS: arquivos lisp tem a extensão .lsp .


Próximo POST

No próximo post, eu irei falar sobre listas: como criar, recuperar elementos, substituir, deletar, etc.


REFERÊNCIAS:

- Wikipédia;
- AutoLISP - I Introdução, João Tavares e Joaquim Fonseca - DEMec, FEUP

domingo, 15 de abril de 2012

Bem Vindos ao blog do AutoLISP Brasil

Ola Pessoal, sejam bem vindos ao meu blog sobre AutoLisp. O meu nome é André, sou formado em ciência da computação na UFMG, e atualmente estou trabalhando com programação para AutoCAD usando ObjectARX.

Programei cerca de três anos em AutoLisp, e pretendo compartilhar com vocês o conhecimento que aprendi com esta linguagem que permite construir muitas rotinas interessantes que ajudam a agilizar a vida dos usuários do AutoCAD.

Resolvi escrever este blog, devido a falta de material sobre autoLisp na nossa língua e o fato de ser difícil encontrar alguns assuntos mais específicos, mesmo em inglês. O blog é destinado a todos tipos de usuários, desde usuários simples do AutoCAD que desejam construir rotinas que lhes serão úteis, à programadores de outras linguagens de programação, que estão entrando neste novo mundo do lisp. Programadores avançados em AutoLisp também são bem vindos, para ajudar e serem ajudados por mim e os demais usuários. Assim a idéia do blog é aprender e ensinar uns aos outros. Tem muita coisa de AutoLisp que eu não sei ou nunca usei, mas espero poder contribuir bastante.

As postagens no blog não terão um dia fixo, mas pretendo postar cerca de duas a três vezes por semana. Serão postagens simples sobre algum assunto de autoLisp com vários exemplos. Inicialmente farei posts sobre assuntos mais básicos e com o decorrer do tempo irei postando coisas mais avançadas. As pessoas que tiverem dúvidas podem deixar comentários, que tentarei responder o mais breve possível.

Dúvidas, sugestões e críticas são bem vindas, pois assim tornaremos o blog cada dia melhor.
No próximo post farei uma introdução ao AutoLisp, falando de como é a linguagem e de algumas coisas bem básicas.