Why the following Common Lisp code does not work?
(defun _load (name) (asdf:operate 'asdf:load-op name))
(load #"path/asdf")
(_load :asdf-install)
=> loading error: no package with name "ASDF"
but the following code does work:
(load #"path/asdf")
(defun _load (name) (asdf:operate 'asdf:load-op name))
(_load :asdf-install)
while I cannot make a forward reference to a symbol in an unloaded
package?
By the way, forward referencing to a symbol in the SAME package work:
(defun f () (g))
(defun g () 1)
(f)
Please help.
From: Ken Tilton
Subject: Re: Common Lisp: Forward reference to a symbol in an unloaded package, possible?
Date:
Message-ID: <4815f495$0$11635$607ed4bc@cv.net>
·······@gmail.com wrote:
> Why the following Common Lisp code does not work?
>
> (defun _load (name) (asdf:operate 'asdf:load-op name))
> (load #"path/asdf")
> (_load :asdf-install)
>
> => loading error: no package with name "ASDF"
>
> but the following code does work:
>
> (load #"path/asdf")
> (defun _load (name) (asdf:operate 'asdf:load-op name))
> (_load :asdf-install)
>
> while I cannot make a forward reference to a symbol in an unloaded
> package?
The Lisp reader deals with resolving package qualifiers, to figure out
which of possibly more than one eponymous symbol to return, and the
reader gets to all the code in a file before any of it runs.
If you were typing those lines in one by onw, apply what I said to the
first line, which gets read /and/ compiled/interpreted before the second
(obviously).
hth, kt
--
http://smuglispweeny.blogspot.com/
http://www.theoryyalgebra.com/
"I've never read the rulebook. My job is to catch the ball."
-- Catcher Josh Bard after making a great catch on a foul ball
and then sliding into the dugout, which by the rules allowed the
runners to advance one base costing his pitcher a possible shutout
because there was a runner on third base.
"My sig is longer than most of my articles."
-- Kenny Tilton
On Apr 28, 11:02 pm, Ken Tilton <···········@optonline.net> wrote:
> ·······@gmail.com wrote:
> > Why the following Common Lisp code does not work?
>
> > (defun _load (name) (asdf:operate 'asdf:load-op name))
> > (load #"path/asdf")
> > (_load :asdf-install)
>
> > => loading error: no package with name "ASDF"
>
> > but the following code does work:
>
> > (load #"path/asdf")
> > (defun _load (name) (asdf:operate 'asdf:load-op name))
> > (_load :asdf-install)
>
> > while I cannot make a forward reference to a symbol in an unloaded
> > package?
>
> The Lisp reader deals with resolving package qualifiers, to figure out
> which of possibly more than one eponymous symbol to return, and the
> reader gets to all the code in a file before any of it runs.
>
> If you were typing those lines in one by onw, apply what I said to the
> first line, which gets read /and/ compiled/interpreted before the second
> (obviously).
>
> hth, kt
>
> --http://smuglispweeny.blogspot.com/http://www.theoryyalgebra.com/
>
> "I've never read the rulebook. My job is to catch the ball."
> -- Catcher Josh Bard after making a great catch on a foul ball
> and then sliding into the dugout, which by the rules allowed the
> runners to advance one base costing his pitcher a possible shutout
> because there was a runner on third base.
>
> "My sig is longer than most of my articles."
> -- Kenny Tilton
Thanks for clarification.
Is there a way to make a forward reference to an unload package? (i.e.
how to (defun _load ...) before (load ...))
From: Ken Tilton
Subject: Re: Common Lisp: Forward reference to a symbol in an unloaded package, possible?
Date:
Message-ID: <4815ff45$0$11619$607ed4bc@cv.net>
·······@gmail.com wrote:
> On Apr 28, 11:02 pm, Ken Tilton <···········@optonline.net> wrote:
>
>>·······@gmail.com wrote:
>>
>>>Why the following Common Lisp code does not work?
>>
>>>(defun _load (name) (asdf:operate 'asdf:load-op name))
>>>(load #"path/asdf")
>>>(_load :asdf-install)
>>
>>>=> loading error: no package with name "ASDF"
>>
>>>but the following code does work:
>>
>>>(load #"path/asdf")
>>>(defun _load (name) (asdf:operate 'asdf:load-op name))
>>>(_load :asdf-install)
>>
>>>while I cannot make a forward reference to a symbol in an unloaded
>>>package?
>>
>>The Lisp reader deals with resolving package qualifiers, to figure out
>>which of possibly more than one eponymous symbol to return, and the
>>reader gets to all the code in a file before any of it runs.
>>
>>If you were typing those lines in one by onw, apply what I said to the
>>first line, which gets read /and/ compiled/interpreted before the second
>>(obviously).
>>
>>hth, kt
>>
>>--http://smuglispweeny.blogspot.com/http://www.theoryyalgebra.com/
>>
>>"I've never read the rulebook. My job is to catch the ball."
>> -- Catcher Josh Bard after making a great catch on a foul ball
>>and then sliding into the dugout, which by the rules allowed the
>>runners to advance one base costing his pitcher a possible shutout
>>because there was a runner on third base.
>>
>>"My sig is longer than most of my articles."
>> -- Kenny Tilton
>
>
> Thanks for clarification.
> Is there a way to make a forward reference to an unload package? (i.e.
> how to (defun _load ...) before (load ...))
Yes, but it is really weird so I am going to hold out for a good reason
before telling you. :)
Less weird would be defining the package yourself just to get away with
loading things in the wrong order, then letting it get redefined, but
maybe you better tell us what you are really trying to do. :) It's not
that hard to load asdf before doing anything else.
kenny
--
http://smuglispweeny.blogspot.com/
http://www.theoryyalgebra.com/
"I've never read the rulebook. My job is to catch the ball."
-- Catcher Josh Bard after making a great catch on a foul ball
and then sliding into the dugout, which by the rules allowed the
runners to advance one base costing his pitcher a possible shutout
because there was a runner on third base.
"My sig is longer than most of my articles."
-- Kenny Tilton
On Apr 28, 11:47 pm, Ken Tilton <···········@optonline.net> wrote:
> ·······@gmail.com wrote:
> > On Apr 28, 11:02 pm, Ken Tilton <···········@optonline.net> wrote:
>
> >>·······@gmail.com wrote:
>
> >>>Why the following Common Lisp code does not work?
>
> >>>(defun _load (name) (asdf:operate 'asdf:load-op name))
> >>>(load #"path/asdf")
> >>>(_load :asdf-install)
>
> >>>=> loading error: no package with name "ASDF"
>
> >>>but the following code does work:
>
> >>>(load #"path/asdf")
> >>>(defun _load (name) (asdf:operate 'asdf:load-op name))
> >>>(_load :asdf-install)
>
> >>>while I cannot make a forward reference to a symbol in an unloaded
> >>>package?
>
> >>The Lisp reader deals with resolving package qualifiers, to figure out
> >>which of possibly more than one eponymous symbol to return, and the
> >>reader gets to all the code in a file before any of it runs.
>
> >>If you were typing those lines in one by onw, apply what I said to the
> >>first line, which gets read /and/ compiled/interpreted before the second
> >>(obviously).
>
> >>hth, kt
>
> >>--http://smuglispweeny.blogspot.com/http://www.theoryyalgebra.com/
>
> >>"I've never read the rulebook. My job is to catch the ball."
> >> -- Catcher Josh Bard after making a great catch on a foul ball
> >>and then sliding into the dugout, which by the rules allowed the
> >>runners to advance one base costing his pitcher a possible shutout
> >>because there was a runner on third base.
>
> >>"My sig is longer than most of my articles."
> >> -- Kenny Tilton
>
> > Thanks for clarification.
> > Is there a way to make a forward reference to an unload package? (i.e.
> > how to (defun _load ...) before (load ...))
>
> Yes, but it is really weird so I am going to hold out for a good reason
> before telling you. :)
>
> Less weird would be defining the package yourself just to get away with
> loading things in the wrong order, then letting it get redefined, but
> maybe you better tell us what you are really trying to do. :) It's not
> that hard to load asdf before doing anything else.
>
> kenny
>
> --http://smuglispweeny.blogspot.com/http://www.theoryyalgebra.com/
>
> "I've never read the rulebook. My job is to catch the ball."
> -- Catcher Josh Bard after making a great catch on a foul ball
> and then sliding into the dugout, which by the rules allowed the
> runners to advance one base costing his pitcher a possible shutout
> because there was a runner on third base.
>
> "My sig is longer than most of my articles."
> -- Kenny Tilton
What I really want to do is to organize code the way I want. I want to
have my utility functions (names begin with '_') defined at one place
(at the top of the files). So instead of:
(load #"path/asdf")
(defun _load (name) (asdf:operate 'asdf:load-op name))
(_load :asdf-install)
(defun _install (lib-name) (asdf-install:install lib-name))
I would like to have, in my RC file:
; my utilities
(defun _load (name) (asdf:operate 'asdf:load-op name))
(defun _install (lib-name) (asdf-install:install lib-name))
(load #"path/asdf")
(_load :asdf-install)
From: Thomas A. Russ
Subject: Re: Common Lisp: Forward reference to a symbol in an unloaded package, possible?
Date:
Message-ID: <ymiabjdsh45.fsf@blackcat.isi.edu>
·······@gmail.com writes:
> Why the following Common Lisp code does not work?
>
> (defun _load (name) (asdf:operate 'asdf:load-op name))
> (load #"path/asdf")
> (_load :asdf-install)
>
> => loading error: no package with name "ASDF"
That is because when the reader encounters "ASDF:LOAD-OP", it doesn't
know about the ASDF package, so there is no place to store the symbol
that the reader needs to create. The package must exist before the
reader needs to use it.
> but the following code does work:
>
> (load #"path/asdf")
> (defun _load (name) (asdf:operate 'asdf:load-op name))
> (_load :asdf-install)
That is because in this case the package will exist when the reader
encounters the symbol. But only if you load a file containing this or
else if you type it in to the read-eval-print loop.
This will fail if you try to compile a file with these contents because
at compile time, the asdf code will not be loaded. And then the reader
will encounter the ASDF package without it being there.
Now, one way to get around this is to delay the symbol creation until
runtime. That is something I have done when I wanted to have some
conditional code that couldn't be sure it was applicable until run
time. In that case you could write
(defun _load (name) (funcall (intern "OPERATE" "ASDF") name))
(load #"path/asdf")
....
As long as the ASDF package exists when _load is called, this will work,
because it delays the interning process until runtime. Normally this
occurs at read-time.
> while I cannot make a forward reference to a symbol in an unloaded
> package?
Because the reader cannot deal with non-existent packages when it is
trying to read input and create symbols. It needs the packages to be
there. Furthermore, to read symbols named using the external symbol
syntax, it also needs the symbols to have already been exported from the
package in question.
That is what the standard requires, so you have no choice about
conforming to it.
> By the way, forward referencing to a symbol in the SAME package work:
>
> (defun f () (g))
> (defun g () 1)
> (f)
You are not "forward referencing a symbol" because the symbol gets
created the first time it is encountered by the reader. So the symbol G
gets created while reading
(defun f () (g))
The forward reference is to a function named G, not the symbol. And
lisp is defined to assume that symbols in the function position really
are functions. If you were to later define G as a macro instead of a
function, the code would not work, because the compiler would have
expected G to name a function.
--
Thomas A. Russ, USC/Information Sciences Institute
Thank Thomas for your solution:
(defun _load (lib-name)
(funcall (intern "OPERATE" "ASDF") (intern "LOAD-OP" "ASDF") lib-
name))
It works well. I tried that before but it failed because I use
"lowercase" names (i.e. (intern "operate" "asdf") does not work). Why
Common Lisp is not case-sensitive?
Also thank Alex for the proper way of doing it:
> generally people have system definition files to track all dependencies. so,
> for example, you create myapp.asd, where you describe how to load your code
> and what libraries does it depend on.
> with this approach problem you're describing simply does not exist -- you
> just don't place REQUIRE in your source code files, it won't work right
> anyway (believe me).
By the way, for a system consisting of small files, is there a simple
solution than using ASDF?
From: John Thingstad
Subject: Re: Common Lisp: Forward reference to a symbol in an unloaded package, possible?
Date:
Message-ID: <op.uac32dthut4oq5@pandora.alfanett.no>
P� Tue, 29 Apr 2008 09:18:25 +0200, skrev <·······@gmail.com>:
> Thank Thomas for your solution:
>
> (defun _load (lib-name)
> (funcall (intern "OPERATE" "ASDF") (intern "LOAD-OP" "ASDF") lib-
> name))
>
> It works well. I tried that before but it failed because I use
> "lowercase" names (i.e. (intern "operate" "asdf") does not work). Why
> Common Lisp is not case-sensitive?
>
It just isn't defined that way. That would break backward compatibility
with old code which was one of the goal s of the standard. (Note that the
symbol table is case sensitive. It is the READER that converts them to
uppercase.) That said most Common Lisp implementations have a case
sensitive mode.
A poor man's choice is to (setf (readtable-case *READTABLE*) :invert)
which will invert the case.
That is if you write the symbols in lowercase the will be stored in
uppercase but printed in lowercase.
This is mostly cosmetic and done because to many people UPPERCASE IS LIKE
SHOUTING!!
> Also thank Alex for the proper way of doing it:
>
>> generally people have system definition files to track all
>> dependencies. so,
>> for example, you create myapp.asd, where you describe how to load your
>> code
>> and what libraries does it depend on.
>> with this approach problem you're describing simply does not exist --
>> you
>> just don't place REQUIRE in your source code files, it won't work right
>> anyway (believe me).
>
> By the way, for a system consisting of small files, is there a simple
> solution than using ASDF?
The simplest solution is to just load the files in the right order.
Then there is a deprecated require/provide set of functions which was the
'classic' way of loading things.
See the hyperspec.
Also many systems have their own definition of defsystem.
--------------
John Thingstad
From: Pascal J. Bourguignon
Subject: Re: Common Lisp: Forward reference to a symbol in an unloaded package, possible?
Date:
Message-ID: <7cskx53w5x.fsf@pbourguignon.anevia.com>
·······@gmail.com writes:
> Thank Thomas for your solution:
>
> (defun _load (lib-name)
> (funcall (intern "OPERATE" "ASDF") (intern "LOAD-OP" "ASDF") lib-
> name))
>
> It works well. I tried that before but it failed because I use
> "lowercase" names (i.e. (intern "operate" "asdf") does not work). Why
> Common Lisp is not case-sensitive?
>
> Also thank Alex for the proper way of doing it:
>
>> generally people have system definition files to track all dependencies. so,
>> for example, you create myapp.asd, where you describe how to load your code
>> and what libraries does it depend on.
>> with this approach problem you're describing simply does not exist -- you
>> just don't place REQUIRE in your source code files, it won't work right
>> anyway (believe me).
>
> By the way, for a system consisting of small files, is there a simplier
> solution than using ASDF?
(load "small-file.lisp")
--
__Pascal Bourguignon__
??>> generally people have system definition files to track all
??>> dependencies. so, for example, you create myapp.asd, where you
??>> describe how to load your code and what libraries does it depend
??>> on. with this approach problem you're describing simply does not exist
??>> -- you just don't place REQUIRE in your source code files, it won't
??>> work right anyway (believe me).
a> By the way, for a system consisting of small files,
a> is there a simple solution than using ASDF?
if you have more than one file, i doubt there is something better than
asdf -- of course you can have some loader.lisp that will just iterate
through file list and load them, but how will it be better than ASDF system
definition?
if it's just a single file, some sort of trickery is required -- either put
REQUIRE on top of file and always use LOAD rather than COMPILE-FILE, or load
libraries manually before you compile file, or load stuff interactively from
IDE.
also you can consider loading libraries in your implementations init file
(e.g. .sbclrc for SBCL) -- that way libraries will always get loaded as soon
as lisp gets loaded. if you're hacking lots of small scripts, it makes sense
to pre-load frequently used libraries. to speed up loading, you can save
core file with those libraries loaded, so it will be loaded instantly.
if you pre-load stuff, you can keep REQUIRE in your code -- they will be
essentially no-ops, just to track what stuff is used.
of course if you ever happen to distribute your code, you need to get sure
that it runs on vanilla SBCL (or whatever) w/o customizations -- but only
small fraction of programs need to be distributed, so it's rarely a problem.
From: Thomas A. Russ
Subject: Re: Common Lisp: Forward reference to a symbol in an unloaded package, possible?
Date:
Message-ID: <ymibq3se9bh.fsf@blackcat.isi.edu>
·······@gmail.com writes:
> Thank Thomas for your solution:
>
> (defun _load (lib-name)
> (funcall (intern "OPERATE" "ASDF") (intern "LOAD-OP" "ASDF") lib-
> name))
>
> It works well. I tried that before but it failed because I use
> "lowercase" names (i.e. (intern "operate" "asdf") does not work). Why
> Common Lisp is not case-sensitive?
But Common Lisp is case-sensitive. If it were NOT case-sensitive, then
it wouldn't matter what case you used when interning the symbols. What
is often confusing to new Lisp programmers is that the default behavior
of the lisp reader is to upcase all of the characters in symbol names
(unless escaped).
So, the symbol-name of the defun symbol is actually "DEFUN", which is
different from a symbol whose name is "defun" or "Defun". It is
case-sensitive, but the reader default makes it appear at first glance
not to be so.
--
Thomas A. Russ, USC/Information Sciences Institute
From: Pascal J. Bourguignon
Subject: Re: Common Lisp: Forward reference to a symbol in an unloaded package, possible?
Date:
Message-ID: <7cve22gd3v.fsf@pbourguignon.anevia.com>
·······@gmail.com writes:
> Why the following Common Lisp code does not work?
>
> (defun _load (name) (asdf:operate 'asdf:load-op name))
> (load #"path/asdf")
> (_load :asdf-install)
>
> => loading error: no package with name "ASDF"
>
> but the following code does work:
>
> (load #"path/asdf")
> (defun _load (name) (asdf:operate 'asdf:load-op name))
> (_load :asdf-install)
>
> while I cannot make a forward reference to a symbol in an unloaded
> package?
>
> By the way, forward referencing to a symbol in the SAME package work:
>
> (defun f () (g))
> (defun g () 1)
> (f)
>
> Please help.
The problem is that to be able to intern a symbol into a package, that
package must already exist.
Fortunately, defpackage doesn't lose the object identity of an
existing package, so you can safely create the package before loading
the files that will define it and populate it.
So if you write:
(defpackage "ASDF"
(:use "CL") ; not really needed here, but a safe guess.
(:export "LOAD-OP" "OPERATE") ; you need to export the symbols you will forward-use.
)
(defun _load (name) (asdf:operate 'asdf:load-op name))
(load #"path/asdf")
(_load :asdf-install)
it will work as you want.
That said, it would be better to load asdf before defining functions
using it. In the case of asdf I don't see why you would try to do
otherwise.
--
__Pascal Bourguignon__
On Apr 28, 11:26 pm, ····@informatimago.com (Pascal J. Bourguignon)
wrote:
> ·······@gmail.com writes:
> > Why the following Common Lisp code does not work?
>
> > (defun _load (name) (asdf:operate 'asdf:load-op name))
> > (load #"path/asdf")
> > (_load :asdf-install)
>
> > => loading error: no package with name "ASDF"
>
> > but the following code does work:
>
> > (load #"path/asdf")
> > (defun _load (name) (asdf:operate 'asdf:load-op name))
> > (_load :asdf-install)
>
> > while I cannot make a forward reference to a symbol in an unloaded
> > package?
>
> > By the way, forward referencing to a symbol in the SAME package work:
>
> > (defun f () (g))
> > (defun g () 1)
> > (f)
>
> > Please help.
>
> The problem is that to be able to intern a symbol into a package, that
> package must already exist.
>
> Fortunately, defpackage doesn't lose the object identity of an
> existing package, so you can safely create the package before loading
> the files that will define it and populate it.
>
> So if you write:
>
> (defpackage "ASDF"
> (:use "CL") ; not really needed here, but a safe guess.
> (:export "LOAD-OP" "OPERATE") ; you need to export the symbols you will forward-use.
> )
> (defun _load (name) (asdf:operate 'asdf:load-op name))
> (load #"path/asdf")
> (_load :asdf-install)
>
> it will work as you want.
>
> That said, it would be better to load asdf before defining functions
> using it. In the case of asdf I don't see why you would try to do
> otherwise.
>
> --
> __Pascal Bourguignon__
Thanks for a solution. But is there another way, without defining the
package and the symbol first?
The reason that I want to define _load first is for code organization.
I want to define utility functions at the top of my files.
From: Ken Tilton
Subject: Re: Common Lisp: Forward reference to a symbol in an unloaded package, possible?
Date:
Message-ID: <48161906$0$11642$607ed4bc@cv.net>
·······@gmail.com wrote:
> On Apr 28, 11:26 pm, ····@informatimago.com (Pascal J. Bourguignon)
> wrote:
>
>>·······@gmail.com writes:
>>
>>>Why the following Common Lisp code does not work?
>>
>>>(defun _load (name) (asdf:operate 'asdf:load-op name))
>>>(load #"path/asdf")
>>>(_load :asdf-install)
>>
>>>=> loading error: no package with name "ASDF"
>>
>>>but the following code does work:
>>
>>>(load #"path/asdf")
>>>(defun _load (name) (asdf:operate 'asdf:load-op name))
>>>(_load :asdf-install)
>>
>>>while I cannot make a forward reference to a symbol in an unloaded
>>>package?
>>
>>>By the way, forward referencing to a symbol in the SAME package work:
>>
>>>(defun f () (g))
>>>(defun g () 1)
>>>(f)
>>
>>>Please help.
>>
>>The problem is that to be able to intern a symbol into a package, that
>>package must already exist.
>>
>>Fortunately, defpackage doesn't lose the object identity of an
>>existing package, so you can safely create the package before loading
>>the files that will define it and populate it.
>>
>>So if you write:
>>
>>(defpackage "ASDF"
>> (:use "CL") ; not really needed here, but a safe guess.
>> (:export "LOAD-OP" "OPERATE") ; you need to export the symbols you will forward-use.
>> )
>>(defun _load (name) (asdf:operate 'asdf:load-op name))
>>(load #"path/asdf")
>>(_load :asdf-install)
>>
>>it will work as you want.
>>
>>That said, it would be better to load asdf before defining functions
>>using it. In the case of asdf I don't see why you would try to do
>>otherwise.
>>
>>--
>>__Pascal Bourguignon__
>
>
> Thanks for a solution. But is there another way, without defining the
> package and the symbol first?
>
> The reason that I want to define _load first is for code organization.
> I want to define utility functions at the top of my files.
The code you want to define first is code that uses an external library.
Which comes first in your mind chicken-egg-wise, a library or something
that uses it?
Yes, function calls can be coded before their definitions have been
encountered by the compiler, but is that how you would normally organize
your code?
The real problem, I think, might be your position on chickens and eggs.
hth, kenny
--
http://smuglispweeny.blogspot.com/
http://www.theoryyalgebra.com/
"I've never read the rulebook. My job is to catch the ball."
-- Catcher Josh Bard after making a great catch on a foul ball
and then sliding into the dugout, which by the rules allowed the
runners to advance one base costing his pitcher a possible shutout
because there was a runner on third base.
"My sig is longer than most of my articles."
-- Kenny Tilton
From: Pascal J. Bourguignon
Subject: Re: Common Lisp: Forward reference to a symbol in an unloaded package, possible?
Date:
Message-ID: <7chcdlhpu1.fsf@pbourguignon.anevia.com>
·······@gmail.com writes:
> On Apr 28, 11:26 pm, ····@informatimago.com (Pascal J. Bourguignon)
> wrote:
>>
>> The problem is that to be able to intern a symbol into a package, that
>> package must already exist.
>>
>> Fortunately, defpackage doesn't lose the object identity of an
>> existing package, so you can safely create the package before loading
>> the files that will define it and populate it.
>>
>> So if you write:
>>
>> (defpackage "ASDF"
>> (:use "CL") ; not really needed here, but a safe guess.
>> (:export "LOAD-OP" "OPERATE") ; you need to export the symbols you will forward-use.
>> )
>> (defun _load (name) (asdf:operate 'asdf:load-op name))
>> (load #"path/asdf")
>> (_load :asdf-install)
>>
>> it will work as you want.
>>
>> That said, it would be better to load asdf before defining functions
>> using it. In the case of asdf I don't see why you would try to do
>> otherwise.
>
> Thanks for a solution. But is there another way, without defining the
> package and the symbol first?
>
> The reason that I want to define _load first is for code organization.
> I want to define utility functions at the top of my files.
Yes, you can even do that:
(defun _load (name)
(let ((asdf (find-package "ASDF")))
(if asdf
(let ((operate (find-symbol "OPERATE" asdf))
(load-op (find-symbol "LOAD-OP" asdf)))
(assert (and operate load-op))
(funcall (symbol-function operate) load-op name))
(error "ASDF has not been loaded."))))
--
__Pascal Bourguignon__
On Apr 28, 7:05 pm, ····@informatimago.com (Pascal J. Bourguignon)
wrote:
> (defun _load (name)
> (let ((asdf (find-package "ASDF")))
> (if asdf
> (let ((operate (find-symbol "OPERATE" asdf))
> (load-op (find-symbol "LOAD-OP" asdf)))
> (assert (and operate load-op))
> (funcall (symbol-function operate) load-op name))
> (error "ASDF has not been loaded."))))
If you find that hard to read, you can do something like the
following:
(defun _load (name)
(declare (special name))
(eval (read-from-string "(asdf:operate 'asdf:load-op name)")))
Anyway, you most probably shouldn't do this. It's evil. Please try
the DEFPACKAGE way before resorting to something nasty that you might
regret later.
Matthias
PJB> Fortunately, defpackage doesn't lose the object identity of an
PJB> existing package, so you can safely create the package before loading
PJB> the files that will define it and populate it.
docs on defpackage say: "If the new definition is at variance with the
current state of that package, the consequences are undefined;".
can't this rebel preliminary definition harm original one then?
From: Pascal J. Bourguignon
Subject: Re: Common Lisp: Forward reference to a symbol in an unloaded package, possible?
Date:
Message-ID: <7cwsmh3wh6.fsf@pbourguignon.anevia.com>
"Alex Mizrahi" <········@users.sourceforge.net> writes:
> PJB> Fortunately, defpackage doesn't lose the object identity of an
> PJB> existing package, so you can safely create the package before loading
> PJB> the files that will define it and populate it.
>
> docs on defpackage say: "If the new definition is at variance with the
> current state of that package, the consequences are undefined;".
> can't this rebel preliminary definition harm original one then?
Well, it also says:
If defined-package-name already refers to an existing package, the
name-to-package mapping for that name is not changed.
So while I was technically correct, for the behavior of the following
defpackage I depend on implementation dependant behavior, I confess.
DEFPACKAGE could indeed start with (unless (find-package pname) ...)
and not do anything if the package is already defined, which would be
quite bad.
--
__Pascal Bourguignon__
a> Why the following Common Lisp code does not work?
a> (defun _load (name) (asdf:operate 'asdf:load-op name))
it does not work because of the way symbols work.
symbols and packages are not some virtual things -- both symbols and
packages are real, concrete entities in CL.
and there is no way to refer to a symbol in specifc package other than
create that actual package and that actual symbol.
also, note that package is not merely a name, but quite a complex thing: it
has lists of internal symbols, external ones, imported packages and symbols
etc.
thus, reader cannot automatically create package for you -- this is very
likely to bring problems.
a> while I cannot make a forward reference to a symbol in an unloaded
a> package?
you can't. you should not. Lisp is a language where order matters, because
each single form is _executed_.
a> By the way, forward referencing to a symbol in the SAME package work:
a> (defun f () (g))
a> (defun g () 1)
a> (f)
symbols are created by a reader. reader automatically creates symbols in
current package, because it knows what this package is.
so (defun f () (g)) creates symbols f and g when it is read.
(defun g () 1) refers to existing symbol g.
On Apr 29, 12:37 am, "Alex Mizrahi" <········@users.sourceforge.net>
wrote:
> a> Why the following Common Lisp code does not work?
>
> a> (defun _load (name) (asdf:operate 'asdf:load-op name))
>
> it does not work because of the way symbols work.
> symbols and packages are not some virtual things -- both symbols and
> packages are real, concrete entities in CL.
> and there is no way to refer to a symbol in specifc package other than
> create that actual package and that actual symbol.
>
> also, note that package is not merely a name, but quite a complex thing: it
> has lists of internal symbols, external ones, imported packages and symbols
> etc.
>
> thus, reader cannot automatically create package for you -- this is very
> likely to bring problems.
>
> a> while I cannot make a forward reference to a symbol in an unloaded
> a> package?
>
> you can't. you should not. Lisp is a language where order matters, because
> each single form is _executed_.
>
> a> By the way, forward referencing to a symbol in the SAME package work:
>
> a> (defun f () (g))
> a> (defun g () 1)
> a> (f)
>
> symbols are created by a reader. reader automatically creates symbols in
> current package, because it knows what this package is.
> so (defun f () (g)) creates symbols f and g when it is read.
> (defun g () 1) refers to existing symbol g.
Is there a way to let reader ignores/not-evaluates the body of a
function, until it is called? So that I can do something like:
(defun f () (p:g))
(require :p)
(f)
instead of:
(require :p)
(defun f () (p:g))
(f)
a> Is there a way to let reader ignores/not-evaluates the body of a
a> function, until it is called?
reader does not evaluate things, it reads them.
the only way you can prevent reading is to place your code inside the
string, and read/evaluate this string in run time
a> So that I can do something like:
a> (defun f () (p:g))
a> (require :p)
a> (f)
a> instead of:
a> (require :p)
a> (defun f () (p:g))
a> (f)
why do you need this? to confuse people who will read your code and to
confuse yourself?
nobody uses library before loading it just as nobody walks upside down, on
their hands.
of course you can use this acrobatics in your code (you already have been
shown couple of ways how to do it),
but why won't you learn first how normal people are organizing their
systems?
generally people have system definition files to track all dependencies. so,
for example, you create myapp.asd, where you describe how to load your code
and what libraries does it depend on.
with this approach problem you're describing simply does not exist -- you
just don't place REQUIRE in your source code files, it won't work right
anyway (believe me).
From: Pascal J. Bourguignon
Subject: Re: Common Lisp: Forward reference to a symbol in an unloaded package, possible?
Date:
Message-ID: <7c63u15bit.fsf@pbourguignon.anevia.com>
·······@gmail.com writes:
> On Apr 29, 12:37 am, "Alex Mizrahi" <········@users.sourceforge.net>
> wrote:
>> a> Why the following Common Lisp code does not work?
>>
>> a> (defun _load (name) (asdf:operate 'asdf:load-op name))
>>
>> it does not work because of the way symbols work.
>> symbols and packages are not some virtual things -- both symbols and
>> packages are real, concrete entities in CL.
>> and there is no way to refer to a symbol in specifc package other than
>> create that actual package and that actual symbol.
>>
>> also, note that package is not merely a name, but quite a complex thing: it
>> has lists of internal symbols, external ones, imported packages and symbols
>> etc.
>>
>> thus, reader cannot automatically create package for you -- this is very
>> likely to bring problems.
>>
>> a> while I cannot make a forward reference to a symbol in an unloaded
>> a> package?
>>
>> you can't. you should not. Lisp is a language where order matters, because
>> each single form is _executed_.
>>
>> a> By the way, forward referencing to a symbol in the SAME package work:
>>
>> a> (defun f () (g))
>> a> (defun g () 1)
>> a> (f)
>>
>> symbols are created by a reader. reader automatically creates symbols in
>> current package, because it knows what this package is.
>> so (defun f () (g)) creates symbols f and g when it is read.
>> (defun g () 1) refers to existing symbol g.
>
> Is there a way to let reader ignores/not-evaluates the body of a
> function, until it is called? So that I can do something like:
Well if you really insist.
;; Define an identifier structure:
(defstruct identifier
package-name
symbol-name)
;; We will be able to transform this identifier into a fully interned symbol:
(defun identifier-symbol (ident)
(intern (identifier-symbol-name ident)
(identifier-package-name ident)))
:; To ease reading forms with identifiers, let's defined a reader macro.
;; #!package:symbol will read an identifier.
;; Note: this is identifier-reader is a Q&D trick, we won't check the
;; exact syntax:
;; constituent+ ':' constituent+
;; We'll accept also constituent+ ' ' constituent+
;; and other horrors.
(defvar *identifier-readtable*
(let ((rt (copy-readtable nil)))
(set-syntax-from-char #\: #\space rt rt)
rt))
(defun identifier-reader (stream sub-char arg)
(assert (not arg) ()
"Cannot put an numerical argument before an identifier.
If your package name starts with digits, then escape them!")
(setf (readtable-case *identifier-readtable*) (readtable-case *readtable*))
(let ((*readtable* *identifier-readtable*)
(*package* (make-package (string (gensym)) :use '())))
(make-identifier
:package-name (string (read stream))
:symbol-name (string (read stream)))))
(set-dispatch-macro-character
#\# #\!
(lambda (stream sub-char arg)
;; This is a stub, that will always call the identifier-reader function,
;; even when it changes.
(identifier-reader stream sub-char arg)))
;; Now, we'll have read forms with identifiers in place of symbols,
;; let's walk these forms interning symbols for these identifiers:
(defun update-identifiers (sexp)
(cond
((identifier-p sexp) (identifier-symbol sexp))
((atom sexp) sexp)
(t (cons (update-identifiers (car sexp))
(update-identifiers (cdr sexp))))))
;; Evaluation of forms with identifiers will have to be delayed,
;; let's keep a list of these forms:
(eval-when (:compile-toplevel :load-toplevel :execute)
(defvar *forms-with-identifiers* '()))
(defmacro with-identifiers (&body body)
`(progn
,@(mapcar (lambda (form)
`(push ',form *forms-with-identifiers*))
body)))
(defun eval-forms-with-identifiers ()
(map nil (lambda (form) (eval (print (update-identifiers form))))
(nreverse *forms-with-identifiers*))
(setf *forms-with-identifiers* '()))
;; So now, you will be able to write:
(with-identifiers
(defun _load (name) (#!asdf:operate '#!asdf:load-op name)))
(require 'asdf)
(eval-forms-with-identifiers)
;; Happy?
--
__Pascal Bourguignon__