sexta-feira, 1 de junho de 2012

6 - Funções de repetição

Olá pessoal, neste post irei falar sobre as funções de repetição da linguagem AutoLisp. A partir dos comandos de repetição podemos fazer com que um determinado trecho de código possa ser repetido. Neste post, eu irei falar dos comandos de repetição WHILE e REPEAT.


- while

O comando de repetição while do AutoLisp permite que um trecho de código seja repetido (loop), enquanto uma expressão lógica for verdadeira. Se esta expressão nunca se tornar falsa, o programa entra no que chamamos em programação de "Loop Infinito", ou seja, um trecho de código será repetido infinitamente. Assim o programador deve estabelecer dentro do trecho a ser repetido, algum mecanismo que torne em algum momento, falso o resultado da expressão avaliada pelo while.
A sintaxe do comando while é a seguinte:

(while (EXPRESSÃO BOOLEANA)
          (COMANDO 1)
          (COMANDO 2)
          (COMANDO 3)
          ...
          (COMANDO N)
)


Exemplos:

- O exemplo abaixo, mostra um loop que nunca será feito, pois a expressão booleana avaliada pelo while, possui sempre o valor nil (falso). Assim, o comando  (princ "loop"), nunca será executado.

(while nil
          (princ "loop")
)


- No exemplo abaixo, é declarado uma variável chamada contador com o valor 0. Em seguida a função while avalia a expressão booleana (< contador 5). Assim, enquanto o valor da variável contador for menor do que 5, o comando que incrementa uma unidade na variável contador é executado:  (setq contador (+ contador 1)).
Quando a variável atingir o valor 5, a expressão booleana irá retornar falso, e o fluxo de execução do programa, sairá do loop.

(setq contador 0)
(while (< contador 5)
          (setq contador (+ contador 1))
)

O loop acima, será executado cinco vezes, parando quando a variável contador atingir o valor 5 e for avaliado pela expressão booleana.


- No exemplo abaixo, é declarado uma variável chamada repetir com o valor T. Em seguida a função while avalia a expressão booleana, que no caso, é verdadeiro (contéudo da variável repetir), assim a função executa os três comandos declarados dentro do while.
O terceiro comando executado de dentro do while, declara a variável repetir como nil, assim, logo em seguida, quando o comando while avalia a expressão boolena novamente, esta retornará falso, o que faz com que o fluxo de execução do programa saia do while.

(setq repetir T)
(while repetir
          (print "linha1")
          (print "linha2")
          (setq repetir nil)
)

O loop acima, será executado apena uma vez, pois após a primeira iteração do loop, a variável repetir assume o valor falso (nil).




- repeat

O comando repeat é bem simples, com ele é possível executar um trecho de código por uma quantidade estabelecida de vezes. A sintaxe do comando repeat é a seguinte:


(repeat INTEIRO
            (COMANDO 1)
            (COMANDO 2)
            (COMANDO 3)
             ...
            (COMANDO N)

)


Na sintaxe acima, o campo INTEIRO deve ser um número inteiro positivo e diferente de zero para que a função repeat execute a sua sequencia de comandos.


Exemplos:

- O código abaixo, repete por duas vezes o comando print, com isto é impresso por duas vezes a palavra "oi" na linha de comando do autocad:

(repeat 2
            (print "oi")
)


- O código abaixo, estabelece inicialmente algumas variáveis, e em seguida é repetido o código contido na função repeat, por dez vezes, o que faz com que as variáveis valor1 e valor2 tenham seus valores modicados a cada passada.

(setq valor1 0)
(setq valor2 0)
(setq quantidade 10)
(repeat quantidade
             (setq valor1 (+ valor1 1))
             (setq valor2 (- valor2 1))
)


Pessoal, isto é tudo! No próximo post, irei falar sobre como declarar funções em AutoLisp, e como criar funções que podem ser usadas para criar comandos no AutoCAD. Funções são usadas para criar os programas em AutoLisp e podem ser salvas e executadas posteriormente pelo usuário.

quarta-feira, 30 de maio de 2012

5 - Funções condicionais

Olá pessoal, neste post irei falar sobre as funções condicionais que a linguagem AutoLisp possui. Estas funções são bem importantes em linguagens de programação, para quem não sabe, com as funções condicionais, podemos fazer com que um trecho de código seja ou não executado. Neste post, eu irei falar dos comandos condicionais IF e COND.



- IF (SE)


O comando condicional if, avalia uma expressão booleana, que ao ser verdadeira permite a execução de um determinado trecho de código. Este comando pode ter um "SENÃO", ou seja, se a expressão booleana não for verdadeira, é executado um trecho de código diferente do trecho que foi atribuído a ser executado quando verdadeiro. O trecho de código que deve ser executado quando se avalia o if, deve estar dentro do parentes do if, assim a sintaxe do comando if é a seguinte:

(if (EXPRESSÃO BOOLEANA)
     (COMANDO A SER EXECUTADO, QUANDO A EXPRESSÃO BOOLEANA É VERDADEIRA)
     (COMANDO A SER EXECUTADO, QUANDO A EXPRESSÃO BOOLEANA É FALSA)
)

A sintaxe apresentada acima, executa apenas um comando se a expressão for verdadeira, e apenas um comando se ela for falsa. Se o programador quiser, que seja executado mais de um comando, é necessário utilizar de um "truque" que é a utilização da expressão progn. Abaixo, podemos ver a sintaxe do comando if mesclado com o progn:

(if (EXPRESSÃO BOOLEANA)
     (progn
          (COMANDO 1 - EXPRESSÃO BOOLEANA É VERDADEIRA)
          (COMANDO 2 - EXPRESSÃO BOOLEANA É VERDADEIRA)
          (COMANDO 3 - EXPRESSÃO BOOLEANA É VERDADEIRA)
          ...
          (COMANDO N - EXPRESSÃO BOOLEANA É VERDADEIRA)
     )  
     (progn
          (COMANDO 1 - EXPRESSÃO BOOLEANA É FALSA)
          (COMANDO 2 - EXPRESSÃO BOOLEANA É  FALSA )
          (COMANDO 3 - EXPRESSÃO BOOLEANA É  FALSA )
          ...
          (COMANDO N - EXPRESSÃO BOOLEANA É  FALSA )
     )  

)


Exemplos:
- (if T (setq x 10) (setq x 20)) , a variável x, sempre receberá o valor 10, pois a expressão sempre é verdadeira.
- (if (= teste 0) (setq x 10)) , se a variável teste for igual a 0, então a variável x receberá o valor 10, caso contrário, nada é executado.
- (if (= teste 0) (setq x 10) (setq x 20)) , se a variável teste for igual a 0, então a variável x receberá o valor 10, caso contrário, receberá o valor 20.
- (if (= teste 0) (progn (setq x 10) (setq y 5)) (setq x 20)) , se a variável teste for igual a 0, então a variável x receberá o valor 10 e a variável y o valor 5, caso contrário, x receberá o valor 20.
- (if (= teste 0) (progn (setq x 10) (setq y 5)) (progn (setq x 20) (setq y 5))) , se a variável teste for igual a 0, então a variável x receberá o valor 10 e a variável y o valor 5, caso contrário, x receberá o valor 20 e y o 5.



- COND


O comando condicional cond, testa uma série de expressões, e executa a primeira que for verdadeira. Este comando é muito parecido com o switch de algumas linguagens de programação como C++. A sintaxe em autolisp para utilizar o comando cond é a seguinte:

(cond ((EXPRESSÃO BOOLEANA 1) (COMANDOS 1))
          ((EXPRESSÃO BOOLEANA 2) (COMANDOS 2))
          ((EXPRESSÃO BOOLEANA 3) (COMANDOS 3))
          ...
          ((EXPRESSÃO BOOLEANA N) (COMANDOS N))
          (T (COMANDOS DEFAULT)) 
)

Pela sintaxe acima, primeiro é verificado a expressão boolena 1, se ela for verdadeira é executado somente os comandos contidos em "comandos 1". Se ela for falsa, então o fluxo do programa avalia a expressão booleana 2 da mesma forma, se ela for verdadeira é executado somente os comandos contidos em "comandos 2", e se for falsa, passa para a próxima expressão boolena se esta existir. 
A última linha mostrada na sintaxe " (T (COMANDOS DEFAULT)) ", mostra uma forma de criar uma expressão opcional do cond, caso o programador precise de um comando padrão (default), que será executado sempre que todas as expressões booleanas anteriores forem falsas.


Exemplos: 

- É declarado a variável numero com o valor 3. Em seguida verifica-se se o número é igual a zero, maior que zero ou menor do que zero através da função cond. Neste exemplo não foi utilizado um comando default. (obs: o comando princ imprime uma string na linha de comando do autocad):
(setq numero 3)
(cond ((= numero 0) (princ "O número é 0"))
          ((> numero 0) (princ "O número é maior do que 0"))
          ((< numero 0) (princ "O número é menor do que 0"))
)

No exemplo acima, será executado a segunda expressão boolena, pois a variável numero é maior do que zero, assim é impresso na linha de comando que o número é maior do que 0.


- No exemplo abaixo, é declarado a variável estado com a string "Bahia", em seguida através da função cond é verificado se uma das expressões é verdadeira, caso alguma seja, é executado os comandos referentes a expressão que for verdadeira:

(setq estado "Bahia")
(cond   ((= estado "Minas Gerais") 
(setq ddd 31) 
(setq capital "Belo Horizonte")
)
((= estado "São Paulo") 
(setq ddd 11) 
(setq capital "São Paulo")
)
((= estado "Rio de Janeiro") 
(setq ddd 21) 
(setq capital "Rio de Janeiro")
)
(T
(princ "Estado não cadastrado!")
)
)

No exemplo acima, será executado a última expressão, que é a default, pois nenhuma das expressão avaliadas anteriormente é verdadeira.


No próximo post, eu irei falar sobre as funções de repetição. Até lá, pessoal!



sábado, 5 de maio de 2012

4 - Operadores lógicos e de comparação

olá pessoal, neste post irei falar um pouco sobre operadores lógicos e operadores de comparação, é um assunto bem simples, mas muito importante.



Operadores de comparação

Assim como em outras linguagens, o AutoLISP permite fazer comparações entre duas entidades, como por exemplo verificar se o conteúdo de duas variáveis são iguais. Toda expressão em lisp retorna um valor, no caso da comparação, existe dois resultados diferentes possíveis: T (verdadeiro) ou nil (falso). Uma expressão de comparação em AutoLisp é sempre composta do comparador, seguidos de dois argumentos. Estes argumentos devem ser átomos, sendo que alguns comparadores podem comparar também listas.

OBS: quando se compara duas strings, ele leva em consideração a ordem lexicográfica, que é análoga à ordem das palavras em um dicionário. Esta ordem  lexicográfica se baseia na ordenação dos caracteres estabelecida na tabela ISO8859-1 (http://pt.wikipedia.org/wiki/ISO_8859-1).
Assim, quando se compara duas strings s e t, procura-se a primeira posição, digamos k, em que as duas strings diferem. Se s[k] vem antes de t[k] na tabela ISO então s é lexicograficamente menor que t.

Abaixo será listado os comparadores mais importantes em AutoLisp, seguidos de sua descrição e exemplos:

  • = (IGUAL)
    • Descrição: compara se dois átomos (ou expressões que retornam átomos) são iguais.
    • Exemplos: 
      • (= 10 10)           , retorna T;
      • (= 1 2)           , retorna nil;
      • (setq a 11)          (setq b 11)          (= a b)           , retorna T
      • (= "autolisp" "autolisp")           , retorna T;
      • (= "brasil" "autolisp")           , retorna nil;
      • (= "autoCAD" "autocad")           , retorna nil;
      • (= 10 (- 20 10))            , retorna T;
    • BUG?
      • As duas expressões abaixo, deveriam retornar ambas T, porém isto não ocorre:
        • (= 6.0 (- 8.1 2.1))           , retorna T;
        • (= 6.0 (- 8.2 2.2))           , retorna nil;
      • Não encontrei uma explicação oficial sobre este bug, mas é bem provável que esteja ocorrendo um erro de arredondamento, pois no teste abaixo verificamos que existe uma influência do número de casas:
        • (= 5.999999999999999 (- 8.2 2.2))           , retorna T;

  • /= (DIFERENTE)
    • Descrição: compara se dois átomos (ou expressões que retornam átomos) são diferentes.
    • Exemplos: 
      • (/= 10 10)           , retorna nil;
      • (/= 1 2)           , retorna T;
      • (setq a 11)          (setq b 11)          (/= a b)           , retorna nil;
      • (/= "autolisp" "autolisp")           , retorna nil;
      • (/= "brasil" "autolisp")           , retorna T;  
      • (/= "autoCAD" "autocad")           , retorna T;
      • (/= 10 (- 20 10))            , retorna nil;

  • > (MAIOR)
    • Descrição: compara se o primeiro argumento é maior do que o segundo.
    • Exemplos: 
      • (> 10 10)           , retorna nil;
      • (> 1 2)           , retorna nil;
      • (> 5 1)           , retorna T;
      • (setq a 55)          (setq b 54)          (> a b)           , retorna T;
      • (> "autolisp" "autolisp")           , retorna nil;
      • (> "brasil" "autolisp")           , retorna T;  
      • (> "autolisp" "brasil")           , retorna nil;   
      • (> "autoCAD" "autocad")           , retorna nil
      • (> (+ 1 2) (- 1 2))            , retorna T;
      • (> (/ 10 2) 5)            , retorna nil;  

  • < (MENOR)
    • Descrição: compara se o primeiro argumento é menor do que o segundo.
    • Exemplos: 
      • (< 10 10)           , retorna nil;
      • (< 1 2)           , retorna T;
      • (< 5 1)           , retorna nil;
      • (setq a 55)          (setq b 54)          (< a b)           , retorna nil;
      • (< "autolisp" "autolisp")           , retorna nil;
      • (< "brasil" "autolisp")           , retorna nil;  
      • (< "autolisp" "brasil")           , retorna T;  
      • (< "autoCAD" "autocad")           , retorna T;  
      • (< (+ 1 2) (- 1 2))            , retorna nil;
      • (< (/ 10 2) 5)            , retorna nil;  

  • >= (MAIOR  OU IGUAL)
    • Descrição: compara se o primeiro argumento é maior ou igual ao segundo.
    • Exemplos: 
      • (>= 10 10)           , retorna T;
      • (>= 1 2)           , retorna nil;
      • (>= 5 1)           , retorna T;
      • (setq a 55)          (setq b 54)          (>= a b)           , retorna T;
      • (>= "autolisp" "autolisp")           , retorna T;
      • (>= "brasil" "autolisp")           , retorna T;  
      • (>= "autolisp" "brasil")           , retorna nil;  
      • (>= "autoCAD" "autocad")           , retorna nil;   
      • (>= (/ 10 2) 5)            , retorna T;  

  • <= (MENOR OU IGUAL)
    • Descrição: compara se o primeiro argumento é menor ou igual ao segundo.
    • Exemplos: 
      • (<= 10 10)           , retorna T;
      • (<= 1 2)           , retorna T;
      • (<= 5 1)           , retorna nil;
      • (setq a 55)          (setq b 54)          (<= a b)           , retorna nil;
      • (<= "autolisp" "autolisp")           , retorna nil;
      • (<= "brasil" "autolisp")           , retorna nil;  
      • (<= "autolisp" "brasil")           , retorna T;  
      • (<= "autoCAD" "autocad")           , retorna T;   
      • (<= (/ 10 2) 5)             , retorna T;  

  • eq (IDÊNTICO)
    • Descrição: compara se os argumentos são derivados um do outro (não compara listas).
    • OBS1: na grande maioria dos casos, o resultado será idêntico ao "=" (IGUAL), como é mostrado nos exemplos abaixo, que são os mesmos utiizados nos exemplos do "=", e que retornaram o mesmo resultado.
    • Exemplos: 
      • (eq 10 10)           , retorna T;
      • (eq 1 2)           , retorna nil;
      • (setq a 11)          (setq b 11)          (eq a b)           , retorna T
      • (eq "autolisp" "autolisp")           , retorna T;
      • (eq "brasil" "autolisp")           , retorna nil;
      • (eq "autoCAD" "autocad")           , retorna nil;
      • (eq 10 (- 20 10))            , retorna T;
    • OBS2: pesquisando na internet, por casos onde o "=" e o "eq" retornam valores diferentes, consegui achar uma situação em que eles se diferem. Quando se salva o nome de uma entidade desenhada, em duas variáveis diferentes, a comparação com o "=" retorna nil, e com "eq" retorna T. Como o código para este exemplo contém assuntos que ainda não expliquei, coloquei o código para este exemplo, ao final deste post, na seção extras.

  • equal (EQUIVALENTE)
    • Descrição: compara se os argumentos são equivalente (pode comparar listas)
    • Exemplos: 
      • (equal 10 10)           , retorna T;
      • (equal 1 2)           , retorna nil;
      • (equal 5 1)           , retorna nil;
      • (setq a 55)          (setq b 54)          (equal a b)           , retorna nil;
      • (equal "autolisp" "autolisp")           , retorna T;
      • (equal "brasil" "autolisp")           , retorna nil;  
      • (equal "autolisp" "brasil")           , retorna nil;  
      • (equal "autoCAD" "autocad")           , retorna nil;   
      • (equal (list 1 2 3) (list 1 2 3))           , retorna T;   
      • (equal (list 1 2) (list 2 1))           , retorna nil;  




Operadores lógicos

Com os operadores lógicos, podemos montar expressões booleanas, que ao serem avaliadas, retornam T (verdadeiro) ou nil (falso). Assim, com ajuda dos operadores de comparação, podemos montar expressões mais complexas. Os operadores lógicos disponíveis em AutoLISP são três: AND, OR e NOT
OBS: toda lista e todo átomo é considerado como T (verdadeiro), sendo que o único valor que é considerado nil (falso) é o próprio átomo nil.

  • AND (e)
    • Descrição: Operador lógico onde a resposta da operação é verdade (T) se ambas as variáveis de entrada forem verdade.
    • Exemplos: 
      • (and 10 10)           , retorna T;
      • (and 1 2)           , retorna T;
      • (setq a 55)          (setq b 54)          (and a b)           , retorna T;
      • (and "brasil" "autolisp")           , retorna T
      • (and (list 1 2) (list 2 1))           , retorna  T;  
      • (and (= (list 1 2)  (list 1 2)) (equal  (list 1 2)  (list 1 2)))            , retorna  nil
      • (and (> 2 0) (< -2 0))            , retorna  T;  
      • (and (= 1 1) (> 1 1))             , retorna  nil
      • (and (< 10 5) (> 10 20))              , retorna  nil
      • (and T nil)               , retorna nil
      • (and T)             , retorna T;  

  • OR (ou)
    • Descrição: Operador lógico onde a resposta da operação é verdade (T) se e somente se pelo menos uma das variáveis de entrada for verdade.
    • Exemplos: 
      • (or 10 10)           , retorna T;
      • (or 1 2)           , retorna T;
      • (setq a 55)          (setq b 54)          (or a b)           , retorna T;
      • (or "brasil" "autolisp")           , retorna T
      • (or (list 1 2) (list 2 1))           , retorna  T;  
      • (or (= (list 1 2)  (list 1 2)) (equal  (list 1 2)  (list 1 2)))            , retorna   T
      • (or (> 2 0) (< -2 0))            , retorna  T;  
      • (or (= 1 1) (> 1 1))             , retorna  T
      • (or (< 10 5) (> 10 20))              , retorna  nil
      • (or T nil)               , retorna T
      • (or T)             , retorna T;  

  • NOT (negação)
    • Descrição: Operador lógico que representa a negação (inverso) da variável atual. Se ela for verdade, torna-se falsa, e vice-versa.
    • OBS: deve avaliar um argumento, que pode ser uma expressão.
    • Exemplos: 
      • (not 10)           , retorna nil;
      • (setq a 55)          (setq b 54)          (not (or a b))           , retorna nil;
      • (not "autolisp")           , retorna nil
      • (not (list 1 2))           , retorna nil;  
      • (not (= (list 1 2)  (list 1 2)))            , retorna T
      • (not (equal  (list 1 2)  (list 1 2)))            , retorna nil
      • (not (> 2 0))            , retorna nil;  
      • (not (> 1 1))             , retorna T
      • (not T)              , retorna nil
      • (not nil)              , retorna T



No próximo post, eu irei falar sobre as funções condicionais. Até lá, pessoal!




REFERÊNCIAS

- Cadeias de caracteres (strings): http://www.ime.usp.br/~pf/algoritmos/aulas/strings.html
- Operadores lógicos: http://pt.wikipedia.org/wiki/Operadores_l%C3%B3gicos
AutoLISP III- Funções de repetição e condicionais, Obter e converter informação, João Tavares e Joaquim Fonseca - DEMec, FEUP
- Fórum com discurssão sobre "=, eq, equal":  http://forums.augi.com/showthread.php?6240-eq-equal




EXTRAS

- Exemplo que mostra um caso, onde as funções "=" e "eq" retornam valores diferentes:
  1) desenhe uma entidade simples qualquer, como por exemplo uma linha.
  2) Salvando o nome da entidade desenhada na variável entA (selecione a linha após o comando): (setq entA (car (entsel)))
  3) Salvando o nome da mesma entidade desenhada na variável entB (selecione a linha após o comando): (setq entB (car (entsel)))
  4) Comparação usando "=": (= entA entB)           , retorna nil ;
  5) Comparação usando "eq": (eq entA entB)           , retorna T

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.