论坛首页 编程语言技术论坛

疑问:yield到底是怎么运作的?

浏览 32447 次
该帖已经被评为精华帖
作者 正文
   发表时间: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.


曲高和寡!
0 请登录后投票
   发表时间: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确实是神的语言阿,我等凡人是没指望了                          
0 请登录后投票
   发表时间:2006-11-02  
那个我确实也是说ruby和python的yield不一样的
只是我的输入法比较难用
少打了个“不”
已经改正了
当时简直郁闷的要死
0 请登录后投票
   发表时间: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.

0 请登录后投票
   发表时间: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的特性
0 请登录后投票
   发表时间:2006-11-03  
python的yield和C# 2.0的yield语义一致
我觉得这完全就是个语法糖
很可能就是编译器生成了个 []
然后每次yield就push
最后返回放满了东西的列表
不过暂时没时间看他的源码了

ps. ruby和python的yield干的事都不一样,没必要比较了
0 请登录后投票
   发表时间:2006-11-04  
其实以前有人在ruby-lang列表里建议把yield改成call什么的,因为yield总是容易让人联想到线程,coroutine上面去。不知道Matz怎么想的。。。
0 请登录后投票
   发表时间: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的涵义是不是更宽一些。
0 请登录后投票
   发表时间: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'

0 请登录后投票
   发表时间:2006-11-09  
get_tree_data里面用了两个yield,我真的没看明白那是什么意思,请高手解释一下
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics