[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: dolist considered harmful
Re: dolist considered harmful
Wed, 31 Oct 2018 23:02:57 +0100
Gnus (5.13), GNU Emacs 25.1.1 (i686-pc-linux-gnu, GTK+ Version 3.22.11) of 2017-09-15, modified by Debian
On 2018-10-30 at 14:39, Stefan Monnier wrote:
> All this pcase-dolist discussion made me take a second look at dolist
> and now I wondering whether we should keep it:
This is still extreme: I never saw anyone suggesting to remove anything
about pcase or its derivative… but I can get quite distracted sometimes
so maybe I missed it. I think pattern-matching, though I’m not fond of
it, is sometimes necessary, and is a must-be in any high-level language,
and as pcase exists and is pretty used…
> Since it can only be used when we're 100% sure that LIST is a LIST,
> (and who can be sure of such a thing in a dynamic language like Emacs
> Lisp), I think we'd be better off deprecating it and changing all uses
> of dolist with a clear while+cdr loop that everyone can understand.
Before people spoke about sarcasm I really thought this all was serious
and first degree, about removing a such now idiomatic form from elisp,
that also exists in common lisp, to end suggesting such much lower level
Also I dislike `while': it looks pretty not lispy to me, very imperative
(but well all emacs and much lisp is imperative as well…)… I’d rather
define `dolist' upon `mapc' than `while'. And if something common and
simple as `dolist' was to be removed, I think I’d end up programming
like in scheme and use recursion everywhere (btw is emacs
tail-recursive?), so in the end that’d divide programming style between
`while' and recursion so all programs becomes half as readable as before
(except recursion-people are afaik more rare, so I’m going to be forced
in `while', and anyway it seems like in the end I made an argument in
favor of `pcase' and against `case' ><).
> - The docstring is incomprehensible:
> Loop over a list.
> Evaluate BODY with VAR bound to each car from LIST, in turn.
> Then evaluate RESULT to get return value, default nil.
> I don't know how to loop over a list.
I must say, that this seems true to me. I regularely prefers recursion
or mapcar/mapc to dolist because they’re simpler and cleaner. I recall
at a time, each time I realized I needed `dolist', I evaled a test using
it so to be sure I still knew how to properly use it. Still today,
before writing it, it is unclear in my mind how I would use dolist to do
something (I have to say I find unnatural to repetedly use setq or use
side-effects (especially to set stuff) to achieve something). Last time
I used `dolist', I first wanted to use recursion before someone noticed
me it was unnatural / strang / unidiomatic in elisp to do that, so I
needed dolist (or seq, which still seems more uncommon to me), while
what I wanted to do was simply to `reduce' composition (I got a list of
functions, I wanted to apply them all to a string, one upon the other:
so if there were a `compose' function, `reduce' it to a sequence of
functions upon a string).
> Did they mean to set the cdr of the last element so it loops back to
> the first element?
I have to say that, though it is closer to real, low-level, actual
meaning/behavior, and not difficult to grasp once you know what’s a
list, “to each element of LIST, in turn” would have been more simple to
read, parse (it is a syntactically simpler phrase), understand,
including for, but not limited to, newcomers.
> "evaluate" is unclear (is it passed to `eval`? Then why not say it?
> What second arg is passed to `eval`?). but why evaluate it several
> times? Also, in which order? How does RESULT communicate the
> return value? Is it RESULT which defaults to nil or the return
> value? If the return value, then when does it default to nil?
Again I have to say “Then return RESULT evaluation, or nil if omitted.”
is simpler and more unambiguous.
> - The docstring says nothing of what happens when LIST is not a list,
> yet a quick grep shows that most uses of dolist use for LIST a simple
> variable rather than a list. What gives?
a variable… returning a list, so being a list (the symbol is not a list,
but it doesn’t say it doesn’t evaluate the variable).
Again I have to say (this formulation is getting a little too much
redundant here and adding “again” is not hiding it well…) I find it is
true that `dolist' docstring is not explicit enough about what is
quoted, to quote, evaluated or not. It no longer happens to me, but I
clearly recall having some pain about `dolist' in my first times I used
it, to understand what I needed to quote and what I needed to put as is…
and that required me several empirical tests to be sure: ideally a clear
docstring should spare you that.
Because there’s some inconstancy to explain there: VAR is not evaluated,
never, it *must* be a symbol as `read' would read it, not something
evaluating to a symbol, LIST is evaluated right away, and RESULT is too,
only once, and at the end.