Pergunta

Estou tentando executar o traçado de raios em forma de código de Paul Graham ANSI Common Lisp no OS X, utilizando LODO com OpenMCL (bem, agora chamado de CCL).No código, há uma constante definida, cujo valor é uma estrutura, e quando eu chamar lodo-compilar-e-load-file ou lodo-compilar-defun em qualquer função que usa a constante, recebo uma mensagem de erro:

Certifique-CARGA-método de FORMULÁRIO é definido por #S(PONTO :X 0 Y :0 Z :200) [Condição do tipo SIMPLES-ERRO]

Eu encontrei um post explicando a complicação e outro lamentando-lo, mas o que precisa ser adicionado ao código para negociar este aspecto da OpenMCL?

Foi útil?

Solução

Quando a ESTRUTURA de Objetos (e alguns outros tipos de objetos) aparecem como literal, constante de objetos no código que está sendo processado pela COMPILAÇÃO do ARQUIVO, COMPILAÇÃO, o ARQUIVO precisa saber como se organizar para que, quando o binário resultante arquivo é carregado, um "equivalente" objeto é criado.Existem muitas definições possíveis do "equivalente" :às vezes, é importante que os componentes do objeto carregado de compartilhamento de estrutura com outros objetos, por vezes, é importante que a inicialização acontece, de uma certa maneira, e, às vezes, nenhuma dessas coisas são importantes.Para determinar como recriar o objecto constante, a COMPILAÇÃO do ARQUIVO chama a função genérica de faz-de-CARGA-FORMULÁRIO;este comportamento deve ser descrito em qualquer CL referência ou tutorial.(Uma referência ou tutorial também de salientar que a implementação não é possível definir o padrão de faz-de-CARGA-FORMULÁRIO de métodos que seria aplicável a todas as instâncias da ESTRUTURA de CLASSE ou PADRÃO de CLASSE, e deve também nota que o faz-de-CARGA-FORMA-de VERÃO-SLOTS é uma função conveniente para usar no faz-de-CARGA-FORMULÁRIO de métodos para objetos cuja inicialização não precisa ser complicado, por exemplo:

(defmethod make-load-form ((p point) &optional env)
  (declare (ignore env))
  (make-load-form-saving-slots p))

Observe que esse método deve ser definido em tempo de compilação, para que COMPILE-ARQUIVO pode chamá-lo para determinar como poupar o constante PONTO de objeto.

Nada disso é CCL-específicos.O que poderia ser é a questão de que as coisas são constantes, literais e objetos que as coisas não são.

No código como:

(defconstant a-point (make-point :x 0 :y 0 :z 200))

(defun return-a-point () a-point)

o compilador é permitido (mas não obrigatório) para substituir o valor de UM PONTO para a referência a ele na função de RETORNO-A-PONTO.(Se o compilador faz isso, o que seria significa que há um literal/PONTO constante do objeto no código a ser compilado, COMPILAÇÃO e ARQUIVO de precisaria chamar de faz-de-CARGA-FORMULÁRIO para determinar como o objeto deve ser salvas e carregadas;se o compilador não fazer essa substituição, em seguida, FAZER-CARGA FORMULÁRIO não precisa ser chamado neste exemplo).

Se uma aplicação não faz este tipo de substituição ou não a implementação.A especificação também deixa não especificado se a forma de valor em um DEFCONSTANT forma é avaliada em tempo de compilação, tempo de carregamento, ou ambos, e as notas que deve ser exercido um cuidado (pelo utilizador) para assegurar que a expressão é avaliada sempre para o mesmo valor.

CCL geralmente tenta avaliar a DEFCONSTANT valor formulário em tempo de compilação, e é bastante agressivo em relação substituindo os valores das constantes nomeadas para referências a eles;em alguns casos, isso significa que o faz-de-CARGA-FORMULÁRIO de métodos em classes de constantes' valores devem ser definidos.Outras implementações podem ser menos dispostos a fazer a substituição de alguns tipos de objetos.Ambas as estratégias estão corretas, portátil e de código não pode assumir que estratégias estão sendo seguidas (apesar de muito supostamente código portátil certamente não para fazer tais suposições.)

O tratamento diferente de coisas definidas por DEFCONSTANT parece ser a mais provável causa desse tipo de coisa (chamadas inesperadas para TORNAR-CARGA de FORMA que ninguém se preocupou em definir).Pode evitar alguns desses problemas em um caminho que deve ser portável fazendo:

(defconstant a-point (make-point :x 0 :y 0 :z 200))

(defun return-a-point () (load-time-value (symbol-value 'a-point)))

Isto terá um efeito semelhante ao simplesmente permitindo uma implementação que quer fazer isso (como CCL não) fazer constante-a substituição, mas o uso de CARGA-TEMPO-VALOR irá garantir que o valor da constante é avaliada em tempo de carga (e que o faz-de-CARGA-FORMULÁRIO de não ser envolvido.)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top