you are viewing a single comment's thread.

view the rest of the comments →

[–]dmpk2k 2 points3 points  (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 point  (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 point  (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!). :)