Metaprogramming Ruby - Blocks Note

  1. A review of the basics of blocks
  2. An overview of scopes and how you can carry variables through scopes by using blocks as closures
  3. How you can further manipulate scopes by passing a block to instance_eval
  4. How you can convert blocks into callable objects that you can set aside
    and call later, such as Procs and lambdas

instance_eval, a little like python's unlocal.

Blocks Are Closures

yield: block's context is where the block is defined.

  1. in block, we can access and change the variables which are defined before(out of) the block

  2. out of block, we can't access a variable defined in the block.
    def just_yield
    yield
    end

    top_level_variable = 1
    
    just_yield do
      top_level_variable += 1
      local_to_block = 1
    end
    
    top_level_variable # => 2
    local_to_block # => Error!
    

Scope Gates

def: leave previous scope and opens a new

  1. Class definitions
  2. Module definitions
  3. Methods

Flattening the Scope

use block to define class or method

Sharing the Scope

shared -- just a free variable
def define_methods
shared = 0

     Kernel.send :define_method, :counter do
       shared
     end

     Kernel.send :define_method, :inc do |x|
       shared += x
     end
   end

   define_methods

   counter # => 0 inc(4)
   counter # => 4

instance_eval

usage:

  1. dynamic run block
  2. Breaking Encapsulation, change the instance private variable.
    Often appears in testing.
  3. Clean Room: Sometimes you create an object just to evaluate blocks inside it.
    A Clean Room is just an environment where you can evaluate your blocks

Callable objects

lambda vs proc

  1. proc returns from the scope where the proc itself was defined:
  2. lambda checks arguments

Method Objects

Unbound Methods

UnboundMethods are like Methods that have been detached from their original class or module

Like JavaSceipt get function from prototype, but the unboundmethods can not be called(You can redefine it to the new Class).
eg: MyModule.instance_method(:my_method)

redefine method
    module Loadable
      def self.exclude_from(base)
        base.class_eval { define_method(:load, Kernel.instance_method(:load)) }
      end
    end

useful methods

block_given?
local_variables, the variables can be saw in current place.

   a = 1
   l = lambda{ local_variables }
   [:l, :a, :_]

$var, global variables.
Proc#lambda?
method: get method by name, (1.method :+).call(1)
Method#to_proc: (1.method :+).to_proc.call(1), solve the scope
arity: Returns an indication of the number of arguments accepted by a method

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • -正念练习 情绪和内在资源 调动起自己的内在资源,有利于正念状态的培育。有意识的调动自己的资源,你是温暖的,被爱的...
    悠悠然a阅读 261评论 0 0
  • 移动应用上的用户交互基本靠“摸”。当然,“摸”也是有各种姿势的:在一个按钮上点击,在一个列表上滑动,或是在一个地图...
    冷洪林阅读 321评论 0 0
  • 孤也不知道,自己这是第几日,寂寂的卧病床榻,无人问津。 记得刚觉身体不适时,孤最宠爱的那几个臣子——竖刁,易牙和公...
    木四谛阅读 684评论 0 2
  • 我们经常忘事,那是因为我们心中没“他”。我们的注意力没有完全放在“他”的身上。 当我们把注意力完全集中时,也就会发...
    王朋彦阅读 165评论 0 0
  • 最近开发一个APP,需要让用户填写数据,然后上传到服务端进行计算并返回结果在客户端中展示。其中需要填写的数据项多达...
    yanging阅读 13,842评论 34 51