all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* "push" creating circular objects
@ 2008-08-20 13:25 Charles Sebold
  2008-08-20 16:27 ` Charles Sebold
  2008-08-21 16:14 ` John Paul Wallington
  0 siblings, 2 replies; 14+ messages in thread
From: Charles Sebold @ 2008-08-20 13:25 UTC (permalink / raw)
  To: help-gnu-emacs

This is killing me.

I'm running GNU Emacs 22.2.1 (i386-mingw-nt5.1.2600), the one that's
distributed from the FSF website.  I've also verified this with 21.3,
21.4, and 22.1 from Debian sarge, etch, and lenny.  I've done this with
"-q -no-site-file".

Here's the code in question:

(defun Textile-list-context (textile-list-tag)
  "Return list of HTML tags corresponding to list context (ol, ul)."
  (let ((my-list nil))
    (dolist (this-tag (delete "" (split-string textile-list-tag "")))
      (cond
       ((string= this-tag "#")
        (push "ol" my-list))
       ((string= this-tag "*")
        (push "ul" my-list))))
    my-list))

What gets passed in is a string, like "** ", and the function ought to
iterate through each character, cons an "ol" onto my-list for "#"
characters or a "ul" for "*" characters, ignore everything else, and
return my-list when it's done.

In the scratch buffer, it works.  In my program, it creates a circular
list, represented as (#1="ul" #1#) as I edebug this.

Why is it doing that?  Bypassing the push macro and using something like
(setq my-list (cons "ol" my-list)) doesn't help.  And I can't figure out
why I can't get it to do this from the scratch buffer with what appears
to be the same string.  The Edebug output looks identical, until the
second push of "ul" onto the list, at which point it becomes circular.
-- 
Charles Sebold                                      20th of August, 2008


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: "push" creating circular objects
  2008-08-20 13:25 "push" creating circular objects Charles Sebold
@ 2008-08-20 16:27 ` Charles Sebold
  2008-08-20 19:07   ` Charles Sebold
  2008-08-21 16:14 ` John Paul Wallington
  1 sibling, 1 reply; 14+ messages in thread
From: Charles Sebold @ 2008-08-20 16:27 UTC (permalink / raw)
  To: help-gnu-emacs

On 20 Aug 2008, Charles Sebold wrote:

> Here's the code in question:
>
> (defun Textile-list-context (textile-list-tag)
> "Return list of HTML tags corresponding to list context (ol, ul)."
> (let ((my-list nil))
> (dolist (this-tag (delete "" (split-string textile-list-tag "")))
> (cond
> ((string= this-tag "#")
> (push "ol" my-list))
> ((string= this-tag "*")
> (push "ul" my-list))))
> my-list))

I just changed it from push to append, with no change in behavior:

(defun Textile-list-context (textile-list-tag)
  "Return list of HTML tags corresponding to list context (ol, ul)."
  (let ((my-list nil))
    (dolist (this-tag (delete "" (split-string textile-list-tag "")))
      (cond
       ((string= this-tag "#")
        (setq my-list (append (list "ol") my-list)))
       ((string= this-tag "*")
        (setq my-list (append (list "ul") my-list)))))
    my-list))

Arrgh.  Anybody have any ideas?
-- 
Charles Sebold                                      20th of August, 2008


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: "push" creating circular objects
  2008-08-20 16:27 ` Charles Sebold
@ 2008-08-20 19:07   ` Charles Sebold
  2008-08-20 21:47     ` weber
  2008-08-20 21:50     ` weber
  0 siblings, 2 replies; 14+ messages in thread
From: Charles Sebold @ 2008-08-20 19:07 UTC (permalink / raw)
  To: help-gnu-emacs

On 20 Aug 2008, Charles Sebold wrote:

> I just changed it from push to append, with no change in behavior:

Now I tried something even more radical, a completely different approach
to the problem, just to see what happens.

(defun Textile-list-context (textile-list-tag)
  "Return list of HTML tags corresponding to list context (ol, ul)."
  (let ((my-list (delete " " (delete "" (split-string textile-list-tag "")))))
    (mapcar (lambda (x)
              (cond
               ((string= x "#")
                "ol")
               ((string= x "*")
                "ul")
               (t
                nil))) my-list)))

_It still returns a circular list._

And it still does the right thing, when I call it from a scratch buffer.

Clearly there is something deep about lists that I don't get right now.
-- 
Charles Sebold                                      20th of August, 2008


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: "push" creating circular objects
  2008-08-20 19:07   ` Charles Sebold
@ 2008-08-20 21:47     ` weber
  2008-08-20 21:50     ` weber
  1 sibling, 0 replies; 14+ messages in thread
From: weber @ 2008-08-20 21:47 UTC (permalink / raw)
  To: help-gnu-emacs

On Aug 20, 4:07 pm, Charles Sebold <cseb...@gmail.com> wrote:
> On 20 Aug 2008, Charles Sebold wrote:
>
> > I just changed it from push to append, with no change in behavior:
>
> Now I tried something even more radical, a completely different approach
> to the problem, just to see what happens.
>
> (defun Textile-list-context (textile-list-tag)
>   "Return list of HTML tags corresponding to list context (ol, ul)."
>   (let ((my-list (delete " " (delete "" (split-string textile-list-tag "")))))
>     (mapcar (lambda (x)
>               (cond
>                ((string= x "#")
>                 "ol")
>                ((string= x "*")
>                 "ul")
>                (t
>                 nil))) my-list)))
>
> _It still returns a circular list._
>
> And it still does the right thing, when I call it from a scratch buffer.
>
> Clearly there is something deep about lists that I don't get right now.
> --
> Charles Sebold                                      20th of August, 2008

It works for me on the scratch. As a sidenot, this is how I normally
write these things:

(defun Textile-list-context (str)
  (let ((my-list nil))
	(with-temp-buffer
	  (insert str)
	  (goto-char (point-min))
	  (while (not (eobp))
		(cond
		  ((looking-at "#")
		   (push "ol" my-list))
		  ((looking-at "\*")
		   (push "ul" my-list)))
		(forward-char 1)))
	my-list))

HTH,
hugo


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: "push" creating circular objects
  2008-08-20 19:07   ` Charles Sebold
  2008-08-20 21:47     ` weber
@ 2008-08-20 21:50     ` weber
  2008-08-21 14:12       ` Charles Sebold
  1 sibling, 1 reply; 14+ messages in thread
From: weber @ 2008-08-20 21:50 UTC (permalink / raw)
  To: help-gnu-emacs

On Aug 20, 4:07 pm, Charles Sebold <cseb...@gmail.com> wrote:
> On 20 Aug 2008, Charles Sebold wrote:
>
> > I just changed it from push to append, with no change in behavior:
>
> Now I tried something even more radical, a completely different approach
> to the problem, just to see what happens.
>
> (defun Textile-list-context (textile-list-tag)
>   "Return list of HTML tags corresponding to list context (ol, ul)."
>   (let ((my-list (delete " " (delete "" (split-string textile-list-tag "")))))
>     (mapcar (lambda (x)
>               (cond
>                ((string= x "#")
>                 "ol")
>                ((string= x "*")
>                 "ul")
>                (t
>                 nil))) my-list)))
>
> _It still returns a circular list._
>
> And it still does the right thing, when I call it from a scratch buffer.
>
> Clearly there is something deep about lists that I don't get right now.
> --
> Charles Sebold                                      20th of August, 2008

Minor variation:

(defun test2 (str)
  (let (my-list)
	(with-temp-buffer
	  (insert str)
	  (goto-char (point-min))
	  (while (not (eobp))
		(cond
		  ((= (char-after) ?#)
		   (push "ol" my-list))
		  ((= (char-after) ?*)
		   (push "ul" my-list)))
		(forward-char 1)))
	my-list))

no need to bind my-list to nil too :)

-hugo


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: "push" creating circular objects
  2008-08-20 21:50     ` weber
@ 2008-08-21 14:12       ` Charles Sebold
  2008-08-21 14:25         ` xraysmalevich
  2008-08-21 18:41         ` Pascal J. Bourguignon
  0 siblings, 2 replies; 14+ messages in thread
From: Charles Sebold @ 2008-08-21 14:12 UTC (permalink / raw)
  To: help-gnu-emacs

On Aug 20, 4:50 pm, weber <hug...@gmail.com> wrote:

> Minor variation:
>
> (defun test2 (str)
>   (let (my-list)
>         (with-temp-buffer
>           (insert str)
>           (goto-char (point-min))
>           (while (not (eobp))
>                 (cond
>                   ((= (char-after) ?#)
>                    (push "ol" my-list))
>                   ((= (char-after) ?*)
>                    (push "ul" my-list)))
>                 (forward-char 1)))
>         my-list))
>
> no need to bind my-list to nil too :)

Useful tip, thanks.

Astoundingly I'm still having the same problem, when I run this in the
context of the larger program.  Against the string "** " it returns
the circular list (#1="ul" #1#).  In the scratch buffer it works (same
as with my function earlier).

So, I must be rebinding something else in a bad way, but heck if I
know how.  I'm going to try to trim the whole problem down to a bare
minimum test case and then if I can't figure it out I'll post the
whole thing and ask people to eval and see what they can come up
with.  Thanks for your time.

Charlie


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: "push" creating circular objects
  2008-08-21 14:12       ` Charles Sebold
@ 2008-08-21 14:25         ` xraysmalevich
  2008-08-21 15:23           ` Charles Sebold
  2008-08-21 18:41         ` Pascal J. Bourguignon
  1 sibling, 1 reply; 14+ messages in thread
From: xraysmalevich @ 2008-08-21 14:25 UTC (permalink / raw)
  To: help-gnu-emacs

On Aug 21, 10:12 am, Charles Sebold <cseb...@gmail.com> wrote:
> On Aug 20, 4:50 pm, weber <hug...@gmail.com> wrote:
>
>
>
> > Minor variation:
>
> > (defun test2 (str)
> >   (let (my-list)
> >         (with-temp-buffer
> >           (insert str)
> >           (goto-char (point-min))
> >           (while (not (eobp))
> >                 (cond
> >                   ((= (char-after) ?#)
> >                    (push "ol" my-list))
> >                   ((= (char-after) ?*)
> >                    (push "ul" my-list)))
> >                 (forward-char 1)))
> >         my-list))
>
> > no need to bind my-list to nil too :)
>
> Useful tip, thanks.
>
> Astoundingly I'm still having the same problem, when I run this in the
> context of the larger program.  Against the string "** " it returns
> the circular list (#1="ul" #1#).  In the scratch buffer it works (same
> as with my function earlier).
>
> So, I must be rebinding something else in a bad way, but heck if I
> know how.  I'm going to try to trim the whole problem down to a bare
> minimum test case and then if I can't figure it out I'll post the
> whole thing and ask people to eval and see what they can come up
> with.  Thanks for your time.
>
> Charlie

To check if you've rebound a function, try running emacs without the
init file (emacs -q) and see if that changes this behavior.


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: "push" creating circular objects
  2008-08-21 14:25         ` xraysmalevich
@ 2008-08-21 15:23           ` Charles Sebold
  0 siblings, 0 replies; 14+ messages in thread
From: Charles Sebold @ 2008-08-21 15:23 UTC (permalink / raw)
  To: help-gnu-emacs

On 21 Aug 2008, xraysmalevich@gmail.com wrote:

> To check if you've rebound a function, try running emacs without the
> init file (emacs -q) and see if that changes this behavior.

Yeah, I mentioned at the top that I tried that (and went to clean
systems elsewhere without my .emacs and so forth and tried it, too).
No, whatever is happening, it's happening in the midst of the program
that's calling this function, I guess.  I don't consciously rebind
anything elsewhere in the file.  I've narrowed it down to one line, but
it's going to take some serious debugging to figure out what that has to
do with anything.  I will post when I've figured it out, though (or when
I've given up, at which point I'll post the test code that produces the
problem and yell for help again).
-- 
Charles Sebold                                      21st of August, 2008


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: "push" creating circular objects
  2008-08-20 13:25 "push" creating circular objects Charles Sebold
  2008-08-20 16:27 ` Charles Sebold
@ 2008-08-21 16:14 ` John Paul Wallington
  2008-08-21 16:49   ` Charles Sebold
  1 sibling, 1 reply; 14+ messages in thread
From: John Paul Wallington @ 2008-08-21 16:14 UTC (permalink / raw)
  To: help-gnu-emacs

Charles Sebold <csebold@gmail.com> writes:

> In the scratch buffer, it works.  In my program, it creates a circular
> list, represented as (#1="ul" #1#) as I edebug this.

Hey Charlie, it's great to see you posting on the Emacs newsgroups!

I'm not certain what's going on.  Are you sure that representation means
circular structure?  Or is it merely labelling the object "ul" for
future reference then referring to it?  (See (elisp)Circular Objects.)

Also, how about consing up the strings with (string ?u ?l) or somesuch
to avoid 'em being treated as the same?


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: "push" creating circular objects
  2008-08-21 16:14 ` John Paul Wallington
@ 2008-08-21 16:49   ` Charles Sebold
  2008-08-23 11:43     ` Nikolaj Schumacher
  2008-08-23 12:17     ` Pascal J. Bourguignon
  0 siblings, 2 replies; 14+ messages in thread
From: Charles Sebold @ 2008-08-21 16:49 UTC (permalink / raw)
  To: help-gnu-emacs

On 21 Aug 2008, John Paul Wallington wrote:

> I'm not certain what's going on.  Are you sure that representation
> means circular structure?  Or is it merely labelling the object "ul"
> for future reference then referring to it?  (See (elisp)Circular
> Objects.)

I am likely confused.  Is this not the same thing?

Oh.  I guess it isn't.  This is one of the insights I needed, I think.

> Also, how about consing up the strings with (string ?u ?l) or somesuch
> to avoid 'em being treated as the same?

I'll give that a try... yeah, that fixed it.  I'm surprised I have to do
this, though.  Why are they being treated as the same?

Knowing this, I replaced (string ?u ?l) with (copy-sequence "ul") and so
forth, and got the same result.

Thanks very much for this.  But I'm surprised I have to do it.
-- 
Charles Sebold                                      21st of August, 2008


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: "push" creating circular objects
  2008-08-21 14:12       ` Charles Sebold
  2008-08-21 14:25         ` xraysmalevich
@ 2008-08-21 18:41         ` Pascal J. Bourguignon
  2008-08-21 20:25           ` Charles Sebold
  1 sibling, 1 reply; 14+ messages in thread
From: Pascal J. Bourguignon @ 2008-08-21 18:41 UTC (permalink / raw)
  To: help-gnu-emacs

Charles Sebold <csebold@gmail.com> writes:

> On Aug 20, 4:50 pm, weber <hug...@gmail.com> wrote:
>
>> Minor variation:
>>
>> (defun test2 (str)
>>   (let (my-list)
>>         (with-temp-buffer
>>           (insert str)
>>           (goto-char (point-min))
>>           (while (not (eobp))
>>                 (cond
>>                   ((= (char-after) ?#)
>>                    (push "ol" my-list))
>>                   ((= (char-after) ?*)
>>                    (push "ul" my-list)))
>>                 (forward-char 1)))
>>         my-list))
>>
>> no need to bind my-list to nil too :)
>
> Useful tip, thanks.
>
> Astoundingly I'm still having the same problem, when I run this in the
> context of the larger program.  Against the string "** " it returns
> the circular list (#1="ul" #1#).  In the scratch buffer it works (same
> as with my function earlier).

This is not a circular list, so whatever you may try or infer from
that will be wrong.


> So, I must be rebinding something else in a bad way, but heck if I
> know how.  I'm going to try to trim the whole problem down to a bare
> minimum test case and then if I can't figure it out I'll post the
> whole thing and ask people to eval and see what they can come up
> with.  Thanks for your time.

(defun circular-length (list)
  "LIST must be either a proper-list or a circular-list, not a dotted-list.
RETURN: the total length ; the length of the stem ; the length of the circle.
"
  (let ((indexes (make-hash-table)))
    (loop
       for i from 0
       for current on list
       do (let ((index (gethash current indexes)))
             (if index
                 ;; found loop
                 (return (values i index (- i index)))
                 (setf (gethash current indexes) i)))
       finally (return (values i)))))


(circular-length '(a b c d e))
--> (5)

(circular-length '(#1=a b #1# d #1#))
--> (5)

(circular-length '#1=(a b c d e . #1#))
--> (5 0 5)

(circular-length '(a b . #1=(c d e . #1#)))
--> (5 2 3)


Since (#1="ul" #1#) is not a circular list, you can print it without print-circle:

(defun print-safely (object)
   (let ((print-circle  (rest (circular-length object))))
      (print object)))

(print-safely '(a b c d e))
prints: (a b c d e)
       
(print-safely  '#1=(a b c d e . #1#))
prints: #1=(a b c d e . #1#)

(print-safely '(#1=a b #1# d #1#))
prints: (a b a d a)

(print-safely '(#1="ul" #1#))
prints: ("ul" "ul")


So what's the difference between ("ul" "ul") and (#1="ul" #1#)?

It's that in ("ul" "ul") we have two different string objects that
happen to contain the same characters in the same order, while in
(#1="ul" #1#) we have the same string object twice:

(let ((items '(#1="ul" #1#)))
   (eq (first items) (second items)))
--> t

(let ((items '("ul" "ul")))
   (eq (first items) (second items)))
--> nil



-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

ADVISORY: There is an extremely small but nonzero chance that,
through a process known as "tunneling," this product may
spontaneously disappear from its present location and reappear at
any random place in the universe, including your neighbor's
domicile. The manufacturer will not be responsible for any damages
or inconveniences that may result.


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: "push" creating circular objects
  2008-08-21 18:41         ` Pascal J. Bourguignon
@ 2008-08-21 20:25           ` Charles Sebold
  0 siblings, 0 replies; 14+ messages in thread
From: Charles Sebold @ 2008-08-21 20:25 UTC (permalink / raw)
  To: help-gnu-emacs

On 21 Aug 2008, Pascal J. Bourguignon wrote:

> This is not a circular list, so whatever you may try or infer from
> that will be wrong.

Yeah, one of the earlier posters pointed out that I hadn't read that
part of the Elisp manual carefully enough, and I was indeed wrong.
-- 
Charles Sebold                                      21st of August, 2008


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: "push" creating circular objects
  2008-08-21 16:49   ` Charles Sebold
@ 2008-08-23 11:43     ` Nikolaj Schumacher
  2008-08-23 12:17     ` Pascal J. Bourguignon
  1 sibling, 0 replies; 14+ messages in thread
From: Nikolaj Schumacher @ 2008-08-23 11:43 UTC (permalink / raw)
  To: help-gnu-emacs

Charles Sebold <csebold@gmail.com> wrote:

>> Also, how about consing up the strings with (string ?u ?l) or somesuch
>> to avoid 'em being treated as the same?
>
> I'll give that a try... yeah, that fixed it.  I'm surprised I have to do
> this, though.  Why are they being treated as the same?

Because they /are/ the same.  A string in your code is a constant.  A
reference, not a copy, is returned each time.

> Knowing this, I replaced (string ?u ?l) with (copy-sequence "ul") and so
> forth, and got the same result.
>
> Thanks very much for this.  But I'm surprised I have to do it.

You don't have to do it.  As long as you treat the strings as read-only,
you're fine.  It's generally a good idea never to manipulate strings
directly:

(defun get-a-string ()
  "ab")

(get-a-string) => "ab"

(aset (get-a-string) 0 ?b)

(get-a-string) => "bb" (!)



regards,
Nikolaj Schumacher




^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: "push" creating circular objects
  2008-08-21 16:49   ` Charles Sebold
  2008-08-23 11:43     ` Nikolaj Schumacher
@ 2008-08-23 12:17     ` Pascal J. Bourguignon
  1 sibling, 0 replies; 14+ messages in thread
From: Pascal J. Bourguignon @ 2008-08-23 12:17 UTC (permalink / raw)
  To: help-gnu-emacs

Charles Sebold <csebold@gmail.com> writes:

> On 21 Aug 2008, John Paul Wallington wrote:
>
>> I'm not certain what's going on.  Are you sure that representation
>> means circular structure?  Or is it merely labelling the object "ul"
>> for future reference then referring to it?  (See (elisp)Circular
>> Objects.)
>
> I am likely confused.  Is this not the same thing?
>
> Oh.  I guess it isn't.  This is one of the insights I needed, I think.
>
>> Also, how about consing up the strings with (string ?u ?l) or somesuch
>> to avoid 'em being treated as the same?
>
> I'll give that a try... yeah, that fixed it.  I'm surprised I have to do
> this, though.  Why are they being treated as the same?
>
> Knowing this, I replaced (string ?u ?l) with (copy-sequence "ul") and so
> forth, and got the same result.
>
> Thanks very much for this.  But I'm surprised I have to do it.


The syntax ##/#= is used to be able to distinguish these cases:

+-----------------------+   +-----------------------+
| (#1="ul" #1#)         |   | ("ul" "ul")           |
|                       |   |                       |
| +---+---+   +---+---+ |   | +---+---+   +---+---+ |
| | * | * |-->| * |nil| |   | | * | * |-->| * |nil| |
| +---+---+   +---+---+ |   | +---+---+   +---+---+ |
|   |           |       |   |   |           |       |
|   |  +--------+       |   |   v           v       |
|   |  |                |   | +------+    +------+  |
|   v  v                |   | | "ul" |    | "ul" |  |
| +------+              |   | +------+    +------+  |
| | "ul" |              |   +-----------------------+
| +------+              |
+-----------------------+


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

"I have challenged the entire quality assurance team to a Bat-Leth
contest.  They will not concern us again."


^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2008-08-23 12:17 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-08-20 13:25 "push" creating circular objects Charles Sebold
2008-08-20 16:27 ` Charles Sebold
2008-08-20 19:07   ` Charles Sebold
2008-08-20 21:47     ` weber
2008-08-20 21:50     ` weber
2008-08-21 14:12       ` Charles Sebold
2008-08-21 14:25         ` xraysmalevich
2008-08-21 15:23           ` Charles Sebold
2008-08-21 18:41         ` Pascal J. Bourguignon
2008-08-21 20:25           ` Charles Sebold
2008-08-21 16:14 ` John Paul Wallington
2008-08-21 16:49   ` Charles Sebold
2008-08-23 11:43     ` Nikolaj Schumacher
2008-08-23 12:17     ` Pascal J. Bourguignon

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.