* What does "lacks a prefix" mean?
@ 2015-07-08 16:32 BobD
2015-07-08 16:45 ` Barry Margolin
` (3 more replies)
0 siblings, 4 replies; 40+ messages in thread
From: BobD @ 2015-07-08 16:32 UTC (permalink / raw
To: help-gnu-emacs
My elisp:
(defun blabba ()
(defvar n 0)
)
byte-compile-file yields this:
In blabba:
test.el:1:8:Warning: global/dynamic var `n' lacks a prefix
What does my elisp lack?
Other than asking here, where can I learn what "lacks a prefix" means?
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
2015-07-08 16:32 What does "lacks a prefix" mean? BobD
@ 2015-07-08 16:45 ` Barry Margolin
2015-07-08 16:59 ` Vaidheeswaran C
` (2 subsequent siblings)
3 siblings, 0 replies; 40+ messages in thread
From: Barry Margolin @ 2015-07-08 16:45 UTC (permalink / raw
To: help-gnu-emacs
In article <1e0ad02f-ca3e-495c-bb85-61f77090d31d@googlegroups.com>,
BobD <daycandle@gmail.com> wrote:
> My elisp:
>
> (defun blabba ()
> (defvar n 0)
> )
>
> byte-compile-file yields this:
>
> In blabba:
> test.el:1:8:Warning: global/dynamic var `n' lacks a prefix
>
> What does my elisp lack?
> Other than asking here, where can I learn what "lacks a prefix" means?
The convention in Emacs Lisp is that global variables should have names
of the form packagename-variable. Giving a global variable a name
without a package prefix is a good way to have collisions between
different packages.
--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
2015-07-08 16:32 What does "lacks a prefix" mean? BobD
2015-07-08 16:45 ` Barry Margolin
@ 2015-07-08 16:59 ` Vaidheeswaran C
2015-07-08 17:10 ` Vaidheeswaran C
2015-07-08 18:17 ` BobD
3 siblings, 0 replies; 40+ messages in thread
From: Vaidheeswaran C @ 2015-07-08 16:59 UTC (permalink / raw
To: help-gnu-emacs
On Wednesday 08 July 2015 10:02 PM, BobD wrote:
> My elisp:
>
> (defun blabba ()
> (defvar n 0)
> )
>
> byte-compile-file yields this:
>
> In blabba:
> test.el:1:8:Warning: global/dynamic var `n' lacks a prefix
>
> What does my elisp lack?
> Other than asking here, where can I learn what "lacks a prefix" means?
>
>
See Second bullet here:
http://www.gnu.org/software/emacs/manual/html_node/elisp/Coding-Conventions.html
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
2015-07-08 16:32 What does "lacks a prefix" mean? BobD
2015-07-08 16:45 ` Barry Margolin
2015-07-08 16:59 ` Vaidheeswaran C
@ 2015-07-08 17:10 ` Vaidheeswaran C
2015-07-08 18:17 ` BobD
3 siblings, 0 replies; 40+ messages in thread
From: Vaidheeswaran C @ 2015-07-08 17:10 UTC (permalink / raw
To: BobD, help-gnu-emacs
On Wednesday 08 July 2015 10:02 PM, BobD wrote:
> My elisp:
>
> (defun blabba ()
> (defvar n 0)
> )
>
> byte-compile-file yields this:
>
> In blabba:
> test.el:1:8:Warning: global/dynamic var `n' lacks a prefix
>
> What does my elisp lack?
> Other than asking here, where can I learn what "lacks a prefix" means?
>
>
See bullet 2 under
http://www.gnu.org/software/emacs/manual/html_node/elisp/Coding-Conventions.html
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
2015-07-08 16:32 What does "lacks a prefix" mean? BobD
` (2 preceding siblings ...)
2015-07-08 17:10 ` Vaidheeswaran C
@ 2015-07-08 18:17 ` BobD
2015-07-08 18:21 ` Pascal J. Bourguignon
3 siblings, 1 reply; 40+ messages in thread
From: BobD @ 2015-07-08 18:17 UTC (permalink / raw
To: help-gnu-emacs
Thanks!
So the warning calls attention to a good-citizenship rule, not a logic issue.
How do I create a variable with local execution scope, i.e. to be known within a function, not to other elisp functions, and regardless of which buffer is local?
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
2015-07-08 18:17 ` BobD
@ 2015-07-08 18:21 ` Pascal J. Bourguignon
2015-07-08 18:45 ` BobD
0 siblings, 1 reply; 40+ messages in thread
From: Pascal J. Bourguignon @ 2015-07-08 18:21 UTC (permalink / raw
To: help-gnu-emacs
BobD <daycandle@gmail.com> writes:
> How do I create a variable with local execution scope, i.e. to be
> known within a function, not to other elisp functions, and regardless
> of which buffer is local?
Using let, of course.
(defun f (x)
(let ((y (+ 1 x)))
(* 2 y)))
--
__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] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
2015-07-08 18:21 ` Pascal J. Bourguignon
@ 2015-07-08 18:45 ` BobD
2015-07-08 23:24 ` Emanuel Berg
[not found] ` <mailman.6590.1436397914.904.help-gnu-emacs@gnu.org>
0 siblings, 2 replies; 40+ messages in thread
From: BobD @ 2015-07-08 18:45 UTC (permalink / raw
To: help-gnu-emacs
On Wednesday, July 8, 2015 at 2:21:07 PM UTC-4, Pascal J. Bourguignon wrote:
> BobD <...> writes:
>
> > How do I create a variable with local execution scope, i.e. to be
> > known within a function, not to other elisp functions, and regardless
> > of which buffer is local?
>
> Using let, of course.
>
> (defun f (x)
> (let ((y (+ 1 x)))
> (* 2 y)))
>
> ...
But of course.
I'm fooling with old elisp that uses "setq" willy-nilly, defying the notational structuring with which latter day programmers have been (properly) indoctrinated. If I must, I can wedge some let's into the code.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
2015-07-08 18:45 ` BobD
@ 2015-07-08 23:24 ` Emanuel Berg
2015-07-09 15:23 ` Filipp Gunbin
[not found] ` <mailman.6612.1436455429.904.help-gnu-emacs@gnu.org>
[not found] ` <mailman.6590.1436397914.904.help-gnu-emacs@gnu.org>
1 sibling, 2 replies; 40+ messages in thread
From: Emanuel Berg @ 2015-07-08 23:24 UTC (permalink / raw
To: help-gnu-emacs
BobD <daycandle@gmail.com> writes:
> But of course. I'm fooling with old elisp that uses
> "setq" willy-nilly, defying the notational
> structuring with which latter day programmers have
> been (properly) indoctrinated. If I must, I can
> wedge some let's into the code.
And: use `let*' if any variable depend on and uses
a previously defined one to do its computation.
Actually I see no harm using let* all the time.
--
underground experts united
http://user.it.uu.se/~embe8573
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
[not found] ` <mailman.6590.1436397914.904.help-gnu-emacs@gnu.org>
@ 2015-07-09 14:01 ` Barry Margolin
2015-07-09 14:10 ` Rusi
2015-07-09 22:19 ` Emanuel Berg
[not found] ` <<barmar-F23189.10014209072015@88-209-239-213.giganet.hu>
1 sibling, 2 replies; 40+ messages in thread
From: Barry Margolin @ 2015-07-09 14:01 UTC (permalink / raw
To: help-gnu-emacs
In article <mailman.6590.1436397914.904.help-gnu-emacs@gnu.org>,
Emanuel Berg <embe8573@student.uu.se> wrote:
> Actually I see no harm using let* all the time.
This is a frequent subject of style arguments.
As far as the computer is concerned, there should be no problem with
using let* all the time. But to human readers, it makes a difference.
Some of us view the * as being a red flag, warning the reader that
something unusual is being done. We'll then expend more mental energy
looking for the dependencies. let is the "normal" method, let* is
"special".
--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
2015-07-09 14:01 ` Barry Margolin
@ 2015-07-09 14:10 ` Rusi
2015-07-09 22:27 ` Emanuel Berg
[not found] ` <mailman.6639.1436481016.904.help-gnu-emacs@gnu.org>
2015-07-09 22:19 ` Emanuel Berg
1 sibling, 2 replies; 40+ messages in thread
From: Rusi @ 2015-07-09 14:10 UTC (permalink / raw
To: help-gnu-emacs
On Thursday, July 9, 2015 at 7:31:44 PM UTC+5:30, Barry Margolin wrote:
> In article
> Emanuel Berg wrote:
>
> > Actually I see no harm using let* all the time.
>
> This is a frequent subject of style arguments.
>
> As far as the computer is concerned, there should be no problem with
> using let* all the time. But to human readers, it makes a difference.
> Some of us view the * as being a red flag, warning the reader that
> something unusual is being done. We'll then expend more mental energy
> looking for the dependencies. let is the "normal" method, let* is
> "special".
Ive sometimes wished for a let-variant that does the duty of both let and let*
eg.
(let (((x 1) (y 2))
((z (foo x y))))
body...)
This kind of let would cost one paren more than the usual let.
But could make dependencies explicit without overspecifying
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
2015-07-08 23:24 ` Emanuel Berg
@ 2015-07-09 15:23 ` Filipp Gunbin
2015-07-09 22:32 ` Emanuel Berg
[not found] ` <mailman.6612.1436455429.904.help-gnu-emacs@gnu.org>
1 sibling, 1 reply; 40+ messages in thread
From: Filipp Gunbin @ 2015-07-09 15:23 UTC (permalink / raw
To: help-gnu-emacs
On 09/07/2015 01:24 +0200, Emanuel Berg wrote:
> BobD <daycandle@gmail.com> writes:
>
>> But of course. I'm fooling with old elisp that uses
>> "setq" willy-nilly, defying the notational
>> structuring with which latter day programmers have
>> been (properly) indoctrinated. If I must, I can
>> wedge some let's into the code.
>
> And: use `let*' if any variable depend on and uses
> a previously defined one to do its computation.
>
> Actually I see no harm using let* all the time.
let* says "I need variables which depend on each other" and if they're
really not, that look strange.
And probably it's a bit slower.
And non-parallelizable theoretically :)
Filipp
^ permalink raw reply [flat|nested] 40+ messages in thread
* RE: What does "lacks a prefix" mean?
[not found] ` <<barmar-F23189.10014209072015@88-209-239-213.giganet.hu>
@ 2015-07-09 15:33 ` Drew Adams
2015-07-12 1:47 ` Emanuel Berg
0 siblings, 1 reply; 40+ messages in thread
From: Drew Adams @ 2015-07-09 15:33 UTC (permalink / raw
To: Barry Margolin, help-gnu-emacs
> > Actually I see no harm using let* all the time.
Harm? Why would *harm* be the only useful or the most useful
criterion?
There's no harm in writing Lisp with no whitespace at all,
except for that needed to distinguish tokens such as symbols
and numbers.
And in fact I once had a colleague (an expert Lisper, BTW) who
wrote Lisp that way, always - no newline chars, no indentation,
no spaces or tabs at all, except what was needed by the
interpreter or byte-compiler to disambiguate the code.
No one else wanted to read, let alone modify his code, but hey,
no "harm" done, right?
He wrote his code at lightning speed, hardly looking at it.
And his code was *good* code - for the applications and the
machine. It just wasn't very good for humans (other than
himself, arguably, and I'm not sure he didn't shoot himself
in the foot sometimes).
> This is a frequent subject of style arguments.
>
> As far as the computer is concerned, there should be no problem
> with using let* all the time. But to human readers, it makes a
> difference.
Indeed, that is the point. (Though I don't entirely agree with
your description of the difference it makes to human readers,
quoted next.)
> Some of us view the * as being a red flag, warning the reader that
> something unusual is being done. We'll then expend more mental
> energy looking for the dependencies. let is the "normal" method,
> let* is "special".
I would say this about using `let' vs `let*' wrt what they
indicate to human readers: `let' indicates that the bindings
are independent; `let*' signals that they might be dependent.
I don't see a red flag from `let*', but yes, it does make me
pay attention and look for dependencies. That "might be" is
where I agree with Barry: `let*' makes you look for whether each
binding after the first might in fact be dependent on a previous
one from the same `let*'.
It's a huge load off one's mind knowing that the bindings of
a `let' are independent. Similarly, it is a great help to know,
from `let*', to look for how the bindings are actually related.
The problem with using `let*' all the time ("harm", actually)
is the problem of affixing the same **WARNING** label to
absolutely everything - it loses all power to draw attention to
anything. If everwhere might involve binding dependencies then
you have no signal to watch for them. You need to always be on
the alert - or never.
I start with `let', and I change to `let*' only when the logic
dictates it, i.e., when I introduce a dependent binding. That
way I know that if I see `let*' there is a dependency.
Does writing this way, privileging `let' when possible, mean
more work for the writer? Of course. When things change in
the code logic, it can happen that you need to change whether
you are using one or the other, or you might even need to add
another `let' or `let*' - or you might be able and want to
remove one.
But saving the writer some maintenance burden is not my priority.
Saving the reader some interpretation burden is more important.
Why? Because the reader, even when s?he is the same human as
the writer, is reading something inherently foreign - s?he is
coming at the code from a distance, and is a priori less
familiar with it.
Even for the same person, time and change of context can provide
enough distance that it is no longer immediately clear what is
going on or why things were written as they are.
(And yes, I even update the code even when it is not absolutely
necessary: if there is no longer any dependency then I change a
`let*' back to `let'. IOW, I try to keep the code telling me
what I want to know about the actual dependencies.)
To me, the discovery that, hey, I can write everything using
just `let*' and never bother with `let', and following up that
discovery with the practice of just using `let*', is the sign
of a novice - someone who hasn't yet learned that you don't just
write code once and for all. Even "throwaway" code can have
a longer life than you might expect. It's about the code long
term; it's not about you just now.
In sum, to me the problem with such an approach is *not*
that it is lazy. The problem is in fact that it is *not lazy
enough*.
Such an approach shows misguided, short-sighted laziness.
True, enlightened laziness takes the longer view: minimize
effort and strain (whether manual or mental) over time and
across multiple maintainers and other readers.
YMMV.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
2015-07-09 14:01 ` Barry Margolin
2015-07-09 14:10 ` Rusi
@ 2015-07-09 22:19 ` Emanuel Berg
1 sibling, 0 replies; 40+ messages in thread
From: Emanuel Berg @ 2015-07-09 22:19 UTC (permalink / raw
To: help-gnu-emacs
Barry Margolin <barmar@alum.mit.edu> writes:
>> Actually I see no harm using let* all the time.
>
> This is a frequent subject of style arguments.
>
> As far as the computer is concerned, there should be
> no problem with using let* all the time. But to
> human readers, it makes a difference. Some of us
> view the * as being a red flag, warning the reader
> that something unusual is being done. We'll then
> expend more mental energy looking for the
> dependencies. let is the "normal" method, let* is
> "special".
That's exactly right! Myself I use both (let and let*)
for this exact reason. Still I don't see any harm
always using let*, and if let* was "let" and the other
way around, I think (?) I'd always use "let".
--
underground experts united
http://user.it.uu.se/~embe8573
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
2015-07-09 14:10 ` Rusi
@ 2015-07-09 22:27 ` Emanuel Berg
[not found] ` <mailman.6639.1436481016.904.help-gnu-emacs@gnu.org>
1 sibling, 0 replies; 40+ messages in thread
From: Emanuel Berg @ 2015-07-09 22:27 UTC (permalink / raw
To: help-gnu-emacs
Rusi <rustompmody@gmail.com> writes:
> Ive sometimes wished for a let-variant that does the
> duty of both let and let* eg.
> (let (((x 1) (y 2))
> ((z (foo x y))))
> body...)
>
> This kind of let would cost one paren more than the usual let.
> But could make dependencies explicit without
> overspecifying
let* already does what let does.
Dependencies aren't explicit anywhere: the only thing
let* does is saying there CAN be dependencies.
Because this is almost a worthless "red flag" that
carries minimal information, I'd say I'd use let all
the time if let was "let*".
The only reason for the distinction is if computation
was made in parallel, then let could allow that and
let* wouldn't.
However, if that was possible without OH to eat the
gain I would like a much more powerful construct than
let*, one which exactly identified what is dependent
on what.
--
underground experts united
http://user.it.uu.se/~embe8573
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
2015-07-09 15:23 ` Filipp Gunbin
@ 2015-07-09 22:32 ` Emanuel Berg
2015-07-10 17:04 ` Stefan Monnier
[not found] ` <mailman.6685.1436547891.904.help-gnu-emacs@gnu.org>
0 siblings, 2 replies; 40+ messages in thread
From: Emanuel Berg @ 2015-07-09 22:32 UTC (permalink / raw
To: help-gnu-emacs
Filipp Gunbin <fgunbin@fastmail.fm> writes:
> let* says "I need variables which depend on each
> other" and if they're really not, that look strange.
It looks strange to the human Lisp brain because we
have trained it is the way it is. I'm doing it that
way as well, but only because I want my Lisp to be
understood by others I don't start re-training it (the
brain) starting right now.
> And non-parallelizable theoretically :)
Is anyone really going to base parallelism on a bunch
of local variables? With let and let*? But yeah, if
that was actually so, it would be cool if not
(probably) that big a deal...
--
underground experts united
http://user.it.uu.se/~embe8573
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
[not found] ` <mailman.6612.1436455429.904.help-gnu-emacs@gnu.org>
@ 2015-07-09 23:27 ` Barry Margolin
[not found] ` <mailman.6643.1436488423.904.help-gnu-emacs@gnu.org>
[not found] ` <<barmar-500871.19271109072015@88-209-239-213.giganet.hu>
1 sibling, 1 reply; 40+ messages in thread
From: Barry Margolin @ 2015-07-09 23:27 UTC (permalink / raw
To: help-gnu-emacs
In article <mailman.6612.1436455429.904.help-gnu-emacs@gnu.org>,
Filipp Gunbin <fgunbin@fastmail.fm> wrote:
> On 09/07/2015 01:24 +0200, Emanuel Berg wrote:
>
> > BobD <daycandle@gmail.com> writes:
> >
> >> But of course. I'm fooling with old elisp that uses
> >> "setq" willy-nilly, defying the notational
> >> structuring with which latter day programmers have
> >> been (properly) indoctrinated. If I must, I can
> >> wedge some let's into the code.
> >
> > And: use `let*' if any variable depend on and uses
> > a previously defined one to do its computation.
> >
> > Actually I see no harm using let* all the time.
>
> let* says "I need variables which depend on each other" and if they're
> really not, that look strange.
>
> And probably it's a bit slower.
If it is, that's a misfeature of the compiler.
> And non-parallelizable theoretically :)
Regular let isn't parallelizable. It specifies that the value
expressions are evaluated in order.
The only difference between the two is the environment within which
later expressions are evaluated.
--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
^ permalink raw reply [flat|nested] 40+ messages in thread
* RE: What does "lacks a prefix" mean?
[not found] ` <<barmar-500871.19271109072015@88-209-239-213.giganet.hu>
@ 2015-07-10 0:33 ` Drew Adams
0 siblings, 0 replies; 40+ messages in thread
From: Drew Adams @ 2015-07-10 0:33 UTC (permalink / raw
To: Barry Margolin, help-gnu-emacs
> > And non-parallelizable theoretically :)
>
> Regular let isn't parallelizable. It specifies that the value
> expressions are evaluated in order.
>
> The only difference between the two is the environment within which
> later expressions are evaluated.
FWIW, Common Lisp specifies that "let performs the bindings
in parallel and let* does them sequentially."
That is theoretical, just a restatement that `let' bindings
are independent. But it means that yes, they *could* be
evaluated in parallel (because they are independent).
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
[not found] ` <mailman.6643.1436488423.904.help-gnu-emacs@gnu.org>
@ 2015-07-10 0:49 ` Pascal J. Bourguignon
2015-07-10 5:04 ` Drew Adams
2015-07-10 14:42 ` Barry Margolin
[not found] ` <<barmar-2BC802.10421910072015@88-209-239-213.giganet.hu>
2 siblings, 1 reply; 40+ messages in thread
From: Pascal J. Bourguignon @ 2015-07-10 0:49 UTC (permalink / raw
To: help-gnu-emacs
Drew Adams <drew.adams@oracle.com> writes:
>> > And non-parallelizable theoretically :)
>>
>> Regular let isn't parallelizable. It specifies that the value
>> expressions are evaluated in order.
>>
>> The only difference between the two is the environment within which
>> later expressions are evaluated.
>
> FWIW, Common Lisp specifies that "let performs the bindings
> in parallel and let* does them sequentially."
>
> That is theoretical, just a restatement that `let' bindings
> are independent. But it means that yes, they *could* be
> evaluated in parallel (because they are independent).
IF they are independent, and notably IF they are side effect free.
(let ((i 0))
(cons (let ((i 42)
(a (print (incf i)))
(b (print (incf i)))
(c (print (incf i))))
(list i a b c))
i))
prints:
1
2
3
--> ((42 1 2 3) . 3)
Here, there's now way the initialization expressions in the inner let
be evaluated in parallel. The left-to-right evaluation order is
imperative, because of the side effects.
--
__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] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
[not found] ` <mailman.6639.1436481016.904.help-gnu-emacs@gnu.org>
@ 2015-07-10 3:10 ` Rusi
2015-07-10 16:00 ` Emanuel Berg
0 siblings, 1 reply; 40+ messages in thread
From: Rusi @ 2015-07-10 3:10 UTC (permalink / raw
To: help-gnu-emacs
On Friday, July 10, 2015 at 4:00:18 AM UTC+5:30, Emanuel Berg wrote:
> Rusi writes:
>
> > Ive sometimes wished for a let-variant that does the
> > duty of both let and let* eg.
>
> > (let (((x 1) (y 2))
> > ((z (foo x y))))
> > body...)
> >
> > This kind of let would cost one paren more than the usual let.
> > But could make dependencies explicit without
> > overspecifying
>
> let* already does what let does.
*** Welcome to IELM *** Type (describe-mode) for help.
ELISP> (setq a 'a b 'b)
b
ELISP> (let ((a b)(b a)) (list a b))
(b a)
ELISP> (let* ((a b)(b a)) (list a b))
(b b)
^ permalink raw reply [flat|nested] 40+ messages in thread
* RE: What does "lacks a prefix" mean?
2015-07-10 0:49 ` Pascal J. Bourguignon
@ 2015-07-10 5:04 ` Drew Adams
0 siblings, 0 replies; 40+ messages in thread
From: Drew Adams @ 2015-07-10 5:04 UTC (permalink / raw
To: Pascal J. Bourguignon, help-gnu-emacs
> IF they are independent, and notably IF they are side effect free.
Yes, clearly. That's not really the point here. But it
is good to point it out. Code with `let' can need to be
examined closely, just like code with `let*'. This is
Lisp, not Haskell.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
[not found] ` <mailman.6643.1436488423.904.help-gnu-emacs@gnu.org>
2015-07-10 0:49 ` Pascal J. Bourguignon
@ 2015-07-10 14:42 ` Barry Margolin
[not found] ` <<barmar-2BC802.10421910072015@88-209-239-213.giganet.hu>
2 siblings, 0 replies; 40+ messages in thread
From: Barry Margolin @ 2015-07-10 14:42 UTC (permalink / raw
To: help-gnu-emacs
In article <mailman.6643.1436488423.904.help-gnu-emacs@gnu.org>,
Drew Adams <drew.adams@oracle.com> wrote:
> > > And non-parallelizable theoretically :)
> >
> > Regular let isn't parallelizable. It specifies that the value
> > expressions are evaluated in order.
> >
> > The only difference between the two is the environment within which
> > later expressions are evaluated.
>
> FWIW, Common Lisp specifies that "let performs the bindings
> in parallel and let* does them sequentially."
It specifies that the bindings are done in parallel, but evaluation of
the initialization forms is sequential. From
http://www.lispworks.com/documentation/HyperSpec/Body/s_let_l.htm#let
"LET ... first evaluates the expressions init-form-1, init-form-2, and
so on, in that order, saving the resulting values. Then all of the
variables varj are bound to the corresponding values"
whereas
"LET* ... first evaluates the expression init-form-1, then binds the
variable var1 to that value; then it evaluates init-form-2 and binds
var2, and so on"
If the forms have no side effects, LET can indeed execute them in
parallel, since there's no way to tell the difference. LET* can also do
that for any initialization expressions that don't refer back to earlier
variables and have no side effects.
--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
^ permalink raw reply [flat|nested] 40+ messages in thread
* RE: What does "lacks a prefix" mean?
[not found] ` <<barmar-2BC802.10421910072015@88-209-239-213.giganet.hu>
@ 2015-07-10 14:53 ` Drew Adams
0 siblings, 0 replies; 40+ messages in thread
From: Drew Adams @ 2015-07-10 14:53 UTC (permalink / raw
To: Barry Margolin, help-gnu-emacs
> [Common Lisp] specifies that the bindings are done in parallel, but
> evaluation of the initialization forms is sequential. From
> http://www.lispworks.com/documentation/HyperSpec/Body/s_let_l.htm#let
>
> "LET ... first evaluates the expressions init-form-1, init-form-2,
> and so on, in that order, saving the resulting values. Then all of
> the variables varj are bound to the corresponding values"
Good clarification.
> If the forms have no side effects, LET can indeed execute them in
> parallel, since there's no way to tell the difference. LET* can also
> do that for any initialization expressions that don't refer back to
> earlier variables and have no side effects.
Also well put.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
2015-07-10 3:10 ` Rusi
@ 2015-07-10 16:00 ` Emanuel Berg
0 siblings, 0 replies; 40+ messages in thread
From: Emanuel Berg @ 2015-07-10 16:00 UTC (permalink / raw
To: help-gnu-emacs
Rusi <rustompmody@gmail.com> writes:
>> let* already does what let does.
>
> *** Welcome to IELM *** Type (describe-mode) for help.
> ELISP> (setq a 'a b 'b)
> ELISP> (let ((a b)(b a)) (list a b))
> (b a)
>
> ELISP> (let* ((a b)(b a)) (list a b))
> (b b)
I have 178 "let"s in my Elisp and I'm confident
I could replace all of them with `let*' without
braking a single defun.
--
underground experts united
http://user.it.uu.se/~embe8573
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
2015-07-09 22:32 ` Emanuel Berg
@ 2015-07-10 17:04 ` Stefan Monnier
2015-07-11 22:42 ` Emanuel Berg
` (2 more replies)
[not found] ` <mailman.6685.1436547891.904.help-gnu-emacs@gnu.org>
1 sibling, 3 replies; 40+ messages in thread
From: Stefan Monnier @ 2015-07-10 17:04 UTC (permalink / raw
To: help-gnu-emacs
>> let* says "I need variables which depend on each
>> other" and if they're really not, that look strange.
If let behaved like let* it wouldn't look strange to you. Many other
functional languages dropped the "simultaneous let" and only kept the
equivalent of let* (or even letrec).
>> And probably it's a bit slower.
Regarding efficiency, there's no clear winner between the two.
It's basically irrelevant.
>> And non-parallelizable theoretically :)
In practice neither is easily parallelizable anyway. And the work
needed to auto-convert a "let*" to a "let" when possible is trivial in
comparison to what's needed to parallelize the code.
So again, it's really irrelevant.
Stefan
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
[not found] ` <mailman.6685.1436547891.904.help-gnu-emacs@gnu.org>
@ 2015-07-10 18:27 ` Barry Margolin
0 siblings, 0 replies; 40+ messages in thread
From: Barry Margolin @ 2015-07-10 18:27 UTC (permalink / raw
To: help-gnu-emacs
In article <mailman.6685.1436547891.904.help-gnu-emacs@gnu.org>,
Stefan Monnier <monnier@iro.umontreal.ca> wrote:
> >> let* says "I need variables which depend on each
> >> other" and if they're really not, that look strange.
>
> If let behaved like let* it wouldn't look strange to you. Many other
> functional languages dropped the "simultaneous let" and only kept the
> equivalent of let* (or even letrec).
It should be noted that the original LET macro in MacLisp was basically
a rearranged LAMBDA:
(let ((var1 val1) (var2 val2) ...) body...)
==>
((lambda (var1 var2 ...) body...) val1 val2 ...)
When written this way, you can see where the order of evaluation of the
values, and the parallel binding of the variables came from: arguments
to a function have to be evaluated before the function is called (except
in "lazy" languages).
Most other languages also have function call syntax, and if they have
anonymous functions they can express the same parallel binding. E.g. in
Javascript you can write an "IIFE":
(function(var1, var2, ...) {body...})(val1, val2, ...)
This is actually a common idiom (and whenever I see it, I cringe that
they somehow discovered the original Lisp syntax, yet didn't adopt the
LET-style rewrite that makes it easier to comprehend).
What they generally don't have is multiple ways to introduce local
variables in the same scope of a function.
--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
2015-07-10 17:04 ` Stefan Monnier
@ 2015-07-11 22:42 ` Emanuel Berg
[not found] ` <mailman.6748.1436654668.904.help-gnu-emacs@gnu.org>
2015-07-13 12:26 ` Filipp Gunbin
2 siblings, 0 replies; 40+ messages in thread
From: Emanuel Berg @ 2015-07-11 22:42 UTC (permalink / raw
To: help-gnu-emacs
Stefan Monnier <monnier@iro.umontreal.ca> writes:
>> let* says "I need variables which depend on each
>> other" and if they're really not, that
>> look strange.
>
> If let behaved like let* it wouldn't look strange to
> you. Many other functional languages dropped the
> "simultaneous let" and only kept the equivalent of
> let* (or even letrec).
>
>> And probably it's a bit slower.
>
> Regarding efficiency, there's no clear winner
> between the two. It's basically irrelevant.
>
>> And non-parallelizable theoretically :)
>
> In practice neither is easily parallelizable anyway.
> And the work needed to auto-convert a "let*" to
> a "let" when possible is trivial in comparison to
> what's needed to parallelize the code. So again,
> it's really irrelevant.
Hear? I couldn't have said it better myself. Wait...
I couldn't! But let me say a couple of other things:
1) "let" looks better and is faster to type, both in
terms of the number of chars used and what those
chars are (i.e., no "*" in "let" which is only
normal letters).
2) With the let/let* distinction, while let* being the
oddball, it sends the signal that the "let" style,
and not the one of "let*", is the one preferred.
But it is actually the "let*" style that should be
favored! It is much more clear and
easily navigated. Compare:
(setq side 3.0)
(let ((cube-volume (* side side side)))
cube-volume)
vs.
(let* ((side 3.0)
(side-area (* side side))
(cube-volume (* side-area side)) )
cube-volume)
"Dependencies" are the most natural things and
aren't anything to be afraid of! Only if you are
the manager of a Linux distro they can get out of
hands sometimes...
3) "let", if let was let*, would be less thinking in
advance since then you wouldn't have to think "so,
will I have variables now which will depend on
each other?" You'd just type "let" in either case!
Likewise, when you modify code long after you
first wrote it, you often insert a new variable
that is "dependent" on another, and then you have
to change the `let' to `let*'. But this is very
easy to forget and it is always a silly mistake
when it happens.
--
underground experts united
http://user.it.uu.se/~embe8573
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
[not found] ` <mailman.6748.1436654668.904.help-gnu-emacs@gnu.org>
@ 2015-07-11 23:58 ` Barry Margolin
0 siblings, 0 replies; 40+ messages in thread
From: Barry Margolin @ 2015-07-11 23:58 UTC (permalink / raw
To: help-gnu-emacs
In article <mailman.6748.1436654668.904.help-gnu-emacs@gnu.org>,
Emanuel Berg <embe8573@student.uu.se> wrote:
> 3) "let", if let was let*, would be less thinking in
> advance since then you wouldn't have to think "so,
> will I have variables now which will depend on
> each other?" You'd just type "let" in either case!
> Likewise, when you modify code long after you
> first wrote it, you often insert a new variable
> that is "dependent" on another, and then you have
> to change the `let' to `let*'. But this is very
> easy to forget and it is always a silly mistake
> when it happens.
This is a reasonable argument. It's not uncommon to start writing a let,
realize that the initialization expression has some repetition, so you
want to refactor it to use variables for them. Then you need to change
it to let*.
--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
2015-07-09 15:33 ` Drew Adams
@ 2015-07-12 1:47 ` Emanuel Berg
2015-07-12 16:59 ` Drew Adams
0 siblings, 1 reply; 40+ messages in thread
From: Emanuel Berg @ 2015-07-12 1:47 UTC (permalink / raw
To: help-gnu-emacs
Drew Adams <drew.adams@oracle.com> writes:
> Harm? Why would *harm* be the only useful or the
> most useful criterion?
>
> There's no harm in writing Lisp with no whitespace
> at all, except for that needed to distinguish tokens
> such as symbols and numbers.
>
> And in fact I once had a colleague (an expert Lisper,
> BTW) who wrote Lisp that way, always - no newline
> chars, no indentation, no spaces or tabs at all,
> except what was needed by the interpreter or
> byte-compiler to disambiguate the code.
>
> No one else wanted to read, let alone modify his
> code, but hey, no "harm" done, right?
>
> He wrote his code at lightning speed, hardly looking
> at it. And his code was *good* code - for the
> applications and the machine. It just wasn't very
> good for humans (other than himself, arguably, and
> I'm not sure he didn't shoot himself in the foot
> sometimes).
I do see the harm in doing as your former colleague but
I don't see the harm in using `let*' instead of `let'.
Apart from convention which can be reprogrammed in the
minds of programmers, even. And, as it stands, apart
from me not liking the syntax (spelling) of "let*"
compared to "let".
> I would say this about using `let' vs `let*' wrt
> what they indicate to human readers: `let' indicates
> that the bindings are independent; `let*' signals
> that they might be dependent.
>
> I don't see a red flag from `let*', but yes, it does
> make me pay attention and look for dependencies.
> That "might be" is where I agree with Barry: `let*'
> makes you look for whether each binding after the
> first might in fact be dependent on a previous one
> from the same `let*'.
>
> It's a huge load off one's mind knowing that the
> bindings of a `let' are independent. Similarly, it
> is a great help to know, from `let*', to look for
> how the bindings are actually related.
>
> The problem with using `let*' all the time ("harm",
> actually) is the problem of affixing the same
> **WARNING** label to absolutely everything - it
> loses all power to draw attention to anything.
> If everwhere might involve binding dependencies then
> you have no signal to watch for them. You need to
> always be on the alert - or never.
This all makes sense if the premise is that
dependencies are anything to look for, be aware of, be
"on the alert", as you say.
But - why do you want to look for them at all?
What does it matter? On the contrary, I consider them
completely natural and a good thing. It is *good* for
humans to see that computation is done in steps, and
for machines, that is the way it happens anyway - it
doesn't matter if you have one all but neverending
line:
(let ((value (computation_1 ( ... (computation_n ...))))))
or the same procedure on a vertical line with names to
illustrate the process. But, to humans, it is more
clear and less error prone, and it is easier to
modify and debug.
If we turn the discussion upside down, if dependencies
indeed were a reason to be on the alert - then I'd
like a much better and more specific construct than
`let*'! If dependencies were something to look for,
I wouldn't want a construct that says "here, there
*might* be dependencies", instead I'd like a construct
that said "here, there *is* a dependency, namely
X depends on Y in terms of Z!"
--
underground experts united
http://user.it.uu.se/~embe8573
^ permalink raw reply [flat|nested] 40+ messages in thread
* RE: What does "lacks a prefix" mean?
2015-07-12 1:47 ` Emanuel Berg
@ 2015-07-12 16:59 ` Drew Adams
2015-07-13 0:46 ` Emanuel Berg
0 siblings, 1 reply; 40+ messages in thread
From: Drew Adams @ 2015-07-12 16:59 UTC (permalink / raw
To: Emanuel Berg, help-gnu-emacs
> > The problem with using `let*' all the time ("harm",
> > actually) is the problem of affixing the same
> > **WARNING** label to absolutely everything - it
> > loses all power to draw attention to anything.
> > If everwhere might involve binding dependencies then
> > you have no signal to watch for them. You need to
> > always be on the alert - or never.
> ...
> I wouldn't want a construct that says "here, there
> *might* be dependencies", instead I'd like a construct
> that said "here, there *is* a dependency, namely
> X depends on Y in terms of Z!"
That's precisely the point. I want the latter, not the former.
In your text that I elided you seem to have missed the point.
It's not about dependencies being somehow bad or dangerous or
abnormal.
It's about recognizing and understanding them. Precisely, I
imagine, why you wrote that you'd appreciate a construct that
identifies them for you. So would I.
In the absence of that, I identify them for myself, explicitly.
When I read code later I often understand it less well than I
did when I wrote it (not always, but often enough). So I as
writer try to help poor me as reader.
`let*' tells you nothing about dependencies, which means more
time examining code to understand it. That's the answer to
your question, "What does it matter?". To understand code
we sometimes need to understand what various parts of it
depend on.
Believe it or not, you do want (or will someday appreciate)
the advantage of knowing - just by looking - where there are
binding dependencies, especially if you have many bindings
at the same level (and perhaps especially if there are
dynamic bindings).
If you use only `let*' all the time then you in fact maximize
what you claim you "wouldn't want" - something that tells you
nothing about where there might be, let alone where there
actually are, dependencies.
Working code that uses `let', on the other hand, does tell
you something useful.
Lacking an automatic indication of dependencies (that would
be nice), my preference is to do the work myself when writing
code, to signal to myself (and any other reader) what my
understanding of the code is at that time:
* These particular bindings, with `let', are not themselves,
as bindings, interdependent. The code would not work if
they were (typically you'd get an unbound variable error).
* These other bindings, with `let*', _do_ involve at least
one dependency - not "might", but "do". The code would not
work if `let*' were changed to `let' here (e.g., unbound
variable error).
It's the "the code would not work" part that makes this
convention a bit more useful than, say, comments about the
writer's understanding of what's going on.
The stricter the use of the convention, the more surely does
`let*' indicate real dependencies. If adhered to strictly
then _every_ `let*' binding expresses a real, not just a
might-be, dependency.
(If you think that `let*' makes every binding depend on those
that precede it, think again. `(let* ((a 1) (b 2))...)' does
not make b's value depend on a's.)
I use `let*' where I know (or think I know) there is a binding
dependency, and `let' where I know (or think) there are none.
It's about expressing my coding-time understanding, so that a
reader has that extra bit of info - info about my thinking,
and maybe about the code.
Whether my understanding is correct when writing is not the
question. At least a reader has the advantage of knowing
what I was thinking. That's the point and, yes, it can
really help. It helps me, as writer and reader of my code.
Separating the two this way lets me know that when I see
`let*' I can rely on there being binding dependency, rather
than knowing only that there might be.
Can `let' also involve dependencies? Of course, especially
with dynamic binding. The point is not that the use of this
convention makes understanding trivial, cut-and-dried. The
point is that understanding what the writer was thinking can
help a reader.
Throwing everything into one giant `let*' is easy, and things
might seem to just work (no pesky unbound variable errors),
but it obscures rather than clarifies what is going on.
A coder knows more about the code than what an all-inclusive
`let*' can tell a reader, so I express it, to help out. In
the absence of language support that does such analysis and
proclaims the outcome in the code, I do it manually.
YMMV. You don't have to write your code the way I write
mine. And I don't have to read and maintain your code. ;-)
I do what I do because it helps me. I describe it here
because I think it could help others, even you.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
2015-07-12 16:59 ` Drew Adams
@ 2015-07-13 0:46 ` Emanuel Berg
2015-07-13 7:26 ` Yuri Khan
0 siblings, 1 reply; 40+ messages in thread
From: Emanuel Berg @ 2015-07-13 0:46 UTC (permalink / raw
To: help-gnu-emacs
Drew Adams <drew.adams@oracle.com> writes:
> That's precisely the point. I want the latter, not
> the former.
>
> In your text that I elided you seem to have missed
> the point. It's not about dependencies being somehow
> bad or dangerous or abnormal. ...
"Dependency" is when one program needs another program
to execute. Or whenever a library needs some other
library to do its taks.
When a variable uses another variable to compute its
value, this is perhaps formally a "dependency" but
mostly it is normal programming that happens
every day, all the time.
You mention when you come back to edit code. Then you
want to know if there are (might be) dependencies by
looking at the let or let*. Why? I never do that, but
look at the variables, instead. I don't think about
variable "dependencies" ever, because I assume they
are there because that is the normal state. I don't
need anything to "warn" me the code is normal.
As said, I think code written in the "let* style",
with tons of variables that incrementally show the
computation stepwise, is *much more* clear/easy to
read and edit/less error prone than code where
everything is done in one binding to keep it
"dependency" free. Why would anyone do that?
We can take an example from a C++ project I once did.
I just brought up a file, and immediately I see:
char* const program_name = const_cast<char*>(program.c_str());
int arg_array_size = argc + 1;
char* program_argv[arg_array_size];
program_argv[0] = program_name;
You see that everything depends on everything. Do you
think this makes any difference?
/* WARNING - DEPENDENCIES AHEAD */
char* const program_name = const_cast<char*>(program.c_str());
int arg_array_size = argc + 1;
char* program_argv[arg_array_size];
program_argv[0] = program_name;
/* Relax - when evil returns, so shall we! */
--
underground experts united
http://user.it.uu.se/~embe8573
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
2015-07-13 0:46 ` Emanuel Berg
@ 2015-07-13 7:26 ` Yuri Khan
2015-07-13 23:47 ` Emanuel Berg
0 siblings, 1 reply; 40+ messages in thread
From: Yuri Khan @ 2015-07-13 7:26 UTC (permalink / raw
To: help-gnu-emacs@gnu.org
On Mon, Jul 13, 2015 at 6:46 AM, Emanuel Berg <embe8573@student.uu.se> wrote:
> You mention when you come back to edit code. Then you
> want to know if there are (might be) dependencies by
> looking at the let or let*. Why? I never do that, but
> look at the variables, instead. I don't think about
> variable "dependencies" ever, because I assume they
> are there because that is the normal state. I don't
> need anything to "warn" me the code is normal.
Variable dependencies start to matter a lot when you’re trying to
refactor code — e.g. to extract part of a function into a new function
of its own. In this case, variables shared by the code that stays and
the code that moves out are a source of complexity, and their number
may be a factor in deciding which refactoring the code actually wants.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
2015-07-10 17:04 ` Stefan Monnier
2015-07-11 22:42 ` Emanuel Berg
[not found] ` <mailman.6748.1436654668.904.help-gnu-emacs@gnu.org>
@ 2015-07-13 12:26 ` Filipp Gunbin
2 siblings, 0 replies; 40+ messages in thread
From: Filipp Gunbin @ 2015-07-13 12:26 UTC (permalink / raw
To: Stefan Monnier; +Cc: help-gnu-emacs
On 10/07/2015 13:04 -0400, Stefan Monnier wrote:
>>> let* says "I need variables which depend on each
>>> other" and if they're really not, that look strange.
>
> If let behaved like let* it wouldn't look strange to you. Many other
> functional languages dropped the "simultaneous let" and only kept the
> equivalent of let* (or even letrec).
But if 90% of users make the distinction and 10% of them don't it would
cause confusion. If everybody uses the same construct then it does not
matter.
letrec is nice :-)
>>> And probably it's a bit slower.
>
> Regarding efficiency, there's no clear winner between the two.
> It's basically irrelevant.
I meant that there could be an extra inner frame for each of the
bindings in let*, while only one in let. I don't have enough knowledge
of emacs lisp implementation to say for sure, that's why "probably" in
my comment.
>>> And non-parallelizable theoretically :)
>
> In practice neither is easily parallelizable anyway.
Is it because each of the value expression could modify something in the
environment?
> And the work needed to auto-convert a "let*" to a "let" when possible
> is trivial in comparison to what's needed to parallelize the code. So
> again, it's really irrelevant.
Ok, thanks.
Filipp
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
2015-07-13 7:26 ` Yuri Khan
@ 2015-07-13 23:47 ` Emanuel Berg
2015-07-14 6:23 ` Yuri Khan
0 siblings, 1 reply; 40+ messages in thread
From: Emanuel Berg @ 2015-07-13 23:47 UTC (permalink / raw
To: help-gnu-emacs
Yuri Khan <yuri.v.khan@gmail.com> writes:
> Variable dependencies start to matter a lot when
> you’re trying to refactor code — e.g. to extract
> part of a function into a new function of its own.
> In this case, variables shared by the code that
> stays and the code that moves out are a source of
> complexity, and their number may be a factor in
> deciding which refactoring the code actually wants.
If you are to muck around with old code, which seldom
is a good idea but sometimes necessary (?), then doing
so will be helped to an unfathomable degree if the
"let* style" has been applied when the code was
originally written, as computation is stepwise
performed and each step is named and put neatly into
a nice looking column!
It is, on the contrary, the "let style" with
(let ((entity (computation_1 (computation_2 ( ... )))))
... )
which is much more difficult to write, not to mention
read, debug, and later maintain and modify.
"Variable dependencies" is all schoolbook stuff -
forget about it, the sooner the better, because it
doesn't work like that. It doesn't increase
"complexity", whatever that is.
--
underground experts united
http://user.it.uu.se/~embe8573
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
2015-07-13 23:47 ` Emanuel Berg
@ 2015-07-14 6:23 ` Yuri Khan
2015-07-14 21:58 ` Emanuel Berg
2015-07-19 0:59 ` Robert Thorpe
0 siblings, 2 replies; 40+ messages in thread
From: Yuri Khan @ 2015-07-14 6:23 UTC (permalink / raw
To: help-gnu-emacs@gnu.org
On Tue, Jul 14, 2015 at 5:47 AM, Emanuel Berg <embe8573@student.uu.se> wrote:
> If you are to muck around with old code, which seldom
> is a good idea but sometimes necessary (?),
Why the (?)? Mucking around with old code is necessary every time you
want to add a feature or debug a failure.
> then doing
> so will be helped to an unfathomable degree if the
> "let* style" has been applied when the code was
> originally written, as computation is stepwise
> performed and each step is named and put neatly into
> a nice looking column!
>
> It is, on the contrary, the "let style" with
>
> (let ((entity (computation_1 (computation_2 ( ... )))))
> ... )
>
> which is much more difficult to write, not to mention
> read, debug, and later maintain and modify.
You’re putting out a strawman by comparing a “let* style” where small
expressions are given names and arranged in a total order with a “let
style” where few names are bound to independent but huge expressions.
The ultimate degree of the “let*” style you describe is code compiled
to assembly. (For the sake of argument, let’s assume a machine with
ten thousand registers, so that we don’t have to argue about register
reuse.) Expressions are very simple but it becomes hard to give them
meaningful names. Additionally, evey modern compiler worth its bits
will interleave independent evaluations if it will help saturate the
CPU pipelines. The resulting code is very complicated — the code is
doing several things at once and one has to unscramble it in order to
reason about it.
The ultimate degree of the “let style” you describe is the UNIX shell
pipeline. Its two main problems are: (1) lack of names for
intermediate values, (2) each unnamed intermediate value can only be
used once. As soon as you want to reuse the result of a subexpression,
you need to give it a name.
As in most things, there is a golden middle where the expressions are
not too complex, names are meaningful enough, and related computations
are clustered together. When structured like this, code is a pleasure
to work with.
> "Variable dependencies" is all schoolbook stuff -
> forget about it, the sooner the better, because it
> doesn't work like that. It doesn't increase
> "complexity", whatever that is.
Schoolbook stuff? No, we were not taught about dependencies at school.
We were taught recipes. Here is how you add, subtract, multiply and
divide; this is how you use standard library functions; this is how
you define your own functions. Oh actually in <this particular
language> you can’t define your own functions; too bad, you’ll have to
make do with subroutines and instead of returning a result assign it
into a global variable.
This is where complexity comes from: people knowing recipes and
applying them out of scale until the code is too complicated to fit in
one head. Especially, code written by a person with an exceptionally
big head will not fit in an average head.
Maybe you can keep 15 named variables and 60 unnamed intermediate
values in your head and reason about them freely. I cannot. I need
devices that help me in that. These devices can be embedded in the
code (meaningful names, auxiliary functions, and/or an occasional
comment) or I can work it out on a sheet of paper, throw it away when
done and have to redo it again the next time.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
2015-07-14 6:23 ` Yuri Khan
@ 2015-07-14 21:58 ` Emanuel Berg
2015-07-19 0:59 ` Robert Thorpe
1 sibling, 0 replies; 40+ messages in thread
From: Emanuel Berg @ 2015-07-14 21:58 UTC (permalink / raw
To: help-gnu-emacs
Yuri Khan <yuri.v.khan@gmail.com> writes:
>> If you are to muck around with old code, which
>> seldom is a good idea but sometimes necessary (?),
>
> Why the (?)? Mucking around with old code is
> necessary every time you want to add a feature or
> debug a failure.
It depends what you mean. Adding a particular feature
or fixing a particular bug is one thing. The
"let* style" simplifies this.
Another thing altogether is "refactoring code",
"optimizing", etc. *in general*. That is a bad idea
and a bad entry point. If the program is poorly
written, why not re-write it from scratch? OTOH, if
the program is written in a good style, there is no
reason to do any overall changes. There are very
likely improvements to be made, and bugs to fix, and
again, using let* makes this easy work because
everything is clearly organized and you can easily
spot the part you need to change/fix.
> You’re putting out a strawman by comparing a “let*
> style” where small expressions are given names and
> arranged in a total order with a “let style” where
> few names are bound to independent but
> huge expressions.
>
> The ultimate degree of the “let*” style you describe
> is code compiled to assembly. (For the sake of
> argument
There is always an extreme example that will make the
most sound attitude bizarre. It is a dead end to argue
like that.
> Schoolbook stuff? No, we were not taught about
> dependencies at school. We were taught recipes.
I was taught, or "told" I should say, a lot about
dependencies at school, and I read about them in many
textbooks. There are many systems how to properly draw
them with boxes and arrows. I believed then, and now,
that this made-up, good-for-nothing "science" is
a very sad routine, rather than comical, and to me it
is a mystery that people do it. 99% of my school time
wasn't like that, so it is fine, but yeah, I get angry
just by thinking about that pompous BS that takes the
fun and creativity out of everything, being told to
kids that are ten or twenty times the hackers as the
teachers "spreading the word". It is a very sad state.
> Maybe you can keep 15 named variables and 60 unnamed
> intermediate values in your head and reason about
> them freely.
... what? *I'm* the one who want stuff named!
--
underground experts united
http://user.it.uu.se/~embe8573
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
2015-07-14 6:23 ` Yuri Khan
2015-07-14 21:58 ` Emanuel Berg
@ 2015-07-19 0:59 ` Robert Thorpe
2015-07-28 0:24 ` Emanuel Berg
1 sibling, 1 reply; 40+ messages in thread
From: Robert Thorpe @ 2015-07-19 0:59 UTC (permalink / raw
To: help-gnu-emacs; +Cc: Yuri Khan
Yuri Khan <yuri.v.khan@gmail.com> writes:
> On Tue, Jul 14, 2015 at 5:47 AM, Emanuel Berg <embe8573@student.uu.se> wrote:
>
>> If you are to muck around with old code, which seldom
>> is a good idea but sometimes necessary (?),
>
> Why the (?)? Mucking around with old code is necessary every time you
> want to add a feature or debug a failure.
For what it's worth, this is my opinion on let vs let*.
When there's a dependency between two of the variables I use let*. If
there's no dependency at all I use let. So, if the code defining y
depends on the code defining x then I use let*.
I don't like the style where let* is used for everything. Here's an
example of the problem. Suppose you're reading through a function. You
have a local variable z and you want to understand what values it could have.
To begin with you want to understand what could happen at the beginning
of the body of the let statement z is defined in.
I.e.:-
(defun foo ()
"blah blah"
(let* ((a (something))
(b (something-else ...))
(z (something-more)))
... here...
...rest of the code...)
Now, let's say the programmer has used let. In that case I know by
looking that I don't have to read the definitions of a & b.
Alternatively, suppose the programmer has used let* even though z isn't
dependent on a or b. In that case let* indicates to me the reader that
they should read the definitions of a & b. But, doing that isn't
immediately necessary, I may not need to understand the details of a & b
to understand the problem.
It's easy to be critical of the process of restructuring or refactoring
code. It's inevitable in large codebases though. The cost and time of
rewriting them is simply too large. Even if the original is badly
written it generally contains undocumented features that people rely on.
If a large program is well written that doesn't mean it won't need
modifications regularly.
BR,
Robert Thorpe
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
2015-07-19 0:59 ` Robert Thorpe
@ 2015-07-28 0:24 ` Emanuel Berg
2015-07-30 1:40 ` Robert Thorpe
[not found] ` <mailman.7638.1438220428.904.help-gnu-emacs@gnu.org>
0 siblings, 2 replies; 40+ messages in thread
From: Emanuel Berg @ 2015-07-28 0:24 UTC (permalink / raw
To: help-gnu-emacs
Robert Thorpe <rt@robertthorpeconsulting.com> writes:
> For what it's worth, this is my opinion on let vs
> let*.
>
> When there's a dependency between two of the
> variables I use let*. If there's no dependency at
> all I use let. So, if the code defining y depends on
> the code defining x then I use let*.
>
> I don't like the style where let* is used for
> everything. Here's an example of the problem.
> Suppose you're reading through a function. You have
> a local variable z and you want to understand what
> values it could have. To begin with you want to
> understand what could happen at the beginning of the
> body of the let statement z is defined in.
>
> I.e.:- (defun foo () "blah blah" (let* ((a
> (something)) (b (something-else ...)) (z
> (something-more))) ... here... ...rest of the code...)
>
> Now, let's say the programmer has used let. In that
> case I know by looking that I don't have to read the
> definitions of a & b. Alternatively, suppose the
> programmer has used let* even though z isn't
> dependent on a or b. In that case let* indicates to
> me the reader that they should read the definitions
> of a & b. But, doing that isn't immediately
> necessary, I may not need to understand the details
> of a & b to understand the problem.
This is the exact same tiresome argument that has been
put forward several times by now and the argument is
still only logical within the framework that is "this
is the way people do it". Yes: I know!
In the other framework, where it is natural and
*desired* that things depend on each other and happen
stepwise - nothing to be afraid of and nothing that
must be marked specifically as it is the natural order
of things - in that framework it doesn't make
sense (surprise, surprise!).
There is a framework of convention but beneath that
there is technology. On top of that we can create any
framework of our minds as we desire. If we create one
that doesn't make sense in terms of technology, if we
use it enough, we'll even start to like it! It is sly!
> It's easy to be critical of the process of
> restructuring or refactoring code. It's inevitable
> in large codebases though.
OK, so how many lines of zsh, C, C++ and Lisp do you
have to write before it gets inevitable to "refactor"
it? I ask because I did my biggest projects in those
languages but apparently they weren't big enough
because I never did any "refactoring", whatever that
is, if it isn't the very normal and everyday thing
that is writing, improving, and fixing bugs in code,
in what case I have done it every day for many years!
What is all this talk?!
I don't understand this whole defaitiste "we know the
drill" mentality. "It is just the way it is." It isn't
- what it is is an empty buffer and it doesn't have to
be anything and it can be whatever you want it to be!
"Do it today, in a different way!" (Scooter 2010)
> The cost and time of rewriting them is simply too
> large. Even if the original is badly written it
> generally contains undocumented features that people
> rely on. If a large program is well written that
> doesn't mean it won't need modifications regularly.
So, everything is so bad, we have to have let/let* -
it is inevitable!
--
underground experts united
http://user.it.uu.se/~embe8573
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
2015-07-28 0:24 ` Emanuel Berg
@ 2015-07-30 1:40 ` Robert Thorpe
[not found] ` <mailman.7638.1438220428.904.help-gnu-emacs@gnu.org>
1 sibling, 0 replies; 40+ messages in thread
From: Robert Thorpe @ 2015-07-30 1:40 UTC (permalink / raw
To: Emanuel Berg; +Cc: help-gnu-emacs
I won't talk about this much more because I think it's getting off-topic
for this list.
Emanuel Berg <embe8573@student.uu.se> writes:
> This is the exact same tiresome argument that has been
> put forward several times by now and the argument is
> still only logical within the framework that is "this
> is the way people do it". Yes: I know!
I think that new languages should be written to do this the same way. I
think the convention for let and let* used in lisp is useful and I wish
it were more widespread. I'm not advocating it just because it's used
in old code. My comments about refactoring were separate.
> In the other framework, where it is natural and
> *desired* that things depend on each other and happen
> stepwise - nothing to be afraid of and nothing that
> must be marked specifically as it is the natural order
> of things - in that framework it doesn't make
> sense (surprise, surprise!).
Certainly there is no point in avoiding dependencies. They always occur
in programming. But, there's no need to make it look as through there
are dependencies where there aren't. There's no point removing tools
that allow use to differentiate one situation from the other easily.
That's the problem with the approach you're advocating.
As I said earlier, let's suppose you're reading through function foo
looking for what happens to variable bar.
Suppose you have:-
(let (.....
(foo (code ...)))
body)
In this case there's no need to read through any of the other variables
defined in the let.
Suppose instead you have:
(let* (.....
(foo (code ...)))
body)
In that case the part I've labeled "code ..." could depend on the other
local variables. In the "let" case it's often possible to eval the
"code ..." part with C-x C-e. That's often not possible in the let*
case. In the let* case you have to read through the rest of the local
variable definitions.
In elisp we have the following meanings:
* let - there aren't dependencies between these variables.
* let* - there are dependencies between these variables.
In other languages that only support something like let* it means "there
may be dependencies between these variables, you have to read all the
code".
>> It's easy to be critical of the process of
>> restructuring or refactoring code. It's inevitable
>> in large codebases though.
>
> OK, so how many lines of zsh, C, C++ and Lisp do you
> have to write before it gets inevitable to "refactor"
> it? I ask because I did my biggest projects in those
> languages but apparently they weren't big enough
> because I never did any "refactoring", whatever that
> is, if it isn't the very normal and everyday thing
> that is writing, improving, and fixing bugs in code,
> in what case I have done it every day for many years!
Of course, refactoring is often exactly what you say. It's improving
code. Some people define it more rigourously. For example, making
local improvements to code without changing the overall design is called
"refactoring". Changing the overall design is called "rearchitecting".
Remember the original reason we discussed this though. You wrote this:
> Why the (?)? Mucking around with old code is necessary every time you
> want to add a feature or debug a failure.
Now, you're advocating "mucking around with old code". Well, that
inevitably requires reading it and understanding it. New features must
always be inserted somewhere.
The original designers of a program can never envisage all of the ways
that it might be extended. Look at Emacs, it's existed for decades and
for all that time it's maintainers have tried to expand
configurability. Yet, every few weeks somebody comes up with a
practical case were a default behaviour can't be changed.
>> The cost and time of rewriting them is simply too
>> large. Even if the original is badly written it
>> generally contains undocumented features that people
>> rely on. If a large program is well written that
>> doesn't mean it won't need modifications regularly.
>
> So, everything is so bad, we have to have let/let* -
> it is inevitable!
Of course I don't think there's any particular threshold in terms of
lines-of-code of the type you describe. What more important is the
overall effort of rewriting vs fixing.
For example, is the existing program merely messy? If so then it's
often better to tidy it up than re-write it even if it's small. If the
program has a few modules that are badly written then those can be
replaced. Is the original full of undocumented features everyone relies
on? If so then re-writing it can be very tricky. Programs that are
badly designed are a difficult case. If they're badly designed but the
design is well executed (i.e. the code is generally well written) then
it can be best to keep them around. If a program is really bad
(i.e. buggy, badly written and difficult to modify) then it may be worth
replacing it even if it's millions of lines long.
Redesigning is one of the most useful and interesting programming skills
to develop. It's about knowing how to re-use what you have to build a
more general program without throwing too much away.
BR,
Robert Thorpe
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
[not found] ` <mailman.7638.1438220428.904.help-gnu-emacs@gnu.org>
@ 2015-07-30 2:49 ` Rusi
2015-07-30 2:53 ` Rusi
0 siblings, 1 reply; 40+ messages in thread
From: Rusi @ 2015-07-30 2:49 UTC (permalink / raw
To: help-gnu-emacs
On Thursday, July 30, 2015 at 7:10:31 AM UTC+5:30, Robert Thorpe wrote:
> I won't talk about this much more because I think it's getting off-topic
> for this list.
>
> Emanuel Berg writes:
> > This is the exact same tiresome argument that has been
> > put forward several times by now and the argument is
> > still only logical within the framework that is "this
> > is the way people do it". Yes: I know!
>
> I think that new languages should be written to do this the same way. I
> think the convention for let and let* used in lisp is useful and I wish
> it were more widespread. I'm not advocating it just because it's used
> in old code. My comments about refactoring were separate.
>
> > In the other framework, where it is natural and
> > *desired* that things depend on each other and happen
> > stepwise - nothing to be afraid of and nothing that
> > must be marked specifically as it is the natural order
> > of things - in that framework it doesn't make
> > sense (surprise, surprise!).
>
> Certainly there is no point in avoiding dependencies. They always occur
> in programming. But, there's no need to make it look as through there
> are dependencies where there aren't. There's no point removing tools
> that allow use to differentiate one situation from the other easily.
> That's the problem with the approach you're advocating.
>
> As I said earlier, let's suppose you're reading through function foo
> looking for what happens to variable bar.
>
> Suppose you have:-
> (let (.....
> (foo (code ...)))
> body)
>
> In this case there's no need to read through any of the other variables
> defined in the let.
>
> Suppose instead you have:
> (let* (.....
> (foo (code ...)))
> body)
>
> In that case the part I've labeled "code ..." could depend on the other
> local variables. In the "let" case it's often possible to eval the
> "code ..." part with C-x C-e. That's often not possible in the let*
> case. In the let* case you have to read through the rest of the local
> variable definitions.
>
> In elisp we have the following meanings:
> * let - there aren't dependencies between these variables.
> * let* - there are dependencies between these variables.
>
> In other languages that only support something like let* it means "there
> may be dependencies between these variables, you have to read all the
> code".
Strongly concur!
Dijkstra made a statement that is as alarming as it is true, viz.
"It takes 100 years for an idea to go from inception to general acceptance"
[dont have exact quote handy...]
Some examples:
Cantor-1880 to New-math-1970 (set theory)
200 years for Leibniz calculus notation to replace the clumsier Newton fluxion notation
600 years for Hindu-Arabic (decimal) numerals to replace roman
30 years between Wright brothers flight and first commercial flight
In the same way
Lisp was invented in 1960
For the next 40 years something vague and acdaemic called 'functional programming'
was talked of but everyone only really had lisp as an example/exemplar.
Finally it is only this century -- Haskell, Clojure, Scala -- that its become
mainstream
And finally its become abc of programming
ACM curriculum 2013 pg 158 lists what EVERY programmer should know of FP.
Seeing this discussion, I am coming to the conclusion that dependencies (and
their minimization) is something that should be added there.
To be fair the one thing I agree with Emanuel is that let* is a clumsy name.
I'd like best a single let with a 'dependency-fence'
So
Say {e,f} depends on {c,d} depends on {a,b} (no inra-set dependency)
The least-dependency way of writing would be
(let ((a ..)
(b ..))
(let ((c ..)
(d ..))
(let ((e ..)
(f ..))
body)))
The sloppy way would be just one let*
Neither is quite satisfactory -- one is over-dependent; the other is over-nested
What I'd like
(newlet ((a ..)
(b ..)
:fence
(c ..)
(d ..)
:fence
(e ..)
(f ..))
body)))
The keyword ":fence" can be improved :-)
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: What does "lacks a prefix" mean?
2015-07-30 2:49 ` Rusi
@ 2015-07-30 2:53 ` Rusi
0 siblings, 0 replies; 40+ messages in thread
From: Rusi @ 2015-07-30 2:53 UTC (permalink / raw
To: help-gnu-emacs
On Thursday, July 30, 2015 at 8:19:42 AM UTC+5:30, Rusi wrote:
> And finally its become abc of programming
> ACM curriculum 2013 pg 158 lists what EVERY programmer should know of FP.
> Seeing this discussion, I am coming to the conclusion that dependencies (and
> their minimization) is something that should be added there.
>
Link to ACM curriculum: https://www.acm.org/education/CS2013-final-report.pdf
My take on it: http://blog.languager.org/2015/06/functional-programming-moving-target.html
^ permalink raw reply [flat|nested] 40+ messages in thread
end of thread, other threads:[~2015-07-30 2:53 UTC | newest]
Thread overview: 40+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-07-08 16:32 What does "lacks a prefix" mean? BobD
2015-07-08 16:45 ` Barry Margolin
2015-07-08 16:59 ` Vaidheeswaran C
2015-07-08 17:10 ` Vaidheeswaran C
2015-07-08 18:17 ` BobD
2015-07-08 18:21 ` Pascal J. Bourguignon
2015-07-08 18:45 ` BobD
2015-07-08 23:24 ` Emanuel Berg
2015-07-09 15:23 ` Filipp Gunbin
2015-07-09 22:32 ` Emanuel Berg
2015-07-10 17:04 ` Stefan Monnier
2015-07-11 22:42 ` Emanuel Berg
[not found] ` <mailman.6748.1436654668.904.help-gnu-emacs@gnu.org>
2015-07-11 23:58 ` Barry Margolin
2015-07-13 12:26 ` Filipp Gunbin
[not found] ` <mailman.6685.1436547891.904.help-gnu-emacs@gnu.org>
2015-07-10 18:27 ` Barry Margolin
[not found] ` <mailman.6612.1436455429.904.help-gnu-emacs@gnu.org>
2015-07-09 23:27 ` Barry Margolin
[not found] ` <mailman.6643.1436488423.904.help-gnu-emacs@gnu.org>
2015-07-10 0:49 ` Pascal J. Bourguignon
2015-07-10 5:04 ` Drew Adams
2015-07-10 14:42 ` Barry Margolin
[not found] ` <<barmar-2BC802.10421910072015@88-209-239-213.giganet.hu>
2015-07-10 14:53 ` Drew Adams
[not found] ` <<barmar-500871.19271109072015@88-209-239-213.giganet.hu>
2015-07-10 0:33 ` Drew Adams
[not found] ` <mailman.6590.1436397914.904.help-gnu-emacs@gnu.org>
2015-07-09 14:01 ` Barry Margolin
2015-07-09 14:10 ` Rusi
2015-07-09 22:27 ` Emanuel Berg
[not found] ` <mailman.6639.1436481016.904.help-gnu-emacs@gnu.org>
2015-07-10 3:10 ` Rusi
2015-07-10 16:00 ` Emanuel Berg
2015-07-09 22:19 ` Emanuel Berg
[not found] ` <<barmar-F23189.10014209072015@88-209-239-213.giganet.hu>
2015-07-09 15:33 ` Drew Adams
2015-07-12 1:47 ` Emanuel Berg
2015-07-12 16:59 ` Drew Adams
2015-07-13 0:46 ` Emanuel Berg
2015-07-13 7:26 ` Yuri Khan
2015-07-13 23:47 ` Emanuel Berg
2015-07-14 6:23 ` Yuri Khan
2015-07-14 21:58 ` Emanuel Berg
2015-07-19 0:59 ` Robert Thorpe
2015-07-28 0:24 ` Emanuel Berg
2015-07-30 1:40 ` Robert Thorpe
[not found] ` <mailman.7638.1438220428.904.help-gnu-emacs@gnu.org>
2015-07-30 2:49 ` Rusi
2015-07-30 2:53 ` Rusi
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.