Prev: ☆☉☉☆ Barely Legal Babes - Free downloads! Videos Images, Barely Legal young teens
Next: does sort always sort vectors in place?
From: Pascal J. Bourguignon on 25 Apr 2010 19:14 Tamas K Papp <tkpapp(a)gmail.com> writes: > On Mon, 26 Apr 2010 00:22:15 +0300, Captain Obvious wrote: > >> Well, with an inspiration from Pascal Costanza I've found one such case >> -- when symbols from different, unrelated pieces of code (and thus from >> different packages) are used in one list. For example, in initarg list >> in make-instance call. >> For example, two classes might be defined in different packages and they >> have slot with same name: >> >> (in-package :foo) >> >> (defclass foo () >> ((frob :initarg :frob))) >> >> (in-package :bar) >> >> (defclass bar () >> ((frob :initarg :frob))) >> >> And you want to use both these classes as ancestors: >> >> (in-package :baz) >> >> (defclass baz (foo bar) >> ()) >> >> (make-instance 'baz :frob 1) >> >> Now, even if slot names look same, they are different: foo::frob in >> first case and bar::frob in second. >> But initargs are keywords and they are same, so you cannot initialize >> both foo::frob and bar::frob via initarg :frob. >> >> But cases like this are very rare, I think. > > Interesting example, thanks for sharing it. > > Considerations of the keyword package aside, I think it would be bad > practice to use the same name for slots that have different > interpretations, it could lead to a lot of confusion. So this is > unlikely to occur. But if it does, it can be solved by adding extra > keywords to the initialize-instance :after method. Why do you think we HAVE to specify the initarg of each slot? So that in this situation we may write: (in-package :foo) (defconstant frob 'frob) (defclass foo () ((frob :initarg frob))) (in-package :bar) (defconstant frob 'frob) (defclass bar () ((frob :initarg frob))) (in-package :baz) (defclass baz (foo bar) ()) (make-instance 'baz foo:frob 1 bar:frob 2) There! You have different keywords named the same in two different packages! -- __Pascal Bourguignon__
From: Stelian Ionescu on 25 Apr 2010 19:27 On Mon, 26 Apr 2010 01:14:23 +0200, Pascal J. Bourguignon wrote: > (make-instance 'baz foo:frob 1 bar:frob 2) > > There! > You have different keywords named the same in two different packages! Lol, we posted nearly identical examples. Btw, you forgot to QUOTE foo:frob and bar:frob -- Stelian Ionescu a.k.a. fe[nl]ix Quidquid latine dictum sit, altum videtur. http://common-lisp.net/project/iolib
From: Thomas A. Russ on 26 Apr 2010 12:39 "Captain Obvious" <udodenko(a)users.sourceforge.net> writes: > And it answers why "keywords in other packages" are not in CL spec -- > they are not important enough. > And as CL is flexible enough to allow users to implement similar things > themselves, it is not a big deal even if there is some use. > > Well, with an inspiration from Pascal Costanza I've found one such case > -- > when symbols from different, unrelated pieces of code (and thus from > different packages) are used in one list. For example, in initarg list > in make-instance call. > For example, two classes might be defined in different packages and they > have slot with same name: > > (in-package :foo) > > (defclass foo () > ((frob :initarg :frob))) > > (in-package :bar) > > (defclass bar () > ((frob :initarg :frob))) > > And you want to use both these classes as ancestors: > > (in-package :baz) > > (defclass baz (foo bar) > ()) > > (make-instance 'baz :frob 1) > > Now, even if slot names look same, they are different: foo::frob in > first case and bar::frob in second. > But initargs are keywords and they are same, so you cannot initialize > both foo::frob and bar::frob via initarg :frob. But this is conflating two different meanings of "keyword" in lisp. The first are keyword symbols in the keyword package. The second is keyword arguments to functions (and by extension to initargs). In the second case, the default behavior and common practice is to use symbols in the keyword package to denote the keyword arguments to functions and init arguments. But this is just the default behavior and it isn't required by the standard. For example, nothing stops a programmer from using symbols in their own package, thusly: (in-package :foo) (defclass foo () ((frob :initarg 'frob))) (in-package :bar) (defclass bar () ((frob :initarg 'frob))) (in-package :baz) (defclass baz (foo:foo bar:bar) ()) (make-instance 'baz 'foo:frob 1 'bar:frob "Mary") So you don't HAVE to use keyword symbols as keyword argument names. That is why there is the extended form of the keyword argument lambda list item: &key ((keyword-name var) init-form supplied-p-parameter) That allows you to use any symbol you want as the KEYWORD-NAME, and that symbol can exist in any package you choose. Of course, you would then need to quote the symbol when calling the function, but you could easily do something like this: (defun my-function (a &key ((foo:a x) 1) ((bar:a y) 1)) (* a x y)) which you would then call like (my-function 10 'foo:a 10 'bar:a 200) and it would work using keyword arguments from two different packages. So you can work around these issues by not using the defaults provided by Common Lisp. It is a bit more work, but for large systems or libraries, particularly if you use common words, it could be a good engineering practice. -- Thomas A. Russ, USC/Information Sciences Institute
From: Thomas A. Russ on 26 Apr 2010 12:24 jimka <jimka(a)rdrop.com> writes: > > 4. All keywords go into the same package. "KEYWORD". What causes the > > evaluator to evaluate keywords to themselves? Is it that they exist > > in this package? The CL syntax for keywords is that the a : preceed > > the name. Other than this extremly handy syntax, is there any other > > reason one might want all keywords in the same package? Is there an > > reasonable argument to allow keywords in other packages? Restated, > > suppose a lisp did not support the : synax for keywords but insisted > > that keywords by identifyable by their inital character being "?". > > Would their be an advantage for that lisp to force all such keywords > > into the same package? > > > > -jim > > It's obvious from the responses to this question that the question is > not stated very well. :-( Let me retry. > > Common lisp, keywords happen to have three very useful properties. > 1. they always evaluate to themselves > 2. they always parse to the same symbol, regardless of the value of > *current-package* > 3. key all have (are in) the same package: "KEYWORD" > > These three properties are really orthogonal, but is it nice the CL > makes sure they are all true simultaneously Well, number 2 isn't really a special property of keywords. Any package-qualified symbol will exhibit behavior #2. It just so happens that "" (the empty string) is a synonym for the KEYWORD package. You could also get keywords by using the full name, such as KEYWORD:FOO The latter also works with the external name format because of special properties of the KEYWORD package. > If the only lisp you have ever used is common lisp or something very > common lisp-like, you might understandably have trouble seperating the > two concepts as you have not so many example of symbols which exhibit > one behavior without exhibiting the other. (T is an example of a > symbol which exhibits #1 and #2, but not #3) Actually, your last comment is incorrect. T does not always parse to the same symbol. It only appears that way because you have presumably only experimented with packages that :USE the COMMON-LISP package. If you don't :use the common lisp package, then you can get other symbols. For example, try this: (defpackage "NEW" (:use)) (eq 't 'new::t) And T is just an example of a constant and obeys all of the normal rules regarding constants.* > #1 means you cannot do the following > (setq :key 42) > will fail, but (eq :key ':key) returns t. Correct. > #2 means that even if the following functions are defined in different > packages, ... > > ;; in package A > (defun fun1 (x) > (eq x ':key)) > > ;; in package B > (defun fun2 (x) > (eq x ':key)) > > ...the the two functions behave the exact behavior, as opposed to the > following two functions which exhibit different behavior. > > ;; in package A > (defun fun3 (x) > (eq x 'key)) > > ;; in package B > (defun fun4 (x) > (eq x 'key)) But that is because you are doing a false comparison. The correct comparison would involve: (defun fun4 (x) (eq x 'my-package:key)) (defun fun5 (x) (eq x 'my-package:key)) What you overlook is that the leading colon in a keyword is not a special syntactic marker but the standard package marker with an empty package name. So what you are really doing is comparing symbols that are interned in the same package. And it works exactly like any other symbol comparison. It isn't special in any way. > > Now because CL combines #1 and #2, you can write fun1 and fun2 without > quoting the keyword. Actually, it is only because of #1 that you don't need to quote the keyword symbol. You can, however, quote it without ill effect in this case because it is self-evaluating. That applies to other self evaluating forms as well, so for example (eq 3 '3) => T > Now, what was my question? > > It was basically this: if a lisp allows users to create symbols which > have attribute #1 > or #2 independently, does this eliminate the need for a single package > which contains them all? Lisp doesn't allow #2 unless you explicitly qualify the package. So if you want to have symbols in a particular package, you can just create them there. What you won't have, however, is an automatic form of #1. That is the only part of the entire keyword handling that is special to keywords. > So I don't understand whether CL conflates the 3 attributes into one > because it only makes > sense to do so, or whether the choice is an arbitrary one. It doesn't conflate anything. The only special thing about keywords is item #1. The two other items follow from the standard behavior of packages for all symbols. Actually, there is one other special treatment of keywords that you don't mention, which is that they are always exported. But this is generally not a problem because it isn't expected that anyone would :USE the KEYWORD package. I suppose that if you did so, Bad Things(tm) could happen as new keywords got interned. But I don't think it is specifically forbidden to do so. Certainly you can't :USE both COMMON-LISP and KEYWORD without getting name conflicts. The main reasons people don't :USE the KEYWORD package are that the auto-export feature makes it extremely prone to name conflicts and also because the clever use of "" as an alternate package name means there is little benefit (for typing) if you :USE the keyword package and you lose a big benefit of making keywords stand out. So nobody does this. But as a general summary, keywords are done the way they are because it has proven useful to have a place to automatically put symbol constants. Since there is some special behavior associated with the constants (namely making them self-evaluate and be automatically exported) it is convenient to do this in a single package. =================== * Pragmatically, some lisp systems take extra care with handling T and NIL to make sure you don't redefine them because that can break the entire system. I always liked the "VERITAS AETERNA" and "NIHIL EX NIHIL" error messages from MacLisp. -- Thomas A. Russ, USC/Information Sciences Institute
From: Thomas A. Russ on 26 Apr 2010 12:51
jimka <jimka(a)rdrop.com> writes: > On Apr 25, 6:01 pm, p...(a)informatimago.com (Pascal J. Bourguignon) > wrote: > > jimka <ji...(a)rdrop.com> writes: > > > 4. All keywords go into the same package. "KEYWORD". What causes the > > > evaluator to evaluate keywords to themselves? Is it that they exist > > > in this package? The CL syntax for keywords is that the a : preceed > > > the name. Other than this extremly handy syntax, is there any other > > > reason one might want all keywords in the same package? > > > > (eq ':x ':x) --> true is a good reason. > > > > Maybe there is somthing fundamental that I misunderstand about CL > packages. Isn't it possible for symbols in two pacakges to be eq? No. Symbols in two packages are definitely not EQ. They cannot be the same object. Now, if you IMPORT a symbol from package A into package B, then you just have one symbol that is ACCESSIBLE (via the reader) from either package. But it is just one symbol, namely the one in package A. For example, if you did (defpackage a) (in-package :a) 'a (defpackage b (:import a::a)) (eq 'a 'a::a) => T (symbol-package 'a) => <Package A> (symbol-package 'b::a) => <Package A> > Isn't this what the :use keyword does on defpackage? It assures you > that the symbols with the same name are eq. No, what :USE does is import all of the exported symbols of the named packages. The fact that all the symbols with the same name are EQ is a consequence of the fact that there is only one symbol with that name, because you have imported that symbol into your package. Once you do the import, you don't have two different symbols. EQ is really about object-equality, so if two things are EQ, they are the same object. So, you could think about it as you say "symbols with the same name are eq", but that is really a shortcut for saying that symbols referred to by either (package qualified) name are actually the same object. Packages are all about managing the NAME => SYMBOL object mapping. They do nothing else. That is the key to understanding how this all works. ======== [OK, technically, there is a special hook for the keyword package that handles the exporting, constant creation and self-evaluation, but that is the only special case.] -- Thomas A. Russ, USC/Information Sciences Institute |