Not quite; @bar is "this.bar", and is an unambiguous reference, not just "bar". In Ruby, because self can be implicit, it's literally just "bar" in both cases, and Ruby gives the local variable precedence over the method name. You can still invoke the method via self.bar, but accessing the method as just "bar" is shadowed by the variable. Additionally, even though the method may be invoked by referencing bar, you can't redefine the method by assigning a new method to bar. Neither Javascript nor Coffeescript has that behavior.
Here's a better example:
Ruby:
def bar
"I called bar!"
end
def foo
puts bar
bar = "I manually assigned bar"
return bar
end
puts foo()
puts bar()
# =>
I called bar!
I manually assigned bar
I called bar!
Coffeescript:
bar = ->
"I called bar!"
foo = ->
console.log bar()
bar = "I manually assigned bar!"
return bar
console.log foo()
console.log bar()
# =>
I called bar!
I manually assigned bar!
TypeError: string is not a function
Your example does demonstrate how CS works. When you assign bar a new value inside its original scope, the value of bar does indeed change.
bar = ->
"I called bar!"
foo = ->
console.log bar()
bar = "I manually assigned bar!"
return bar
console.log foo()
console.log bar()
Here is a slightly less contrived example:
log = (data) ->
console.log data
enhance_logging = ->
i = 0
log = (data) ->
i += 1
console.log i, data
log "no line numbers"
enhance_logging()
log "line one"
log "line two"
Here is the output:
> coffee foo.coffee
no line numbers
1 'line one'
2 'line two'
When I said the two programs have the same behavior, I was simply referring to the end result--what they output. I understand how both languages work here. Ruby solves a problem that simply doesn't exist in CS. In JS/CS "bar" never implicitly refers to "this.bar", so there's no ambiguity in the first place.
Here's a better example:
Ruby:
Coffeescript: