Introducing the "it" keyword

B

Brian Candler

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.
 
G

Greg Fodor

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.
 
C

Chad Perrin

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

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.
 
E

Eleanor McHugh

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.

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
 
E

Eleanor McHugh

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
 
E

Eleanor McHugh

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
 
C

Chad Perrin

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.
 
R

Robert Klemme

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
 
R

Robert Klemme

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
 
R

Robert Dober

Unfortunately this would greatly complicate the situation in which a
return without value is intended...
That does not exist :)
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 ;)



Cheers
Robert
 
E

Eleanor McHugh

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).

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
 
E

Eleanor McHugh

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
 
R

Robert Klemme

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

:)

Kind regards

robert


PS: Thanks for teaching me another British(?) English idiom - hadn't
known "by dint of" so far. :)
 
R

Robert Dober

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

Robert Klemme

That's true.

No, nil! SCNR :)
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
 
E

Eleanor McHugh

I am not a native speaker but nevertheless I get the feeling that you
are cheating here ;)
Am I right?

Guilty as charged ;)
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
 
E

Eleanor McHugh

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.


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

I must admit that until this thread it had never occurred to me to
use instance_eval for this, even though it's bloody obvious the
moment you see it written down. I'll probably roll it into a
framework I'm currently working on and see how it compares to its VB
prototype: it is the one statement I miss from that particular
language as it saves so much unnecessary typing and some runtime
overhead (classic VB's object model being built on top of COM, the
cost of runtime method lookup on deeply nested objects can be
prohibitive on older hardware).
PS: Thanks for teaching me another British(?) English idiom -
hadn't known "by dint of" so far. :)

Seems like a fair exchange for the new Ruby idiom :)

Ellie

Eleanor McHugh
Games With Brains
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top