A major ruby annoyance!


#1

I am a newbie in Ruby. I have read several books including pickaxe and
wrote
several thousands lines of code. So far, as an ex perl user, I have
found
the major annoyance with ruby is the lack of declaration of variables.
Automatic creation, in perl jargon autovification is the common feature
of
many high level languages such as perl, paython, visual basic etc. but
most
of the these languages have seen that this not necessarily a good thing
and
created flags, commands to prohibit it if the developer wants to. I
really
wish ruby had one. Last several hours I spent debugging a
malfunctioning
code just to see mistyped variable name was causing all the problem. I
had
to put many log statements which polluted to the code.

I guess in Pickaxe book, unit testing is presented as the cure for this
problem which I do not agree. I can not write a test code for every
peace of
little functionality, besides I am eager to make the compiler or
interpreter
to work for me. Why not tell the interpreter to check the code, instead
of
writing very detailed test programs. I am not a very good typist and I
often
mistype variable names, often I had to depend on vim’s auto completion
feature. But I do not want to depend to an editor or an IDE for this.

I have also found the ruby’s -w flag does not work as I perl -w flag
does.
In perl warnings are really descriptive. You can even use a module
called
diagnostics which almost teaches to fix the problem that crashes program
or
generates warning etc. I often do not use -w as because I receive
warnings
from libraries that my code includes or warnings I do not understand at
all.

May be I am the only one who is bothered with these. I do not know.


#2

On May 6, 2006, at 7:00 PM, Talha O. wrote:

thing and
problem which I do not agree. I can not write a test code for every
I have also found the ruby’s -w flag does not work as I perl -w
May be I am the only one who is bothered with these. I do not know.
Only instance variables are auto-vivified.

% irb
irb(main):001:0> puts a
NameError: undefined local variable or method `a’ for main:Object
from (irb):1
irb(main):002:0>

I would suggest using the attr_* methods or writing your own
accessors for any case where you might need to access an instance
varible

@something = exp

is probably a bad sign anywhere but initialize and/or

def something=(x)

end

likewise a = @something should almost always be a = self.something


#3

On May 6, 2006, at 6:00 PM, Talha O. wrote:

I am a newbie in Ruby. I have read several books including pickaxe
and wrote
several thousands lines of code. So far, as an ex perl user, I have
found
the major annoyance with ruby is the lack of declaration of variables.
Automatic creation, in perl jargon autovification is the common
feature of
many high level languages such as perl, paython, visual basic etc.
but most

You can customize autovivification in Ruby. Consider the Hash

h1 = Hash.new { |h,k| h[k] = 0 }
h1[:a] #=> 0

h2 = Hash.new { |h,k| h[k] = 1 }
h2[:a] #=> 1

h3 = Hash.new { |h,k| h[k] = [] }
h2[:a] << “alpha” #=> [“alpha”]

l = lambda { |h,k| h[k] = Hash.new &l }
h4 = Hash.new &l
h[:a][:b][:c] = 5 #=> { :a => { :b => { :c => {} }}}

of the these languages have seen that this not necessarily a good
thing and
created flags, commands to prohibit it if the developer wants to. I
really
wish ruby had one. Last several hours I spent debugging a
malfunctioning
code just to see mistyped variable name was causing all the
problem. I had
to put many log statements which polluted to the code.

You can try to up the warning level. It might also help to make
smaller methods.
I you want, post your code and let some people take a look to give
you some pointers on how to prevent this type of thing.

mistype variable names, often I had to depend on vim’s auto completion
feature. But I do not want to depend to an editor or an IDE for this.

The compiler can’t think for you. In Ruby, a little bit of code can
do a lot,
in fact, a lot more than a compiler can guess at. Consider:

[1,2,3].inject(0) { |prod,x| prod * x }
[1,2,3].inject(1) { |prod,x| prod * x }

How is an interpretive language supposed to know (or take the time to
know)
that the second case is what you want, not the first?

May be I am the only one who is bothered with these. I do not know.

Some mental reprogramming takes time. We can’t brain wash you
overnight. :wink:

Jim F.


#4

I think this is what the OP is getting at. In ruby:

hard_to_spell_variable = 43

puts 'run a few statements'
puts "maybe output the var #{hard_to_spell_variable}"


hard_to_speel_variable = 'a new value' # oops...

print "output the new value."
puts  "  Should == 'a new value': #{hard_to_spell_variable}" # 

doh!!!

Whereas in perl, under the strict pragma, you get:

my $hard_to_spell_variable = 43

# ...

$hard_to_speel_variable = 'a new value' # perl throws a hissy fit.

This does present problems in other places as well. I’ve seen it a
couple of times when people are trying to define DSLs. You want to
force ruby to dispatch to missing_method, but it won’t because it
assumes that you are trying to assign to a new local variable

my_dsl do
  please_dispatch_method = 'some value'
  # undefined local variable!
end

#5

Uhm, I need to correct some hasty typos.

h3 = Hash.new { |h,k| h[k] = [] }
h2[:a] << “alpha” #=> [“alpha”]
should be
h3[:a] << “alpha” #=> [“alpha”]

l = lambda { |h,k| h[k] = Hash.new &l }
h4 = Hash.new &l
h[:a][:b][:c] = 5 #=> { :a => { :b => { :c => {} }}}
should be
h4[:a][:b][:c] = 5 #=> { :a => { :b => { :c => 5 }}}

Jim F.


#6

Weeellll…

if this does really bother you sooo much
(actally it bothers me a bit as well), you
can anytime trap the object creation process.

Simplest possibility would be to add two
functions to allow/disallow/throw-a-fit/or-
whatever-you-like-best on any attempt to
create an object.

Where is the problem?

Regards, 0ffh


#7

Also, how is Ruby meant to know wether something is a typo, or a new
var?

Joey


#8

In my case, I use -w always, and try to depend on autocompletion feature
available
in vim. (^P, ^N, ^XO) Other than that, AFAIK, there are no alternatives
in
the language
which doesn’t have variable declaration feature.

Thought Ruby has syntax check facility, “ruby -wc”, it does not find
typos.
It just check
syntactic errors.

Sincerely,
Minkoo S.


#9

Okay, this should be a start!

---------------- cut here ----------------<

def local(context,*declared)
declared=declared.map{|e| e.id2name}
found=eval(“local_variables”,context)
found.each do |name|
if !declared.include?(name)
raise “hell”
end
end
end

def test
local binding,:foo,:bar
foo=0
bar=0

baz=0 # uncomment to raise hell!

end

---------------- and here ----------------<

Beautify and extend this for a few days,
and you may have something you can live with.

Regards, 0ffh


#10

On May 7, 2006, at 5:00 AM, removed_email_address@domain.invalid wrote:

is probably a bad sign anywhere but initialize and/or
a subsystem (instance variables) that have other uses too.

David

I wans’t suggesting only using ivars for accessors, but I believe
strongly in the uniform access principle. Even if you using ivars for
something completely internal that no one sees, you should still wrap
the accesses to them in methods (private ones).


#11

Hi –

On Sun, 7 May 2006, Logan C. wrote:

likewise a = @something should almost always be a = self.something

It all depends. The attr_* family uses instance variables to do what
it does, but there’s no reason that should be viewed as the only or
best or likeliest use of instance variables. It’s layered on top of
a subsystem (instance variables) that have other uses too.

David


#12

Hi,

Thank you all for the posts. They were all helpful and inspiring. I am
neither live in States(I live in Turkey) nor a native speaker and Louis
J.
Scoras presented my problem beautifully much better than I could. So I
especially thank him for that.

First of all, I would like to say that the problem is valid for all
types of
variables. You can mistype a local variable name in the same block and
you
just create a second variable instantly. You can create an instance
variable
anywhere in the class by adding @ in front of the variable name. If you
mistyped an instance variable name in a method, probably the one you had
properly initialized in your constructor, oops, sorry, you just created
a
new variable and had a brand new bug. If you are agile guy, and spent
double
time writing test for every little functionality, hopefully you would
find
it soon. Nothing protecting us from these kinds of errors. For global
variables, constants they have all the same problem.

What I have understood from all the posts, is that; there is no
syntactical
way for predeclaration of variables. All the solutions that you have
provided includes partial solutions to the problem and includes some
kind
of error handling or conventional code and using them consistently
which I
do not want. According to me, they look ugly in such a consistent
beautiful
language. Besides that kind of custom solutions, according to me, just
increase the complexity of the code.

I would like to comment against posts which simply emphasizes that the
interpreter can not think for us. I know that of course. What if we
could
tell the interpreter by saying that these are the variables that I am
going
to use in the class scope, in a block, in a method or in global scope
etc.
and ask the interpreter not to allow any other variable usage in the
specified scope? Then the interpreter would definitely know our intent?
I
meant that.

What I liked most about ruby how easy to write classes. While using ruby
I
had to mind shift myself persistently for using object oriented
techniques
in even small scripts. Writing classes, using objects are no longer
burden.
The built in attr_* removes all burden of getters and setters etc. For
example to write a class in perl, java, c++ one has to implement all the
getters or setters. In perl, one can use some custom modules from cpan
which
creates a class for you, but all of which all are non-standard
modules.(Okay
some of the most widely used ones come with the distribution, but they
are
not part of the language) There are many other jewels that ruby has
built-in
or in its standard libraries. Ruby made unconventional, custom
implementations made public and mainstream by making them built-in to
the
language as in attr_* example. On the other hand, for the problem that I
present in my post, I am required to implement custom solutions which
partially solve the problem. The problem that I stated here is one of
the
biggest sources of unintentional bugs. Ruby is supposed to cut down
development time and reduce the unintentional complexity dramatically.
It is
one of most high level languages I have encountered. So I believe ruby
should have not missed this feature. I really hope to see that ruby
language
supports these with a new set of keywords in its next releases.
Otherwise, I
do not think that ruby would be able get of out scripting and the
lightweight web world or get into world big production systems. I
believe
ruby has a capacity to go forward if these kinds of doors could be
closed.

Of course, I talk without understanding the language guts. I know that
variables are just references and everything is dynamically decided etc.
It
may not be easy to implement this. I do not know. But as the
user/customer
of ruby, I find that my development time does not dramatically increased
as
much as I expected. Yes I develop faster, but I lose the time that I
gained
in coding in testing. I prefer testing the functionality and the
requirements not the guts. If I can run the code, I expect that language
issues must be solved. I am very much suprised when I receive a no
method
error. Why do I have to run the statement just to see that object does
not
have that method implemented. I would like to deal with bugs that are
caused
by the misapprehension or misimplementation of the problem. I expect the
compiler, interpreter to handle inconsistencies in the language usage
itself. Ruby currently mixes the problem domain with the language
domain
because it does not let developer inform itself about language set the
developer wants to use. I do not expect the language to be as strict as
Ada
by default but it should let the developer to configure how strict the
interpreter should be. In perl, a developer can dynamically command the
perl
interpreter how strictly interpret the code. If perl can, whose latest
major
release about 12 years old, ruby has got to do this.

I prefer a language that loudly shouts at with discriptive information
when
I do something wrong instead of running but producing erroneous results.
Just because of this I have the habit of using zillions of assertions in
my
code when I developed in other languages. I have not been able to find
an
assertion module in ruby by the way (yes I know, you do not need it
because
it is very easy to write one or hey, another answer why do I ever need
it…:)). I really admire you all guys because of your self confidence.

Yes, as the Pickaxe books says strict typing made some code less
portable
and less reusable, but I am ready to make that compromise most of the
time
if my name depends on the correct functionality of the software I wrote.

My comments are not to criticize ruby language and its community but to
contribute to it’s perfection. I already feel myself as rubyist but
want this language make its way more broader domain, even better to my
domain…:slight_smile:

Sincerely.


#13

And now I shall go off on a tangent, demonstrating the seeds of
methods for “declaring variables” in ruby. It’s not complete or
perfect by any means, but I’m sure it can be improved by greater
coders than I. It makes use of Binding.of_caller which for
convenience I have stuck in the actual source file. It also makes use
of an Evil Global Variable?

% cat locals.rb

File lib/extensions/binding.rb, line 107

def Binding.of_caller(&block)
old_critical = Thread.critical
Thread.critical = true
count = 0
cc, result, error = Continuation.create(nil, nil)
error.call if error

tracer = lambda do |*args|
type, context = args[0], args[4]
if type == “return”
count += 1
# First this method and then calling one will return –
# the trace event of the second event gets the context
# of the method which called the method that called this
# method.
if count == 2
# It would be nice if we could restore the trace_func
# that was set before we swapped in our own one, but
# this is impossible without overloading set_trace_func
# in current Ruby.
set_trace_func(nil)
cc.call(eval(“binding”, context), nil)
end
elsif type != “line”
set_trace_func(nil)
error_msg = "Binding.of_caller used in non-method context or " +
“trailing statements of method using it aren’t in the block.”
cc.call(nil, lambda { raise(Exception, error_msg ) })
end
end

unless result
set_trace_func(tracer)
return nil
else
Thread.critical = old_critical
yield result
end
end

File lib/extensions/continuation.rb, line 61

def Continuation.create(*args, &block)
cc = nil
result = callcc { |c|
cc = c
block.call(cc) if block and args.empty?
}
result ||= args
return *[cc, *result]
end

def declare_locals(*symbols)
$__LVARS ||= []
$__LVARS.concat(symbols)
end

def ensure_locals
Binding.of_caller do |b|
lvar_set = eval(‘local_variables’, b)
undecld_vars = lvar_set - ($__LVARS || [])
unless undecld_vars.empty?
warn “Undeclared var(s): #{undecld_vars}”
end
end
end

declare_locals ‘a’, ‘b’
a = 1
b = 2
c = 4
puts a + b
ensure_locals

% ruby locals.rb
3
Undeclared var(s): c

Originally I tried to do this with ‘set_trace_func’ but that doesn’t
apparently have an event for setting a variable.


#14

How about a programming editor that just looks at the variable names you
have and then compares them with others to see if they are similar, the
editor could even pop up a tool tip that says “Hey are you sure you dont
mean {variable_name}?” I am not really familiar with any editor that
does that i am new to programming and ruby altogether but thats what i
would look for if i was having the same issue.


#15

You probably should really invest some time into unittesting - it’s
worth a lot.
And it is true, i spend at least half of my time on unittests (using
RSpec http://rspec.rubyforge.org/ and RubySelenium
http://rubyselenium.rubyforge.org) but have a solution that works ™
and that i can use universally afterwards - always being confident
that it behaves the way i want it to.
I am sorry that I don’t have time to answer lengthy on your mail - but
i have to say that wrapping your head around unittesting is worth the
effort and really rewarding in the end.
ah, and controlled declaration of variables would probably kill me :expressionless:


#16

Talha O. wrote:

Hi,

Thank you all for the posts. They were all helpful and inspiring. I am
neither live in States(I live in Turkey) nor a native speaker and Louis J.
Scoras presented my problem beautifully much better than I could. So I
especially thank him for that.

[snip]

I am not trying to say your concerns are not valid. But every
newbie comes to Ruby and wants to change it.

My advice is always: Use it for 90 days as it is, and then think
about it some more.

The top things, as I recall, that people insist Ruby absolutely
HAS TO HAVE are:

  1. significant whitespace as in Python
  2. braces instead of keyword…end
  3. static typing
  4. variable declarations

But in my opinion Ruby doesn’t “have to have” any of these things.
In fact, Ruby evolved from languages that had those things. It
evolved away from them, not toward them.

Humans’ evolutionary forebears might feel that gills or a tail or
full-body fur are indispensable. I as a human do not feel a special
need for them.

Hal


#17

Hi

I have a good friend from Turkey.
You’ve moved farther than him, he still clings to Perl and thinks
$%; help readability. But other than that, you have a lot of
similarities.

He has no time for unit testing. The reason? He’s too busy fixing bugs.

On May 7, 2006, at 6:18 PM, Talha O. wrote:

meant that.
One could do this. I’m not sure of the performance hit though. Probably
wouldn’t be used by experienced Rubyists.

much as I expected. Yes I develop faster, but I lose the time that
I gained
in coding in testing. I prefer testing the functionality and the
requirements not the guts.

Are you sure? You need to consider the aggregate of time wasted
by your users and yourself from releasing bugs that could have been
caught from simple unit tests. From my experience, coding without
testing is 4x bad. Programmers can produce twice the code with
twice the bugs instead of 1x the code and 0.01x the bugs.

If I can run the code, I expect that language
issues must be solved.

This is not even true with static languages.

I am very much suprised when I receive a no method
error. Why do I have to run the statement just to see that object
does not
have that method implemented.

Try unit testing for a while and you will see. After doing

  1. write code
  2. write test
  3. run test and see it succeed

you start to get paranoid that your tests aren’t being run. :slight_smile:
Seeing them fail, then succeed has a euphoric effect.

I would like to deal with bugs that are caused
by the misapprehension or misimplementation of the problem.

Unit tests help here a lot since you essentially have to state the
problem
from the users perspective.

I prefer a language that loudly shouts at with discriptive
information when
I do something wrong instead of running but producing erroneous
results.

Dynamic languages typically don’t shout. Ruby has much more decorum.

Just because of this I have the habit of using zillions of
assertions in my
code when I developed in other languages. I have not been able to
find an

Why are you willing to write assertions but not unit tests?

Jim F.


#18

On 5/8/06, Corey removed_email_address@domain.invalid wrote:

How about a programming editor that just looks at the variable names you
have and then compares them with others to see if they are similar, the
editor could even pop up a tool tip that says “Hey are you sure you dont
mean {variable_name}?” I am not really familiar with any editor that
does that i am new to programming and ruby altogether but thats what i
would look for if i was having the same issue.

I saw a Perl module once that caught any exceptions in your running
code,
and decided for itself what you really meant. So if you mis-typed a
variable name, it took a guess at the variable you might have intended
to
use.

That only worked when the code was actually running, so not quite the
same.
It was pretty funny though… I bet you could knock up a Ruby version in
a
day.

;Daniel

PS I couldn’t find it after 90 seconds of searching on CPAN. Anyone
else
remember this?


#19

On May 7, 2006, at 9:56 PM, Roy S. wrote:

I’m not sure why everyone automatically assumed he did not use unit
testing. Unit testing certainly can point out there -is- an
error. The fix he proposes for his problem (typoing variable
names) tells him -where- the problem is. Unit tests can tell you
generally where you problem is but it still takes the debugging
work to step in and find out what -caused- the problem. I think
people are doing Talha a disservice by assuming that if he just
tested better his problems would go away.

There have been a couple of good suggestions, but they don’t exist
yet. One was an editor
that understood Ruby and could flag new variables. The other was an
addition to the Ruby
parser to point out new variables. Sadly, these don’t exist.

I can’t remember the last time I had a typo problem with Ruby. Years
ago. And it only lasted
a few seconds. However, I did just have one today with Rails, but
that was with a filename.
(It had the wrong pluralization.) That problem lasted for about 45sec.

If this is Talha’s biggest problem, then he’s doing better than most
and us mere mortals
can’t relate. :slight_smile:
The reality is I don’t see typo’s being a big problem for most people
and costing huge chunks
of time on a continuous basis.

Concerning unit testing, Talha may be doing unit testing, but he sure
is complaining
alot about it being non productive. I think most people are saying
that unit testing
is more productive than he realizes, he just needs to give it some time.

Jim F.


#20

Jim F. wrote:

specified scope? Then the interpreter would definitely know our
intent? I
meant that.

One could do this. I’m not sure of the performance hit though. Probably
wouldn’t be used by experienced Rubyists.
I doubt very much there’d be a performance hit at all for this.

I am very much suprised when I receive a no method
error. Why do I have to run the statement just to see that object
does not
have that method implemented.

Try unit testing for a while and you will see. After doing

  1. write code
  2. write test
  3. run test and see it succeed

I’m not sure why everyone automatically assumed he did not use unit
testing. Unit testing certainly can point out there -is- an error. The
fix he proposes for his problem (typoing variable names) tells him
-where- the problem is. Unit tests can tell you generally where you
problem is but it still takes the debugging work to step in and find out
what -caused- the problem. I think people are doing Talha a disservice
by assuming that if he just tested better his problems would go away.

Roy