2010-08-24 6 views
2

Je joue actuellement avec lispbuilder-sdl sur SBCL sous Windows.Lisp différences de paquet entre repl et compiler le fichier

Mon code source est la suivante:

(asdf:operate 'asdf:load-op :lispbuilder-sdl) 
(asdf:operate 'asdf:load-op :lispbuilder-sdl-binaries) 
(asdf:operate 'asdf:load-op :lispbuilder-sdl-examples) 
(sdl-examples:squashed) 

Quand je compile le fichier que je reçois l'erreur: package "SDL-EXEMPLES" non trouvé.

Si je supprime le (sdl-examples: écrasé) du fichier, il est compilé correctement. Je peux alors taper (sdl-examples: écrasé) au repl et le jeu de démo commence bien.

Pourquoi le paquetage sdl-examples est-il trouvé depuis le repl mais pas quand je compile le fichier?

Répondre

2

Toute la compilation de ce fichier se produit avant l'exécution de l'un des load-op s. Ainsi, lorsque Lisp compile la ligne (sdl-examples:squashed), il n'a pas exécuté le load-op qui définit votre package.

Vous pouvez contourner ce problème en ne mentionnant pas le paquet sdl-examples qui nécessite le lecteur pour localiser son symbole squashed avant la load-op est réellement exécuté:

(funcall (symbol-function (intern (symbol-name '#:squashed) 
            (find-package (symbol-name '#:sdl-examples))))) 

L'idée est de calculer le paquet à partir de son nom symbolique, recherchez le symbole nommant votre fonction, et récupérez la fonction qu'il nomme - mais cette méthode nécessite que le paquet n'existe que lorsque le code est exécuté, et non lors de sa première lecture. Ensuite, vos quatre instructions peuvent toutes être compilées, exécutées dans l'ordre, et au moment où la dernière instruction est exécutée, vos load-op auront créé le paquet.


est donc ici un peu plus d'informations sur ce qui se passe ici:

  • L'écriture '#:some-name fait référence à un symbole qui ne fait pas partie de colis. De cette façon, nous pouvons faire une référence à un nom symbolique sans (1) supposer que son paquet existe ou (2) copier un autre paquet avec le nom.
  • Ensuite, '(symbol-name #:some-name) extrait le nom du symbole sous la forme d'une chaîne. Pourquoi ne pas simplement écrire "some-name"? Vous pourriez, et cela fonctionnera habituellement. Mais cette manière est un peu plus robuste dans le cas d'un Lisp sensible à la casse en "mode moderne".
  • Le find-package mappe un nom de chaîne à la représentation Lisp d'un package. Rappelez-vous, au moment où vous exécutez cette ligne, votre paquet existera.
  • intern Renvoie le symbole avec le prénom qui réside dans le package donné.
  • symbol-function renvoie l'objet fonction (une abstraction lambda, ou plus probablement, sa représentation compilée) associée au symbole. Ensuite, funcall invoque cette fonction. C'est un peu maladroit, mais malheureusement, il n'y a pas vraiment de meilleure façon de mélanger les appels qui chargent du code pour créer un paquet avec les noms qui vivent dans ce paquet dans le même fichier.
+0

Merci pour la réponse. C'est un peu au-delà de ma compréhension du Lisp. Je suis une jeune sauterelle dans l'exigence de la cire sur la cire. Quand j'exécute cela, la fonction de symbole dit qu'elle ne nécessite qu'un seul argument. Comment est-ce que je concatène l'objet de paquet à la chaîne de symbole? Je suppose que c'est ce qui ne va pas. –

+1

Oups! Ma mauvaise --- a oublié l'appel à 'intern' pour coller le nom de la fonction et le paquet ensemble. Il est édité pour corriger maintenant. – JohnMaraist

+0

Merci beaucoup pour l'explication. Cela m'a aidé à comprendre quels symboles et la différence avec la compilation et l'exécution sont. Je suppose que si je devais commencer à programmer une application réelle ce désagrément serait évité en définissant le code dans un fichier asd séparé? –

Questions connexes