Introducing the "it" keyword

On 2007-06-01 22:52:31 +0900 (Fri, Jun), Brian C. wrote:

return a if with:a(v+1) < 10

return a,b if ( with:a(v+1) + with:b(x*y) ) < 10

But if you’re going to label them anyway, then why not write

return a,b if ((a = v+1) + (b = x*y)) < 10

The whole discussion started because this code does not work in current
ruby parser rules.

In the part ‘return a,b’ “a” and “b” are treated as method calls, but
in ‘if ((a = v+1) + (b = x*y)) < 10’ they are treated as local
variables.

If you try to execute this line (use irb) you will get error
‘NameError: undefined local variable or method `a’ for main:Object’

On Sat, Jun 02, 2007 at 12:03:25AM +0900, Mariusz P??kala wrote:

The whole discussion started because this code does not work in current
ruby parser rules.

OK, but maybe fixing this is an easier language change than adding
“with:foo(bar)”?

That is, the above could be defined to be identical to

if ((a = v+1) + (b = x*y)) < 10
return a,b
end

I agree this would make the already somewhat “magical” rule about where
local variables spring into life more difficult to understand; rather
than
being based on a strict left-to-right tokenisation, it would have to be
based on the parse tree.

That is, given

expr1 if expr2

then expr2 would be treated as logically “earlier” in the source file
than
expr1, for the purposes of local variable creation. But that’s fairly
sensible, since if expr1 and/or expr2 ever get executed, expr2 must be
executed before expr1.

B.

I agree that having the assignment case work would be great,
but there is still the problem of the programmer having to
come up with names. If there’s anything Rails has taught us,
it’s that there is power in convention. I think having the
‘it’ variable be the ruby implicit default name would be
powerful if taken to it’s logical limits. It’s like a safe,
less hacky version of $_ from perl that reads nicer too.

Think of how many times you come up with a meaningless name
to pass to a block. These meaningless names serve to confuse
your readers if they are not required to disambiguate nested
blocks, etc. In this case:

return a if (a = v+1) > 10

the name ‘a’ is really a waste, if you can leverage the power
of convention to use ‘it’.

As I’ve thought more about this, I am quite happy with the
‘let’ implementation which just yields it’s values forward.
This gets me all the semantics I want, but its just a bit
cumbersome to write and I still have to come up with those
damn meaningless names so ruby has something to bind with.
This is the last pain point:

You say foo, I say bar, bob says boo, and chuck says baz,
so depending on who writes it, we end up with:

with (v+1) { |foo| return foo if foo < 10 }
with (v+1) { |bar| return bar if bar < 10 }
with (v+1) { |boo| return boo if boo < 10 }
with (v+1) { |baz| return baz if baz < 10 }

When you’ve got 12 programmers, this disconnect gets hairy.

By adding the “‘it’ is default name” rule, everyone who
knows their Ruby will write:

with (v+1) { return it if it < 10 }

by adding the 'bars around expression get transformed into
call to ‘with’ rule on top of that (debatable since the
semantics are a bit sloppy):

return it if |v+1| < 1

Personally, the ‘default name is ‘it’’ rule seems incredibly
useful, the bars are nice too but I don’t have my heart
set on them.

Of course, I might find the with:a(v+1) syntax more readable if it were
used in a language where that sort of thing was normal. It just looks
un-Rubylike enough to me that it throws me off in a Ruby context.

The point of enabling something like with:a(v+1){ … } in addition to
with(v+1){ |a| …} is simply a proposal in answer to the original
proposition about ‘it’:
return it if |v+1| < 10

something like:

return it if with:it(v+1) < 10

return a if with:a(v+1) < 10

return a,b if ( with:a(v+1) + with:b(x*y) ) < 10

Where this:

return it if with:it(v+1) < 10

Would be translated by the interpreter into exactly the same thing as
this:

with:it(v+1) do
return it if it < 10
end

which is exactly the same thing as this:

with(v+1) do |it|
return it if it < 10
end

On Fri, Jun 01, 2007 at 10:45:33PM +0900, Jacob B. wrote:

with(v+1) do |it|
return it if it < 10
end

Yes . . . I was just pointing out that, of those, the third is the only
one that really seems particularly readable to me in a Ruby context.

Something about with:it(v+1) just doesn’t look very readable to me. It
might have something to do with the lack of space separating tokens, but
I’m pretty sure that’s not all there is to it.

On 2 Jun 2007, at 01:09, Chad P. wrote:

Something about with:it(v+1) just doesn’t look very readable to
me. It
might have something to do with the lack of space separating
tokens, but
I’m pretty sure that’s not all there is to it.

I tend to agree, although that’s because I’d really like Ruby to have
the ‘with’ syntactic sugar that VB has. I also much prefer the idea
of being able to choose my own block variable name rather than being
stuck with ‘it’ which to my eye is an ungainly word. It still bothers
me though that a formulation that’s intended to make for a simple
atomic statement would now cover three lines onscreen…

Ellie

Eleanor McHugh
Games With Brains

raise ArgumentError unless @reality.responds_to? :reason

On 31 May 2007, at 06:35, Robert D. wrote:

But maybe things should really by simple

return if x > 42
return unless (x+1)%2 == 0 # not zero? here

could probably made syntactically work (differently than now) and
return the LHS of the expression iff the expression evaluates to true
or false respectively.

Unfortunately this would greatly complicate the situation in which a
return without value is intended…

Ellie

Eleanor McHugh
Games With Brains

raise ArgumentError unless @reality.responds_to? :reason

On Mon, Jun 04, 2007 at 02:46:55AM +0900, Eleanor McHugh wrote:

Well as I said in my original post, %$ was intended purely as a
placeholder. I did also consider <= which could play an analogous
role to => in hash literals but it looked even stranger. Another
possibility would be:

return f(x) if != y
return f(x) unless == y

which would complicate the parser but is quite readable.

Unfortunately for the <= idea, <= means “less than or equal to” as a
comparison operator already. I do like the readability of your return
statement syntax, though.

On 03.06.2007 19:34, Eleanor McHugh wrote:

end
Something about with:it(v+1) just doesn’t look very readable to me. It
might have something to do with the lack of space separating tokens, but
I’m pretty sure that’s not all there is to it.

I tend to agree, although that’s because I’d really like Ruby to have
the ‘with’ syntactic sugar that VB has. I also much prefer the idea of
being able to choose my own block variable name rather than being stuck
with ‘it’ which to my eye is an ungainly word. It still bothers me
though that a formulation that’s intended to make for a simple atomic
statement would now cover three lines onscreen…

I believe Ruby does not have “with” because there is instance_eval -
it’s more to type but can be easily aliased and has the same effect -
rebinding “self”. (I know that some talk about another “with”, that
rebinds arbitrary variable names. But I believe the original idea of
“with” was, that you could invoke methods without explicit receiver).

Kind regards

robert

On 03.06.2007 19:47, Eleanor McHugh wrote:

Unfortunately this would greatly complicate the situation in which a
return without value is intended…

In Ruby there is no such thing. Every method returns something - even
if it’s nil.

Kind regards

robert

On 31 May 2007, at 04:46, Chad P. wrote:

== x’. This becomes even more important when the test is even more
convoluted such as checking for the position of a string in another
string and returning if it is in a specific location.

I’m afraid I must disagree. The only thing I find “unreadable” about
that is the complete lack of obvious association between %$ and the
source of the value it contains/labels. The composition of the
expression itself, such that the condition test is on the same line as
the rest of the action, produces absolutely zero difficulty for me.

Well as I said in my original post, %$ was intended purely as a
placeholder. I did also consider <= which could play an analogous
role to => in hash literals but it looked even stranger. Another
possibility would be:

return f(x) if != y
return f(x) unless == y

which would complicate the parser but is quite readable.

Ellie

Eleanor McHugh
Games With Brains

raise ArgumentError unless @reality.responds_to? :reason

On 6/3/07, Eleanor McHugh [email protected] wrote:

Unfortunately this would greatly complicate the situation in which a
return without value is intended…
That does not exist :slight_smile:
Therefore the only tread off would be to write

return nil if/unless whatever which would be an equivalent to nowadays

return if/unless

But I am not advocating this change into the language it was just an
idea in a crazy discussion :wink:

Cheers
Robert

On 3 Jun 2007, at 20:45, Robert K. wrote:

effect - rebinding “self”. (I know that some talk about another
“with”, that rebinds arbitrary variable names. But I believe the
original idea of “with” was, that you could invoke methods without
explicit receiver).

It’s not entirely clear to me that ‘instance_eval’ would obey the
same scoping rules as ‘with’ in VB by dint of introducing a block. I
also just happen to prefer the syntactic form in the same way that
there are people who routinely use ‘for’ statements in their Ruby code.

Ellie

Eleanor McHugh
Games With Brains

raise ArgumentError unless @reality.responds_to? :reason

On 3 Jun 2007, at 20:45, Robert K. wrote:

or false respectively.
Unfortunately this would greatly complicate the situation in which
a return without value is intended…

In Ruby there is no such thing. Every method returns something -
even if it’s nil.

That’s true. But how many of us are in the habit of doing so
explicitly with ‘return nil’? Having to do that in this particular
circumstance adds an extra element of surprise to the language.

Ellie

Eleanor McHugh
Games With Brains

raise ArgumentError unless @reality.responds_to? :reason

On 6/4/07, Eleanor McHugh [email protected] wrote:

true

or false respectively.

Unfortunately this would greatly complicate the situation in which a
return without value is intended…
That does not exist :slight_smile:

The intent often exists, regardless of the fact that Ruby always
returns a value :wink:
I am not a native speaker but nevertheless I get the feeling that you
are cheating here :wink:
Am I right?
Cheers
Robert

On 04.06.2007 16:29, Eleanor McHugh wrote:

it’s more to type but can be easily aliased and has the same effect -
rebinding “self”. (I know that some talk about another “with”, that
rebinds arbitrary variable names. But I believe the original idea of
“with” was, that you could invoke methods without explicit receiver).

It’s not entirely clear to me that ‘instance_eval’ would obey the same
scoping rules as ‘with’ in VB by dint of introducing a block.

I’m not too familiar with VB (I’m kinda happy that I could stay away
from it.) so I cannot really comment on the scoping question.

I also
just happen to prefer the syntactic form in the same way that there are
people who routinely use ‘for’ statements in their Ruby code.

Tastes, tastes… Well, you can of course have your “with”:

module Kernel
private
def with(obj, &b)
obj.instance_eval(&b)
end
end

with “foo” do
puts length
end

same as

“foo”.instance_eval do
puts length
end

:slight_smile:

Kind regards

robert

PS: Thanks for teaching me another British(?) English idiom - hadn’t
known “by dint of” so far. :slight_smile:

On 04.06.2007 16:31, Eleanor McHugh wrote:

or false respectively.
Unfortunately this would greatly complicate the situation in which a
return without value is intended…

In Ruby there is no such thing. Every method returns something - even
if it’s nil.

That’s true.

No, nil! SCNR :slight_smile:

But how many of us are in the habit of doing so explicitly
with ‘return nil’? Having to do that in this particular circumstance
adds an extra element of surprise to the language.

True, I should have read the bit above your statement more thoroughly.
You are right of course. I’m against this “it” anyway, so…

Kind regards

robert

On 4 Jun 2007, at 06:09, Robert D. wrote:

or false respectively.

Unfortunately this would greatly complicate the situation in which a
return without value is intended…
That does not exist :slight_smile:

The intent often exists, regardless of the fact that Ruby always
returns a value :wink:

Ellie

Eleanor McHugh
Games With Brains

raise ArgumentError unless @reality.responds_to? :reason

On 4 Jun 2007, at 15:48, Robert D. wrote:

and
returns a value :wink:
I am not a native speaker but nevertheless I get the feeling that you
are cheating here :wink:
Am I right?

Guilty as charged :wink:
Whilst I think syntax such as

return if x > 42

being equivalent to

return (x | nil) if x > 42

is elegant, it would mandate that

return nil

always be explicit in this particular case. I know that I’d have a
devil of a time remembering to do that consistently lol

Ellie

Eleanor McHugh
Games With Brains

raise ArgumentError unless @reality.responds_to? :reason

Greg F. wrote:

or

and

return it if |v + 1| < 10

Hasn’t ‘it’ effectively been reserved as a keyword by the RSpec team

bowling_spec.rb

require ‘bowling’

describe Bowling do
before(:each) do
@bowling = Bowling.new
end

it “should score 0 for gutter game” do
20.times { @bowling.hit(0) }
@bowling.score.should == 0
end
end


Brad P.
http://xtargets.com