簡體   English   中英

在Ruby on Rails上解釋Iterator語法

[英]Explain Iterator Syntax on Ruby on Rails

我開始學習Ruby on Rails並發現自己對語法感到困惑,所以我不得不閱讀一些Ruby語法。 我從http://www.cs.auckland.ac.nz/references/ruby/doc_bundle/Manual/man-1.4/syntax.html學習了語法:

method_call do [`|' expr...`|'] expr...end

他們稱之為迭代器。 我理解一個迭代器運行循環,但我不明白我應該如何閱讀這個或者在這個語法中發生了什么。 我一直在RoR的截屏視頻中看到它並且這些詞語有意義,但我實際上不知道發生了什么。 誰有人向我解釋這個?

編輯:示例

respond_to do |format|
    format.json
    format.xml { render :xml => @posts }
end

方法可以采用稱為“塊”的構造。 這些是傳遞給方法的匿名方法。

另一種語法是:

method_call { |var| do_something(var) }

基本上,您是說對於迭代中的每個項目,將其命名為“var”並對該項執行某些操作。 該方法只是調用您傳入的塊,因為它會“生成”項目。

這有幫助嗎?

編輯:在你的例子中,他們以一種有趣的方式使用迭代器模式...可能只將一個format對象傳遞到你的塊中,這樣你就可以告訴它要處理哪些格式,以及當你看到它時要做什么。

換句話說,他們正在使用該模式創建各種DSL,以便您配置響應的內容。

在迭代器的情況下,將它們想象成Java中的接口:您可以在Ruby中執行for循環,但是您可能想要迭代的所有對象(應該)實現占用塊的“each”方法(即一個閉包,一個匿名函數)。

塊在Ruby中被遍地使用。 想象一下你有這個數組:

[1, 2, 3, 4, 5, 6].each do |i| puts i.to_s end

在這里,您正在創建數組,然后您在其上調用'each'方法。 你把塊傳遞給它。 您可以將其分開,如下所示:

arr = [1, 2, 3, 4, 5, 6]
string_printer = lambda do |i| puts i.to_s end
arr.each(&string_printer)

這種接口在其他方面實現:Hash集合允許您遍歷鍵值對:

{:name => "Tom", :gender => :male}.each do |key, value| puts key end

do..end可以替換為大括號,如下所示:

[1, 2, 3, 4, 5, 6].each {|i| puts i.to_s }

由於Ruby使用的函數式編程,這種迭代成為可能:如果要創建一個需要迭代某些東西的類,您還可以實現每個方法。 考慮:

class AddressBook
  attr_accessor :addresses
  def each(&block)
    @addresses.each {|i| yield i }
  end
end

各種類通過這種塊模式實現了有趣的功能:例如,查看String的each_line和each_byte方法。

method_call do [`|' expr...`|'] expr...end

不僅限於迭代函數。

在ruby中,任何方法都可以將塊作為參數。 然后可以通過該方法調用該塊。 在迭代器的情況下,該方法看起來像這樣:

def iter
  for i in [:x,:y,:z]
    yield i
  end
end

如果你用一個塊調用iter ,它將循環遍歷[:x, :y, :z]並將它們中的每一個放到塊中,然后可以執行任何操作。 例如打印出來:

iter { |z| puts z }

您還可以使用它來隱藏初始化和清理步驟,例如打開和關閉文件。 例如File.open File.open,如果它是在純ruby中實現的(它在C中表示性能)會做這樣的事情。

def File.open filename, opts
  f = File.new filename, opts
  yield f
  f.close
end

這就是你可以使用的原因

File.open 'foobar', 'w' do |f|
  f.write 'awesome'
end

respond_to是類似的。 它的工作原理如下:(查看這里的實際實現)

   def respond_to
     responder = Responder.new(self)
     block.call(responder)
     responder.respond
   end

它創建一個響應器對象,其中包含html方法,它們會將塊傳遞給您。 事實證明這非常方便,因為它可以讓你做以下事情:

def action
  @foo = Foo.new params[:foo]
  respond_to do |format|
    if @foo.save
      format.html { redirect_to foo_path @foo }
      format.xml { render :xml => @foo.to_xml }
    else
      flash[:error] = "Foo could not be saved!"
      format.html { render :new }
      format.xml { render :xml => {:errors => @foo.errors }.to_xml}
    end
  end
end

看看我如何改變依賴於塊內保存的行為? 沒有它,這樣做會更煩人。

<function> do |<temp variable>|
    <code to operate on temp variable>
end

這將創建一個臨時匿名函數,該函數將項接受到臨時變量中,然后讓事物對該項進行操作。 匿名函數被傳遞給指定的原始<function> ,以對該函數產生的項進行操作。

你看到的是一段代碼,當你第一次看到它時,語法有點尷尬。

所以,基本上,對於迭代器,你有一個可以重復的“東西”,它會收到一個塊來知道該怎么做。

例如, Range類有一個名為“each”的方法,它接收要在該范圍內的每個元素上執行的代碼塊。

假設您要打印它:

range = 1..10 #range literal 
range.each {|i|
    puts i
}

代碼: {|i| puts i} {|i| puts i}是一個塊,它表示當這個范圍迭代每個元素時該怎么做。 替代語法是您發布的語法:

 range.each do |i|
      puts i 
 end

這些塊與迭代器一起使用,但它們不限於“迭代”代碼,您可以在其他場景中使用它們,例如:

class Person 
  def initialize( with_name ) 
    @name = with_name
  end
  # executes a block 
  def greet 
      yield @name #passes private attribute name to the block 
  end 
end 

p = Person.new "Oscar" 
p.greet { |n|
     puts "Name length = #{n.length}"
     puts "Hello, #{n}"
}

打印:

Name length = 5
Hello, Oscar

因此,使用塊而不是使用具有固定行為的greet方法,讓開發人員指定要做什么,這對迭代器非常有幫助,但是你只是見證了不是唯一的地方。 在您的情況下,該塊允許您指定在respond_to方法中執行的操作。

你正在閱讀的文件很古老 - 實際上是史前的。 如果網頁可能會聚集灰塵,那么會有一層厚厚的網頁。

ruby-lang網站上試用參考資料。 此外, Programming Ruby (pickaxe)書籍是必不可少的參考書。

我認為你可以稱之為迭代器,因為通常會多次調用塊函數。 如:

5.times do |i|
  puts "#{i} "
end

“在幕后”,進行了以下步驟:

  • 調用對象實例5的方法times ,傳遞代碼puts "#{i} "放入Proc對象實例中。
  • times方法中,此代碼在循環內部調用,將當前索引作為參數傳遞。 這就是times 可能看起來像( 它在C,實際上 ):

class Fixnum
  def times_2(&block) # Specifying &block as a parameter is optional
    return self unless block_given?
    i = 0
    while(i < self) do
      yield i # Here the proc instance "block" is called
      i += 1
    end
    return self
  end
end

請注意,范圍(即局部變量等)被復制到塊函數中:

x = ' '
5.times do { |i| puts "#{i}" + x }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM