Hal Fulton писал 03.07.2012 00:39:
There have been times that I wanted to just skip to the bottom of
the current file.
For one example, consider this idiom (not as popular as it used
to be):
if $0 == __FILE__
# Possibly many lines
end
I'd like to write this as:
break if $0 != __FILE__
But of course, that doesn't work. And of course, exit would be
appropriate if your program itself is in the current file.
Has anyone else ever thought along these lines? I grant that the
usefulness is very limited.
Well, this is pretty easy to implement and, I admit, somewhat logical.
Could you post your feature request at http://redmine.ruby-lang.org/ ?
If it will be 'approved' by someone from Ruby Core team I'd just go
and implement that for MRI.
A part of me thought: Well, should "break" just jump to the bottom
of the innermost enclosing context? And a part of me likes this, but
a part feels there are excellent reasons not to do it.
For example: If you're inside a method but not inside a loop, break
would act the same as return. It might confuse you if you think your
break is inside a loop but isn't -- it would return instead of giving an
error. (But if you can't tell the inside of a loop from the outside, your
code needs to be made prettier.)
I'm not sure if I like this or not. On one hand, break already has double
semantics (block and loop context). On the other one, I never quite liked
this feature, as it's somewhat confusing.
Break inside a block, of course, is like a "return" from/for the block.
That, I suppose, is the only time break takes a value -- but I don't
think it would break anything (inside a method) if it *always* took a
value.
In that case, loops and class definitions could have (meaningful)
return values.
Break from a loop makes the loop return a value, too.
i = 0; while i < 5; i += 1; end
# => nil
i = 0; while i < 5; i += 1; break 1; end
# => 1
And class definitions very certainly can return a meaningful value. Here
is a real-world example: getting a singleton class syntactically.
o = Object.new; p class << o; self; end
# => #<Class:#<Object:0x000000025b47b0>>
The only time I envision this "break <value>" being truly useless is
breaking from inside a required file -- we don't want to harm the
semantics of require() returning true/false, and I can't think where
else the value would go.
Unless we made "break" at toplevel of a require return true by default --
but that seems even uglier.
Return value of `require' has nothing to do with the contents of the loaded
file, and we definitely should keep it that way. (Note that I'm not saying
it is anyhow useful. IMHO `require' could just return nil as well, and in
those very rare cases when you actually need to know if a feature was loaded
previously you could just check $LOAD_PATH.)
On a side note, the "$0 == __FILE__" expression is ugly to me. What
I really would like if something like:
break if __REQUIRED__
Note that `require' is not the only true way to load files in Ruby. You also
have `load', `eval' and so on, so the name __REQUIRED__ would be misleading.
Also, making it a keyword will break those (probably very rare) cases where
it's been used as a variable name. (I've been bitten by someone from TC-39
committee.)
or simply
__MAIN__
This is, again, confusing and incompatible. Not only this will require adding
new keywords for doubtful reasons, it's also not clear what this code does.
`if $0 == __FILE__' will be understood by anyone familiar with Unix ("familiar
with Unix" implies that you're familiar with Bash and C); at least __FILE__
can be easily googled, it's present in keyword list and it has broader usage
than just that statement alone. What you're trying to add is, actually, a
completely new control flow construct for just one corner case.
(Also, using $0 as argv[0] and $[1..262144] for regexp unnamed captures was
an utterly moronic decision. Only several things are worse, like Perl-style
global variables. Do you remember what $/ does and which functions are
affected by $= ?)
···
But this is just me rambling. Comment or ignore as you wish.
Cheers,
Hal
--
WBR, Peter Zotov.