0
Posted on Tuesday, August 29, 2017 by 醉·醉·鱼 and labeled under



  1. def...end, class...end, module...end都是作用域门,进入他们就会出现新的scope
  2. block是特殊的scope,block中initialize的局部变量在外部没法访问
  3. 扁平作用域可以用,define_method, Class.new, Module.new来实现。
0
Posted on Friday, August 25, 2017 by 醉·醉·鱼 and labeled under
钩子们,来吧

https://www.sitepoint.com/rubys-important-hook-methods/

# included
module Person
  
  def name
    puts "My name is Person"
  end

  module ClassMethods
    def class_method_1
      puts "Class method is called"
    end
  end

  module InstanceMethods
    def instance_method_1
      puts "instance method is called"
    end
  end

  def self.included(receiver)
    receiver.extend         ClassMethods
    receiver.send :include, InstanceMethods
    puts "#{receiver} included #{self}"
  end
end


class User
  include Person
end

user = User.new
user.name
user.instance_method_1
user.class.class_method_1
p User.ancestors

puts "="*16
# extended
module Animal
  def name
    puts "I'm an animal"
  end

  def self.extended(receiver)
    puts "#{receiver} extended #{self}"
  end
end

class Dog
  extend Animal
end

Dog.name

puts "="*16
# prepended
module Ship
  def name
    puts "I'm a ship"
  end

  module ClassMethods
    def class_method_1
      puts "Class method is called"
    end
  end

  module InstanceMethods
    def instance_method_1
      puts "instance method is called"
    end
  end

  def self.prepended(receiver)
    receiver.extend         ClassMethods
    receiver.send :prepend, InstanceMethods
    puts "#{receiver} prepended #{self}"
  end

end

class Boat
  prepend Ship

  def name
    puts "I'm a boat. I should be overried by Ship so you won't see me."
  end
end

Boat.new.name
Boat.new.instance_method_1
p Boat.ancestors
Boat.class_method_1

puts "="*16
# inherited
class Parent

  def self.inherited(child_class)
    puts "#{child_class} inherits #{self}"
  end

  def name
     "My name is Parent"
  end
end

class Child < Parent
end

puts Child.new.name # => My name is Parent
p Child.ancestors

puts "="*16
# method_missing
class Coffee
  def price
    2
  end

  def name
    "I'm a coffee"
  end
end

class Milk
  def initialize(coffee)
    @coffee = coffee
  end
  
  def price
    super + 0.2
  end
  
  def method_missing(meth, *args)
    "#{meth} not defined on #{self}"
    if @coffee.respond_to?(meth)
      @coffee.send(meth, *args)
    else
      super
    end
  end

end

coffee = Coffee.new
coffee_with_milk = Milk.new(coffee)
p coffee_with_milk.price
p coffee_with_milk.name
p coffee_with_milk.class.instance_methods(false) #you won't see #name method






0
Posted on Friday, August 25, 2017 by 醉·醉·鱼 and labeled under
Ruby中的继承不仅仅可以继承实例方法,还可以继承类方法。但是,对于MIXIN的类方法,只能够用BASE.EXTEND来实现了。


class Person
  def self.method_1
    puts "I'm Person class method 1"
  end

  class << self
    def method_2
      puts "I'm Person class method 2"
    end
  end

  def method_3
    puts "I'm instance method 3"
  end


  protected

  def protected_method_1
    puts "I'm protected_method_1"
  end

  private

  def private_method_1
    puts "I'm private_method_1"
  end


end

class Phoenix < Person
  
  def method_4
    puts "I'm instance method 4"
  end

  def call_protected_method_1
    puts "going to call protected_method_1 from Phoenix"
    protected_method_1
  end

  def call_private_method_1
    puts "going to call private_method_1 from Phoenix"
    private_method_1
  end
end

Phoenix.method_1 #ok to inherit class methods
Phoenix.method_2 #ok to inherit class methods

phoenix = Phoenix.new

phoenix.method_3 #ok to inherit instance methods
phoenix.method_4 #ok

phoenix.call_protected_method_1 #ok to call protected method in parent class
# phoenix.protected_method_1 # failed. you could not call it directly
phoenix.call_private_method_1 #ok to call private method in parent class
# phoenix.private_method_1 #failed

# However, mixin class methods could not be inherited unless call base.extend
0
Posted on Friday, August 25, 2017 by 醉·醉·鱼 and labeled under
修饰,是设计模式里面提到的,不影响原始的对象,给对象附上多个组件,让其能够支持多个方法。https://robots.thoughtbot.com/evaluating-alternative-decorator-implementations-in提到了几种方法,对比了一下,觉得SimpleDelegator还不错。对于简单的case,还可以直接用Forwardable。

相对于继承,修饰的好处是不需要像继承一样创建很多方法,直接就可以转到原始对象上去。



require 'delegate'

class Coffee
  def cost
    2
  end

  def origin
    "Colombia"
  end
end


module DecoratorClass
  def class
    __getobj__.class
  end
end

class Milk < SimpleDelegator
  include DecoratorClass

  def cost
    super + 0.4
  end
end

class Sugar < SimpleDelegator
  include DecoratorClass

  def cost
    super + 0.2
  end
end

p Milk.ancestors
coffee = Coffee.new
p Sugar.new(Milk.new(coffee)).cost   # 2.6
p Sugar.new(Sugar.new(coffee)).cost  # 2.4
p Milk.new(coffee).origin            # Colombia
p Sugar.new(Milk.new(coffee)).class  # Coffee
0
Posted on Thursday, August 24, 2017 by 醉·醉·鱼 and labeled under
最近在http://exercism.io/上面刷题玩,遇到字母算术题。这个应该是目前最难的一道题了。实在不知道如何解,于是在网上搜了一下。找到一个算法,其实就是穷举法。
http://www.poboke.com/study/python-solve-alphametics.html
简单换成Ruby,还可以工作。

其实内容和Python一样的,只是换成ruby而已。刚好Ruby里面也有permutation这样的方法,直接就可以用了。但是性能不是很好,虽然代码行数比较少。

题外话:说Python比Ruby简洁的,你们试试把Ruby的end抹掉以后再对比行数吧。

module Alphametics
  def self.solve(input)
    words = input.scan(/\w+/)
    uniq_characters = words.join.chars.uniq
    answer_list = []
    (0..9).to_a.permutation(uniq_characters.size).each do |e|
      next if words.any? { |word| word.tr(uniq_characters.join, e.join(''))[0] == '0' }
      if instance_eval(input.tr(uniq_characters.join, e.join('')))
        answer_list = e
        break
      end
    end
    return {} if answer_list.empty?
    Hash[Hash[uniq_characters.zip answer_list].sort]
  end
end
1
Posted on Wednesday, August 23, 2017 by 醉·醉·鱼 and labeled under


https://www.toptal.com/ruby/ruby-concurrency-and-parallelism-a-practical-primer
https://www.igvita.com/2008/11/13/concurrency-is-a-myth-in-ruby/
http://blog.ifyouseewendy.com/blog/2016/02/16/ruby-concurrency-in-theory/#concurrency-vs-paralelism

并发 V.S. 并行
concurrency v.s. parallelism
如果理解没有偏差,并行就像是4个进程各自利用一个CPU执行任务。有的进程快些,有的进程慢些,但都无所谓,至少是可以一块执行的。
并发,只是说要同时处理很多事情,无关乎并行与否。如果在单核上面,启动多个线程,CPU的调度会频繁在线程之间切换,看上去是并行,实际上不是的。

在Ruby 1.9之后,可以支持多个native thread。可是,由于GIL的存在,同一时刻只允许一个线程在执行,多线程没法充分利用多核。但是,Ruby是可以利用多核的,那就是你启动多个进程,那么就可以利用多核了。