锁定老帖子 主题:疑问:yield到底是怎么运作的?
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2006-11-01
When I started to learn ruby, I felt that Ruby was too complicated, and many average programmers might not be able to understand and master it.
The people on this forum are really great, high/deep level developers. From the discussion above, which seems confirmed my thought to certain extent. ![]() 曲高和寡! |
|
返回顶楼 | |
发表时间:2006-11-02
布娃娃:你理解错了,aardvark的例子里是调用函数fibUpTo在维护状态,被调用的block本身是无状态的。
whisper:我就是为了证明python的yield和ruby的yield不是一回事啊呵呵。你说的yield有点累赘也有道理,不过ruby的哲学就是同一件事有几种不同做法,所以各取所爱拉。 那段haskell的map定义写成ruby的话: def map(a, &f) if a.empty? then [] else b,*c = a; map(c,&f).insert(0, f.call(b)) end end >>map([1,2,3]){|x| x+1} =>[2,3,4] BTW, haskell确实是神的语言阿,我等凡人是没指望了 |
|
返回顶楼 | |
发表时间:2006-11-02
那个我确实也是说ruby和python的yield不一样的
只是我的输入法比较难用 少打了个“不” 已经改正了 当时简直郁闷的要死 ![]() |
|
返回顶楼 | |
发表时间:2006-11-02
sorry. 我前面是写错了。 我想写的是,aardvark的第一段代码中, generator 部分 (就是 fibUpTo)维护了状态。 这正是 iterator 的 特点。 从这一点来看, ruby yield 和 python yield 在 generator 部分,是一样的。 不过,Ruby yield 的 receiver 部分是一个 block -- callback。这个 block 是不能保持状态的。 这点和 Python Yield 的 receiver 部分不一样。 aardvark的第二段代码,就表示了ruby yield generator + block receiver 的真实含义 -- 一个 visitor。block receiver 是一个 visitor callback function. |
|
返回顶楼 | |
发表时间:2006-11-02
buaawhl 写道 从这一点来看, ruby yield 和 python yield 在 generator 部分,是一样的。 Ruby的yield不是generator。 你应该仔细看看aardvark和cookoo的两个fib函数, Ruby的是while i1 <= max, Python的是while 1:。 Ruby的yield可以看是低开销的Proc#call, 而Python中的yield具有了一些continuation的特性 |
|
返回顶楼 | |
发表时间:2006-11-03
python的yield和C# 2.0的yield语义一致
我觉得这完全就是个语法糖 很可能就是编译器生成了个 [] 然后每次yield就push 最后返回放满了东西的列表 不过暂时没时间看他的源码了 ps. ruby和python的yield干的事都不一样,没必要比较了 |
|
返回顶楼 | |
发表时间:2006-11-04
其实以前有人在ruby-lang列表里建议把yield改成call什么的,因为yield总是容易让人联想到线程,coroutine上面去。不知道Matz怎么想的。。。
|
|
返回顶楼 | |
发表时间:2006-11-04
cookoo 写道 其实以前有人在ruby-lang列表里建议把yield改成call什么的,因为yield总是容易让人联想到线程,coroutine上面去。不知道Matz怎么想的。。。
Matz是从别人那抄来的。这么实现iterator是MIT一个女博士的发明: http://en.wikipedia.org/wiki/CLU_programming_language 我没有仔细看过CLU,不知道在CLU里面yield的涵义是不是更宽一些。 |
|
返回顶楼 | |
发表时间:2006-11-09
这段程序有个错误,关系到yield的调用,请各位帮忙看一下:
view里的调用: <div id="mytree" class="mytree"> <% @ancestors = @item.ancestors.collect{|parent| parent.id} unless !@item.has_parent? %> <% @items = Item.find(:all) %> <%= get_tree_data(@items,0){|n| link_to_remote n.name, :url=>{:controller=>'items',:action=>'display_clicked_item',:id=>n.id}, :loading=>"Element.show('tree_indicator')", :complete=>"Element.hide('tree_indicator')" } %> <% @items.each do |node| %> <%= draggable_element node.id.to_s+'_tree_div',:revert=>true,:snap=>false, :handle=>"'#{node.id.to_s}_drag_image'" %> <%= drop_receiving_element(node.id.to_s+'_tree_div', :accept=>'inner_tree_element', :url=>{:controller=>'collection', :action=>'sort_my_tree', :parent_id=>node.id,:id=>nil}, :loading=>"Element.show('sort_tree_indicator')", :complete=>"Element.hide('sort_tree_indicator');" )%> <% end %> <%= image_tag 'indicator.gif', :id=>'sort_tree_indicator', :style=>'display:none' %> </div> controller: def get_tree_data(tree, parent_id) ret = "<div class='outer_tree_element' >" tree.each do |node| if node.parent_id == parent_id node.style = (@ancestors and @ancestors.include?(node.id))? 'display:inline' : 'display:none' display_expanded = (@ancestors and @ancestors.include?(node.id))? 'inline' : 'none' display_collapsed = (@ancestors and @ancestors.include?(node.id))? 'none' : 'inline' ret += "<div class='inner_tree_element' id='#{node.id}_tree_div'>" if node.has_children? ret += "<img id='#{node.id.to_s}expanded' src='/images/expanded.gif' onclick='javascript: return toggleMyTree(\"#{node.id}\"); ' style='display:#{display_expanded}; cursor:pointer;' /> " ret += "<img style='display:#{display_collapsed}; cursor:pointer;' id='#{node.id.to_s}collapsed' src='/images/collapsed.gif' onclick='javascript: return toggleMyTree(\"#{node.id.to_s}\"); ' /> " end ret += " <img src='/images/drag.gif' style='cursor:move' id='#{node.id}_drag_image' align='absmiddle' class='drag_image' /> " ret += "<span id='#{node.id}_tree_item'>" ret += yield node ret += "</span>" ret += "<span id='#{node.id}children' style='#{node.style}' >" ret += get_tree_data(node.children, node.id){|n| yield n} ret += "</span>" ret += "</div>" end end end 这段调用总是报错: 引用 Showing app/views/items/_ajax_tree.rhtml where line #71 raised:
can't convert Array into String Extracted source (around line #71): 68: <div id="mytree" class="mytree"> 69: <% @ancestors = @item.ancestors.collect{|parent| parent.id} unless !@item.has_parent? %> 70: <% @items = Item.find(:all) %> 71: <%= get_tree_data(@items,0){|n| 72: link_to_remote n.name, 73: :url=>{:controller=>'items',:action=>'display_clicked_item',:id=>n.id}, 74: :loading=>"Element.show('tree_indicator')", Trace of template inclusion: /app/views/items/show.rhtml RAILS_ROOT: ./script/../config/.. Application Trace | Framework Trace | Full Trace #{RAILS_ROOT}/app/helpers/application_helper.rb:22:in `+' #{RAILS_ROOT}/app/helpers/application_helper.rb:22:in `get_tree_data' #{RAILS_ROOT}/app/helpers/application_helper.rb:5:in `get_tree_data' #{RAILS_ROOT}/app/helpers/application_helper.rb:22:in `get_tree_data' #{RAILS_ROOT}/app/helpers/application_helper.rb:5:in `get_tree_data' #{RAILS_ROOT}/app/views/items/_ajax_tree.rhtml:71:in `_run_rhtml_items__ajax_tree' #{RAILS_ROOT}/app/views/items/show.rhtml:8:in `_run_rhtml_items_show' |
|
返回顶楼 | |
发表时间:2006-11-09
get_tree_data里面用了两个yield,我真的没看明白那是什么意思,请高手解释一下
|
|
返回顶楼 | |