From: dpapathanasiou
Subject: Hashtable iteration: performing early breaks
Date: 
Message-ID: <1140625634.513239.123940@g44g2000cwa.googlegroups.com>
When using maphash, is there a way to break off the iteration early if
a condition is met?

As an example, I have this function that scans all the values in a hash
table for a specific property (the property either exists in one value,
or it's not in the hash at all):

(defun confirm-loaded (n-val)
  "Scan the current contents of *data* and confirm whether or not n-val
already exists."
  (let ((match-key nil))
    (maphash #'(lambda (k v)
		 (when (equalp n-val v)
		   (setf match-key k)))
	     *data*)
    match-key))

This does what I want it to do, but in the event of a match, it's
really unnecessary for the mapash iteration to continue, so is there a
way to do this more efficiently?

From: Christophe Rhodes
Subject: Re: Hashtable iteration: performing early breaks
Date: 
Message-ID: <sq8xs3z70x.fsf@cam.ac.uk>
"dpapathanasiou" <···················@gmail.com> writes:

> This does what I want it to do, but in the event of a match, it's
> really unnecessary for the mapash iteration to continue, so is there a
> way to do this more efficiently?

Block names have lexical scope and dynamic extent, so you can use them
to return from functions passed as arguments (but not stored and later
reused).

(defun confirm-loaded (n-val)
  "Scan the current contents of *data* and confirm whether or not n-val
already exists."
  (maphash #'(lambda (k v)
               (when (equalp n-val v)
                 (return-from confirm-loaded k)))
	   *data*))

(untested)

Christophe
From: Frode Vatvedt Fjeld
Subject: Re: Hashtable iteration: performing early breaks
Date: 
Message-ID: <2hek1v2gzr.fsf@vserver.cs.uit.no>
"dpapathanasiou" <···················@gmail.com> writes:

> (defun confirm-loaded (n-val)
>   "Scan the current contents of *data* and confirm whether or not n-val
> already exists."
>   (let ((match-key nil))
>     (maphash #'(lambda (k v)
> 		 (when (equalp n-val v)
> 		   (setf match-key k)))
> 	     *data*)
>     match-key))

Any old control jump construct will do. In addition to block return
that Christophe described, a multi-paradigm languange of course also
supports pre-structured-programming-paradigm constructs such as "goto"
(this code also untested):

(defun confirm-loaded (n-val)
  "Scan the current contents of *data* and confirm whether or not n-val
already exists."
  (let ((match-key nil))
    (prog
       (maphash #'(lambda (k v)
                    (when (equalp n-val v)
                      (setf match-key k)
                      (go done)))
                *data*)
      done)
    match-key))

-- 
Frode Vatvedt Fjeld
From: Barry Margolin
Subject: Re: Hashtable iteration: performing early breaks
Date: 
Message-ID: <barmar-20216E.23550422022006@comcast.dca.giganews.com>
In article <··············@vserver.cs.uit.no>,
 Frode Vatvedt Fjeld <······@cs.uit.no> wrote:

> "dpapathanasiou" <···················@gmail.com> writes:
> 
> > (defun confirm-loaded (n-val)
> >   "Scan the current contents of *data* and confirm whether or not n-val
> > already exists."
> >   (let ((match-key nil))
> >     (maphash #'(lambda (k v)
> > 		 (when (equalp n-val v)
> > 		   (setf match-key k)))
> > 	     *data*)
> >     match-key))
> 
> Any old control jump construct will do. In addition to block return
> that Christophe described, a multi-paradigm languange of course also
> supports pre-structured-programming-paradigm constructs such as "goto"
> (this code also untested):
> 
> (defun confirm-loaded (n-val)
>   "Scan the current contents of *data* and confirm whether or not n-val
> already exists."
>   (let ((match-key nil))
>     (prog
>        (maphash #'(lambda (k v)
>                     (when (equalp n-val v)
>                       (setf match-key k)
>                       (go done)))
>                 *data*)
>       done)
>     match-key))

Except that you misspelled TAGBODY.  PROG starts with a list of local 
variables.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Frode Vatvedt Fjeld
Subject: Re: Hashtable iteration: performing early breaks
Date: 
Message-ID: <2h7j7m2s7h.fsf@vserver.cs.uit.no>
Barry Margolin <······@alum.mit.edu> writes:

> Except that you misspelled TAGBODY.  PROG starts with a list of
> local variables.

That's right. Thanks.

-- 
Frode Vatvedt Fjeld
From: Alex Mizrahi
Subject: Re: Hashtable iteration: performing early breaks
Date: 
Message-ID: <43fdd221$0$15791$14726298@news.sunsite.dk>
(message (Hello 'dpapathanasiou)
(you :wrote  :on '(22 Feb 2006 08:27:14 -0800))
(

 d> (defun confirm-loaded (n-val)
 d>   "Scan the current contents of *data* and confirm whether or not n-val
 d> already exists."
 d>   (let ((match-key nil))
 d>     (maphash #'(lambda (k v)
 d>    (when (equalp n-val v)
 d>      (setf match-key k)))
 d>       *data*)
 d>     match-key))

 d> This does what I want it to do, but in the event of a match, it's
 d> really unnecessary for the mapash iteration to continue, so is there a
 d> way to do this more efficiently?

unless you absolutely want to do it with maphash it would be much simplier 
if you do

(defun confirm-load (n-val)
    (loop for k being each hash-key of *data* using (hash-value v)
        if (equalp n-val v) return k))

)
(With-best-regards '(Alex Mizrahi) :aka 'killer_storm)
"People who lust for the Feel of keys on their fingertips (c) Inity")