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