`

Yet another Ruby Memoization

    博客分类:
  • Ruby
阅读更多
night_stalker: http://www.iteye.com/topic/406220
Hooopo: http://www.iteye.com/topic/810957
两位大仙都讨论过Ruby Memoization
首先说一下什么是Memoization:
举个例子,fib数列:
def fib(n)
  return n if (0..1).include? n
  fib(n-1) + fib(n-2)
end

递归调用,有很多重复的计算,如果我们能够将计算过的结果保存下来,下一次
需要计算的时候,直接出结果就ok了,这就是动态规划的思想。
于是乎:
def fib(n)
     @result ||= []
     return n if (0..1).include? n
     @result[n] ||= fib(n-1) + fib(n-1)
end

我们使用一个@result数组来保存已经计算的结果,并且如果计算过直接返回。
||=是Ruby作为Lazy init和cache的惯用法。
但是对于false和nil的结果,由于||的特性,无效:
def may_i_use_qq_when_i_have_installed_360?
  @result ||= begin
     puts "我们做出了一个艰难的决定..."
     false
  end
end

每次都的做出艰难的决定...
James 写了一个module,http://blog.grayproductions.net/articles/caching_and_memoization可以专门用作Memoization
代码类似如下:
module Memoizable
    def memoize( name, cache = Hash.new )
        original = "__unmemoized_#{name}__"
        ([Class, Module].include?(self.class) ? self : self.class).class_eval do
            alias_method original, name
            private
            original
            define_method(name) { |*args| cache[args] ||= send(original, *args) }
        end
    end
end

使用这个模块,我们只需要include这个module,然后memoize :meth即可
include Memoizable

def fib(n)
    return n if (0..1).include? n
    fib(n-1) + fib(n-2)
end

memoize :fib

可以使用
module Functional
  #
  # Return a new lambda that caches the results of this function and 
  # only calls the function when new arguments are supplied.
  #
  def memoize
    cache = {}  # An empty cache. The lambda captures this in its closure.
    lambda {|*args|
      # notice that the hash key is the entire array of arguments!
      unless cache.has_key?(args)  # If no cached result for these args
        cache[args] = self[*args]  # Compute and cache the result
      end
      cache[args]                  # Return result from cache
    }
  end
  # A (probably unnecessary) unary + operator for memoization
  # Mnemonic: the + operator means "improved"
  alias +@ memoize        # cached_f = +f
end

class Proc; include Functional; end
class Method; include Functional; end

这样:
factorial = lambda {|x| return 1 if x==0; x*factorial[x-1]; }.memoize
# Or, using the unary operator syntax
factorial = +lambda {|x| return 1 if x==0; x*factorial[x-1]; }





James的博客很不错:
http://blog.grayproductions.net/
分享到:
评论
4 楼 fuliang 2010-12-01  
恩,这样就ok了。
orcl_zhang 写道


3 楼 orcl_zhang 2010-11-29  
fuliang 写道
orcl_zhang 写道
这样true和false也能Memoization。很好。转载下。

false和nil还是不可以的。

有数组了,判断下has_key?就可以了吧?
module Memoizable
    def memoize( name, cache = Hash.new )
        original = "__unmemoized_#{name}__"
        ([Class, Module].include?(self.class) ? self : self.class).class_eval do
            alias_method original, name
            private
            original
            define_method(name) { |*args| cache.has_key?(args) ? cache[args] : cache[args] ||= send(original, *args) }
        end
    end
end

def may_i_use_qq_when_i_have_installed_360?  
  @result ||= begin  
     puts "我们做出了一个艰难的决定..."  
     false  
  end  
end 

cc = Hash.new
include Memoizable  
memoize :may_i_use_qq_when_i_have_installed_360?,cc


may_i_use_qq_when_i_have_installed_360?
may_i_use_qq_when_i_have_installed_360?
may_i_use_qq_when_i_have_installed_360?

def fib(n)  
    puts n
    return n if (0..1).include? n  
    fib(n-1) + fib(n-2)  
end  
  
memoize :fib ,cc

fib 10
fib 10
fib 10

irb(main):002:0> module Memoizable
irb(main):003:1>     def memoize( name, cache = Hash.new )
irb(main):004:2>         original = "__unmemoized_#{name}__"
irb(main):005:2>         ([Class, Module].include?(self.class) ? self : self.class).class_eval do
irb(main):006:3*             alias_method original, name
irb(main):007:3>             private
irb(main):008:3>             original
irb(main):009:3>             define_method(name) { |*args| cache.has_key?(args) ? cache[args] : cache[args] ||= send(original, *args) }
irb(main):010:3>         end
irb(main):011:2>     end
irb(main):012:1> end
=> nil
irb(main):013:0> 
irb(main):014:0* def may_i_use_qq_when_i_have_installed_360?  
irb(main):015:1>   @result ||= begin  
irb(main):016:2*      puts "我们做出了一个艰难的决定..."  
irb(main):017:2>      false  
irb(main):018:2>   end  
irb(main):019:1> end 
=> nil
irb(main):020:0> 
irb(main):021:0* cc = Hash.new
=> {}
irb(main):022:0> include Memoizable  
=> Object
irb(main):023:0> memoize :may_i_use_qq_when_i_have_installed_360?,cc
=> #<Proc:0xb7833db4@(irb):9>
irb(main):024:0> 
irb(main):025:0* 
irb(main):026:0* may_i_use_qq_when_i_have_installed_360?
我们做出了一个艰难的决定...
=> false
irb(main):027:0> may_i_use_qq_when_i_have_installed_360?
=> false
irb(main):028:0> may_i_use_qq_when_i_have_installed_360?
=> false
irb(main):029:0> 
irb(main):030:0* def fib(n)  
irb(main):031:1>     puts n
irb(main):032:1>     return n if (0..1).include? n  
irb(main):033:1>     fib(n-1) + fib(n-2)  
irb(main):034:1> end  
=> nil
irb(main):035:0>   
irb(main):036:0* memoize :fib ,cc
=> #<Proc:0xb7833db4@(irb):9>
irb(main):037:0> 
irb(main):038:0* fib 10
10
9
8
7
6
5
4
3
2
1
0
=> 55
irb(main):039:0> fib 10
=> 55
irb(main):040:0> fib 10
=> 55
irb(main):041:0> fib 10
=> 55
irb(main):042:0> cc
=> {[4]=>3, []=>false, [10]=>55, [1]=>1, [7]=>13, [0]=>0, [6]=>8, [3]=>2, [9]=>34, [2]=>1, [8]=>21, [5]=>5}
 


2 楼 fuliang 2010-11-29  
orcl_zhang 写道
这样true和false也能Memoization。很好。转载下。

false和nil还是不可以的。
1 楼 orcl_zhang 2010-11-28  
这样true和false也能Memoization。很好。转载下。

相关推荐

    yet another smooth scrolling

    标题“yet another smooth scrolling”指的是一个Firefox浏览器的扩展插件,其主要功能是提供更平滑、更流畅的页面滚动体验。在描述中提到,这个插件的目标是为Firefox用户带来类似于Opera浏览器的平滑滚动效果,...

    YSJSW(Yet Another Java Service Wrapper)

    YSJSW,全称为"Yet Another Java Service Wrapper",是一个强大的工具,主要用于将Java应用程序转换为Windows服务。这个工具使得Java应用能够在Windows操作系统环境下无缝运行,就像原生的Windows服务一样,提供了...

    yet-another-emoji-support,这是intellij插件,支持使用内容辅助在编辑器中插入emoji。.zip

    《IntelliJ IDEA插件:Yet Another Emoji Support详解》 在现代编程环境中,代码注释、日志记录、甚至团队沟通中,表情符号(Emoji)的使用已经变得日益普遍,它们为文字信息增添了情感色彩,使得沟通更加生动有趣...

    chrome插件Yet Another REST Client

    A free and easy-to-use REST Client. Use it to develop, test and debug RESTful services.

    Yet Another Shell

    世界上最小的shell程序,有利于理解shell程序的基本原理。

    PHP开发框架手册-Yaf(Yet Another Framework)用户手册.rar

    PHP开发框架手册-Yaf(Yet Another Framework)用户手册.rar。PHP开发框架手册-Yaf(Yet Another Framework)用户手册.rar。PHP开发框架手册-Yaf(Yet Another Framework)用户手册.rar。PHP开发框架手册-Yaf(Yet Another ...

    Yet Another Coldfusion CMS

    Yet Another Coldfusion CMS coldfusion 代码学习用哦

    Yet Another Haskell Tutorial

    《Yet Another Haskell Tutorial》是一份详尽的指南,旨在为初学者提供全面的Haskell编程语言入门。Haskell是一种在编程领域中具有独特地位的语言,它被定义为一种懒惰的、纯函数式编程语言。这份教程由Hal Daume ...

    Yet-Another-EfficientDet-Pytorch.zip

    在Pytorch平台上实现的Yet-Another-EfficientDet-Pytorch项目,为开发者提供了一种方便的工具,用于快速搭建和训练EfficientDet模型。 首先,我们来了解一下EfficientDet的核心设计。EfficientDet的核心是Efficient...

    Yet Scheme Another Tutorial中译版

    这个教程“Yet Scheme Another Tutorial”(YSAT)是为那些希望学习Scheme并准备参加SCIP(Scheme编程竞赛)的初学者精心编写的。本文将深入探讨Scheme的基础知识、核心特性以及在YSAT教程中可能涵盖的关键概念。 *...

    Scheme入门教程—Yet Another Scheme Tutorial

    Yet Another Scheme Tutorial——Scheme入门教程 中文版。其中文地址为:http://deathking.github.io/yast-cn/。pdf只是于2018。08把上面的内容加了目录、标题序号,制作成了pdf。 本教程的目的在于给读者在Scheme...

    Yet ANother pattern recognition matlab toolbox.zip

    "Yet Another pattern recognition matlab toolbox.zip" 是一个专为模式识别设计的MATLAB工具箱,它包含了一系列函数和脚本,旨在帮助用户在MATLAB环境中进行模式识别和机器学习相关的研究与开发工作。这个工具箱...

    强大的unity3d对象池工具插件Yet Another Object Pooler

    [Unity3D] Yet Another Object Pooler YAOP是开发项目中使用的工具。它越小、越快越精简越好。如果需要,它可以动态缩小自身,减少程序内存使用。 安装和使用说明: 1. 下载包并导入。 2. 通过右键单击层次结构或...

    Yet-Another-EfficientDet-Pytorch-master.rar

    `Yet-Another-EfficientDet-Pytorch-master`是一个基于Pytorch的EfficientDet实现,提供了7种不同规模的网络架构,适应不同的性能和资源需求。这些预训练模型包括从EfficientDet-D0到EfficientDet-D7,D0是最轻量级...

    common, Yet another serial port debugger..zip

    common, Yet another serial port debugger.

    YASA(Yet Another Spindle Algorithm):一个Python包,用于分析多导睡眠图的睡眠记录

    YASA(又一个主轴算法)是 Python 中的一个命令行睡眠分析工具箱。YASA的主要功能是: 多导睡眠图数据的自动睡眠分期(参见预印本文章)。 事件检测:单通道或多通道 EEG 数据上的睡眠纺锤波、慢波和快速眼球运动。...

    Yet another Facebook clone written in C.zip

    【标题】:“Yet another Facebook clone written in C.zip” 这个标题暗示了一个项目,它是一个使用C语言编写的Facebook的复制品,或者可以说是一个社交网络平台的克隆版。在IT行业中,"Yet another" 这样的表达...

    贪婪BT(Yet Another Bittorrent Client) V2.6.9源码

    全新的BT客户端ABC [Yet Another Bittorrent Client&gt;,开一个可以下载多个BT,相信很多人已经找了好久,但是一直没有满意的吧?ABC是一个非常棒的单窗口BT客户端。稳定,占内存非常小,速度快!新版修正一个Shad0w...

    【Unity插件】YAPP - Yet Another Prefab Painter 强大且灵活的工具,极大地提高了环境和关卡设

    文件名:YAPP - Yet Another Prefab Painter v1.6.0.unitypackage YAPP - Yet Another Prefab Painter 是一款专为 Unity 开发者设计的工具,旨在简化和加速在场景中批量放置和绘制 Prefab(预制体)的过程。通过...

    Yet Another Bacnet Explorer:Yabe-BACnet设备的图形资源管理器程序-C#代码-开源

    用C#编写的图形化资源管理器程序,用于浏览BACnet设备(在Windows和Linux上运行)。 当前同时支持BACnet IPv4,IPv6 + BACnet MSTP + BACnet PTP + BACnet以太网。 用于读取,写入,读取多个,写入多个,iam,whois...

Global site tag (gtag.js) - Google Analytics