unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
From: pjb@informatimago.com (Pascal J. Bourguignon)
To: help-gnu-emacs@gnu.org
Subject: Re: "push" creating circular objects
Date: Thu, 21 Aug 2008 20:41:27 +0200	[thread overview]
Message-ID: <87pro2ciso.fsf@hubble.informatimago.com> (raw)
In-Reply-To: 4990de62-178c-478a-9362-cedc660f9335@j22g2000hsf.googlegroups.com

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.


  parent reply	other threads:[~2008-08-21 18:41 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87pro2ciso.fsf@hubble.informatimago.com \
    --to=pjb@informatimago.com \
    --cc=help-gnu-emacs@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).