* Re: cl-dolist, dolist, cl-return,
[not found] <mailman.6511.1436314595.904.help-gnu-emacs@gnu.org>
@ 2015-07-08 3:25 ` Pascal J. Bourguignon
2015-07-08 10:17 ` Emanuel Berg
0 siblings, 1 reply; 17+ messages in thread
From: Pascal J. Bourguignon @ 2015-07-08 3:25 UTC (permalink / raw)
To: help-gnu-emacs
Emanuel Berg <embe8573@student.uu.se> writes:
> I just wrote the below code.
>
> `cl-return' works for `cl-dolist', but not for
> `dolist' because it hasn't an "implicit nil block ...
> established around the loop". And there is no
> `return'! I think this "cl-" stuff is confusing.
> Anyone cares to explain?
emacs lisp is too limited, it lack Common Lisp packages or any other way
of namespace. Therefore people have to use prefixes instead of package
names.
> By the way, I know there are one zillion loops
> in Lisp. What is the conventional way to
>
> 1. iterate a list
> 2. until some condition is met for some element
> 3. then break, to speak in C
>
> ?
(loop for item in list
until (some-condition-p item))
> And: With [cl-]dolist, if the list is an expression
> and not an atom, does that get evaluated once, or does
> it happen every iteration like, say, a string length
> test would, again in C?
Once.
> Also: why isn't there a "neq"?
(defun neq (x y) (not (eq x y))
; now there is.
--
__Pascal Bourguignon__ http://www.informatimago.com/
“The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.” -- Carl Bass CEO Autodesk
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: cl-dolist, dolist, cl-return,
2015-07-08 3:25 ` cl-dolist, dolist, cl-return, Pascal J. Bourguignon
@ 2015-07-08 10:17 ` Emanuel Berg
2015-07-08 14:02 ` Drew Adams
0 siblings, 1 reply; 17+ messages in thread
From: Emanuel Berg @ 2015-07-08 10:17 UTC (permalink / raw)
To: help-gnu-emacs
"Pascal J. Bourguignon" <pjb@informatimago.com>
writes:
> (loop for item in list until (some-condition-p
> item))
These loops are brilliant! Only there are so many,
which overlap... Perhaps one could draw a
"periodic table" of Lisp loops. I remember something
like that from the book "Land of Lisp", but I read
that at the library so I can't check.
Good book, anyway.
@book{land-of-lisp,
title = {Land of Lisp},
author = {Conrad Barski},
publisher = {No Starch},
year = 2010,
ISBN = 1593272812
}
In C there are what I remember only three loops (if
you don't count recursion, or gotos for that matter) -
the familiar for, while, and 'do while'. It is
possible to construct all (?) loops with these, but
I like the Lisp way more where it can be expressed in
syntax, not merely constructed in code.
The loop finally turned up like this:
(cl-loop for b in (erc-buffer-list)
when (neq b (current-buffer)) do ...
--
underground experts united
http://user.it.uu.se/~embe8573
^ permalink raw reply [flat|nested] 17+ messages in thread
* RE: cl-dolist, dolist, cl-return,
2015-07-08 10:17 ` Emanuel Berg
@ 2015-07-08 14:02 ` Drew Adams
2015-07-08 23:10 ` Emanuel Berg
[not found] ` <mailman.6588.1436397019.904.help-gnu-emacs@gnu.org>
0 siblings, 2 replies; 17+ messages in thread
From: Drew Adams @ 2015-07-08 14:02 UTC (permalink / raw)
To: Emanuel Berg, help-gnu-emacs
> there are so many, which overlap...
> In C there are what I remember only three loops (if
> you don't count recursion, or gotos for that matter) -
> the familiar for, while, and 'do while'.
Because it is easy in Lisp to define your own so-called "control
structures".
So people do. And they share them. And they keep defining them
and sharing them. And some of them get large communities of
adherents or get established as "standard" or conventional for a
given Lisp dialect.
This is different from languages where certain structures are
provided as defining the language, and you must learn them and
stick to them.
You like `do'. I like `while'.
You like `loop'. I like `iterate'.
Tomayto, tomahto, potayto, potahto.
Let's call the whole thing Lisp.
(https://common-lisp.net/project/iterate/doc/index.html)
^ permalink raw reply [flat|nested] 17+ messages in thread
* cl-dolist, dolist, cl-return,
@ 2015-07-08 0:14 Emanuel Berg
2015-07-08 0:31 ` John Mastro
0 siblings, 1 reply; 17+ messages in thread
From: Emanuel Berg @ 2015-07-08 0:14 UTC (permalink / raw)
To: help-gnu-emacs
I just wrote the below code.
`cl-return' works for `cl-dolist', but not for
`dolist' because it hasn't an "implicit nil block ...
established around the loop". And there is no
`return'! I think this "cl-" stuff is confusing.
Anyone cares to explain?
By the way, I know there are one zillion loops
in Lisp. What is the conventional way to
1. iterate a list
2. until some condition is met for some element
3. then break, to speak in C
?
And: With [cl-]dolist, if the list is an expression
and not an atom, does that get evaluated once, or does
it happen every iteration like, say, a string length
test would, again in C?
Also: why isn't there a "neq"?
Keep it up!
;; whole file: http://user.it.uu.se/~embe8573/conf/emacs-init/erc-my.el
(defun neq (a b)
(not (eq a b) ))
(defun erc-kill-buffer-stay ()
"Close the current ERC buffer (e.g., to leave a channel)
but stay in ERC if possible."
(interactive)
(cl-dolist (b (erc-buffer-list))
(when (neq (current-buffer) b)
(erc-cmd-LEAVE "")
(switch-to-buffer b)
(cl-return) )))
--
underground experts united
http://user.it.uu.se/~embe8573
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: cl-dolist, dolist, cl-return,
2015-07-08 0:14 Emanuel Berg
@ 2015-07-08 0:31 ` John Mastro
2015-07-08 3:09 ` Stefan Monnier
2015-07-08 10:23 ` Emanuel Berg
0 siblings, 2 replies; 17+ messages in thread
From: John Mastro @ 2015-07-08 0:31 UTC (permalink / raw)
To: help-gnu-emacs@gnu.org
Emanuel Berg <embe8573@student.uu.se> wrote:
> I just wrote the below code.
>
> `cl-return' works for `cl-dolist', but not for
> `dolist' because it hasn't an "implicit nil block ...
> established around the loop". And there is no
> `return'! I think this "cl-" stuff is confusing.
> Anyone cares to explain?
The `cl' prefix stands for Common Lisp, from whence the functionality
there came (or was inspired by).
> By the way, I know there are one zillion loops
> in Lisp. What is the conventional way to
>
> 1. iterate a list
> 2. until some condition is met for some element
> 3. then break, to speak in C
I don't know if there's one most-conventional way, but here are a couple
options:
;; Use `catch' and `throw'
(catch 'done
(dolist (elt list)
(do-something elt)
(when (some-condition)
(throw 'done t))))
;; Use `while' and a condition variable
(let (done)
(while (and list (not done))
(let ((elt (pop list)))
(do-something elt)
(when (some-condition)
(setq done t)))))
> And: With [cl-]dolist, if the list is an expression
> and not an atom, does that get evaluated once, or does
> it happen every iteration like, say, a string length
> test would, again in C?
Just once. Besides inefficiency, evaluating it every time would lead to
wrong results.
> Also: why isn't there a "neq"?
I don't know the real answer, but it may be because then people would
expect `n=', `neql', `nequal', `nequalp', `nstring=', and so on. Or
perhaps some would have a "not variant" and others wouldn't, in which
case we'd need to remember which did and didn't. IMHO it's simpler and
cleaner to have a single `not' which can be used with any predicate as
needed.
--
john
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: cl-dolist, dolist, cl-return,
2015-07-08 0:31 ` John Mastro
@ 2015-07-08 3:09 ` Stefan Monnier
2015-07-08 10:25 ` Emanuel Berg
2015-07-08 10:23 ` Emanuel Berg
1 sibling, 1 reply; 17+ messages in thread
From: Stefan Monnier @ 2015-07-08 3:09 UTC (permalink / raw)
To: help-gnu-emacs
> Just once. Besides inefficiency, evaluating it every time would lead to
> wrong results.
Right, the question often makes sense for loop boundary computations,
but for this specific case, if you think enough about it, it makes no
sense to re-evaluate it: you'd have to use an index into the list,
and at each iteration, increment the index, recompute the list, and do
an (nth <index> <list>), which would overall be *really* inefficient.
Stefan
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: cl-dolist, dolist, cl-return,
2015-07-08 3:09 ` Stefan Monnier
@ 2015-07-08 10:25 ` Emanuel Berg
2015-07-08 14:44 ` Stefan Monnier
0 siblings, 1 reply; 17+ messages in thread
From: Emanuel Berg @ 2015-07-08 10:25 UTC (permalink / raw)
To: help-gnu-emacs
Stefan Monnier <monnier@iro.umontreal.ca> writes:
>> Just once. Besides inefficiency, evaluating it
>> every time would lead to wrong results.
>
> Right, the question often makes sense for loop
> boundary computations, but for this specific case,
> if you think enough about it, it makes no sense to
> re-evaluate it: you'd have to use an index into the
> list, and at each iteration, increment the index,
> recompute the list, and do an (nth <index> <list>),
> which would overall be *really* inefficient.
No, of course I don't want to re-evaluate it! I didn't
think it did re-evaluate, but I wasn't sure so
I thought about putting it in a `let' before
asking here. It is good I don't have to.
--
underground experts united
http://user.it.uu.se/~embe8573
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: cl-dolist, dolist, cl-return,
2015-07-08 10:25 ` Emanuel Berg
@ 2015-07-08 14:44 ` Stefan Monnier
2015-07-08 23:19 ` Emanuel Berg
0 siblings, 1 reply; 17+ messages in thread
From: Stefan Monnier @ 2015-07-08 14:44 UTC (permalink / raw)
To: help-gnu-emacs
>> Right, the question often makes sense for loop boundary computations,
>> but for this specific case, if you think enough about it, it makes no
>> sense to re-evaluate it: you'd have to use an index into the list,
>> and at each iteration, increment the index, recompute the list, and
>> do an (nth <index> <list>), which would overall be
>> *really* inefficient.
> No, of course I don't want to re-evaluate it! I didn't
My point was that the re-evaluation part would be just a side-problem:
even if your expression is a mere variable (so re-evaluating it is very
cheap), the need to use `nth' at each step would force an O(N^2)
complexity to this loop.
Stefan
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: cl-dolist, dolist, cl-return,
2015-07-08 14:44 ` Stefan Monnier
@ 2015-07-08 23:19 ` Emanuel Berg
2015-07-09 1:49 ` John Mastro
2015-07-10 16:57 ` Stefan Monnier
0 siblings, 2 replies; 17+ messages in thread
From: Emanuel Berg @ 2015-07-08 23:19 UTC (permalink / raw)
To: help-gnu-emacs
Stefan Monnier <monnier@iro.umontreal.ca> writes:
>> No, of course I don't want to re-evaluate it!
>
> My point was that the re-evaluation part would be
> just a side-problem: even if your expression is
> a mere variable (so re-evaluating it is very cheap),
> the need to use `nth' at each step would force an
> O(N^2) complexity to this loop.
You mean `nth' is linear, and `dotimes' is linear, so
the whole thing is linear**2 = quadratic?
But I'm not using nth - probably you misread "neq".
(Ha! - maybe a reason not to do it just presented
itself...)
Here is the code, which is linear, O(n), unless
there is a hidden nth somewhere...
(defun neq (a b)
(not (eq a b) ))
(defun erc-kill-buffer-stay ()
"Close the current ERC buffer (e.g., to leave a channel)
but stay in ERC if possible."
(interactive)
(cl-loop for b in (erc-buffer-list)
when (neq b (current-buffer)) do
(erc-cmd-LEAVE "")
(switch-to-buffer b) ))
--
underground experts united
http://user.it.uu.se/~embe8573
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: cl-dolist, dolist, cl-return,
2015-07-08 23:19 ` Emanuel Berg
@ 2015-07-09 1:49 ` John Mastro
2015-07-09 22:00 ` Emanuel Berg
[not found] ` <mailman.6636.1436479362.904.help-gnu-emacs@gnu.org>
2015-07-10 16:57 ` Stefan Monnier
1 sibling, 2 replies; 17+ messages in thread
From: John Mastro @ 2015-07-09 1:49 UTC (permalink / raw)
To: help-gnu-emacs@gnu.org
Emanuel Berg <embe8573@student.uu.se> wrote:
>> My point was that the re-evaluation part would be
>> just a side-problem: even if your expression is
>> a mere variable (so re-evaluating it is very cheap),
>> the need to use `nth' at each step would force an
>> O(N^2) complexity to this loop.
>
> You mean `nth' is linear, and `dotimes' is linear, so
> the whole thing is linear**2 = quadratic?
>
> But I'm not using nth - probably you misread "neq".
> (Ha! - maybe a reason not to do it just presented
> itself...)
>
> Here is the code, which is linear, O(n), unless
> there is a hidden nth somewhere...
Stefan means that if, given `(dolist (x (list 1 2 3)) ...)', you
evaluated `(list 1 2 3)' on every iteration you would end up doing
something the moral equivalent of
(setq elt (nth 0 (list 1 2 3))) ;; first iteration
(setq elt (nth 1 (list 1 2 3))) ;; second iteration
and so on, rather than
(let ((the-list (list 1 2 3)))
(setq elt (pop the-list)) ;; first iteration
(setq elt (pop the-list))) ;; second iteration
The latter case (which is how things really work) is obviously much
more efficient, because the former case needlessly re-walks
the list.
--
john
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: cl-dolist, dolist, cl-return,
2015-07-09 1:49 ` John Mastro
@ 2015-07-09 22:00 ` Emanuel Berg
[not found] ` <mailman.6636.1436479362.904.help-gnu-emacs@gnu.org>
1 sibling, 0 replies; 17+ messages in thread
From: Emanuel Berg @ 2015-07-09 22:00 UTC (permalink / raw)
To: help-gnu-emacs
John Mastro <john.b.mastro@gmail.com> writes:
> Stefan means that if, given `(dolist (x (list 1 2
> 3)) ...)', you evaluated `(list 1 2 3)' on every
> iteration you would end up doing something the moral
> equivalent of
>
> (setq elt (nth 0 (list 1 2 3))) ;; first iteration
> (setq elt (nth 1 (list 1 2 3))) ;; second iteration
>
> and so on, rather than
>
> (let ((the-list (list 1 2 3))) (setq elt (pop
> the-list)) ;; first iteration (setq elt (pop
> the-list))) ;; second iteration
>
> The latter case (which is how things really work) is
> obviously much more efficient, because the former
> case needlessly re-walks the list.
Yes, there is no doubt in my mind the list shouldn't
be evaluated on each iteration, for I don't know how
many reasons!
The reason I asked is the C for loop, which looks like
this in C99 style:
for (int i = 0; i < a_size; i++) { a[i] = ... ; }
But sometimes, people are tempted to do like this:
for (int i = 0; i < sizeof(a)/sizeof(a[0]); i++) {
a[i] = ... ;
}
In the real world probably it won't matter one bit
most of the time but in the world of programming the
craftsman don't want the computation to take place at
every iteration, especially since the property
doesn't change!
If you don't have to deal with this in `dolist' I'm
happy :)
--
underground experts united
http://user.it.uu.se/~embe8573
^ permalink raw reply [flat|nested] 17+ messages in thread
[parent not found: <mailman.6636.1436479362.904.help-gnu-emacs@gnu.org>]
* Re: cl-dolist, dolist, cl-return,
[not found] ` <mailman.6636.1436479362.904.help-gnu-emacs@gnu.org>
@ 2015-07-10 18:44 ` Barry Margolin
2015-07-11 18:52 ` Emanuel Berg
0 siblings, 1 reply; 17+ messages in thread
From: Barry Margolin @ 2015-07-10 18:44 UTC (permalink / raw)
To: help-gnu-emacs
In article <mailman.6636.1436479362.904.help-gnu-emacs@gnu.org>,
Emanuel Berg <embe8573@student.uu.se> wrote:
> The reason I asked is the C for loop, which looks like
> this in C99 style:
>
> for (int i = 0; i < a_size; i++) { a[i] = ... ; }
>
> But sometimes, people are tempted to do like this:
>
> for (int i = 0; i < sizeof(a)/sizeof(a[0]); i++) {
> a[i] = ... ;
> }
You're making the wrong analogy. The list parameter of dolist is
equivalent to the initialization part of the "for", not the repetition
or update parts. So if you did:
for (int i = func(x); ...)
you wouldn't expect func(x) to be called every time through the loop,
would you?
The C equivalent of dolist is:
for (list_ptr* p = <list expr>; p; p = p->next) {
...
}
As above, you wouldn't expect <list expr> to be evaluated each time.
--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: cl-dolist, dolist, cl-return,
2015-07-10 18:44 ` Barry Margolin
@ 2015-07-11 18:52 ` Emanuel Berg
0 siblings, 0 replies; 17+ messages in thread
From: Emanuel Berg @ 2015-07-11 18:52 UTC (permalink / raw)
To: help-gnu-emacs
Barry Margolin <barmar@alum.mit.edu> writes:
>> The reason I asked is the C for loop, which looks
>> like this in C99 style:
>>
>> for (int i = 0; i < a_size; i++) { a[i] = ... ; }
>>
>> But sometimes, people are tempted to do like this:
>>
>> for (int i = 0; i < sizeof(a)/sizeof(a[0]); i++) { a[i] = ... ; }
>
> You're making the wrong analogy. The list parameter of
> dolist is equivalent to the initialization part of
> the "for", not the repetition or update parts. So if
> you did:
>
> for (int i = func(x); ...)
>
> you wouldn't expect func(x) to be called every time
> through the loop, would you?
>
> The C equivalent of dolist is:
>
> for (list_ptr* p = <list expr>; p; p = p->next) { ...
> }
>
> As above, you wouldn't expect <list expr> to be
> evaluated each time.
That's exactly right!
Very nice - you even put the asterisk with the
variable type and not its name.
I was about to say this discussion is meaningless as
several posts ago it was clear the list isn't
re-evaluated, which was the intuition as well, but now
I've changed my mind, when you put things this way,
please go on.
--
underground experts united
http://user.it.uu.se/~embe8573
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: cl-dolist, dolist, cl-return,
2015-07-08 23:19 ` Emanuel Berg
2015-07-09 1:49 ` John Mastro
@ 2015-07-10 16:57 ` Stefan Monnier
1 sibling, 0 replies; 17+ messages in thread
From: Stefan Monnier @ 2015-07-10 16:57 UTC (permalink / raw)
To: help-gnu-emacs
> But I'm not using nth - probably you misread "neq".
No, I'm talking about the code used internally by dolist. If the list
over which we iterate were re-computed each time, then to find the "next"
element, we'd need to use nth at each iteration.
IOW it's a different problem from the re-computation of array bounds at
each iteration (which would be inefficient in itself but wouldn't impose
additional inefficiencies on the rest of the loop).
Stefan
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: cl-dolist, dolist, cl-return,
2015-07-08 0:31 ` John Mastro
2015-07-08 3:09 ` Stefan Monnier
@ 2015-07-08 10:23 ` Emanuel Berg
1 sibling, 0 replies; 17+ messages in thread
From: Emanuel Berg @ 2015-07-08 10:23 UTC (permalink / raw)
To: help-gnu-emacs
John Mastro <john.b.mastro@gmail.com> writes:
> The `cl' prefix stands for Common Lisp, from whence
> the functionality there came (or was inspired by).
Of course, only confusion kicks in when it is
duplicated, but not fully so as the lack of "return"
and nil block with `dolist' shows.
>> Also: why isn't there a "neq"?
>
> I don't know the real answer, but it may be because
> then people would expect `n=', `neql', `nequal',
> `nequalp', `nstring=', and so on.
...and those would be nice! I'll add those as
I need them.
> Or perhaps some would have a "not variant" and
> others wouldn't, in which case we'd need to remember
> which did and didn't. IMHO it's simpler and cleaner
> to have a single `not' which can be used with any
> predicate as needed.
It is cleaner in one way but it also slower to type
and longer to read, and more error prone
with the additional pair of parenthesis, and more
likely to make the code overflow the right margin (I
have 85 chars/line!), so I think it is still better
with "neq" than (not (eq ... )).
--
underground experts united
http://user.it.uu.se/~embe8573
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2015-07-11 18:52 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <mailman.6511.1436314595.904.help-gnu-emacs@gnu.org>
2015-07-08 3:25 ` cl-dolist, dolist, cl-return, Pascal J. Bourguignon
2015-07-08 10:17 ` Emanuel Berg
2015-07-08 14:02 ` Drew Adams
2015-07-08 23:10 ` Emanuel Berg
[not found] ` <mailman.6588.1436397019.904.help-gnu-emacs@gnu.org>
2015-07-08 23:56 ` Pascal J. Bourguignon
2015-07-08 0:14 Emanuel Berg
2015-07-08 0:31 ` John Mastro
2015-07-08 3:09 ` Stefan Monnier
2015-07-08 10:25 ` Emanuel Berg
2015-07-08 14:44 ` Stefan Monnier
2015-07-08 23:19 ` Emanuel Berg
2015-07-09 1:49 ` John Mastro
2015-07-09 22:00 ` Emanuel Berg
[not found] ` <mailman.6636.1436479362.904.help-gnu-emacs@gnu.org>
2015-07-10 18:44 ` Barry Margolin
2015-07-11 18:52 ` Emanuel Berg
2015-07-10 16:57 ` Stefan Monnier
2015-07-08 10:23 ` Emanuel Berg
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).