#lang racket ; Estes são alguns exemplos feitos em sala de aula. ; A maioria dos exemplos não faz tratamento de erro dos parâmetros, ; assim, fica mais claro a excência da função. (require rackunit) ; Funções para auxiliar nos testes (define => 'arrow) (define (fact result arrow expected) (unless (equal? arrow =>) (fail "O segundo deve ser =>")) (check-equal? result expected)) ;; Verifica se um objeto é uma lista (define (lista? lst) (cond [(null? lst) #t] [(not (cons? lst)) #f] [else (lista? (cdr lst))])) (fact (lista? '()) => #t) (fact (lista? '(1 2 3)) => #t) (fact (lista? (cons 1 2)) => #f) (fact (lista? (cons 1 (cons 2 3))) => #f) ;; Pega os primeiros n elementos de uma lista (define (take lst n) (if (zero? n) '() (cons (first lst) (take (rest lst) (sub1 n))))) (fact (take '(1 5 7 9) 0) => '()) (fact (take '(1 5 7 9) 1) => '(1)) (fact (take '(1 5 7 9) 2) => '(1 5)) ;; Cria uma lista com os valores inteiros no intervalo [inicio, fim] ; versão recursiva - cria a lista do menor para o maior (define (intervalo inicio fim) (if (> inicio fim) null (cons inicio (intervalo (+ 1 inicio) fim)))) (fact (intervalo 1 3) => '(1 2 3)) (fact (intervalo 5 3) => '()) ; versão interativa - cria a lista do maior para o menor (define (intervalo-acc inicio fim) (define (iter inter n) (if (< n inicio) inter (iter (cons n inter) (sub1 n)))) (iter '() fim)) (fact (intervalo-acc 1 3) => '(1 2 3)) (fact (intervalo-acc 5 3) => '()) ;; Calcula o tamanho de uma lista ; Dois problemas com esta função ; 1 - não é recursiva em cauda ; 2 - baixo nível de abstração (percorre a lista elemento por elemento) (define (tamanho lst) (if (null? lst) 0 (+ 1 (tamanho (rest lst))))) (fact (tamanho '()) => 0) (fact (tamanho '(1)) => 1) (fact (tamanho '(1 1)) => 2) ; Esta versão resolve o primeiro problema, mas não o segundo (define (tamanho-acc lst) (define (iter acc lst) (if (null? lst) acc (iter (add1 acc) ; calcula o novo acumulador (rest lst)))) (iter 0 lst)) (fact (tamanho-acc '()) => 0) (fact (tamanho-acc '(1)) => 1) (fact (tamanho-acc '(1 1)) => 2) ;; Encontra o valor mínimo de uma lista ; Dois problemas com esta função ; 1 - não é recursiva em cauda ; 2 - baixo nível de abstração (percorre a lista elemento por elemento (define (minimo lst) (define (min a b) (if (< a b) a b)) (if (null? (rest lst)) (first lst) (min (first lst) (minimo (rest lst))))) (fact (minimo '(6 2 3)) => 2) (fact (minimo '(-1 2 3)) => -1) (fact (minimo '(6 2 -3)) => -3) ; Esta implementação resolve o primeiro problema, mas não o segundo (define (minimo-acc lst) (define (min a b) (if (< a b) a b)) (define (iter acc lst) (if (null? lst) acc (iter (min (first lst) acc) ; calcula o novo acumulador (rest lst)))) (iter (first lst) (rest lst))) (fact (minimo-acc '(6 2 3)) => 2) (fact (minimo-acc '(-1 2 3)) => -1) (fact (minimo-acc '(6 2 -3)) => -3) ; No arquivo exemplos-funcoes.rkt é usado funções de alta-ordem para ; resolver o segundo problema, isto é, uma solução mais alto nível ; é usada.