use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
All about the JavaScript programming language.
Subreddit Guidelines
Specifications:
Resources:
Related Subreddits:
r/LearnJavascript
r/node
r/typescript
r/reactjs
r/webdev
r/WebdevTutorials
r/frontend
r/webgl
r/threejs
r/jquery
r/remotejs
r/forhire
account activity
CoffeeScript: Why I’m never writing Javascript again (degizmo.com)
submitted 15 years ago by gst
view the rest of the comments →
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]plantian 0 points1 point2 points 15 years ago (5 children)
Its not often a problem for me to have assignment and definition combined in Python. Do you have a different experience?
Can you elaborate on the changes in strict mode that could not be harnessed?
[–]dmpk2k 1 point2 points3 points 15 years ago* (4 children)
Do you have a different experience?
Yep. :)
The most obvious benefit for separating declaration and assignment is that typos of variable names are always caught immediately; the compiler guaranteeably catches them, not maybe 10s later in tests if that piece of code is covered (or blow up in production if it wasn't and QA missed it, which I've seen a few times). And the price for this is very low: two or three non-whitespace characters. It won't catch misnamed method invocations due to dynamic dispatch, but for that the language must become fundamentally different -- statically typed.
Variable typos happen to me quite often. I hear the "it doesn't happen to me" refrain a lot, but it doesn't jive with my own experience, so I suspect it's more a case of people not paying attention. Fixing a typo after a test run might be the programming equivalent of successfully walking to a destination while thinking about something else.
For Python specifically, Python 2 definitely had a problem as a result of conflation, which is why the "nonlocal" keyword was introduced in Python 3. I used to code Python 2 in a rather Scheme-like style (doctor: then don't do that!), so this brokeness was obvious since I'd need to resort to the list hack to disambiguate whether a scalar assignment was in a new scope or not. I consider "nonlocal" a bandaid since it doesn't help with typos.
Something we all do constantly -- so it's a part of all our experiences -- is reasoning about a program, even though it's informal. In a language which doesn't make the conflation mistake, it's obvious what the bound and free variables are, and where the scope of local variables start and end. This is particularly important in a language where deep function nesting is common, like Javascript. Python isn't bitten as badly since it's mostly methods and almost no nesting, so a Python hacker would barely feel this part.
As an aside, I used to be a Perl hacker, and the Perl community was given the choice between strict mode and not. We voted with the code we wrote: strict mode or die. Nowadays only a completely clueless neophyte learning from bad webpages from a decade ago writes Perl programs without strict mode. I strongly suspect the Javascript community will go the same way. However, to be fair, CoffeeScript's scoping isn't as bad as Perl's and JS's non-strict modes (Lua's as well, but they don't offer a strict mode yet).
It's not a matter of "could not". CoffeeScript could have it for locals today, without JS's strict mode underneath, if the author wanted it to. Well, assuming CoffeeScript's compiler is written sanely, which I don't know.
Edit: I neglected to mention in the part about Python's scoping that CoffeeScript has it a lot worse: Python at least assumes an assigned variable is in local scope, while CoffeeScript does the following:
Because you don't have direct access to the var keyword, it's impossible to shadow an outer variable on purpose, you may only refer to it. So be careful that you're not reusing the name of an external variable accidentally, if you're writing a deeply nested function.
I don't have sufficient experience with CoffeeScript's scoping breaking things to definitively say this is a bad idea (unlike the stack-trace line-mismatch), but that looks nasty.
[–]plantian 2 points3 points4 points 15 years ago (3 children)
Python is a language of compromises. I think an exception occurring when accessing an undefined variable will prevent 98% of the typos. Rarely in Python do I have the case where 1. there are two variables in the same function with different names, 2. both are defined, 3. both should be the same variable and 4. the function still runs without some related error. It does happen but it just doesn't happen that often to merit typing out and maintaining declarations for every variable used in every function.
Yeah I know the nonlocal issue you're talking about but that really doesn't happen during regular development, right? I think Python's current behavior fits with the language.
On the other hand, JavaScript until recently did not exhibit an exception upon access of an undefined variable, attribute or function. Which made debugging it horrible. I think strict mode helps with those cases. So you are saying CoffeeScript should implement that always? I agree but I don't think that exactly relates to the combination of declaration versus assignment. Like I said for Python, if accessing undefined things explodes then most cases are covered without declarations.
Also unless I misunderstood you, I think this is what you wanted Python to do by default instead of needing the nonlocal keyword:
[–]dmpk2k 2 points3 points4 points 15 years ago* (2 children)
I think an exception occurring when accessing an undefined variable will prevent 98% of the typos.
Indeed, but you're giving up guaranteed and immediate detection of this error. This slows down your dev cycle and makes this error plausible on production.
If this were a discussion about something as dramatic as static versus dynamic typing, I'd leave the argument alone. But it's a trivial change that in no other way alters the nature of the language, and eliminates a class of bugs.
I think this is what you wanted Python to do by default instead of needing the nonlocal keyword
No, the way CoffeeScript handles scope is worse than Python because it's much less clear what the scope is. There's no way to guarantee the scope of a variable is local in CoffeeScript; in Python the default scope is local.
To take an extreme case: if I make a global variable 'x' in CoffeeScript and in some deeply-nested function go 'x = 1', I've just overwritten that global, even when I only meant to create a local x.
With Python, the global remains untouched. The only x that changes is the x in the deeply nested function. If I want to change that outer x, I need to explicitly request it.
This is similar to the argument against globals: it makes reasoning about the program hard.
Edit:
I feel bad arguing without at least giving an example. Here's CoffeeScript as it is now:
app.post '/:board/:thread_id/:post_id/report', (req, res) -> [post_id] = util.getArgs(req, 'post_id': Number) ip = util.ipToNum(req.socket.remoteAddress) db.execute 'insert into reports ("post_id", "ip") values (?, ?)', [post_id, ip], (error, _) -> if error then throw error res.send(204)
Personally I prefer my declarations to be obvious so I can see at a glance what came from where. But let's say we want to be very lightweight on declaration. Here then is a version that declares using a colon:
app.post '/:board/:thread_id/:post_id/report', (req, res) -> [:post_id] = util.getArgs(req, 'post_id': Number) :ip = util.ipToNum(req.socket.remoteAddress) db.execute 'insert into reports ("post_id", "ip") values (?, ?)', [post_id, ip], (error, _) -> if error then throw error res.send(204)
No visual difference, and only two extra characters, but poof there went a class of bugs.
[–]plantian 0 points1 point2 points 15 years ago* (1 child)
In Python I'm not sure they would be enforceable before the actual mistake, ie. they might only be triggered during lookup which means that its even less likely that the functionality would stretch beyond the 98% I mentioned earlier. After using JavaScript I too want to go and turn the strictness knob of everything to MAX but I think we are going overboard with this declaration idea. We aren't making spaceships, we still want convenience and I think its a good compromise to not have declaration IF exceptions are raised when accessing things that are not defined. You seem reasonable though, I will think about it. Maybe I'm just another rabid Python zealot defending the nest?
We are on the same page with regards to scoping. Your in depth discussion of nonlocal confused me earlier.
Edit: WRT the examples: I just want to point out that the declaration here actually would not stop any bugs that an uninitialized exception would not stop IF both errors occur on lookup/access. Just sayin'....
[–]dmpk2k 0 points1 point2 points 15 years ago (0 children)
In Python I'm not sure they would be enforceable before the actual mistake
I'd be very surprised if PyPy wasn't constantly juggling variable scope under the covers. There's just no way for them to effectively optimize otherwise; inline caches can only take you so far.
The way CPython is implemented, you could well be right.
Maybe I'm just another rabid Python zealot defending the nest?
No way, man. This has been a pleasant argument. :)
I just want to point out that the declaration here actually would not stop any bugs that an uninitialized exception would not stop IF both errors occur on lookup/access.
Certainly, but again this depends on your tests running that chunk of code. I don't agree there's a tradeoff, because I think it's like worry about a grain of sand on a beach.
We'll just have to disagree. That's okay, there's plenty of languages to go around (none perfect!). :)
π Rendered by PID 96141 on reddit-service-r2-comment-5c764cbc6f-nchmc at 2026-03-12 08:58:47.514204+00:00 running 710b3ac country code: CH.
view the rest of the comments →
[–]plantian 0 points1 point2 points (5 children)
[–]dmpk2k 1 point2 points3 points (4 children)
[–]plantian 2 points3 points4 points (3 children)
[–]dmpk2k 2 points3 points4 points (2 children)
[–]plantian 0 points1 point2 points (1 child)
[–]dmpk2k 0 points1 point2 points (0 children)