Begining programmer questions

Hi –

On Mon, 15 May 2006, Francis C. wrote:

with Klassname.new, or one of the shorthands like x=[]). Of course, if you
call a method that returns an object, that object will have a type
(determined by the writer of the method) and you can use it without
declaring it, but that doesn’t mean Ruby figured out the type on its own.

It sounds like you’re talking about class, rather than type. A
string, for example (that is, an object that says “String” when you
ask it its class), can allow integers to be added to it, and is
therefore of class String but of type “string-like thing that lets
you add integers to it” (or whatever).

So the type of Ruby objects is almost a tautology: the type of object
o is “the type of objects that have the capabilities and interface of
object o.” Class, meanwhile, though more tangible in a sense, is only
the starting point for the object’s life-cycle.

David

Agreed. In fact, at its core, I would say that Ruby is “untyped,”
since everything is of the same type (Object). The only meaningful
information about the qualifications of an object for a certain task
is whether it responds to certain necessary methods, as you said.
Based on this, I would say that Ruby simply attempts to blindly
execute the code with no type checking at all, but simply chokes if
a method is missing. Is this a bad way to think of it?

  • Jake McArthur

On 5/14/06, Bill G. [email protected] wrote:

On 5/14/06, corey konrad [email protected] wrote:

yup i’ll get it, need a break now though, you know when you read tacos
as a misspelling of “to cos” that you have been studying programming and
math all day.

Yeah, definitely a natural. It won’t be long before you wake up
dreaming of code :wink:

Oh man, code comes to you at the WEIRDEST times. I can’t tell you how
many times I’ve half-woken up at 3am, and in that mid-dreamy state
somehow figured out the answer to a problem. Then I hop out of bed
and make it happen. Sometimes it doesn’t work, and then you’re like,
“It’ll only take 10 minutes or so” and you find yourself still
pounding at the keyboard at 7am. “hrm, better shower and go to work.”
I like it better when my dream code works perfectly though :slight_smile:

Also, I have a lot of answers come to me in the shower for some
reason. I keep a small whiteboard and grease pen in the shower so I
can write it down, instead of prematurely ending my shower or having
to repeat the solution in my head over and over until I’m done.

Corey, don’t worry if some of this stuff seems hard. I remember when
I first started, I would literally stare at the same 10 lines of code
for hours, not having any clue that I was just missing a semicolon or
something stupid like that. The very beginning is cumbersome, to say
the least, but it teaches you perhaps one of the most important things
about programming - how to read documentation and look up errors.

Pat

Hi –

On Mon, 15 May 2006, Jake McArthur wrote:

object o." Class, meanwhile, though more tangible in a sense, is only
the starting point for the object’s life-cycle.
Agreed. In fact, at its core, I would say that Ruby is “untyped,” since
everything is of the same type (Object). The only meaningful information
about the qualifications of an object for a certain task is whether it
responds to certain necessary methods, as you said. Based on this, I would
say that Ruby simply attempts to blindly execute the code with no type
checking at all, but simply chokes if a method is missing. Is this a bad way
to think of it?

I would apply the word “class” to Object (rather than type), and leave
“type” available for that other thing you’re talking about – the
thing where a given object can do some things and not do others.
People sometimes refer to this as an object’s “duck type”, but it’s
really just its type (and duck typing is, in my view, simply
programming in Ruby in a way that embraces how type [not “duck type”]
operates).

I think it’s right to say that variables are untyped, but not that
objects are. It’s true, though, that type – understood as the
aggregate of an object’s capabilities at some given point in runtime
– is almost an invisible concept. No designation or discussion of an
object’s type actually has any bearing on what happens when that
object gets sent a message.

Of course the vast majority of Ruby objects that get created do not,
in fact, deviate from the type laid down by their class. But when
they do, the only way to understand what’s happening is to have
understood already that they can. Without that understanding, even
something like class methods (where a particular Class instance
deviates from the type of a freshly-created Class instance) becomes a
huge mystery. And then we start hearing about running with scissors,
and rope and shooting in foot, and all that :slight_smile:

David

I have to admit I don’t understand the distinction you’re making between
“class” and type. To level-set: I care about this discussion primarily
because plenty of people (but no one on this thread, of course)
criticize
Ruby as being less strongly-typed than C++ or Java, whereas the truth is
that Ruby is dynamically typed rather than weakly typed. In Ruby, an
object never changes its type (although delegation and the ability to
add
methods to a single object instance also may make it seem like it does).

More to the point, Ruby will never implicitly perform operations on an
object that are not part of its type, as a result of inferences about
some
particular statement of code. This Ruby code will generate an error:
“abc” + 5
because Fixnum can’t be an argument to the String method named +. Both C
and
Ruby will perform certain type-transformations automatically (mostly
widening numeric types) but these are well defined and stated upfront in
the
language definition.

Weak typing (such as you see in languages like Perl and Javascript) can
often be the source of very difficult errors. Ruby and other dynamic,
strongly-typed languages (Python) don’t go this far. However, they do
relax
the requirement that the object bound to a particular variable be
constant
throughout the run of a program. Types are attributes of objects, not of
variables. For example:
a = “abc”
b = a
a = 5
isn’t permitted in a static program but is permitted in a dynamic one.
The
object “abc” (of type String) still exists (it’s bound to variable b at
the
end of the fragment) but it’s meaningless to speak of the type of
variable
a. Rather, at the end of the run, a is bound to an object of type Fixnum
(and value 5). This throws people who are used to the fact that
compilers
can find a large class of errors in languages that don’t permit
variables to
be rebound to objects of different types. However, the key insight of
dynamic languages is that this class of statically-discoverable errors,
while large, is not deep or difficult.

I’ve noticed that younger programmers seem to have much less conceptual
trouble with “duck typing” and dynamic languages than older people like
me.
I wonder if it’s because for a while, CS programs taught people with
functional languages like Scheme, where the distinction between objects
and
variable-bindings is explicit and clear. (Nowadays of course, all the
younger people coming out of university seem to have learned nothing but
Java…)

Hi,

On Mon, May 15, 2006 at 08:46:58AM +0900, Michael G. wrote:

puts info
end

Hmmm... note that the "sort" method _doesn't_ change the object. You

should put either (1) info.sort! instead of info.sort, or (2) replace
both
lines with “puts info.sort”.

Logan C. [email protected] writes:

I don’t
know if ruby is necessarily the best programming language for a
beginner either, since it was designed by Matz. for Matz. (And I’m
pretty sure Matz. isn’t a beginning programmer).

That’s the reason it is that good. :slight_smile:

Now, if there only was a way to become an expert programmer without
being influenced by the languages you (had to) use to become one—I
really wonder what that language would look like.

Francis C. wrote:
(Nowadays of course, all the

younger people coming out of university seem to have learned nothing but
Java…)

At the risk of tangenting a tangent, I’ve noticed this as well. I’m very
curious why this is the case. My best guess right now is that many CS
professors are very fimilar with C or C+ and Java seems a bit easier to
teach than either of them to undergrads. It’s an easy step to teach Java
for them; easy for the professor to pick up and apply a lot of concepts
that they used to teach in C, since the syntax for C and Java is very
similar, and easier to teach than C in some ways.

If this is the case, then its seems like a weird reason to have a lot of
people coming out of university coding in Java.

I’m not the original OP, but found this post quite helpful. But, in the
interest of knowing what’s going on under the hood, I wanted to expound
on
some things (based on my understanding) to find out if my understanding
is
correct:

On Sunday 14 May 2006 08:50 pm, Daniel B. wrote:

there". Here’s a picture:

info ----------> String “hello there”

Actually, to be a little more pedantic, it creates a string in memory
containing “hello there” and then creates a variable info which points
to it.
(?)

When you say:

info = []

…that makes a pointer from the variable “info” to a new, empty array.

Again, this creates a new, empty array in memory, then changes the
contents of
the variable info to point to it instead of to the string containing
“hello
there” (that may be a stilted way of saying it).

The string “hello there” still exists in memory, but (unless something
else
has been done, like another variable created (not mentioned so far)
pointing
to that string), it is no longer accessible and is subject to garbage
collection (when Ruby, in it’s infinite wisdom, decides it is
appropriate to
collect garbage). (?)

Randy K.

PS: Just to go off on a tangent, for a (poor) programmer with experience
in
some other languages, in some other languages, the:

info = “hello there”

statement might create a string in memory and permanently associate
“info”
with the address of that string.

If someone then tried:

info = []

either that address in memory would have “hello string” wiped out and
replaced
with an empty array, or (in a typed language), the statement
would fail because the types don’t match.

Well, I have a somewhat different theory. Because remember five to ten
years ago, when all the young people were coming out having learned
Scheme and nothing else, so they were useless? I think someone told
the professors they need to train people for the real world, but they
responded by picking Java as the default choice. Seems like it would
be nice to find a happy medium between solid training in CS
fundamentals and practical knowledge. The Java training they’re
getting now seems to be little more than recipes.

On May 15, 2006, at 12:50 PM, Regg wrote:

I would have hoped that once a type has been established for an
object,
the object would only adhere to the rules of that object…not change
itself into a new object type.

This is the case. However, variables are only references and are
themselves “typeless,” in a sense. While you cannot change the object
a variable points to from one type to another, you can have the
variable point to a different object entirely which can be of a
different type. Here is something that won’t work:

“5” + 5

Since the two objects are different types, they cannot be added/
appended. The two correct variations are below:

“5”.to_i + 5 # => 10
“5” + 5.to_s => “55”

Hope that clears things up.

  • Jake McArthur

I’m a newbie to Ruby, but not to programming.

But the follow statement made by “Michael G.” is confusing.

“When you did ‘info = gets.chomp’, you wiped out your array and made it
a
simple String object.”

I thought that Ruby was a strong typed language.
How can it change an Array to a String…I would have expected an error
to be produced in this instance.

I would have hoped that once a type has been established for an object,
the object would only adhere to the rules of that object…not change
itself into a new object type.

I agree…this stuff can make you pull your hair out!!

Argh…

Michael G. wrote:

‘gets’ will read a string from input and build a new string object.

When you did ‘info = gets.chomp’, you wiped out your array and made it a
simple String object.

‘exit’ is being stored because your program logic is placing the string
into
the Array, and then checking to see if the last retrieved value is
‘exit’.

You may be better off using a temporary variable first, checking it, and
then storing it.

Regg wrote:

I’m a newbie to Ruby, but not to programming.

But the follow statement made by “Michael G.” is confusing.

“When you did ‘info = gets.chomp’, you wiped out your array and made it
a
simple String object.”

I thought that Ruby was a strong typed language.
How can it change an Array to a String…I would have expected an error
to be produced in this instance.

I would have hoped that once a type has been established for an object,
the object would only adhere to the rules of that object…not change
itself into a new object type.

Names and Objects!

When you do “info = gets.chomp”, you are saying "take the object
returned from gets.chomp and associate it with the name ‘info’.
Thereafter, anytime you use the name ‘info’, you are refering to the
object associated with info.

The original array object wasn’t really wiped out. It still exists, and
if another name is associated with it, you can still use it. However,
the name ‘info’ no longer refers to it.

– Jim W.

But when I hear statements about Ruby being a strong type language, I
would expect that to be applied to variables.

Most assignments happen between variables.

But if what you are saying is that variables are “typeless”, then I have
to go with the belief that Ruby is a “weak” typed langauge and not a
strong one.

In C++ (a strong typed language) you can’t do this:

MyOtherClass *m_otherclass = new MyOtherClass();
MyClass *m_class = new MyClass();

m_class = m_otherclass; <–ERROR (Can’t convert MyOtherClass to
MyClass)

but this seems to be possible in Ruby.

Please correct me if I’m wrong (I want to be wrong here). :slight_smile:

This is the case. However, variables are only references and are
themselves “typeless,” in a sense. While you cannot change the object
a variable points to from one type to another, you can have the
variable point to a different object entirely which can be of a
different type. Here is something that won’t work:

“5” + 5

Since the two objects are different types, they cannot be added/
appended. The two correct variations are below:

“5”.to_i + 5 # => 10
“5” + 5.to_s => “55”

Hope that clears things up.

  • Jake McArthur

On May 15, 2006, at 1:14 PM, Regg wrote:

But when I hear statements about Ruby being a strong type language, I
would expect that to be applied to variables.

Most assignments happen between variables.

Variables are not objects. They are simply names associated with
objects. A name can be associated with any type of object.

a = 1
b = a
a = “foo”

a # => “foo”
b # => 1

What’s special about the above? The returned 1 is the exact same
object as the original literal when it was assigned to a! The object
did not change type at all, only which objects the variables pointed to.

but this seems to be possible in Ruby.
I’m going to have to help you distinguish between strong typing and
static typing…

C is a statically, weakly typed language. It is static because a
variable can only be on a certain type, but it is weak because the
data associated with that variable can be of any type. For example
(untested and syntax may be bad):

struct vector {
double x, y, z;
};

struct some24ByteStruct {
int a, b;
char c, d, e, f;
double g, h;
};

struct vector a = {2.0, 3.0, 4.0};
struct some24ByteStuct b = (struct some24ByteStruct)a;

We know that we have some integers (b.a and b.b), some characters
(b.c, b.d, b.e, and b.f), and some doubles (b.g and b.h), but this is
scary stuff since we have no idea what kind of data will be in those
variables. The former point is what makes C statically typed, but the
latter point makes it weakly typed.

Ruby is a dynamically, strongly typed language. It is dynamic because
a variable can point to data of any type, but strong because that
data will never change type. The Ruby example I gave above
demonstrates this.

Make any more sense now?

  • Jake McArthur

In your example:

" struct vector a = {2.0, 3.0, 4.0};
struct some24ByteStuct b = (struct some24ByteStruct)a;"

You are manually forcing this relationship my casting one type to
another.

To me that is one of the things I love about C is that it will allow you
do something that the compiler otherwise would not allow.

But in Ruby you are not “forcing” the type casting, it just does it
without any warning or error.

So I still can’t see how it can be said that “Ruby is a dynamically,
strongly typed language”.

It seems to be a dynamically, “any” typed language.

What benefit is gained from a variable being (switched/pointed to) from
one type to another? (This is an honest question, maybe I’m missing
something)

It seems like a recipe for disaster.

Thanks

C is a statically, weakly typed language. It is static because a
variable can only be on a certain type, but it is weak because the
data associated with that variable can be of any type. For example
(untested and syntax may be bad):

struct vector {
double x, y, z;
};

struct some24ByteStruct {
int a, b;
char c, d, e, f;
double g, h;
};

struct vector a = {2.0, 3.0, 4.0};
struct some24ByteStuct b = (struct some24ByteStruct)a;

We know that we have some integers (b.a and b.b), some characters
(b.c, b.d, b.e, and b.f), and some doubles (b.g and b.h), but this is
scary stuff since we have no idea what kind of data will be in those
variables. The former point is what makes C statically typed, but the
latter point makes it weakly typed.

Ruby is a dynamically, strongly typed language. It is dynamic because
a variable can point to data of any type, but strong because that
data will never change type. The Ruby example I gave above
demonstrates this.

Make any more sense now?

  • Jake McArthur

Regg wrote:

But when I hear statements about Ruby being a strong type language, I
would expect that to be applied to variables.

One must be clear on exactly what “strong typing” means. Often people
confuse strong typing with the static declaration of variable types.
There are actually (at least) three dimensions to the type question:

static VS dynamic
strong VS weak
manifest VS implicit

C++ is statically typed (variable types are known statically at compile
time), manifestly typed (type declarations must be explicitly made for
all variables), and mildly strongly typed (some common type errors are
caught at compile time, but no runtime checking whatsoever, leaving type
holes big enough to drive a truck through).

Ruby, on the other hand, is dynamically typed (the type of objects
associated with variable names are determined at run time), implicitly
typed (no need to declare types of variables) and strongly typed (type
errors are always caught).

Most assignments happen between variables.

In C, C++, Java and many other languages, an assignment statement means
“copy this data from that location to this location”. In Ruby, Python,
Lisp and most other dynamic languages, an assignment means “bind this
name to that object”.

In languages that have “copy” semantics, its important to know that the
copied data ends up in a location where it can be properly interpreted.
This is especially important because the interpretation of that data
depends on the declared type of that memory location.

In languages that “bind names”, that issue is not nearly as important.
Since the object itself (not the declared type of the location)
determines its interpretation, there is never any confusion.

But if what you are saying is that variables are “typeless”, then I have
to go with the belief that Ruby is a “weak” typed langauge and not a
strong one.

In C++, a variable is a location in memory that contains the data in
question. Variables in Ruby are not locations at all, i.e. they have
no L-Value. Variables in Ruby are truely just names used to lookup
objects. It is the Objects that have a “type”.

In C++ (a strong typed language) you can’t do this:

MyOtherClass *m_otherclass = new MyOtherClass();
MyClass *m_class = new MyClass();

The purpose of strong typing is to prevent performing type-inappropriate
actions on objects. Since C++ carries almost no runtime type
information about its objects, the only way it can prevent inappropriate
type actions is to do all the checking at compile time.

In C++ you can do this:

MyClass * m_class = NULL;
m_class->do_something();

And the results are undefined (by the language standard).[1] If you are
lucky, you might get segmentation fault. However, the equivalent in
Ruby:

m_class = nil
m_class.do_something

is a predictable runtime error than can be handled like all the other
runtime errors that are possible in a program.

m_class = m_otherclass; <–ERROR (Can’t convert MyOtherClass to
MyClass)

but this seems to be possible in Ruby.

In summary:

Unlike C++, variable names are not associated with a particular type.
Unlike C++, it is not possible to perform type-unsafe operations.

– Jim W.

[1] Some might quibble that attempting to dereference a null pointer is
not really a type violation. Perhaps. But consider the following code:

MyClass * m_class = (MyClass) m_otherclass;
m_class->do_something();

Obviously the hammer cast breaks the type safety, and produces similar
undefined behavior. It all about having the wrong data in the m_class
pointer variable. In one case it’s a null pointer, in the other case
it’s an inappropriate pointer. I would call them both type errors.

On May 15, 2006, at 2:04 PM, Regg wrote:

do something that the compiler otherwise would not allow.
Sure, but in order for you to manipulate that data in the new
structure, you probably have to translate the data from the first
form to the other anyway. An explicit cast is really most useful when
casting from one primitive to another (moot in Ruby, of course), but
not for more complex data types (excluding buffers, which is the only
special case I can think of right now… also moot in Ruby).

But in Ruby you are not “forcing” the type casting, it just does it
without any warning or error.

There is no type casting going on in the Ruby code that I can see. Do
you mean the reassignment of the variable to an object of a different
type? There is no conversion taking place.

What benefit is gained from a variable being (switched/pointed to)
from
one type to another? (This is an honest question, maybe I’m missing
something)

It seems like a recipe for disaster.

Consider this:

class Foo
def do_something
puts “FOO!”
end
end

class Bar
def do_something
puts “BAR!”
end
end

def call_do_something(arg)
arg.do_something
end

call_do_something(Foo.new)
call_do_something(Bar.new)

Notice something cool here? We didn’t have to subclass to pass two
different types into the same method. This is known by some as “duck
typing,” referring to the “looks like a duck, talks like a duck”
metaphor. Any object that responds to the do_something method can be
passed into the call_do_something method, and it will work perfectly.
This is powerful, and not as dangerous as you think.

  • Jake McArthur

On May 15, 2006, at 1:27 PM, Regg wrote:

This is something that YOU are forcing the compiler to do.
You are FORCING the compiler to accept this assignment even if it’s
wrong.
That is not the fault of the language but the fault of the developer.

But in Ruby you are not forcing it, it just allows it to happen
with no
warning.

In ruby it does not happen at all. when you bind foo = 5, that is
fine. when it’s bound to “hi” that is fine as well. there are no
objects that foo shouldn’t be bound too.

there is no cast happening when you do

foo = “hi”
foo = 5

foo just points to something new, now, and the “hi” gets lost in the
abyss (unless something else is pointing to it)

the C code above treated some bits representing one thing as if they
were representing something else. ruby doesn’t do that just by
assignment. when you do foo = 5 ruby now treats foo like an integer
not a string. if you want 5 treated like a string you have to convert
it.

– Elliot T.

Hi –

On Mon, 15 May 2006, Francis C. wrote:

I have to admit I don’t understand the distinction you’re making between
“class” and type.

Basically, class is the thing that the object is an instance of. Type
is the sum of the object’s behaviors – which may or may not be
exactly the same as the behaviors it started out with.

To level-set: I care about this discussion primarily
because plenty of people (but no one on this thread, of course) criticize
Ruby as being less strongly-typed than C++ or Java, whereas the truth is
that Ruby is dynamically typed rather than weakly typed. In Ruby, an
object never changes its type (although delegation and the ability to add
methods to a single object instance also may make it seem like it does).

It never changes its class, but it can change its type.

More to the point, Ruby will never implicitly perform operations on an
object that are not part of its type, as a result of inferences about some
particular statement of code. This Ruby code will generate an error:
“abc” + 5

Yes, but this won’t:

irb(main):004:0> a = “abc”
=> “abc”
irb(main):005:0> def a.+(other); self << other.to_s; end
=> nil
irb(main):006:0> a + 3
=> “abc3”

The thing about type in Ruby is that there are no words for different
types. There’s no need for them; the fact that a defines + the way it
does is all you’d need to know. There’s no need for a word that
means, “the type of objects that start out as strings but redefine +
so that it performs an automatic to_s…” And since the type
spectrum is infinite, there’s no way to have words for all of them.

I’ve noticed that younger programmers seem to have much less conceptual
trouble with “duck typing” and dynamic languages than older people like me.
I wonder if it’s because for a while, CS programs taught people with
functional languages like Scheme, where the distinction between objects and
variable-bindings is explicit and clear. (Nowadays of course, all the
younger people coming out of university seem to have learned nothing but
Java…)

I’d be at least mildly surprised if you’re older than I am :slight_smile: But in
any case, it comes down to this: There are two things going on with
Ruby objects. One is their class. The other is the fact that they
are dynamic; their behaviors can change, and even two objects that
report themselves to be of the same class can have different
behaviors.

It’s conventional to refer to the first of these things as class, and
the second as type. The disadvantage of referring to the first one as
both class and type is that then we need a new word to refer to the
second one, when in fact “type” is really the best word.

(See the Pickaxe (2nd edition) for a lengthy and enlightening
discussion of the difference between class and type in Ruby.)

David