Skip to content

Latest commit

 

History

History
150 lines (111 loc) · 3.97 KB

aula-28.org

File metadata and controls

150 lines (111 loc) · 3.97 KB

Aula 28

Hoje revisamos uma breve explicação sobre os problemas decorrentes de usarmos o modelo de estados e atribuição de valores. Revisamos os problemas que temos ao permitir que eventualmente uma função que altere um estado ou seja influenciada por um estado seja executada de forma concorrente. Também falamos sobre streams apresentando o código abaixo.

Nos prolongamos sobre a explicação de macros e a diferença entre as duas implementações abaixo da função cons-stream, explicando porque a implementação como função não funciona como o esperado.

(define (cons-stream head tail)
  (cons head (delay tail)))

(define-syntax cons-stream
  (syntax-rules ()
    ((cons-stream head tail)
     (cons head (delay tail)))))

Para exemplificar macros, também usei como exemplo a macro em CL abaixo. Observamos que while não poderia ser implementada como função

(defun while (test body)
  (if test
      (progn
        body
        (while test body))))

(defmacro while (test  &body body)
  `(do ()
       ((not ,test))
     ,@body))

Para saber como a macro é expandida, em CL, podemos usar:

(macroexpand-1 '(while (< x 10) (print x)))

A implementação completa que vimos nas aulas de streams em Racket segue abaixo.

#lang racket

(require math/number-theory)

(define the-empty-stream '())

(define (stream-null? stream)
  (null? stream))

(define-syntax cons-stream
  (syntax-rules ()
    ((cons-stream head tail)
     (cons head (delay tail)))))

(define (stream-car stream)
  (car stream))

(define (stream-cdr stream)
  (force (cdr stream)))

(define (stream-enumerate-interval low high)
      (if (> low high)
          the-empty-stream
          (cons-stream
            low
            (stream-enumerate-interval (+ low 1) high))))

(define (stream-filter pred stream)
  (cond ((stream-null? stream) the-empty-stream)
        ((pred (stream-car stream))
         (cons-stream (stream-car stream)
                      (stream-filter pred (stream-cdr stream))))
        (else (stream-filter pred (stream-cdr stream)))))

(stream-car (stream-cdr (stream-filter prime?
                                       (stream-enumerate-interval 10000 1000000))))

Os alunos interessados podem comparar o tempo de processamento da implementação com streams versus a implementação com listas comuns abaixo:

#lang racket

(require math/number-theory)

(define (sum-primes a b)
  (define (iter count accum)
    (cond ((> count b) accum)
          ((prime? count)
           (iter (+ count 1) (+ count accum)))
          (else (iter (+ count 1) accum))))
(iter a 0))

(define (reverse list)
  (define (rev-iter list new-list)
    (if (null? list)
        new-list
        (rev-iter (cdr list) (cons (car list) new-list))))
  (rev-iter list empty))

(define (enumerate-interval l h)
  (define (enumerate-int-iter l h new-list)
    (if (> l h)
        (reverse new-list)
        (enumerate-int-iter (+ 1 l) h (cons l new-list))))
  (enumerate-int-iter l h empty))


(car (cdr (filter prime? (enumerate-interval 10000 1000000))))

Para o uso do código do livro, podemos ainda usar a linguagem sicp que foi disponibiliza em Racket, por exemplo:

#lang sicp

(cons-stream 1 2)
...

Ou seja, dá para implementar todo o código acima sem precisar definir a macro cons-stream. Notem que a sintaxe de macros de CL e Racket é bem diferente, comentamos sobre isso.

Para isso será necessário instalar um pacote no DrRacket, menu arquivo Package Manager instalar o pacote sicp.

Links