From: kmb
Subject: Strange issue with packages
Date: 
Message-ID: <1154671561.202566.68970@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

From: Lars Rune Nøstdal
Subject: Re: Strange issue with packages
Date: 
Message-ID: <1154672761.236441.222430@p79g2000cwp.googlegroups.com>
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/
From: kmb
Subject: Re: Strange issue with packages
Date: 
Message-ID: <1154678416.814482.139570@b28g2000cwb.googlegroups.com>
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/
From: Bill Atkins
Subject: Re: Strange issue with packages
Date: 
Message-ID: <1154702273.799887.116940@i3g2000cwc.googlegroups.com>
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
From: kmb
Subject: Re: Strange issue with packages
Date: 
Message-ID: <1154752806.841961.287490@i42g2000cwa.googlegroups.com>
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
From: Peder O. Klingenberg
Subject: Re: Strange issue with packages
Date: 
Message-ID: <kslkq4kjjy.fsf@beto.netfonds.no>
"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.
From: Pascal Costanza
Subject: Re: Strange issue with packages
Date: 
Message-ID: <4jggl8F7cmpmU1@individual.net>
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/
From: Lars Brinkhoff
Subject: Re: Strange issue with packages
Date: 
Message-ID: <85u04sx39y.fsf@junk.nocrew.org>
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. ;-)
From: Pascal Costanza
Subject: Re: Strange issue with packages
Date: 
Message-ID: <4jgj2bF7tttfU1@individual.net>
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/
From: Ken Tilton
Subject: Re: Strange issue with packages
Date: 
Message-ID: <9YTAg.222$Fs3.6@fe09.lga>
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
From: Nathan Baum
Subject: Re: Strange issue with packages
Date: 
Message-ID: <Pine.LNX.4.64.0608050506330.21556@localhost>
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
>
From: Petter Gustad
Subject: Re: Strange issue with packages
Date: 
Message-ID: <87slkcx1ol.fsf@gustad.com>
"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?
From: Andreas Thiele
Subject: Re: Strange issue with packages
Date: 
Message-ID: <eav1ug$kmm$00$1@news.t-online.com>
"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
From: kmb
Subject: Re: Strange issue with packages
Date: 
Message-ID: <1154752511.547832.265590@i42g2000cwa.googlegroups.com>
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