I'm learning Ruby and RoR at the moment, and I came across this:
<% for post in @posts %>
in the Rails guide. I'd understood that the idiomatic way to do this in Ruby is with:
<% @posts.each do |post| %>
If there is a difference then what is it? And if there isn't a difference then wouldn't it be better for the Rails people to be pushing proper Ruby idioms (rather than this, which looks more pythonic to me)?
Edit: I've just found two conflicting explanations of this: Tutorials Point says they're the same except "a for loop doesn't create a new scope for local variables", whereas CS.Auckland.ac.NZ says for
is just syntactic sugar for the equivalent .each
.
Edit2: The for ... in
in question was for the index.html.erb
generated in app/views/posts
by script/generate scaffold
. I've done a quick check and that now generates the .each
syntax. I guess that part of the guide was written at an earlier stage of rails development when the scaffold generated for ... in
.
Edit3: I can now confirm that for x in y
was used in Rails 2.2.2, but by 2开发者_Python百科.3.8 it is using y.each do |x|
. Just so you know.
The tutorialpoint page is correct, for
is equivalent to each
except for the scoping difference. Here's a demonstration:
arr = [1,2,3]
arr.each do |x|
last = x
end
last # NameError
vs.
arr = [1,2,3]
for x in arr
last = x
end
last #=> 3
If you want to make it work using each
, you need to do last = nil
before the loop. This is, as the link pointed out, because blocks start a new scope while for
does not.
Note however that this rarely makes a practical difference and few people are even aware of it.
When people use for
in ruby it's most often because that's what they're used to coming from other languages - not because of any differences between for
and each
.
The thing is that the first example (for post in @posts
) looks more "procedural", while the second (@posts.each do |post|
) looks more "functional". Unfortunately, procedural way to read code is still considered more popular, more clear and less "geeky". That's why, perhaps, many would prefer it to the "native" way of iterating through containers.
If it looks pythonic (I'm not sure if it's true), then it may be considered even better, since it improves accessibility of Rails by developers that come from other platforms.
Personally, I'd like ruby and "functional" ways to be pushed. But the above reasons demonstrate that it can be done either way.
Some day I was developing the feature of generating PDF reports for the website I was working on.
The plugin I was using had many limitations. Those limitations enforced me to produce the solution which was very imperative and procedural. I was using constructions like while
or for
just to emphasis this style of programming.
In fact, this was the only situation when I used those keywords in ruby.
You may want to use for x in y
if you're trying to do ruby profiling and your version of ruby-prof doesn't have method elimination.
One more thing about for x in y
is that you can do for i in 1..5
which will work like a standard for loop, starting at i = 1
and going through i = 5
.
The handy thing about this is that you can use a range like 3..8
or x..y
, you are not stuck starting from zero, which you would be by using n.times
method.
精彩评论