• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

joaoqalves

[Scheme] If's

9 mensagens neste tópico

Boas pessoal, depois de uma pausa no Scheme, voltei e, desta vez, com mais vontade ainda. Comecei por ler um pouco do manual que o vbmaster recomendou (MIT) e estava a tentar fazer um exercício proposto por eles que é o seguinte: Dados três números a,b e c calcular a soma dos quadrados dos dois maiores números.

Bem, eu comecei fazendo isto:

(define (square x) (* x x))

(define (square-max a b c)
 (and (> a b) (> a c)
     (if (> b c)
         (+ (square a) (square b))
         (+ (square a) (square c))))
 (and (> b a) (> b c)
     (if (> a c)
         (+ (square b) (square a))
         (+ (square b) (square c))))
 (and (> c a) (> c b)
     (if (> a b)
         (+ (square c) (square a))
         (+ (square c) (square b))))) 

Isto apenas funciona para o caso do if ser verdadeiro (p ex: (square-max 1 2 3)), mas caso contrário (p ex: (square-max 3 1 2)) já não funciona. E, já agora, elucidem-me sobre a utilização dos operadores condicionais if e cond, qual utilizam mais, qual o "melhor" para cada situação? E, por fim, qual é o operador de "diferente" ?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Não terás trocado o "if" e o "and"? Isso para mim faz pouco sentido, tens o if dentro do and em vez de ser o and dentro do if..

Já agora, precisas de elses.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Não terás trocado o "if" e o "and"? Isso para mim faz pouco sentido, tens o if dentro do and em vez de ser o and dentro do if..

Já agora, precisas de elses.

Penso que o "and" pode ser usado assim sem a presença do "if" (ou seja, pondo o "and", ele reconhece "automaticamente" como sendo um "if")... e quanto ao "else", pensei que no caso do if não fosse necessário, visto que há exemplos como:

(if (< x 0)
      (- x)
      x))

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Sim, isso é o else.

O and não serve como if.

Não percebeste como funciona o if:

Ele tem 3 parametros. O primeiro é a comparação, o segundo o then, e o terceiro o else.

Nesse teu exemplo, ele retorna -x se x < 0 ou x se x>=0. Ou seja, retorna sempre o valor absoluto. Tens ali o else.

No teu código também usaste elses, mas eu estava-me a referir a teres que usar elses entre os ifs exteriores (que neste momento tens ands)..

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Bem, parece que já resolvi, mas não sei se foi da melhor forma, por isso espero críticas, se as houver. ;)

Código:

(define (square x) (* x x))

(define (square-max a b c)
 (if (and (> a b) (> a c))
     (begin
       (if (> b c)
           (+ (square a) (square b))
           (+ (square a) (square c))))
     (begin
       (if (and (> b a) (> b c))
           (begin
             (if (> a c)
                 (+ (square b) (square a))
                 (+ (square b) (square c))))
           (if (and (> c a) (> c b))
               (begin
                 (if (> a b)
                     (+ (square c) (square a))
                     (+ (square c) (square b)))))))))

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
(define (square-max a b c)
 (and (> a b) (> a c)
(...))
 (and (> b a) (> b c)
(...))
 (and (> c a) (> c b)
     (if (> a b)
         (+ (square c) (square a))
         (+ (square c) (square b)))))

No post inicial, fazeste aqui uma "salganhada" esquisita, mas parece que já descobriste.

No Scheme, *só* o resultado da última forma do procedimento é que é devolvido. Naquele procedimento, tu puseste três formas (ands), por isso é que só a última estava a fazer efeito.

Aliás, isso devia dar erro (estás a ANDar dois valores lógicos com um número, porque no teu código o if dá-te um número).

Isto apenas funciona para o caso do if ser verdadeiro (p ex: (square-max 1 2 3)), mas caso contrário (p ex: (square-max 3 1 2)) já não funciona.

Não percebi de que if estavas a falar, mas os exemplos que deste confirmam o que eu disse.

E, já agora, elucidem-me sobre a utilização dos operadores condicionais if e cond, qual utilizam mais, qual o "melhor" para cada situação? E, por fim, qual é o operador de "diferente"?

Utiliza o if quando tiveres:

- Uma condição

- Uma ou mais expressões no ramo then (só a última é que é devolvida).

- Opcionalmente, uma ou mais expressões no ramo else (só a última é que é devolvida)

Semanticamente, o if funciona mais ou menos como as expressões condicionais do C (condicao?expressao2:expressao2). Se quiseres mais de uma forma dentro do then ou do else, usa a forma especial (begin).

Ah... e quando eu falo em "then" e "else", não estou a dizer que tens de lá escrever isso!

O cond é mais ou menos como um if-then-elseif-then-elseif-then-else:

- Várias condições

- Uma ou mais expressões para cada condição (só a última de cada condição é que é devolvida).

- Opcionalmente, uma ou mais expressões no ramo else (neste caso, tens mesmo de lá escrever "else").

Obs.: não precisas de usar o (begin).

JJ

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
Bem, parece que já resolvi, mas não sei se foi da melhor forma, por isso espero críticas, se as houver. ;)

Aqui vai.

Primeiro, tens 4 begins desnecessários. Quando tens só uma forma num dos "ramos" do if, não precisas de a agrupar. Por exemplo:

(if (> x y)
  (begin (display "O x eh maior")))

É igual a:

(if (> x y)
  (display "O x eh maior"))

Talvez não seja fácil descobrir que só tens uma forma dentro do begin. Uma dica: se está rodeada por parêntices, é só uma.

(define (square x) (* x x))

(define (square-max a b c)
 (if (and (> a b) (> a c))
     (if (> b c)
         (+ (square a) (square b))
         (+ (square a) (square c)))
     (if (and (> b a) (> b c))
         (if (> a c)
               (+ (square b) (square a))
               (+ (square b) (square c)))
         (if (and (> c a) (> c b))
             (if (> a b)
                 (+ (square c) (square a))
                 (+ (square c) (square b)))))))

Agora, podes tirar a "cascata" se transformares aqueles dois if's num cond:

(define (square x) (* x x))

(define (square-max a b c)
 (cond ((and (> a b) (> a c))
        (if (> b c)
            (+ (square a) (square b))
            (+ (square a) (square c))))

       ((and (> b a) (> b c))
        (if (> a c)
            (+ (square b) (square a))
            (+ (square b) (square c))))

       ((and (> c a) (> c b))    ; Podia ser substituido por else ou por #t
        (if (> a b)
            (+ (square c) (square a))
            (+ (square c) (square b))))))

A sintaxe do cond é:

(cond (CONDICAO EXPRESSAO)+)

Onde CONDICAO deve ser uma expressão cujo resultado seja #t ou #f (ou então pode ser "else"). Aquele + significa que o que vem antes aparece pelo menos uma vez (mas pode aparecer mais).

Basicamente, o interpretador avalia (i.e. calcula o resultado) as condições, uma a uma. Quando encontra uma que dê #t, avalia a respectiva expressão associada, e a forma devolve o resultado dessa avaliação.

(Não precisas do begin porque já tens os parêntices exteriores)

JJ

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Boas..

Apresento aqui uma solução mais simples e a funcionar a 100%..

(define quadrados
 (lambda (a b c)
   (cond ((and (<= a b)
                    (<= a c))
             (calcula b c))
            ((and (<= b a)
                    (<= b c))
             (calcula a c))
            ((and (<= c a)
                    (<= c b))
             (calcula a b)))))

(define calcula
 (lambda (x y)
   (+ (* x x) (* y y))))

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora