How much would variable declarations in Ruby make you wince?

  • Thread starter Just Another Victim of the Ambient Morality
  • Start date
R

Robert Klemme

2007/12/10 said:
I too often complain about missing end's.
But I was one of those coders that, in PHP, often forgot a ';'

I cant tell you how happy I am with ruby. No more need for ';'

About the missing end's, over time I kinda developed a habit of
knowing where I made an error and can fix it up quickly.
It is not really that problematic for me. HOWEVER, I would actually
not mind some magical per-file way to omit end's based on
indent. :>

There are actually at least two measures that help preventing this: 1.
use an editor with proper syntax indentation and highlighting. 2.
Exercise the habit to enter matching pairs always together before you
enter the content (some editors will actually help with this as well
because they can enter the matching closing element when you enter the
opening element).

Kind regards

robert
 
M

MonkeeSage

The two most popular sources of bugs for me when programming in Ruby
are:

1) Passing the wrong object as a parameter to a method.
2) Accidentally creating a new variable.

1.) How does predeclaration help?

var l = [1,2,3]
var h = {:a=>"b"}
wants_an_array(h) # => error

2.) While that may alleviate the typo problem, it introduces another
class of bugs which are just as subtle:

var list = create_useful_list
if should_modify_list(list)
# I meant to modify the variable "list" here...
var list = modify_list(list)
end
use_list(list)

Once one became accustomed to typing "var", there is every chance that
it would be used places where a pre-existing variable was meant, but
the "var" just got typed out of habit.

Regards,
Jordan
 
E

Eivind Eklund

2.) While that may alleviate the typo problem, it introduces another
class of bugs which are just as subtle:

var list = create_useful_list
if should_modify_list(list)
# I meant to modify the variable "list" here...
var list = modify_list(list)
end
use_list(list)

Once one became accustomed to typing "var", there is every chance that
it would be used places where a pre-existing variable was meant, but
the "var" just got typed out of habit.

This happens to me in perl, possibly about as often as the typo
problem in Ruby, possibly more. I'll note that I have a habit
intended to avoid typo problems: I fairly consistently use Vim's
"Ctrl-N" (complete based on string search in other parts of code),
even for short strings, just to avoid typos.

Eivind.
 
J

Just Another Victim of the Ambient Morality

Trans said:
def some_method(a,b,c)
contract_for_some_method(a,b,c) if $DEBUG
...
end

def contract_for_some_method(a,b,c)
raise ArgumentError unless a.is_a?(Foo)
raise ArgumentError unless b.is_a?(Bar)
raise ArgumentError unless c.is_a?(Baz)
# or whatever
end

This is interesting but kind of overkill. Checking for a contract is a
non-trivial, especially if you want to keep duck-typing. This would
increase programmer effort so much that it would become comparable to
programming in C, I think...

Why do you have troubles like this? How big are your methods? Keep
them small and this, I think, would be very rare.

They're not that big. Having said that, it's often hard to keep a
method definition too small 'cause, well, sometimes there's a lot to do!
Sometimes there's a lot to do that's inherently related and splitting that
up would serve no logical purpose other than to keep the method definition
small. Finally, I've actually worked with entire programs where no function
body was more than six lines of code. It wasn't understandable nor easy to
work with. It was extremely difficult to tell what any function did and it
was difficult to modify code to do something else. I don't think
artificially keeping method definitions small necessarily solves anything...

The most annoying bug I ever have is tracking an errant "end".

I've had this problem, before, but luckily it's quite rare for me.
Perhaps it's because I've gotten into the habit of typing out my loop bounds
before filling in the loop body. I've always considered this a bad habit of
mine but perhaps it's not so bad...
 
J

Just Another Victim of the Ambient Morality

Dumaiu said:
Hum. Why don't you try comp.lang.ruby.like.but.not.ruby instead? I
hear it's "phat."


Seriously, as someone prone to lack of concentration, I agree. A
great many programmers have concluded, probably from painful
experience, that typed variables reduce error. Also I think that
building error-testing into the code will scale better than reliance
only on unit testing.

I actually don't think this is the case. Statically typed languages
didn't come from long experience with bugs, it was just happenstance...
If I'm not mistaken, typed variables came from a world where compiled
programming languages failed to completely shield the user from the
hardware. Back then, you had to declare variables so that the compiler can
know to allocate them from static store when creating the executable image.
Later on, when functions became more popular, they also had to do this for
the stack. A lot of C syntax comes from how close it is to assembly
language...
 
J

Just Another Victim of the Ambient Morality

Robert Klemme said:
Bottom line: if you want a safer language with typed and declared
variables use one. This is such a fundamental change to the language that
it does not fit in very well. I also suggest to keep methods short. This
will help improve structure of the code and avoid all sorts of other bugs
as well.

Typed variables would be a huge change to Ruby but I disagree that
declaration would be. It's a small, simple change and a feature that many
languages have, including other dynamically typed languages and Ruby's
precurser (if one can call it that). It's a little against Ruby culture but
it's not hard to implement nor would it change the language much...
 
J

Just Another Victim of the Ambient Morality

Todd Benson said:
Hmm. Maybe, but I kind of doubt it. var temp is no more or less
succinct than anything else. It doesn't guarantee you "safeness".
Safeness is what databases are for. Pre-declaration is sort of an
empty promise in flow-control.

You're really not thinking this through.
How on God's green Earth are you going to accidentally prepend an
extraneous "var " (or whatever keyword is decided upon) to a variable's
assignment. Because this is highly unlikely, the described problem will
only happen if you accidentally want to declare a new variable. This is
rather distinct from wanting to use a variable and so the bug should occur
far less frequently...
 
J

Just Another Victim of the Ambient Morality

MonkeeSage said:
The two most popular sources of bugs for me when programming in Ruby
are:

1) Passing the wrong object as a parameter to a method.
2) Accidentally creating a new variable.

1.) How does predeclaration help?

var l = [1,2,3]
var h = {:a=>"b"}
wants_an_array(h) # => error

It wouldn't help at all and no one claimed that it would. Did you read
my post?

2.) While that may alleviate the typo problem, it introduces another
class of bugs which are just as subtle:

var list = create_useful_list
if should_modify_list(list)
# I meant to modify the variable "list" here...
var list = modify_list(list)
end
use_list(list)

Once one became accustomed to typing "var", there is every chance that
it would be used places where a pre-existing variable was meant, but
the "var" just got typed out of habit.

You don't really believe this, do you? Do you program in C/C++ at all?
Do you find yourself accidentally typing "int" when using a variable or
function in that language?
Just because you need this keyword for declaring variables doesn't mean
you're going to get so used to typing it that you'll accidentally type it
out all the time. That's just silly...
 
M

MonkeeSage

You're really not thinking this through.
How on God's green Earth are you going to accidentally prepend an
extraneous "var " (or whatever keyword is decided upon) to a variable's
assignment. Because this is highly unlikely, the described problem will
only happen if you accidentally want to declare a new variable. This is
rather distinct from wanting to use a variable and so the bug should occur
far less frequently...

Far less frequent, given the way you do things now...but just wait
until "var" is the norm; you'll be saying the opposite. When you're
used to typing "var" for everything, you'll inevitably use it in
places you don't mean it. Then the complaint will be that ruby allows
*too much* control. The basic fact is that programmers are fallible,
and no matter how much "safety" is built into the language; there will
still be error between user and keyboard. I might ask how on God's
green earth one could type "liist" instead of "list'...but it happens
anyhow, despite my incredulity.

Regards,
Jordan
 
T

Trans

This is interesting but kind of overkill. Checking for a contract is a
non-trivial, especially if you want to keep duck-typing. This would
increase programmer effort so much that it would become comparable to
programming in C, I think...

Sure, but you asked ;)
They're not that big. Having said that, it's often hard to keep a
method definition too small 'cause, well, sometimes there's a lot to do!
Sometimes there's a lot to do that's inherently related and splitting that
up would serve no logical purpose other than to keep the method definition
small. Finally, I've actually worked with entire programs where no function
body was more than six lines of code. It wasn't understandable nor easy to
work with. It was extremely difficult to tell what any function did and it
was difficult to modify code to do something else. I don't think
artificially keeping method definitions small necessarily solves anything...

Nah... Sure, a lot of small methods requires a little more tracking
around, but if they are named well and organized well the whole will
be much easier to work with and understand. The method names should
actually help self document the program, not obscure it. When you
divide a problem into small components it becomes much more manageable
and easier to test too.
I've had this problem, before, but luckily it's quite rare for me.
Perhaps it's because I've gotten into the habit of typing out my loop bounds
before filling in the loop body. I've always considered this a bad habit of
mine but perhaps it's not so bad...

Of course it is fairly rare (it usually occurs during refactoring, not
first write). But when it does happen I haven't found a better way to
track it down then to just look for it or comment out sections of
code, which sucks. Highlighting would help, but alas my editor does
not support it --even so, it wouldn't completely solve the problem.

T.
 
E

Eivind Eklund

You're really not thinking this through.
How on God's green Earth are you going to accidentally prepend an
extraneous "var " (or whatever keyword is decided upon) to a variable's
assignment. Because this is highly unlikely, the described problem will
only happen if you accidentally want to declare a new variable. This is
rather distinct from wanting to use a variable and so the bug should occur
far less frequently...

It isn't so distinct that the error don't happen, as I've done the
error in Perl. I suspect this has to do with the way either of us
write code; I write a lot of small methods, and I often combine
initialization and variable creation. So, to my mind, first
initialization of a variable is mentally equivalent to declaring the
variable - so I'll just write "my" when I write the first
initialization. When this happens to be inside a code block (e.g,
inside an if statement), I need to expand the context of the variable,
so I'll throw a declaration before the code block.

With Ruby, this is just an initialization - "variable = nil". With
Perl it's "my variable" - alas, that variable is the shadowed by the
other my declaration I wrote later in the code and earlier in time.

I had this bug just last week.

In my opinion, the noise of repeated "var <stuff>"-declarations (or
"my <stuff>" declarations) makes the code less readable, with the
corresponding increase in correctness checking being a benefit of less
worth than the cost. This is the same as my view of (other) type
declarations in most cases: Their cost in terms of being in the way of
code readability/transformability exceeds their benefits.

Eivind.
 
J

Just Another Victim of the Ambient Morality

Eivind Eklund said:
It isn't so distinct that the error don't happen, as I've done the
error in Perl. I suspect this has to do with the way either of us
write code; I write a lot of small methods, and I often combine
initialization and variable creation. So, to my mind, first
initialization of a variable is mentally equivalent to declaring the
variable - so I'll just write "my" when I write the first
initialization. When this happens to be inside a code block (e.g,
inside an if statement), I need to expand the context of the variable,
so I'll throw a declaration before the code block.

I'm not exactly sure what you're describing, here. Are you describing
behaviour in PERL? Is PERL like C/C++, where variables declared in "if"
blocks (or any code blocks, for that matter!) are local to that block? In
Ruby, variables leak right out of if and loop code blocks, so your coding
style wouldn't be any worse off by this change. If I haven't been
misinformed, variables in Ruby blocks (the things that are closures) are
going to leak too, so there will be no situation where your habit will trip
you up. Variable declarations will help prevent some bugs and will not
encourage any others (that I've thought of)!

With Ruby, this is just an initialization - "variable = nil". With
Perl it's "my variable" - alas, that variable is the shadowed by the
other my declaration I wrote later in the code and earlier in time.

I had this bug just last week.

In my opinion, the noise of repeated "var <stuff>"-declarations (or
"my <stuff>" declarations) makes the code less readable, with the
corresponding increase in correctness checking being a benefit of less
worth than the cost. This is the same as my view of (other) type
declarations in most cases: Their cost in terms of being in the way of
code readability/transformability exceeds their benefits.

As I've mentioned, above, there should be no cost except that of
actually having to type it out. My guess is that declarations are far less
common than variable use, so I don't think you'd have to type it out all
that often, either. It will even have the strange side effect of
encouraging funcitonal programming, which is funny...
 
D

Dumaiu

I actually don't think this is the case. Statically typed languages
didn't come from long experience with bugs, it was just happenstance...
If I'm not mistaken, typed variables came from a world where compiled
programming languages failed to completely shield the user from the
hardware. Back then, you had to declare variables so that the compiler can
know to allocate them from static store when creating the executable image.
Later on, when functions became more popular, they also had to do this for
the stack. A lot of C syntax comes from how close it is to assembly
language...


Sounds reasonable. However, I didn't mention the languages'
provenance, but that people continue to be interested in them. And
not just for static typing. People like... you, for example?
 
D

Dumaiu

This happens to me in perl, possibly about as often as the typo
problem in Ruby, possibly more. I'll note that I have a habit
intended to avoid typo problems: I fairly consistently use Vim's
"Ctrl-N" (complete based on string search in other parts of code),
even for short strings, just to avoid typos.

Eivind.


Thank you. That's a good suggestion.

-J
 
D

Dumaiu

Variable declarations will help prevent some bugs and will not
encourage any others (that I've thought of)!

I think what he's describing is a situation something like this:

[Horb-dee-dorb-dee-dorb, I need a new function to say hello.]

def say_hello
var first_name = "Jay"
puts "Hi, #{first_name}."
end

[Great, that works perfectly. Two weeks later: I need to add some
initialization to that.]

def say_hello
init_screen
init_printer
init_window_system
init_text_to_speech

var first_name = "Jay"
puts "Hi, #{first_name}."
end

[Wonderful. Two weeks later: Oh, yeah, I should actually use those
outputs.]

def say_hello(destination)
var destination

if (destination == "screen")
init_screen
if (destination == "printer")
init_printer
if (destination == "window")
init_window_system
if (destination == "voice")
init_text_to_speech

var first_name = "Jay"
destination.puts "Hi, #{first_name}."
end

[Two weeks later: More cruft I don't feel like making up a fake example
for.]

def say_hello(destination)
var destination

if (destination == "screen")
init_screen
if (destination == "printer")
init_printer
if (destination == "window")
init_window_system
if (destination == "voice")
init_text_to_speech

var first_name = "Jay"

var a = 3 * 4 + 5
Thread.join
acts_as_bad_example

destination.puts "Hi, #{first_name}."
end

[Two weeks later: Hey, why is the name even hard-coded?]

def say_hello(destination, first_name)
var destination
var first_name

if (destination == "screen")
init_screen
if (destination == "printer")
init_printer
if (destination == "window")
init_window_system
if (destination == "voice")
init_text_to_speech

var first_name = "Jay"

var a = 3 * 4 + 5
Thread.join
acts_as_bad_example

destination.puts "Hi, #{first_name}."
end

Oooooops.

And even if you remember to delete the hardcoding of "first_name"
completely, you could just as easily misspell it in the new definition.

The problem is that requiring "var" on the first use of a variable works
really well if, and only if, you write all your code in order.


In languages that support this, isn't it normal for the compiler to
generate an error if you declare the same variable twice at the same
scope level? So even if you do make this kind of mistake, it
announces its presence on the first pass?
 
E

Eivind Eklund

As I've mentioned, above, there should be no cost except that of
actually having to type it out.

I think maybe we would communicate better if you read what you were replying to?

One strength of Ruby - an important one - is that it is succinct.
There is very little extra noise compared to what is strictly
necessary to say what the program is doing. Your proposal introduce
extra noise. This noise has a cost for readability in some cases. My
opinion is that this cost is higher than the utility of the construct,
as the construct guard against an error that is easy to guard against
in other ways, other ways that are generally better, like unit
testing or string completion.
My guess is that declarations are far less common than variable use,

This depends on code style. Those that use a lot of short methods
also have more variable declarations compared to variable assignments,
in my experience.

Eivind.
 
D

Dumaiu

Sure, but again, if you mistyped the chronologically-second,
semantically-first var as

def say_hello(destination, first_name)
var destination

Boy, I know that if I were implementing this 'var' stuff, I would
make that illegal too!
var firsst_name

...And that wouldn't get written at all...
Hey, no error, no overlap!

...and the real issue would be how to handle the naming of block
parms, which I don't think has been brought up yet.
Ruby already has a way (several ways, actually!) for all these errors to be
announced on the "first pass". Test::Unit, RSpec, etc.

I can get back to you once I've tried RSpec.

-Jonathan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,262
Messages
2,571,043
Members
48,769
Latest member
Clifft

Latest Threads

Top