[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: In praise of globals
- From: Jay Carlson <nop@...>
- Date: Wed, 24 Apr 2013 19:32:42 -0400
Since I can't get it out of my head. This came out of browsing through some vintage Paul Graham macro-y Lisp triumphalism from 2002, which looks pretty silly with Ruby eating the world ten years later. http://www.paulgraham.com/icad.html led eventually to a footnote in Matthias Felleisen's http://www.ccs.neu.edu/scheme/pubs/scp91-felleisen.ps.gz noting that in the paper's framework, some languages with interaction are formally more powerful than those without.
On Apr 15, 2013, at 2:38 AM, Dirk Laurie wrote:
[local ipairs=ipairs]
> Now, I don't want to knock this style of programming altogether. I've used
> it myself. But to preach that is the One Correct Way is going too far.
> If one is using Lua via the interactive interpreter (which I do a lot)
> it is intensely annoying to cut-and-paste code written this way. Those
> locals last only for the chunk in which they are defined, and the
> interactive interpreter bites off the smallest chunks possible. I keep
> forgetting to make extra `do`..`end` blocks all the time.
Backing up a level, I think we are watching a divergence between written and spoken language dialects. If I see a typeset block of code like:
===
for k,v in pairs(t) do
print(k,v)
end
===
I know what it does. If I see the following, I don't:
===
local p = pairs
for k,v in p(t) do
print(k,v)
end
===
...because the semantics of the (default) interactive REPL are different from the general load() semantics. Notably, the REPL ends a chunk at any newline *if possible*.
The newline-sensitivity of this reminds me of the languages participating in the "semicolons are optional at newlines" debacle. But that's not an argument, that's just guilt by association.
Divergence between the written form (modules) and the spoken form (REPL) isn't fatal. Some choices in module infrastructure--forking an environment--makes the written and spoken forms more similar. Switching to a module's _ENV is then useful even if not quite the same as writing code at the bottom of the file module.lua. I think that's what I usually want when I'm debugging: act like I'm inside the naughty module and adding code there.
But there's no trivial way of interactively adding code at the bottom of a fully localized module.lua. You can't extend the lexical environment of the chunk; worse, the local keyword *does* extend the lexical environment:
===
local a=7
local a
print(a)
===
In this example it doesn't matter whether you paste this at the REPL or not. :-) But more seriously this shows up in simple things like
local SCALE=7
not being idempotent[1] as after each invocation, functions capturing SCALE will get the freshest one. So even if possible, this would make interactive programming hopeless in the localized style. Something as simple as using the debugger to set SCALE to 9 would have effects not easy to predict without a complete history of interaction.
Finally, "we'll just fix up local/global brain mistakes with a parse-tree fontlock in the IDE" doesn't help interactive usage. It's easy to say "get a real editor". (What *is* the state of the art in lua in emacs these days?) But it's a lot harder to say "get a real REPL" although admittedly people who live in their IDE's debugger could use whatever highlight/warning affordances it provides in interaction.
I don't have any suggestions. But writing your code in localized style implies you either won't be *interacting* with it, or that you have a more sophisticated IDE than just an xterm.
Jay
[1]: No Operation Partners aka nop.com has the marketing line: "Enterprise-class idempotency for identity solutions in the global enviroment. Instrumental in paradigm-breaking design and time-critical execution." This has yet to be included in marketing collateral; the inclusion of "Don't Forget To Smash The State" was rejected out of hand.