Static typing ain't so bad, after all...

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

Just Another Victim of the Ambient Morality

I was debugging someone else's code the other day (it was htmltools,
actually) and I was in the middle of some function trying to figure out
what it does. That's when I noticed that I had no clue what the passed in
parameter was. I mean, I can see how it was used but it really didn't
reveal what it was. In fact, it could have been anything. I could have
tried to do a search to see when this method was called and try to
investigate what was passed in at each instance but that would not
necessarily be revealing since the object may not have been created in
those methods and, instead, passed into them.
The problem is that dynamic typing, while very powerful, also hid the
intent of the method. Obviously, any object that satisfied whatever the
method was trying to do will suffice as a parameter, and that would be the
point of duck typing, there was obviously some concrete example of some
type the method was expecting. It would really have helped to let me know
what that was...
Now, the answer to this is simply better documentation. Write a damn
comment that says what the method is expecting and, hell, while you're at
it, you could mention what the method does, too. However and
unfortunately, I've been a professional programmer way too long to expect
code to come with good documentation. Out here, in the real world, you're
lucky if the code works...
Has anyone noticed this? How do you deal with this issue?
Thank you...
 
F

Farrel Lifson

I was debugging someone else's code the other day (it was htmltools,
actually) and I was in the middle of some function trying to figure out
what it does. That's when I noticed that I had no clue what the passed in
parameter was. I mean, I can see how it was used but it really didn't
reveal what it was. In fact, it could have been anything. I could have
tried to do a search to see when this method was called and try to
investigate what was passed in at each instance but that would not
necessarily be revealing since the object may not have been created in
those methods and, instead, passed into them.
The problem is that dynamic typing, while very powerful, also hid the
intent of the method. Obviously, any object that satisfied whatever the
method was trying to do will suffice as a parameter, and that would be the
point of duck typing, there was obviously some concrete example of some
type the method was expecting. It would really have helped to let me know
what that was...
Now, the answer to this is simply better documentation. Write a damn
comment that says what the method is expecting and, hell, while you're at
it, you could mention what the method does, too. However and
unfortunately, I've been a professional programmer way too long to expect
code to come with good documentation. Out here, in the real world, you're
lucky if the code works...
Has anyone noticed this? How do you deal with this issue?
Thank you...

In my experience the way to handle this is to have parameters and
variables with logical, consistent names. If I'm debugging a function
'foo(i)' it's almost impossible to know what is. If the function
instead was defined as 'foo(categoryName)' it's a lot easier to deduct
that it's a (string or an object that should be able to ducktyped to a
string).

Farrel
 
L

Lyle Johnson

Has anyone noticed this? How do you deal with this issue?

Most of the time I'm able to deduce what kind of object the method is
expecting, but I agree that sometimes I have to do a lot of detective
work to find out how to use the code.

If an object is passed in to a method, and is *only* used within that
method, it's usually straightforward to just use the duck typing
assumption: I just need to pass in some object that's capable of
responding to the messages that will be sent to it in this context.

But what if the object is passed down into some other method as an
argument? Or stored in an instance variable for later use? In those
situations, I have to chase that rabbit all around the code, seeing
how it's used elsewhere, before I can know for sure what kind of
object I need to provide.

It's definitely a documentation issue, in my book. But I'm looking
forward to other responses.
 
D

dblack

Hi --

I was debugging someone else's code the other day (it was htmltools,
actually) and I was in the middle of some function trying to figure out
what it does. That's when I noticed that I had no clue what the passed in
parameter was. I mean, I can see how it was used but it really didn't
reveal what it was. In fact, it could have been anything. I could have
tried to do a search to see when this method was called and try to
investigate what was passed in at each instance but that would not
necessarily be revealing since the object may not have been created in
those methods and, instead, passed into them.
The problem is that dynamic typing, while very powerful, also hid the
intent of the method. Obviously, any object that satisfied whatever the
method was trying to do will suffice as a parameter, and that would be the
point of duck typing, there was obviously some concrete example of some
type the method was expecting. It would really have helped to let me know
what that was...
Now, the answer to this is simply better documentation. Write a damn
comment that says what the method is expecting and, hell, while you're at
it, you could mention what the method does, too. However and
unfortunately, I've been a professional programmer way too long to expect
code to come with good documentation. Out here, in the real world, you're
lucky if the code works...
Has anyone noticed this? How do you deal with this issue?

I think a good first step is to read "Programming Ruby" by Dave Thomas
et al., especially the part where he explains in detail that type and
class are not the same thing in Ruby.

Also, please -- PLEASE -- read the hundreds, or perhaps thousands, of
posts about this in the ruby-talk archives. I'm not optimistic about
breaking the cycle; it seems we're doomed to have this thread repeated
three or four times a year. But, I don't know, maybe one of these
years we can stop.

Don't take my curmudgeonliness personally. It's just that there's
really not much else left to say on the topic.


David

--
http://www.rubypowerandlight.com => Ruby/Rails training & consultancy
----> SEE SPECIAL DEAL FOR RUBY/RAILS USERS GROUPS! <-----
http://dablog.rubypal.com => D[avid ]A[. ]B[lack's][ Web]log
http://www.manning.com/black => book, Ruby for Rails
http://www.rubycentral.org => Ruby Central, Inc.
 
F

Francis Cianfrocca

At the risk of sounding flip, I would give two answers. First, don't
name your methods "foo." There was a criticism upthread of
parameter-names that are nonindicative of their purpose, and that
certainly matters if your methods take more than one parameter. But
even more important (in addition to proper documentation) is to name
your methods well. Method names (ideally) should be verbs, long enough
to indicate what they do as precisely as possible, but short enough
not to offend the eye. Another problem is adding side-effects to
methods after they've been defined and named, when you're modifying
your code later on. When you do this, your method is now misnamed and
will give you less help as you (or someone else) tries to read your
code. In addition, well-named methods generally tend to be smaller,
which is a plus in the Ruby stylebook.

The second (flip) answer to your question is: "it doesn't matter."
Most of the time when duck-typing is working well, there is little
question about the right kind of argument for a method. Especially
since you're writing your documentation as you write your methods.
When there is a mismatch, your unit tests will generally emit an error
that's not hard to diagnose. There are cases when you'll tear your
hair out over a hard-to-find type error, and these cases are the heart
of the argument against dynamic typing, but in practice they are very
few indeed.

Another point of style is to write methods in anticipation that they
will be called with several different types (like Arrays or Strings,
or any of a raft of IO types) and just do the right thing in your
method.
 
T

Trans

Just said:
I was debugging someone else's code the other day (it was htmltools,
actually) and I was in the middle of some function trying to figure out
what it does. That's when I noticed that I had no clue what the passed in
parameter was. I mean, I can see how it was used but it really didn't
reveal what it was. In fact, it could have been anything. I could have
tried to do a search to see when this method was called and try to
investigate what was passed in at each instance but that would not
necessarily be revealing since the object may not have been created in
those methods and, instead, passed into them.
The problem is that dynamic typing, while very powerful, also hid the
intent of the method. Obviously, any object that satisfied whatever the
method was trying to do will suffice as a parameter, and that would be the
point of duck typing, there was obviously some concrete example of some
type the method was expecting. It would really have helped to let me know
what that was...
Now, the answer to this is simply better documentation. Write a damn
comment that says what the method is expecting and, hell, while you're at
it, you could mention what the method does, too. However and
unfortunately, I've been a professional programmer way too long to expect
code to come with good documentation. Out here, in the real world, you're
lucky if the code works...
Has anyone noticed this? How do you deal with this issue?
Thank you...

Zen.

T.
 
W

William Crawford

Just said:
The problem is that dynamic typing, while very powerful, also hid
the
intent of the method.

For preventing the problem, my answer is the same as everyone else's...
Good naming techniques.

For figuring them out... Unit Testing! If it doesn't already have some
tests, write some. As Francis said, you'll get some informative
messages back. It's kind of a perversion of unit testing, but I often
use it to quickly experiment with classes I don't completely understand.
Once I can make working tests for something, I usually understand it
pretty well. And I've always got them to look back at in case I forget
how I managed to make it work. (Without hunting through tons of code.)

As for static typing... I feel your pain. It's heresy, but I prefer
static typing. Inheritance provides everything I need that Duck Typing
does for me. (At least, so far. I'm really new to Ruby.)

-sigh- Victim, your name triggers the spam filter here. Am I the only
one annoyed by this?
 
J

Just Another Victim of the Ambient Morality

Hi --



I think a good first step is to read "Programming Ruby" by Dave Thomas
et al., especially the part where he explains in detail that type and
class are not the same thing in Ruby.

I don't think this semantic argument has much to do with my problem...

Also, please -- PLEASE -- read the hundreds, or perhaps thousands, of
posts about this in the ruby-talk archives. I'm not optimistic about
breaking the cycle; it seems we're doomed to have this thread repeated
three or four times a year. But, I don't know, maybe one of these
years we can stop.

I don't know what you're talking about. What is this "ruby-talk" of
which you speak? I assume that, whatever it is, it has archives...
I've been on this newsgroup for some time now and I haven't heard
anyone complain about this so either you're exaggerating the frequency of
this question or you're very impatient...

Don't take my curmudgeonliness personally. It's just that there's
really not much else left to say on the topic.

I don't take your "curmudgeonliness" personally, although I suspect
that there's plenty to say about this topic...
 
D

dblack

Hi --

I don't think this semantic argument has much to do with my problem...



I don't know what you're talking about. What is this "ruby-talk" of
which you speak? I assume that, whatever it is, it has archives...

ruby-talk is this mailing list. It's mirrored to comp.lang.ruby.
Have a look at
http://blade.nagaokaut.ac.jp/ruby/ruby-talk/index.shtml. You can
start with the 694 messages that come up on a search for "static
typing". Then the 393 on "strong typing". Then see what's left to
say about typing, class vs. type, strong vs. static, duck vs.
whatever....

Also, see http://www.rcrchive.net/rejected.html#rcr120.

Honestly, this is, like, the king of ruby-talk perma-threads. You can
rehash the thread if you end up feeling it's necessary, but do please
look at the six years of discussion and analysis first.


David

--
http://www.rubypowerandlight.com => Ruby/Rails training & consultancy
----> SEE SPECIAL DEAL FOR RUBY/RAILS USERS GROUPS! <-----
http://dablog.rubypal.com => D[avid ]A[. ]B[lack's][ Web]log
http://www.manning.com/black => book, Ruby for Rails
http://www.rubycentral.org => Ruby Central, Inc.
 
J

Just Another Victim of the Ambient Morality

Farrel Lifson said:
In my experience the way to handle this is to have parameters and
variables with logical, consistent names. If I'm debugging a function
'foo(i)' it's almost impossible to know what is. If the function
instead was defined as 'foo(categoryName)' it's a lot easier to deduct
that it's a (string or an object that should be able to ducktyped to a
string).

...but this is often not enough. What if the parameter is called
"node." In context, how can this be better? "parse_node?"
"html_parse_node?" What's in this "html_parse_node?" Is it lazy parsing
or did it do the processing as it parsed and the node contains the parsed,
processed data? How would I know this? I can't look up any of the objects
that will be passed in because any object can be passed in; this language
is dynamically typed! I could look for a "class Node" in the hopes that
that is the name of one of the object classes passed in but who knows? It
could be called anything and there's no way for me to know what that
anything is!
If the language were statically typed, I would know straight away what
type the parameter was and can look up, exactly, what it does and can
probably easily discern what it's role is.

Now, don't misunderstand me, I'm not advocating turning Ruby into a
statically typed language. I enjoy that Ruby has no "templates" (in the
C++ sense) because every method is "templatized!" The mere fact that C++
has templates is testimony to the power of dynamic typing. I'm just saying
that static typing "ain't so bad," in that this is one problem I would not
have had were I working with a statically typed language. I'm also looking
for how people deal with this issue, since it surely must come up from time
to time...
 
J

Just Another Victim of the Ambient Morality

William Crawford said:
For preventing the problem, my answer is the same as everyone else's...
Good naming techniques.

For figuring them out... Unit Testing! If it doesn't already have some
tests, write some. As Francis said, you'll get some informative
messages back. It's kind of a perversion of unit testing, but I often
use it to quickly experiment with classes I don't completely understand.
Once I can make working tests for something, I usually understand it
pretty well. And I've always got them to look back at in case I forget
how I managed to make it work. (Without hunting through tons of code.)

As for static typing... I feel your pain. It's heresy, but I prefer
static typing. Inheritance provides everything I need that Duck Typing
does for me. (At least, so far. I'm really new to Ruby.)

-sigh- Victim, your name triggers the spam filter here. Am I the only
one annoyed by this?

Yeah, I'm sorry about the spam filter. I've been using this name for
about a decade now and I'm a little reticent about giving up my anonymity
(although, really, now anonymous can I be after using the same name for so
long?). At least it's a fairly unique name to search for in google news.
You can see how helpful (or not) I've been during my entire usenet career!
If your spam filter was triggered, how did you come to read my post?
I'm also interested to hear if anyone else is annoyed by my name...
 
L

Leslie Viljoen

...but this is often not enough. What if the parameter is called
"node." In context, how can this be better? "parse_node?"
"html_parse_node?" What's in this "html_parse_node?" Is it lazy parsing
or did it do the processing as it parsed and the node contains the parsed,
processed data? How would I know this? I can't look up any of the objects
that will be passed in because any object can be passed in; this language
is dynamically typed! I could look for a "class Node" in the hopes that
that is the name of one of the object classes passed in but who knows? It
could be called anything and there's no way for me to know what that
anything is!
If the language were statically typed, I would know straight away what
type the parameter was and can look up, exactly, what it does and can
probably easily discern what it's role is.

I have on occasion solved this problem by putting "breakpoint" as the
first line of the method and then inspecting the object that was
received in a debug console. Of course that doesn't always work or
can't always be done, but it has been useful.

Something else that bothers me is that sometimes code raises
exceptions, sometimes it returns nil, and when programming I often
can't decide which is better. When I go with the 'nil' approach I find
myself hunting for where the object became 'nil', often several
methods back. Anyone have any guidelines on this?

Les
 
G

Gene Tani

I think a good first step is to read "Programming Ruby" by Dave Thomas
et al., especially the part where he explains in detail that type and
class are not the same thing in Ruby.

McConnell's Code Complete, too, for basic engineering practices

http://cc2e.com/
 
A

ara.t.howard

If the language were statically typed, I would know straight away what
type the parameter was and can look up, exactly, what it does and can
probably easily discern what it's role is.

i think that's a silly thing to say. straight away, tell me what role this
function plays:

void (*signal(volatile int x, void (*const y)(int )))(int );

??

and i don't think that's being unfair. the reason is that static typing
builds up mountains of information for even mildly complex function
definitions. there is a reason a program exists (cdecl) to decode them! it's
very existence backs my assertion that little can be groked 'staight away'
merely by statically/explicitly typing function signatures.

in addition, languages like ocaml, while also statically typed, leave this
information out of the source while still be readable:

let double x = x * 2;;

let sum x y = x + y;;

let factorial x =
if (0 > x) then (raise Exit) else
match x with
0 -> 1
| n -> (n * (factorial (n - 1)));;


notice - this is statically typed. also notice the lack of explicitly encoded
typing - the compiler figures it out.

my point, in going down this tangent, is hopefully to point out what i always
point out in these threads - that people generally do not even understand what
it means to be statically (c is static ruby is not) or strongly typed (ruby is
strongly typed, c and java are not) and, furthermore, that having this
explicitly written by the programmer has nothing to do with the existence if a
feature in the language - taking ocaml's type inference as an example.

so, to drive it home further, you seem to think 'static' means 'explicitly
written by the programmer' - but of course that's not what it means.
fortunately, the 'explicit' route is available to you in ruby by simply
following certain pratices, either comment functions or cast arguments using
the 'class name as casting ctor pattern' used all over the place in ruby. for
isntance

def m a, b, c
a = String a
b = Integer b
c = Float f

....
end

now, that's not static, but it is explicit. you can obivously follow this
pattern with user defined classes.

regards.

Now, don't misunderstand me, I'm not advocating turning Ruby into a
statically typed language. I enjoy that Ruby has no "templates" (in the
C++ sense) because every method is "templatized!" The mere fact that C++
has templates is testimony to the power of dynamic typing.

templates are not dynamic typing though - i'd say they are testimony to how
much of a bastard a strong/static/non-inferred type system can be and how
adding compiler features to do the work for us is essential. note that
templates and any other sort of compiler inference feature __remove__ explicit
type info from the source!
I'm just saying that static typing "ain't so bad," in that this is one
problem I would not have had were I working with a statically typed
language.

correct - you'd simply have different ones.
I'm also looking for how people deal with this issue, since it surely must
come up from time to time...

well, i showed one solution above. there are plenty of others.

cheers.

-a
 
W

William Crawford

Just said:
If your spam filter was triggered, how did you come to read my post?
I'm also interested to hear if anyone else is annoyed by my name...

I use http://www.ruby-forum.com actually. It's their spam filter that
freaks out about it. The only 'problem' with your name is that I can't
post anything with your name in it, hence the replacement in the quote.
 
C

Chris Gehlker

Has anyone noticed this? How do you deal with this issue?

I must be missing something. i can't see why you didn't just ask the
debugger by typing <parametername>.class
 
J

Just Another Victim of the Ambient Morality

Chris Gehlker said:
I must be missing something. i can't see why you didn't just ask the
debugger by typing <parametername>.class

That's a good question...
I wasn't looking at the source at runtime... I could have run it and
stuck a breakpoint but that's when the problem occured to me. In a
hypothetical case, the code might be hard to execute. Indeed, if you're
looking at someone else's code then you might have no clue as to how to
execute it. You could write some code to call it directly but that
wouldn't give you insight into how the method is used.
In my case, the debugger is really slow and it would have taken quite a
while to reach the breakpoint...
 
C

Chris Gehlker

That's a good question...
I wasn't looking at the source at runtime...

Aha, I interpreted "I was debugging..." as "I was running the debugger"
I could have run it and
stuck a breakpoint but that's when the problem occured to me. In a
hypothetical case, the code might be hard to execute. Indeed, if
you're
looking at someone else's code then you might have no clue as to
how to
execute it.

True, but I don't see how static typing would help in this case.
You could write some code to call it directly but that
wouldn't give you insight into how the method is used.

But there are times when you can figure out how to call the code that
calls the code without starting from the very beginning.
In my case, the debugger is really slow and it would have taken
quite a
while to reach the breakpoint...

True, the debugger is sometimes very slow when executing up to a
breakpoint. Sometimes I fall back on print statements.

---
Neither a man nor a crowd nor a nation can be trusted to act humanely
or to think sanely under the influence of a great fear.

-Bertrand Russell, philosopher, mathematician, author, Nobel laureate
(1872-1970)
 
C

Chris Gehlker

you can try ruby-debug extension. It's several times faster than
standard
debug.rb

gem install ruby-debug

Kewl,
Some times the best part of these threads is the parenthetical advice.
 
I

Isaac Gouy

i think that's a silly thing to say. straight away, tell me what role this
function plays:

void (*signal(volatile int x, void (*const y)(int )))(int );

??

and i don't think that's being unfair. the reason is that static typing
builds up mountains of information for even mildly complex function
definitions. there is a reason a program exists (cdecl) to decode them! it's
very existence backs my assertion that little can be groked 'staight away'
merely by statically/explicitly typing function signatures.

in addition, languages like ocaml, while also statically typed, leave this
information out of the source while still be readable:

let double x = x * 2;;

let sum x y = x + y;;

let factorial x =
if (0 > x) then (raise Exit) else
match x with
0 -> 1
| n -> (n * (factorial (n - 1)));;


notice - this is statically typed. also notice the lack of explicitly encoded
typing - the compiler figures it out.

Yes type inference is wonderful, and for completeness let's note that
in OCaml (and Haskel and Clean and...) we can also choose to add
explicit type declarations.
my point, in going down this tangent, is hopefully to point out what i always
point out in these threads - that people generally do not even understand what
it means to be statically (c is static ruby is not) or strongly typed (ruby is
strongly typed, c and java are not) and, furthermore, that having this
explicitly written by the programmer has nothing to do with the existence if a
feature in the language - taking ocaml's type inference as an example.

Maybe part of it is easier to understand if we speak about
statically-type-checked and dynamically-type-checked.

What people mean by "strongly typed" is more puzzling to me. I'll just
agree with this:

'So what is "strong typing"? This appears to be a meaningless
phrase, and people often use it in a nonsensical fashion. To some it
seems to mean "The language has a type checker". To others it means
"The language is sound" (that is, the type checker and run-time
system are related). To most, it seems to just mean, "A language like
Pascal, C or Java, related in a way I can't quite make precise". If
someone uses this phrase, be sure to ask them to define it for you.
(For amusement, watch them squirm.)'

p263 Type Soundness, "Programming Languages: Application and
Interpretation"
http://www.cs.brown.edu/~sk/Publications/Books/ProgLangs/
 

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

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,739
Latest member
Clint8040

Latest Threads

Top