Hello all,
I'm having a strange problem with packages, that I hope someone can
educate me. If I load the following:
(defpackage :test-package
(:use :common-lisp)
(:export :count-a))
(in-package :test-package)
(defun count-a (lst)
(let ((count 0))
(dolist (obj lst)
(if (eql 'A obj)
(setf count (+ count 1))
))
count))
If I call this function from CL-USER (for example) the result of this
fuction is always 0. The value of count never changes, becuase the
expression (eql 'A obj) always returns nil. Observe:
CL-USER> (test-package:count-a '(A A))
0
However, if I switch to the package, then it works as expected:
CL-USER> (in-package test-package)
#<The TEST-PACKAGE package>
TEST-PACKAGE> (count-a '(A A))
2
Why does the function not behave as I would expect when called from
outside the package? Have I not used defpackage correctly, or do I
need to somehow export the return value of the function? Any help
would be appreciated.
Thanks in advance,
Kevin
kmb wrote:
> Hello all,
>
> I'm having a strange problem with packages, that I hope someone can
> educate me. If I load the following:
>
> (defpackage :test-package
> (:use :common-lisp)
> (:export :count-a))
>
> (in-package :test-package)
>
> (defun count-a (lst)
> (let ((count 0))
> (dolist (obj lst)
> (if (eql 'A obj)
> (setf count (+ count 1))
> ))
> count))
>
> If I call this function from CL-USER (for example) the result of this
> fuction is always 0. The value of count never changes, becuase the
> expression (eql 'A obj) always returns nil. Observe:
>
> CL-USER> (test-package:count-a '(A A))
> 0
>
> However, if I switch to the package, then it works as expected:
>
> CL-USER> (in-package test-package)
> #<The TEST-PACKAGE package>
> TEST-PACKAGE> (count-a '(A A))
> 2
>
> Why does the function not behave as I would expect when called from
> outside the package? Have I not used defpackage correctly, or do I
> need to somehow export the return value of the function? Any help
> would be appreciated.
I'll just paste some code - I think you'll see what's going on:
(defpackage :test-package
(:use :common-lisp)
(:export :count-a))
(in-package :test-package)
(defun count-a (lst)
(format t "The package of the first symbol supplied is: ~A~%"
(symbol-package (first lst)))
(let ((count 0))
(dolist (obj lst)
(if (eql 'A obj)
(setf count (+ count 1))))
count))
cl-user> (format t "The package of the symbol 'A is: ~A~%"
(symbol-package 'A))
The package of the symbol 'A is: #<package "COMMON-LISP-USER">
nil
cl-user> (test-package:count-a '(A A))
The package of the first symbol supplied is: #<package
"COMMON-LISP-USER">
0
cl-user> (test-package:count-a '(test-package::A test-package::A))
The package of the first symbol supplied is: #<package "TEST-PACKAGE">
2
cl-user> (in-package :test-package)
#<package "TEST-PACKAGE">
test-package> (test-package::count-a '(A A))
The package of the first symbol supplied is: #<package "TEST-PACKAGE">
2
(Google Groups splits one of the lines in the code)
--
mvh, Lars Rune Nøstdal
http://lars.nostdal.org/
Thanks Lars,
I should have considered the package of the incoming symbols.
Incidentally, I wonder if there is any way that I could "cast" the
immediate 'A comparator used in the function to be of the same package
as the object being compared to. That way the caller doesn't have to
specify the package directly.
Thanks,
Kevin
Lars Rune Nøstdal wrote:
> kmb wrote:
> > Hello all,
> >
> > I'm having a strange problem with packages, that I hope someone can
> > educate me. If I load the following:
> >
> > (defpackage :test-package
> > (:use :common-lisp)
> > (:export :count-a))
> >
> > (in-package :test-package)
> >
> > (defun count-a (lst)
> > (let ((count 0))
> > (dolist (obj lst)
> > (if (eql 'A obj)
> > (setf count (+ count 1))
> > ))
> > count))
> >
> > If I call this function from CL-USER (for example) the result of this
> > fuction is always 0. The value of count never changes, becuase the
> > expression (eql 'A obj) always returns nil. Observe:
> >
> > CL-USER> (test-package:count-a '(A A))
> > 0
> >
> > However, if I switch to the package, then it works as expected:
> >
> > CL-USER> (in-package test-package)
> > #<The TEST-PACKAGE package>
> > TEST-PACKAGE> (count-a '(A A))
> > 2
> >
> > Why does the function not behave as I would expect when called from
> > outside the package? Have I not used defpackage correctly, or do I
> > need to somehow export the return value of the function? Any help
> > would be appreciated.
>
> I'll just paste some code - I think you'll see what's going on:
>
>
> (defpackage :test-package
> (:use :common-lisp)
> (:export :count-a))
> (in-package :test-package)
>
>
> (defun count-a (lst)
> (format t "The package of the first symbol supplied is: ~A~%"
> (symbol-package (first lst)))
> (let ((count 0))
> (dolist (obj lst)
> (if (eql 'A obj)
> (setf count (+ count 1))))
> count))
>
> cl-user> (format t "The package of the symbol 'A is: ~A~%"
> (symbol-package 'A))
> The package of the symbol 'A is: #<package "COMMON-LISP-USER">
> nil
> cl-user> (test-package:count-a '(A A))
> The package of the first symbol supplied is: #<package
> "COMMON-LISP-USER">
> 0
> cl-user> (test-package:count-a '(test-package::A test-package::A))
> The package of the first symbol supplied is: #<package "TEST-PACKAGE">
> 2
> cl-user> (in-package :test-package)
> #<package "TEST-PACKAGE">
> test-package> (test-package::count-a '(A A))
> The package of the first symbol supplied is: #<package "TEST-PACKAGE">
> 2
>
>
> (Google Groups splits one of the lines in the code)
>
> --
> mvh, Lars Rune Nøstdal
> http://lars.nostdal.org/
kmb wrote:
> Thanks Lars,
>
> I should have considered the package of the incoming symbols.
> Incidentally, I wonder if there is any way that I could "cast" the
> immediate 'A comparator used in the function to be of the same package
> as the object being compared to. That way the caller doesn't have to
> specify the package directly.
>
> Thanks,
> Kevin
STRING= will compare symbol names without regard to the symbol's
package:
(defpackage #:foo)
(string= 'foo::bar 'cl-user::bar) => T
The built-in function COUNT can do what you want, without the need for
a custom function:
(count 'a '(cl-user::a foo::a) :test #'string=) => 2
--
Bill Atkins
Bill Atkins wrote:
> kmb wrote:
> > Thanks Lars,
> >
> > I should have considered the package of the incoming symbols.
> > Incidentally, I wonder if there is any way that I could "cast" the
> > immediate 'A comparator used in the function to be of the same package
> > as the object being compared to. That way the caller doesn't have to
> > specify the package directly.
> >
> > Thanks,
> > Kevin
>
> STRING= will compare symbol names without regard to the symbol's
> package:
>
> (defpackage #:foo)
> (string= 'foo::bar 'cl-user::bar) => T
>
> The built-in function COUNT can do what you want, without the need for
> a custom function:
>
> (count 'a '(cl-user::a foo::a) :test #'string=) => 2
>
> --
> Bill Atkins
Thanks for your reply Bill, that is a very nice solution. Thanks also
to everyone else who replied, I really appreciate all of the help.
Kevin
"kmb" <···········@gmail.com> writes:
> Incidentally, I wonder if there is any way that I could "cast" the
> immediate 'A comparator used in the function to be of the same package
> as the object being compared to. That way the caller doesn't have to
> specify the package directly.
If you want to compare the names of the symbols, as opposed to their
identity, you could look at using the SYMBOL-NAME function. That
would mean comparing strings though, which EQL is not appropriate
for.
...Peder...
--
I wish a new life awaited _me_ in some off-world colony.
kmb wrote:
> Thanks Lars,
>
> I should have considered the package of the incoming symbols.
> Incidentally, I wonder if there is any way that I could "cast" the
> immediate 'A comparator used in the function to be of the same package
> as the object being compared to. That way the caller doesn't have to
> specify the package directly.
Looks to complicated to me. Just pass the symbol to count as a parameter:
(defun count (element list)
(loop for x in list
count (eql x element)))
Pascal
--
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
Pascal Costanza <··@p-cos.net> writes:
> (defun count (element list)
> (loop for x in list
> count (eql x element)))
I think that's taking LOOP worship too far. Just use the existing
COUNT function. ;-)
Lars Brinkhoff wrote:
> Pascal Costanza <··@p-cos.net> writes:
>> (defun count (element list)
>> (loop for x in list
>> count (eql x element)))
>
> I think that's taking LOOP worship too far. Just use the existing
> COUNT function. ;-)
;)
--
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
Lars Brinkhoff wrote:
> Pascal Costanza <··@p-cos.net> writes:
>
>>(defun count (element list)
>> (loop for x in list
>> count (eql x element)))
>
>
> I think that's taking LOOP worship too far. Just use the existing
> COUNT function. ;-)
Dammit. When the user says they want to write a function to count
something, c.l.l is allowed only to help them do exactly what they ask,
without any of your presumptuous imposition of your own idea of what is
right, no matter how superior that solution.
Try to keep up, will you?!
kenny
--
Cells: http://common-lisp.net/project/cells/
"I'll say I'm losing my grip, and it feels terrific."
-- Smiling husband to scowling wife, New Yorker cartoon
On Fri, 4 Aug 2006, Ken Tilton wrote:
>
> Lars Brinkhoff wrote:
>> Pascal Costanza <··@p-cos.net> writes:
>>
>> > (defun count (element list)
>> > (loop for x in list
>> > count (eql x element)))
>>
>>
>> I think that's taking LOOP worship too far. Just use the existing
>> COUNT function. ;-)
>
> Dammit. When the user says they want to write a function to count something,
> c.l.l is allowed only to help them do exactly what they ask, without any of
> your presumptuous imposition of your own idea of what is right, no matter how
> superior that solution.
>
> Try to keep up, will you?!
We can satisfy everyone by writing a new function which uses the old
function...
(shadow 'count)
(defun count (element list)
(cl:count element list))
> kenny
>
> --
> Cells: http://common-lisp.net/project/cells/
>
> "I'll say I'm losing my grip, and it feels terrific."
> -- Smiling husband to scowling wife, New Yorker cartoon
>
"kmb" <···········@gmail.com> writes:
> I should have considered the package of the incoming symbols.
You can keep all your symbols in a separate package, or you could use
symbols in the keyword package, e.g. replace 'A with :A in count-a:
CL-USER> (test-package::count-a '(:a :a :b :c :d :a))
3
Petter
--
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
"kmb" <···········@gmail.com> schrieb im Newsbeitrag ····························@s13g2000cwa.googlegroups.com...
> Hello all,
>
> I'm having a strange problem with packages, that I hope someone can
> educate me. If I load the following:
>
> (defpackage :test-package
> (:use :common-lisp)
> (:export :count-a))
>
> (in-package :test-package)
>
> (defun count-a (lst)
> (let ((count 0))
> (dolist (obj lst)
> (if (eql 'A obj)
> (setf count (+ count 1))
> ))
> count))
>
> If I call this function from CL-USER (for example) the result of this
> fuction is always 0. The value of count never changes, becuase the
> expression (eql 'A obj) always returns nil. Observe:
>
> CL-USER> (test-package:count-a '(A A))
> 0
>
> However, if I switch to the package, then it works as expected:
>
> CL-USER> (in-package test-package)
> #<The TEST-PACKAGE package>
> TEST-PACKAGE> (count-a '(A A))
> 2
>
> Why does the function not behave as I would expect when called from
> outside the package? Have I not used defpackage correctly, or do I
> need to somehow export the return value of the function? Any help
> would be appreciated.
>
> Thanks in advance,
> Kevin
>
Kevin,
Lars already pointed out your misunderstanding. I am not sure what a real world application of your example could be. Instead of writing a function count-a I'd suggest a function count-symbol like in the following:
(defpackage :test-package
(:nicknames :tp)
(:use :common-lisp)
(:export :count-symbol :count-symbol2))
(in-package :test-package)
(defun count-symbol (lst symbol)
(let ((count 0))
(dolist (obj lst)
(when (eql symbol obj) (incf count)))
count))
(defun count-symbol2 (lst &key (symbol 'common-lisp-user::a))
(let ((count 0))
(dolist (obj lst)
(when (eql symbol obj) (incf count)))
count))
With this you'd have more flexibility and you'd avoid the "package problem" because symbol already is in the calling package:
CL-USER 6 > (tp:count-symbol '(A B A) 'a)
2
CL-USER 7 > (tp:count-symbol2 '(A B A))
2
CL-USER 8 > (tp::count-symbol2 '(A B A) :symbol 'b)
1
Andreas
Andreas Thiele wrote:
> "kmb" <···········@gmail.com> schrieb im Newsbeitrag ····························@s13g2000cwa.googlegroups.com...
> > Hello all,
> >
> > I'm having a strange problem with packages, that I hope someone can
> > educate me. If I load the following:
> >
> > (defpackage :test-package
> > (:use :common-lisp)
> > (:export :count-a))
> >
> > (in-package :test-package)
> >
> > (defun count-a (lst)
> > (let ((count 0))
> > (dolist (obj lst)
> > (if (eql 'A obj)
> > (setf count (+ count 1))
> > ))
> > count))
> >
> > If I call this function from CL-USER (for example) the result of this
> > fuction is always 0. The value of count never changes, becuase the
> > expression (eql 'A obj) always returns nil. Observe:
> >
> > CL-USER> (test-package:count-a '(A A))
> > 0
> >
> > However, if I switch to the package, then it works as expected:
> >
> > CL-USER> (in-package test-package)
> > #<The TEST-PACKAGE package>
> > TEST-PACKAGE> (count-a '(A A))
> > 2
> >
> > Why does the function not behave as I would expect when called from
> > outside the package? Have I not used defpackage correctly, or do I
> > need to somehow export the return value of the function? Any help
> > would be appreciated.
> >
> > Thanks in advance,
> > Kevin
> >
>
> Kevin,
>
> Lars already pointed out your misunderstanding. I am not sure what a real world application of your example could be. Instead of writing a function count-a I'd suggest a function count-symbol like in the following:
>
> (defpackage :test-package
> (:nicknames :tp)
> (:use :common-lisp)
> (:export :count-symbol :count-symbol2))
>
> (in-package :test-package)
>
> (defun count-symbol (lst symbol)
> (let ((count 0))
> (dolist (obj lst)
> (when (eql symbol obj) (incf count)))
> count))
>
> (defun count-symbol2 (lst &key (symbol 'common-lisp-user::a))
> (let ((count 0))
> (dolist (obj lst)
> (when (eql symbol obj) (incf count)))
> count))
>
> With this you'd have more flexibility and you'd avoid the "package problem" because symbol already is in the calling package:
>
> CL-USER 6 > (tp:count-symbol '(A B A) 'a)
> 2
>
> CL-USER 7 > (tp:count-symbol2 '(A B A))
> 2
>
> CL-USER 8 > (tp::count-symbol2 '(A B A) :symbol 'b)
> 1
>
> Andreas
Andreas, thanks for your reply. Actually, there is no real world
example, :-) I'm working on the exercises in Graham's book, and wanted
to put my implementations into a package as part of unit tests I was
writing for them. Your code was very helpful, thanks again!
Kevin