Pergunta

Eu tenho lido sobre o SICP (estrutura e intrimição de programas de computador) e fiquei realmente empolgado ao descobrir essa maravilhosa forma especial: "Make-Aurneratment", que eles demonstram usar em combinação com a avaliação como uma maneira de escrever código modular (trecho da seção 4.3 em "Pacotes"):

(define scientific-library
  (make-environment
   ...
   (define (square-root x)
    ...)))

Eles então demonstram como funciona com

((eval 'square-root scientific-library) 4)

No exemplo deles, eles depois demonstram exatamente O uso que eu gostaria - uma maneira elegante e minimalista de fazer o estilo "oo" no esquema ... eles "contras" juntos um "tipo", que é na verdade o que foi devolvido pela forma especial "Make -Ambernment" ( ou seja, o vtable) e um arg ("o estado") ...

Eu estava tão empolgado porque isso é exatamente O que eu tenho procurado como uma maneira de fazer despacho polimórfico "por símbolo" no esquema sem ter que escrever muito código explícito ou macros.

ou seja, eu quero criar um "objeto" que tenha, digamos, dois funções, que eu chamo em diferentes contextos ... mas não quero me referir a eles por "carro" e "cdr", eu quero ambos declarar e Avalie eles por seus nomes simbólicos.

De qualquer forma, quando li isso, mal podia esperar para chegar em casa e experimentar.

Imagine minha decepção então quando experimentei o seguinte esquema PLT e Chez:

> (make-environment (define x 3))
Error: invalid context for definition (define x 3).
> (make-environment)
Error: variable make-environment is not bound.

O que aconteceu com o "Make-Aurnerment", conforme referenciado no SICP? Tudo parecia tão elegante, e exatamente o que eu quero, mas não parece ser apoiado em nenhum intérprete de esquema moderno?

Qual é a lógica? É simplesmente que "Make-Aurnerment" tem um nome diferente?

Mais informações encontradas mais tarde

Eu olhei para a versão online:

http://mitpress.mit.edu/sicp/full-text/book/book-zh-28.html#%_sec_4.3

Eu estava lendo foi a primeira edição do SICP. A segunda edição parece ter substituído a discussão sobre pacotes por uma seção sobre programação não determinística e o operador "AMP".

Foi útil?

Solução

Depois de mais cavar, descobri isso Tópico informativo no Newsnet:

"Os especificadores de avaliação e ambiente do R5RS são um compromisso entre aqueles que não gostam profundamente de ambientes de primeira classe e desejam uma avaliação restrita e aqueles que não conseguem aceitar/entender avaliar sem um segundo argumento que é um ambiente".

Além disso, encontrou este "trabalho de trabalho":

(define-syntax make-environment 
  (syntax-rules () 
    ((_ definition ...) 
     (let ((environment (scheme-report-environment 5))) 
       (eval '(begin definition 
                     ...) 
             environment) 
       environment)))) 


(define arctic 
  (make-environment 
    (define animal 'polarbaer))) 

(Tirado de isto)

No entanto, acabei adotando um estilo de "mensagem que passa", como o primeiro cara sugerido - eu devolvo um alist de funções e tenho um método "Enviar" genérico para invocar uma função específica pelo nome ... ou seja, algo assim

(define multiply
  (list
    (cons 'differentiate (...))
    (cons 'evaluate (lambda (args) (apply * args)))))

(define lookup
  (lambda (name dict)
    (cdr (assoc name dict))))

; Lookup the method on the object and invoke it
(define send
  (lambda (method arg args)
    ((lookup method arg) args))

((send 'evaluate multiply) args)

Eu tenho lido mais e estou ciente de que há todo o Clos se eu realmente queria adotar um estilo totalmente OO - mas acho que mesmo acima é um pouco exagerado.

Outras dicas

O esquema não possui ambientes de primeira classe por motivos de desempenho. Quando o esquema foi criado, não era o idioma mais rápido devido a coisas bacanas, como funções de primeira classe, continuações etc. A adição de ambientes de primeira classe teria prejudicado o desempenho ainda mais. Por isso, foi uma troca feita nos primeiros dias do esquema.

Eles escreveram assim porque o esquema do MIT tem, de fato, ambientes de primeira classe e, presumivelmente, é com isso que os escritores planejavam ensinar sua aula (já que o livro foi escrito no MIT).

Verificação de saída http://groups.csail.mit.edu/mac/projects/scheme/

No entanto, notei que o esquema do MIT, embora ainda seja desenvolvido ativamente, carece de muitos dos recursos que um esquema realmente moderno teria, como uma interface de função estrangeira ou suporte da GUI. Você provavelmente não gostaria de usá -lo para um projeto sério de desenvolvimento de software, pelo menos não por si só.

Would a classical dispatcher function work? I think this is similar to what you're looking for.

(define (scientific-library f)
  (define (scientific-square-root x) (some-scientific-square-root x))
  (cond ((eq? f 'square-root) scientific-square-root)
        (else (error "no such function" f))))
(define (fast-library f)
  (define (fast-square-root x) (some-fast-square-root x))
  (cond ((eq? f 'square-root) fast-square-root)
        (else (error "no such function" f))))

((scientific-library 'square-root) 23)
((fast-library 'square-root) 23)

You could even combine the example scientific and fast libraries into one big dispatch method:

(define (library l f)
  (define (scientific-library f)
    ...)
  (define (fast-library f)
    ...)
  (cond ((eq? l 'scientific) (scientific-library f))
        ((eq? l 'fast) (fast-library f))
        (else (error "no such library" l))))
(library 'fast 'square-root)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top