New to Python: my impression v. Perl/Ruby

Different strokes for different folks, I guess. I remember
that one of the first things I saw about Ruby was that even
interger literals were objects that can receive messages and
thinking how wonderful that was. As you say, you’re not

Ints are objects in python too:

a=1
a.lshift(1)
2

Though “sending messages” to int literals is a syntax error.

> 10.times do something end

> is somehow so clear.  It's almost zenlike.

It’s cute and fun to write, but less cute for people who have to read
lots of such code in short time. I have a soft spot for such style
also; I kinda like Python’s “\n”.join([“foo”,“bar”]), even if most
seem to consider it a wart for readability reasons.

···


Ville Vainio http://tinyurl.com/2prnb

Though “sending messages” to int literals is a syntax error.

>> 10.times do something end

>> is somehow so clear.  It's almost zenlike.

It’s cute and fun to write, but less cute for people who have to read
lots of such code in short time.

Ville,

10.times do something end

How is the the above code less ‘cute’ for people who have to read lots of
code? If the person reading the code knows any of the basic abilities and
syntax of Ruby then they should be able to point out rather quickly that you
are repeating a block of code 10 times.

Zach

“Ville Vainio” ville.spamstermeister.vainio@thisisspamprotectiontut.finland wrote in message
news:du71xpue3rm.fsf@mozart.cc.tut.fi

> Different strokes for different folks, I guess.  I remember
> that one of the first things I saw about Ruby was that even
> interger literals were objects that can receive messages and
> thinking how wonderful that was.  As you say, you're not

Ints are objects in python too:

a=1
a.lshift(1)
2

Though “sending messages” to int literals is a syntax error.

Try this:

(1).lshift(1)
2

– Serge.

“Ville Vainio”
ville.spamstermeister.vainio@thisisspamprotectiontut.finland wrote in
message news:du71xpue3rm.fsf@mozart.cc.tut.fi

> Different strokes for different folks, I guess.  I remember
> that one of the first things I saw about Ruby was that even
> interger literals were objects that can receive messages and
> thinking how wonderful that was.  As you say, you're not

Ints are objects in python too:

a=1
a.lshift(1)
2

Though “sending messages” to int literals is a syntax error.

> 10.times do something end

> is somehow so clear.  It's almost zenlike.

It’s cute and fun to write, but less cute for people who have to read
lots of such code in short time. I have a soft spot for such style
also; I kinda like Python’s “\n”.join([“foo”,“bar”]), even if most
seem to consider it a wart for readability reasons.

Tacking an iterator on an integer isn’t all that bad from
a readability viewpoint - except for the .step iterator.
…times, .upto and .downto read very nicely, but .step is
a monstrosity. Conceptually, .step has three parameters,
and separating them that way simply doesn’t read right.

It’s also not consistent with the .each iterator attached to
range objects in Ruby, which is at least intelligible, and is
consistent with the way iterators are done with all other
objects.

The trouble with .join() in Python
is that it reads backwards, at least to me. The arguement that
…join isn’t a natural list method makes sense, but nobody seems
to want to consider that there are other solutions that read
fairly well. Of course, they’re also consequences of fairly
generic changes to the language.

John Roth

···


Ville Vainio http://tinyurl.com/2prnb

Though “sending messages” to int literals is a syntax error.

> 10.times do something end

> is somehow so clear.  It's almost zenlike.

It’s cute and fun to write

It’s not “cute”, it’s legible. “10.times do” is much clearer
about what’s going on than, for instance, C’s “for (i=0;i<10;++i)”.
The Python idiom is probably something with a Range, which is clearer
than the C, but not as clear as the Ruby.

I kinda like Python’s “\n”.join([“foo”,“bar”]), even if most
seem to consider it a wart for readability reasons.

Well, I think it’s a kludge, designed that way only because strings have
recently grown a base class to which methods could be added,
whereas sequences have no such basis, so there’s nowhere to define
something clearer like [“foo”,“bar”].join(“\n”).

And the lack of such a basis is part of my whole problem with
Python, the lack of true object-orientedness. The ability you cite
to treat primitive types as objects is a fairly recent development;
the above was originally done by importing ‘string’ and calling
‘string.join(“\n”, [“foo”, “bar”])’ (I believe that was the correct argument
order). The object-orientedness just doesn’t cut deep enough. I mean,
it’s not as much of an afterthought as it is in Perl, but
holdovers from the procedural design poke through everywhere.
Things like “len” and “dir”, which should logically be methods, are
instead global functions. And why “len” instead of “length” in
a language vaunted for its readability? Or “dir” - the filesystem
analogy makes a certain amount of sense, but there must have been a more
transparent name for it.

I somewhat like, from an elegance perspective, the idea - shared by Python and
JavaScript - that functions and methods are just variables whose value is a
Proc (in Ruby terms), and trailing parentheses are an “invoke” operator.
But I don’t like the resulting merger of namespaces - if an object has
a method named ‘foo’, it can’t have a member variable named ‘foo’, etc.
I also don’t like that object members are public by default.

Also, the one time I tried mixing Python and C, it was not terribly
easy to do. Again, we’re not talking XS here, but Ruby’s design lets
you write Ruby in C just as if it were Ruby. I love that.

-Mark

···

On Tue, Jan 20, 2004 at 10:58:21PM +0200, Ville Vainio wrote:

Ville Vainio ville.spamstermeister.vainio@thisisspamprotectiontut.finland wrote in message news:du71xpue3rm.fsf@mozart.cc.tut.fi

> 10.times do something end

> is somehow so clear.  It's almost zenlike.

It’s cute and fun to write, but less cute for people who have to read
lots of such code in short time. I have a soft spot for such style
also; I kinda like Python’s “\n”.join([“foo”,“bar”]), even if most
seem to consider it a wart for readability reasons.

A lot of this has to do with how you conceptualize objects. In some
languages objects are big and heavyweight. So the few things that get
to be called Objects are blessed with special powers, and the lowly
primitive values are supposed to look up to them with admiration and
reverence.

In other languages everything can be an object, which means that you
have to think of the “object” idea differently. In Ruby integers are
objects, but there’s a lot of syntactic sugar to make that happen.
After all,

10.times do something end

is basically just fancy talk for

for (i = 0; i < 10; i++ ) { something }

or whatever you think should be more explicit. This method might break
your conceptual model of what an object is, depending on which model
you like.

Personally, I love the Fixnum#times method, since it means I never
make fence-post errors anymore. More time for interesting problems,
less time spent on tediously stepping through code one iteration at a
time. And if my conceptual model is getting in the way of my ability
to write error-free code, then it’s the conceptual model that has to
change.

Besides, once a language is Turing-complete, everything else is
syntactic sugar. So you might as well get the best syntactic sugar you
can get …

Francis

Mark J. Reed wrote:

JavaScript - that functions and methods are just variables whose value is a
Proc (in Ruby terms), and trailing parentheses are an “invoke” operator.
But I don’t like the resulting merger of namespaces - if an object has
a method named ‘foo’, it can’t have a member variable named ‘foo’, etc.

While that might be true of those languages, what do you think of the
way common lisp solves that problem? Ie, letting each symbol have a
value cell and a function cell (and a few more for that matter).

“Zach Dennis” zdennis@mktec.com wrote in message news:AKEKIKLMCFIHPEAHKAAICEOHHFAA.zdennis@mktec.com

Though “sending messages” to int literals is a syntax error.

>> 10.times do something end

>> is somehow so clear.  It's almost zenlike.

It’s cute and fun to write, but less cute for people who have to read
lots of such code in short time.

Ville,

10.times do something end

How is the the above code less ‘cute’ for people who have to read lots of
code?

Well, that isn’t too confusing. But one issue with looping using the
object.method() constructs is when you are dealing with variables.

That is:

10.times do something end

is extremely nice and very clear to read.

However:

i = 10 # somewhere out there

and then somewhere else…

i.times do something end

is confusing as you have no clue what class i is and as such, no idea
what times may be doing.
In those cases, a for or while loop is preferable and should be
enforced, in my opinion.
In my experience, it is much more common for algorithms to be looping
involving arbitrary numbers stored in variables than predetermined
times, so I also tend to agree that such constructs are cute but not
something I’d likely use often in real code.

I think it complicates the elegance of the design; I’m a big believer in
one variable=one value (even if that value is itself multivalued, with
keyed or indexed or otherwise accessed components).

-Mark

···

On Tue, Jan 20, 2004 at 11:59:41PM +0100, Linus Sellberg wrote:

While that might be true of those languages, what do you think of the
way common lisp solves that problem? Ie, letting each symbol have a
value cell and a function cell (and a few more for that matter).

Received: Wed, 21 Jan 2004 16:59:59 +0900
And lo GGarramuno wrote:

i = 10 # somewhere out there

and then somewhere else…

i.times do something end

is confusing as you have no clue what class i is and as such, no idea
what times may be doing.
In those cases, a for or while loop is preferable and should be
enforced, in my opinion.
In my experience, it is much more common for algorithms to be looping
involving arbitrary numbers stored in variables than predetermined
times, so I also tend to agree that such constructs are cute but not
something I’d likely use often in real code.

Ever since I started using ruby, I don’t believe I’ve actually looped based on numbers for actual programming. Why should I, since there is usually a number of better ways to do so, especially when doing it the ‘ruby way’.

String’s “each_byte” and Array’s ‘each’ method defeats over 99% of the ‘for (i=0;i<somenum;i++)’ loops I’d use in C.

array.each do |item| … end

loop do
break if …
end

Doing it that way is a lot more readable and understandable than using a for, while, etc loop.

Huzzah for Proc blocks!

  • Walker

GGarramuno,

I may be wrong, but I don’t think I’ve seen a ‘times’ method to any class
but an Integer. You could almost expect that when dealing with:

i = 10 # somewhere out there

and then somewhere else…

i.times do something end

that i is an Integer or will be treated like one. I don’t think that in all
iterative situations you should use the times method, but I disagree that it
is merely a ‘cute’ thing to have in Ruby, but nothing worthy of real code
use. Even if you switched your above code to:

i = 10#somewhere out there
#somehwere else
for x in (1…i) do
puts x; end

You still dont’ know what class i is. You are assuming it is an Integer, and
it should be, but you still have the same amount of nonclarification in your
for loop as you do with your times iterator. You are making an assumption
that you or whomever else typed in that code made sure that i will be an
integer.

Of course if the times method is used by another class then my statement is
invalid because then there is an extra layer of nonclarification to what
class ‘i’ is, but until then I am not seeing the confusion you speak of. The
same assumptions are being made or should be made by the code reader, ‘i’ is
an Integer in a for loop or a times iterative method.

Zach

···

-----Original Message-----
From: GGarramuno [mailto:GGarramuno@aol.com]
Sent: Wednesday, January 21, 2004 3:00 AM
To: ruby-talk ML
Subject: Re: New to Python: my impression v. Perl/Ruby

“Zach Dennis” zdennis@mktec.com wrote in message
news:AKEKIKLMCFIHPEAHKAAICEOHHFAA.zdennis@mktec.com

Though “sending messages” to int literals is a syntax error.

>> 10.times do something end

>> is somehow so clear.  It's almost zenlike.

It’s cute and fun to write, but less cute for people who have to
read
lots of such code in short time.

Ville,

10.times do something end

How is the the above code less ‘cute’ for people who have to read lots of
code?

Well, that isn’t too confusing. But one issue with looping using the
object.method() constructs is when you are dealing with variables.

That is:

10.times do something end

is extremely nice and very clear to read.

However:

i = 10 # somewhere out there

and then somewhere else…

i.times do something end

is confusing as you have no clue what class i is and as such, no idea
what times may be doing.
In those cases, a for or while loop is preferable and should be
enforced, in my opinion.
In my experience, it is much more common for algorithms to be looping
involving arbitrary numbers stored in variables than predetermined
times, so I also tend to agree that such constructs are cute but not
something I’d likely use often in real code.

for i in (0…i); something; end

to me has a bunch of advantages over times, step and the such. With the above
construct you know that:
a) i has to be a number
b) i has to be positive for the loop to run
c) there IS a loop after all, as ‘for’ indicates a loop in pretty much every
computer language.
d) it is more efficient as no blocks are created.
e) you can change the starting point (ie. not start at 0).

With i.times() I really don’t get any of the above. One can asume that i.times
means a loop as it is perhaps a common construct in ruby.
But the truth is that i.times() also leaves room for that behavior to not be
true. It could mean something else, too. It could be a fancy benchmarking
object measuring the following block. Or any object with a times() method, for
that matter.
Pre-assuming it is a loop to me is not as obvious as with a for loop.
And you always get the performance hit of opening a block, which is a big no-no
to me when speed matters.

Iterating with each is a much nicer way and it indeed removes the need for many
for/loops as they appear in C. But it only is helpful when you are dealing
with some form of enumerable collection (arrays, hashes, etc). It also suffers
from the block performance hit, but likely that is compensated by not having to
do sth. like a[idx], and being able to rely on a.succ.
Still, the each construct does not help you for numeric algorithms such as that
from the original poster, where no collection is available (where you are
indeed just counting numbers).

Gregory Millam wrote:

Ever since I started using ruby, I don’t believe I’ve actually looped based on numbers for actual programming. Why should I, since there is usually a number of better ways to do so, especially when doing it the ‘ruby way’.

String’s “each_byte” and Array’s ‘each’ method defeats over 99% of the ‘for (i=0;i<somenum;i++)’ loops I’d use in C.

Well, here is an example of “times” from a real program. The point is
to determine whether 2^n-1 is a prime, given that n is an odd prime.

tprime = (1 << n) - 1
test = 4
(n - 2).times {test = (test * test - 2) % tprime}
puts "(2**#{n})-1, #{tprime}, is prime" if test.zero?
···


John W. Kennedy
“But now is a new thing which is very old–
that the rich make themselves richer and not poorer,
which is the true Gospel, for the poor’s sake.”
– Charles Williams. “Judgement at Chelmsford”

Quoteing ggarramuno@aol.com, on Thu, Jan 22, 2004 at 05:59:58AM +0900:

for i in (0…i); something; end

to me has a bunch of advantages over times, step and the such. With the above
construct you know that:
a) i has to be a number

Are you sure? Can’t i be a RegEx? If not, the … operator is a special
case. Most operators are user definable:

j = i + 1

Is i necessarily a number? Nope. What does that statement do? Depends on
what i is! And j, for that matter.

Why is

i.times { … }

any more or less confusing than

c.each { … }

or indeed

o.do_me { … }

Unless you know the type of the object, you don’t know what the method
does. Of course, there are naming conventions (#each, #times) for
methods with commonly similar behaviour.

This is the kind of thing people who don’t like OO at all, preferring
procedural languages, say about OO (“you never know what the call really
does”). Well, that’s an ancient flame war, but if you’re using an OO
language, I’d think you’d be on the OO side of the argument by now…

Sam

GGarramuno wrote:

b) i has to be positive for the loop to run

(-1).times do
puts “Foo!”
end

Produces no output. How is that different from for?

(-1).times do
a = 0
end

puts a

Produces an error because a is undefined since the body hasn’t been
executed, which is
a difference from for (where a would be auto-initialized to nil). This
is a difference, but
one is not noticably more correct than the other.

d) it is more efficient as no blocks are created.

In “for …” you need to create a range object 0…i

Also, wondering if this is true, I did the following:

def do_times(i)
n = 0

i.times do
    n = n + 1
end

end

def do_for(i)
n = 0

for k in (0..i)
    n = n + 1
end

end

t1 = Time.new

100000.times do
do_times 10
end

t2 = Time.new

100000.times do
do_for 10
end

t3 = Time.new

puts "#times: ", t2 - t1
puts " for: ", t3 - t2

Results:

#times:
0.982
for:
2.103

So the for method is less efficient (unless I’ve made an error).

With i.times() I really don’t get any of the above. One can asume that i.times
means a loop as it is perhaps a common construct in ruby.
But the truth is that i.times() also leaves room for that behavior to not be
true. It could mean something else, too. It could be a fancy benchmarking
object measuring the following block. Or any object with a times() method, for
that matter.
Pre-assuming it is a loop to me is not as obvious as with a for loop.
And you always get the performance hit of opening a block, which is a big no-no
to me when speed matters.

We probably shouldn’t use #each either, because you can override #each
to mean anything you want. Block creation also seems to be less expensive
than general object creation (or at least range creation), so the
performance
argument is incorrect.

  • Dan

for i in (0…i); something; end

to me has a bunch of advantages over times, step and the such. With the above
construct you know that:
a) i has to be a number

a = ‘a’
b = ‘z’

100 lines of code

for i in (a…b); something; end

e) you can change the starting point (ie. not start at 0).

The thing I like about #times over #each or ‘for’ is that you don’t
use a needless variable.

for i in (1…10) …

(1…10).each { |i| …

(1…10).each { …

10.times { …

If I just want to do something 10 times, why should I involve ‘i’?

Gavin

···

On Thursday, January 22, 2004, 7:59:58 AM, GGarramuno wrote:

Right. But I could do:

(‘a’…‘z’).each { |i| … }

With Ruby, things don’t need to be numbers to work intelligibly. Also,
your point d is, um, well, not true. In Ruby, the for construct is syntax
sugar for another loop. Aside from this, why stick with x.times?

x.upto(y) { |i| … }

x could be -9 or 32768; as long as y is larger than x, it will work.

This pretty much eliminates all of the objections you had. Once you get used
to iteration instead of explicit loops, then it’s not a big deal to do
x.times, x.upto(y) or y.downto(x).

-austin

···

On Thu, 22 Jan 2004 05:59:58 +0900, GGarramuno wrote:

for i in (0…i); something; end

to me has a bunch of advantages over times, step and the such. With the
above construct you know that: a) i has to be a number b) i has to be
positive for the loop to run c) there IS a loop after all, as ‘for’
indicates a loop in pretty much every computer language. d) it is more
efficient as no blocks are created. e) you can change the starting point
(ie. not start at 0).


austin ziegler * austin@halostatue.ca * Toronto, ON, Canada
software designer * pragmatic programmer * 2004.01.21
* 23.07.29

GGarramuno wrote:

for i in (0…i); something; end

to me has a bunch of advantages over times, step and the such. With the above
construct you know that:
a) i has to be a number
b) i has to be positive for the loop to run

No, as a matter of fact, it doesn’t.

You’ve pretty much demonstrated one of the reasons that “times” is a
Good Thing.

···


John W. Kennedy
“But now is a new thing which is very old–
that the rich make themselves richer and not poorer,
which is the true Gospel, for the poor’s sake.”
– Charles Williams. “Judgement at Chelmsford”

So, what you’re saying is, you don’t want to use Ruby’s features because
the same names could be used in other ways.

That’s a fair reason to not use Ruby, I suppose. Feel free not to. But
you’re not going to convince anyone else with that argument.

Joe

···

In article 20040121155809.22006.00000323@mb-m22.aol.com, GGarramuno wrote:

for i in (0…i); something; end

to me has a bunch of advantages over times, step and the such. With the above
construct you know that:
a) i has to be a number
b) i has to be positive for the loop to run
c) there IS a loop after all, as ‘for’ indicates a loop in pretty much every
computer language.
d) it is more efficient as no blocks are created.
e) you can change the starting point (ie. not start at 0).

With i.times() I really don’t get any of the above. One can asume that i.times
means a loop as it is perhaps a common construct in ruby.
But the truth is that i.times() also leaves room for that behavior to not be
true. It could mean something else, too. It could be a fancy benchmarking
object measuring the following block. Or any object with a times() method, for
that matter.
Pre-assuming it is a loop to me is not as obvious as with a for loop.
And you always get the performance hit of opening a block, which is a big no-no
to me when speed matters.

“John W. Kennedy” jwkenne@attglobal.net wrote in message news:fpIPb.57035$OM2.16265939@news4.srv.hcvlny.cv.net

tprime = (1 << n) - 1
test = 4
(n - 2).times {test = (test * test - 2) % tprime}
puts “(2**#{n})-1, #{tprime}, is prime” if test.zero?

Well, as a new user, that kind of constructs would scare me quite a
lot as an example of times() being used in real code.

Perhaps having been doing too much python has spoiled me, but I had to
read the line 2 or 3 times before I realized where times() even was
and where its block begun, unlike the previous clear examples using
do/end constructs.