Too Many Ways?

Bob Sidebotham writes:
>
> As a nuby, even when you *know* there's two ways to do something, you're
> stuck wondering if there is some subtle reason that one is better (or
> simply different) than the other. You see two mechanisms, can't find
> anything written that describes when to use one or the other, and are
> left puzzled and confused.

that's what documentation is for.
there can never be two many ways as long as they are well described.

Klaus Schillling

Good point, Bob. I normally baulk at sensitivity to TMTOWTDI, but
this case registers clearly in my mind as a potential for confusion.
I guess from now on, when instructing someone in this area, I'll show
them both ways at the same time and deal with confusion upfront.

Stylistically, I tend to favour 'yield' when a block is optional, and
'block.call' when it's not.

  def foo(a, b, &block)

visually suggests to me that a block is required. I usually mark a
method like this as well:

  def foo(a, b) # :yield: peanut

I wonder what other people think/do?

Cheers,
Gavin

···

On Sunday, October 3, 2004, 3:34:57 AM, Bob wrote:

And if you use the first syntax, there is the leap you have to make sooner
or later: "hang on - how do I pass this block to another method?"; or
conversely, "I have a proc object, but how do I pass it to a method which
expects a block?"

Well, yes, I got hung up on this right off the bat--I got it into my
head that yield was somehow dynamic, so that it would find some magic
block up the stack to yield to . So I was very puzzled when I couldn't
yield from within a method called by the method with the block.

I had assumed this level of dyanmicity since the block wasn't
specified--it seemed obvious to me that objects would be simply invoked
in a context where a yield would magically invoke some block defined
somewhere.

If I'd had to declare the block from the start, then this would never
have been an issue.

As a nuby, even when you *know* there's two ways to do something, you're
stuck wondering if there is some subtle reason that one is better (or
simply different) than the other. You see two mechanisms, can't find
anything written that describes when to use one or the other, and are
left puzzled and confused.

I have been thinking lately about rangess and I will give you the two different range operators and what comes to mind first.

Operator One: .. (two dots)
Example: 1..5
What comes to mind: Exclusive
How It Works: Inclusive (the last number 5, is included)

Operator Two: ... (three dots)
Example: 1...5
What comes to mind: Inclusive
How It Works: Exclusive (the last number 5, is excluded)

How range operators work seems sort of backwards to me. It would appear as if the "..." (three dots) would be the inclusive one, including the last value and the ".." (two dots) would be exclusive and exclude the last value.

Am I off in my own little world here or have others pondered this? (Perhaps it has been brought up before?) I am not requesting a change on this, I am merely pointing out what seems unnatural in a very natural language.

Zach

Sometimes I'm tempted to think this is already the way; in the doco for
these duplicate methods, usually one will simply be a reference to the
other. I think it would be nice if one was "canonical".

Bad example:
% ri Hash#each_pair
--------------------------------------------------------- Hash#each_pair
     hsh.each_pair {| key, value | block } -> hsh

···

------------------------------------------------------------------------
     Synonym for Hash#each.

"Gavin Kistner" <gavin@refinery.com> wrote:

On Thu, 30 Sep 2004, Robert Klemme wrote:

If only the things that make life easier for newcomers could disappear
later, like training wheels on a bicycle.... :slight_smile:

I suppose that's my wish, too. As unrealistic as it may be.
("Sorry, play time is over. All your existing code may crash and burn, but
in the end it'll make you a better programmer.")

What I'd think was nice is if a bunch of things were officially
deprecated; no runtime warning (although perhaps with a -w or something)
but where exact duplicates exist, the King from on High would say "thou
shalt use #foo and not #bar". (I was even thinking of removing the
deprecated names from the documentation, but then that's no good for
someone needing to decipher existing code.)

(snip)

I never use yield. But I'll tell you what, I too think the above suggests that
&block is required. I really dislike inconsistency, so I even put in an RCR
about it, to the effect that

   def foo(a, b, &block=nil)

would be needed to make the block optional. Matz said that it might be a good
idea, but would break code.

But since then, I've completely flipped positions, and more in concert with
the ideas of duck-typing, I wish all arguments worked like &block. e.g.

   def foo(a, b)
     "#{a}#{b}"
   end

   foo(1) #=> "1"

Just as block is nil in the above, so would b here. Likewise:

  foo(1,2,3) #=> "12"

and 3 would be ignored.

Among other things this would reduce the need for (instantiating a method
object and) checking arity.

T.

···

On Saturday 02 October 2004 10:12 pm, Gavin Sinclair wrote:

> As a nuby, even when you *know* there's two ways to do something, you're
> stuck wondering if there is some subtle reason that one is better (or
> simply different) than the other. You see two mechanisms, can't find
> anything written that describes when to use one or the other, and are
> left puzzled and confused.

Good point, Bob. I normally baulk at sensitivity to TMTOWTDI, but
this case registers clearly in my mind as a potential for confusion.
I guess from now on, when instructing someone in this area, I'll show
them both ways at the same time and deal with confusion upfront.

Stylistically, I tend to favour 'yield' when a block is optional, and
'block.call' when it's not.

  def foo(a, b, &block)

visually suggests to me that a block is required. I usually mark a
method like this as well:

  def foo(a, b) # :yield: peanut

I wonder what other people think/do?

510046470588-0001@t-online.de (klaus schilling) wrote in message news:<16734.60152.928837.828142@gargle.gargle.HOWL>...

Bob Sidebotham writes:
>
> As a nuby, even when you *know* there's two ways to do something, you're
> stuck wondering if there is some subtle reason that one is better (or
> simply different) than the other. You see two mechanisms, can't find
> anything written that describes when to use one or the other, and are
> left puzzled and confused.

that's what documentation is for.
there can never be two many ways as long as they are well described.

Klaus Schillling

Hear, hear. Whenever you have to learn a large subject, you're not
going to learn it all at once anyway. The question for the educator
is: Where is the student starting, and what's the best path to take
them into the material?

There's been a lot of talk about newbies in this thread but I don't
think there's any one kind of newbie; there are many. There are people
who have never programmed in a dynamic language, like the Java
refugees. There are people who are coming from a more design-centric
past, maybe they know Javascript and Flash's ActionScript, and are
looking for something meatier. There are the folks who come from other
languages, such as Smalltalk or Lisp or Haskell, that might make them
able to absorb some of the heavy concepts behind Ruby and maybe they
just need a crash course in the syntax.

The point is, you can't communicate with just a vague general idea of
a person. You have to target your message for a targeted audience. A
lot of documentation (Ruby and non-Ruby) doesn't do that.

F.

Zach Dennis wrote:

I have been thinking lately about rangess and I will give you the two different range operators and what comes to mind first.

Operator One: .. (two dots)
Example: 1..5
What comes to mind: Exclusive
How It Works: Inclusive (the last number 5, is included)

Operator Two: ... (three dots)
Example: 1...5
What comes to mind: Inclusive
How It Works: Exclusive (the last number 5, is excluded)

How range operators work seems sort of backwards to me. It would appear as if the "..." (three dots) would be the inclusive one, including the last value and the ".." (two dots) would be exclusive and exclude the last value.

Am I off in my own little world here or have others pondered this? (Perhaps it has been brought up before?) I am not requesting a change on this, I am merely pointing out what seems unnatural in a very natural language.

Zach

Hello Zach,

very good point you make. I imagine that the inclusive version is used more often, so someone thought, lets save a point here.

But I have to admit I just learned it and never questioned it. Thats a bad thing :wink:

Regards,

Brian

···

--
Brian Schröder
http://ruby.brian-schroeder.de/

It's the distinction between
  0..5 == [0, 5] # mathematical notation
and
  0...5 == [0, 5) # mathematical notation

In part, this is something that Ruby inherits -- I *think* -- from
Perl, which uses the .. and ... in this way.

-austin

···

On Thu, 30 Sep 2004 22:30:51 +0900, Zach Dennis <zdennis@mktec.com> wrote:

How range operators work seems sort of backwards to me. It would appear
as if the "..." (three dots) would be the inclusive one, including the
last value and the ".." (two dots) would be exclusive and exclude the
last value.

Am I off in my own little world here or have others pondered this?
(Perhaps it has been brought up before?) I am not requesting a change on
this, I am merely pointing out what seems unnatural in a very natural
language.

--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca
: as of this email, I have [ 6 ] Gmail invitations

"Zach Dennis" <zdennis@mktec.com> schrieb im Newsbeitrag
news:415C0A1E.4050501@mktec.com...

I have been thinking lately about rangess and I will give you the two
different range operators and what comes to mind first.

Operator One: .. (two dots)
Example: 1..5
What comes to mind: Exclusive
How It Works: Inclusive (the last number 5, is included)

Operator Two: ... (three dots)
Example: 1...5
What comes to mind: Inclusive
How It Works: Exclusive (the last number 5, is excluded)

How range operators work seems sort of backwards to me. It would appear
as if the "..." (three dots) would be the inclusive one, including the
last value and the ".." (two dots) would be exclusive and exclude the
last value.

Am I off in my own little world here or have others pondered this?
(Perhaps it has been brought up before?) I am not requesting a change on
this, I am merely pointing out what seems unnatural in a very natural
language.

I never thought about this but it seems you are right. (Sometimes it
seems better to not think about everything :slight_smile:

    robert

How range operators work seems sort of backwards to me. It would appear as if the "..." (three dots) would be the inclusive one, including the last value and the ".." (two dots) would be exclusive and exclude the last value.

I was thinking this exact same thing in the shower yesterday morning.

I've tried to memorize what _why said about them, to remember:

Think of it as an accordion which has been squeezed down for carrying. (Sure, you can build a great sense of self-worth by carrying around an unfolded accordion, but sometimes a person needs to wallow in self-doubt, carefully concealing the squeeze-box.) The parentheses are the handles on the sides of a smaller, handheld accordion. The dots are the chain, keeping the folds tightly closed.

Normally, only two dots are used. If a third dot is used, the last value in the range is excluded.

(0...5) represents the numbers 0 through 4.

When you see that third dot, imagine opening the accordion slightly. Just enough to let one note from its chamber. The note is that end value. We’ll let the sky eat it.

Source: http://poignantguide.net/ruby/chapter-3.html#section2

···

On Sep 30, 2004, at 7:30 AM, Zach Dennis wrote:

Zach Dennis ha scritto:

How range operators work seems sort of backwards to me. It would appear as if the "..." (three dots) would be the inclusive one, including the last value and the ".." (two dots) would be exclusive and exclude the last value.

actually, I thought till one moment ago that ... was going to be deprecated. I looked up and found that I misremembered this:
http://www.rubyist.net/~matz/slides/rc2003/mgp00025.html

I'd strongly advocate the elimination of z...y .
It is completely non obvious, and it has no advantage _i can see_ over x..k .

Maybe you can submit an rcr about it, you'll get many positive votes, I guess.

PS
I also think that if x...k disappear we could have an x.. literal, (equivalent to x..-1 to express unlimited Ranges) without ambiguity.

I would love to have :
'ciao'[1..]=='iao' #=>true
instead of
'ciao'[1..-1]=='iao' #=>true

what comes to mind for me is the english meaning of continued, not finished,
open ended, incomplete, ...

-a

···

On Thu, 30 Sep 2004, Zach Dennis wrote:

Operator Two: ... (three dots)
Example: 1...5
What comes to mind: Inclusive
How It Works: Exclusive (the last number 5, is excluded)

--

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
A flower falls, even though we love it;
and a weed grows, even though we do not love it. --Dogen

===============================================================================

Yep, at first glance I read the dots as "up to" and "up to including".
Took a bit to reverse that to "up to excluding". It wasn't intuitive
for me.

Given the choices of reversing it, losing the '...' or leaving it
alone, I'd probably go with leave it alone. I've already paid the
price of learning it, and I have used it, so might as well keep it.

···

On Thu, 30 Sep 2004 22:30:51 +0900, Zach Dennis <zdennis@mktec.com> wrote:

How range operators work seems sort of backwards to me. It would appear
as if the "..." (three dots) would be the inclusive one, including the
last value and the ".." (two dots) would be exclusive and exclude the
last value.

Am I off in my own little world here or have others pondered this?
(Perhaps it has been brought up before?) I am not requesting a change on
this, I am merely pointing out what seems unnatural in a very natural
language.

--
Bill Guindon (aka aGorilla)

Zach Dennis <zdennis@mktec.com> writes:

I have been thinking lately about rangess and I will give you the two
different range operators and what comes to mind first.

Whose mind?

Operator One: .. (two dots)
Example: 1..5
What comes to mind: Exclusive
How It Works: Inclusive (the last number 5, is included)

Operator Two: ... (three dots)
Example: 1...5
What comes to mind: Inclusive
How It Works: Exclusive (the last number 5, is excluded)

I'd be curious to know, provided it lies close enough to the
consciousness level, why 1..5 brings to your mind the idea of
exclusive whereas 1...5 brings to your mind the idea of inclusive.

To me 1..5 is `from one to five', and should I say to someone ``go
from point one to five'', I'd surely mean it to reach point five in
the end, not just stop short of it.

1...5 is simply nothing I had ever thought of and, as such, it
couldn't go against anything that came to mind (since nothing came to
mind). A couple of years ago someone here wrote something like ``Just
think of it as the same of 1..5, just with the 5 pushed aside and thus
not reached''. I didn't need anything else.

But, of course, I might just be one among a thousand with something in
my head wired backwards. Then again, I might not.

Massimiliano

Zach Dennis wrote:

I have been thinking lately about rangess and I will give you the two
different range operators and what comes to mind first.

Operator One: .. (two dots)
Example: 1..5
What comes to mind: Exclusive
How It Works: Inclusive (the last number 5, is included)

Operator Two: ... (three dots)
Example: 1...5
What comes to mind: Inclusive
How It Works: Exclusive (the last number 5, is excluded)

How range operators work seems sort of backwards to me. It would
appear as if the "..." (three dots) would be the inclusive one,
including the last value and the ".." (two dots) would be exclusive
and exclude the last value.

Am I off in my own little world here or have others pondered this?
(Perhaps it has been brought up before?) I am not requesting a change
on this, I am merely pointing out what seems unnatural in a very
natural language.

Zach

I don't know about potential parsing problems (or ugliness), but what about:

0..5 inclusive
0..<5 exclusive

Mike

Zach Dennis wrote:

How range operators work seems sort of backwards to me. It would appear as if the "..." (three dots) would be the inclusive one, including the last value and the ".." (two dots) would be exclusive and exclude the last value.

If you think of "..." as ellipsis (an English language punctuation mark), then these definitions seem to match the Ruby interpretation:

Ellipsis: From the Greek for "to come short", originally used in geometry.

http://www.u-aizu.ac.jp/~tripp/punc.html
Ellipsis (...) is used to show that something has been omitted.

an ellipsis (plural: ellipses) is a row of three dots (…) or asterisks (* * *) indicating an intentional omission.

Bob Sidebotham

Those semantics would be more consistent with yield and blk.call, and
generally I applaud anything which improves consistency:

  def foo
    yield 1
  end

  foo {|a,b| p a,b} # prints 1, nil

  def bar(&blk)
    blk.call(1)
  end

  bar {|a,b| p a,b} # prints 1, nil

However I tend towards the other position: that both the above examples
should raise an "incorrect number of arguments" exception. It tends to trap
errors sooner, rather than later. But I don't feel too strongly about which
way it's done; I feel much more strongly that it should be consistent!

I quite like your suggestion of &blk=nil though. At the moment in Ruby the
presence/absence of a block makes no difference, until you try to 'yield'
when no block is given. In particular, you can pass a block to a method
which doesn't expect one; I've been caught by that before!

So in an ideal world I'd have

  def foo(a,b) # block forbidden, raise exception if you pass one
  def foo(a,b,&c) # block required, raise exception if it's missing
  def foo(a,b,&c=nil) # block optional

That syntax would also allow a 'default block':

  def foo(a,b,&c=proc{|x| $stderr.puts x})

Regards,

Brian.

···

On Sun, Oct 03, 2004 at 12:29:39PM +0900, trans. (T. Onoma) wrote:

But since then, I've completely flipped positions, and more in concert with
the ideas of duck-typing, I wish all arguments worked like &block. e.g.

   def foo(a, b)
     "#{a}#{b}"
   end

   foo(1) #=> "1"

Just as block is nil in the above, so would b here. Likewise:

  foo(1,2,3) #=> "12"

and 3 would be ignored.

Hi!

From an intellectual point I sort of understand the '..' and '..' notation. What distracts me most, is the visual difference ... that the visually longer three dot form contains fewer elements than the shorter two dot form.

(1..5).to_a
=>[1,2,3,4,5]
(1...5).to_a
=>[1,2,3,4]

Henrik
Gavin Kistner wrote:

···

On Sep 30, 2004, at 7:30 AM, Zach Dennis wrote:

How range operators work seems sort of backwards to me. It would appear as if the "..." (three dots) would be the inclusive one, including the last value and the ".." (two dots) would be exclusive and exclude the last value.

I was thinking this exact same thing in the shower yesterday morning.

I've tried to memorize what _why said about them, to remember:

Think of it as an accordion which has been squeezed down for carrying. (Sure, you can build a great sense of self-worth by carrying around an unfolded accordion, but sometimes a person needs to wallow in self-doubt, carefully concealing the squeeze-box.) The parentheses are the handles on the sides of a smaller, handheld accordion. The dots are the chain, keeping the folds tightly closed.

Normally, only two dots are used. If a third dot is used, the last value in the range is excluded.

(0...5) represents the numbers 0 through 4.

When you see that third dot, imagine opening the accordion slightly. Just enough to let one note from its chamber. The note is that end value. We’ll let the sky eat it.

Source: http://poignantguide.net/ruby/chapter-3.html#section2

I agree. Having a separate operator for exclusive ranges just
complicates things. Why not just have '..' and the user can specify
either start..end or start..(end + 1) ?

Bill Atkins

···

On Thu, 30 Sep 2004 23:25:02 +0900, gabriele renzi <rff_rff@remove-yahoo.it> wrote:

Zach Dennis ha scritto:

> How range operators work seems sort of backwards to me. It would appear
> as if the "..." (three dots) would be the inclusive one, including the
> last value and the ".." (two dots) would be exclusive and exclude the
> last value.

actually, I thought till one moment ago that ... was going to be
deprecated. I looked up and found that I misremembered this:
http://www.rubyist.net/~matz/slides/rc2003/mgp00025.html

I'd strongly advocate the elimination of z...y .
It is completely non obvious, and it has no advantage _i can see_ over
x..k .

Maybe you can submit an rcr about it, you'll get many positive votes, I
guess.

PS
I also think that if x...k disappear we could have an x.. literal,
(equivalent to x..-1 to express unlimited Ranges) without ambiguity.

I would love to have :
'ciao'[1..]=='iao' #=>true
instead of
'ciao'[1..-1]=='iao' #=>true

gabriele renzi wrote:

Zach Dennis ha scritto:

How range operators work seems sort of backwards to me. It would appear as if the "..." (three dots) would be the inclusive one, including the last value and the ".." (two dots) would be exclusive and exclude the last value.

actually, I thought till one moment ago that ... was going to be deprecated. I looked up and found that I misremembered this:
http://www.rubyist.net/~matz/slides/rc2003/mgp00025.html

I'd strongly advocate the elimination of z...y .
It is completely non obvious, and it has no advantage _i can see_ over x..k .

Maybe you can submit an rcr about it, you'll get many positive votes, I guess.

PS
I also think that if x...k disappear we could have an x.. literal, (equivalent to x..-1 to express unlimited Ranges) without ambiguity.

I would love to have :
'ciao'[1..]=='iao' #=>true
instead of
'ciao'[1..-1]=='iao' #=>true

That is nice, but why does it conflict with having the ... operator?
I've used ... when I translated some algorithms from pseudocode in constructs like
for i = 0...n

I like that I don't have to write n-1. On the other hand that seems a bit cryptic (and we don't want to end up with perl like line noise :wink:

And most for constructions can be better expressed by iterators/generators.

Anyhow. Why does your proposal conflict with the ... operator?

Regards,

Brian

···

--
Brian Schröder
http://ruby.brian-schroeder.de/