Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ruby - Can your language do this?

Ruby - Can your language do this?

Georgy Angelov

June 24, 2016
Tweet

More Decks by Georgy Angelov

Other Decks in Programming

Transcript

  1. Often people, especially computer engineers, focus on the machines. They

    think, "By doing this, the machine will run faster. By doing this, the machine will run more effectively. By doing this, the machine will something something something." They are focusing on machines. But in fact we need to focus on humans, on how humans care about doing programming or operating the application of the machines. We are the masters. They are the slaves. -- Matz
  2. Конференции (2015) Garden City RubyConf Ruby devroom at FOSDEM Ruby

    ConfAustralia Rubyfuza Ruby on Ales Tropical Ruby MountainWest RubyConf Bath Ruby Conference wroc_love.rb RubyConfLT Ancient City Ruby RubyConfPhilippines Ruby ConfIndia RailsConf ROSSConf Vienna RubyConfKenya Ruby Conference Kiev RedDotRubyConf RubyNation Gotham Ruby Conference Brighton Ruby JRubyConfEU Burlington Ruby Conference eurucamp DeccanRubyConf Madison+ Ruby Ruby Midwest Barcelona Ruby Conf RubyConfTaiwan RubyConfPortugal WindyCityRails RubyConfBrazil Rocky Mountain Ruby Conference ROSSConf Berlin ArrrrCamp Los Angeles Ruby Conference RubyConfColombia EuRuKo Keep Ruby Weird RubyWorld Conference RubyDay RubyConf RailsIsrael RubyKaigi
  3. require 'open-uri' require 'nokogiri' CONFERENCES_SITE = 'http://rubyconferences.org/past/' doc = Nokogiri::HTML(open(CONFERENCES_SITE))

    headings = doc.css('article#past dt').map { |heading| heading.content.strip } dates = doc.css('article#past dd').map { |desc| desc.css('li').first.content } conferences = headings.zip(dates) .select { |_, description| description.include? '2015' } .map(&:first) puts conferences
  4. classification = if age < 13 'младок' elsif age <

    20 'тийн' else 'старец' end puts classification
  5. def foo(a, b = a, c = b) c end

    puts foo('bar') # => 'bar'
  6. def doge(a, b = def doge(a); 'W'; end) a end

    puts doge('W', 1) + doge('O') + doge('whatever') # => WOW
  7. a = 5 * 2 #=> 10 b = 10

    ** 2 #=> 100 a.class #=> Fixnum
  8. class A def foo 'bar' end end class_a = A

    class_a.new.foo #=> 'bar'
  9. class String def such; "such #{self}"; end def wow; "#{self}.

    wow!"; end end 'cool'.such.wow #=> 'such cool. wow!'
  10. class Numeric MM_SIZE = 0.001 UNITS = [:mm, :cm, :dm,

    :m, :dam, :hm, :km] UNITS.reduce(MM_SIZE) do |size, unit| define_method(unit) { self * size } size * 10 end end
  11. liar = [1, 2, 3] liar.size #=> 3 def liar.size

    42 end liar.size #=> 42 [1, 2, 3].size #=> 3
  12. class Numeric def day self * 24.hours end def hour

    self * 60.minutes end def minute self * 60.seconds end def second self end end
  13. true .if_true { 'yes' }.if_false { 'no' } #=> 'yes'

    false.if_true { 'yes' }.if_false { 'no' } #=> 'no' 'wtf'.if_true { 42 }.if_false { 666 } #=> 42
  14. class BasicObject def if_true; yield; end def if_false; self; end

    end def false.if_true; self; end def nil.if_true; self; end def false.if_false; yield; end def nil.if_false; yield; end
  15. class Class alias_method :[], :new end Array[1, 2, 3] #=>

    [1, 2, 3] String[] #=> '' A[] #=> #<A:0x007fb953bcae58>
  16. class A class << self private :new end end A.new

    #=> NoMethodError: private method `new' called
  17. class A def self.new @instance ||= super end end A.new

    #=> #<A:0x007fb953bcae58> A.new #=> #<A:0x007fb953bcae58> A.new #=> #<A:0x007fb953bcae58>
  18. class Fibonacci memoized def calculate(n) return 1 if n <=

    2 puts "Calculating fib(#{n})" calculate(n – 1) + calculate(n – 2) end end
  19. f = Fibonacci.new f.calculate(8) # Calculating fib(8) # Calculating fib(6)

    # Calculating fib(4) # Calculating fib(3) # Calculating fib(5) # Calculating fib(7) #=> 21 f.calculate(8) #=> 21
  20. class Class def memoized(method_name) original = "#{method_name}_original" alias_method original, method_name

    define_method method_name do |*args| cache_key = [method_name, args] @_method_cache ||= {} @_method_cache[cache_key] ||= send(original, *args) end end end
  21. class Class def memoized(method_name) decorate method_name do |method, *args| cache_key

    = [method_name, args] @_method_cache ||= {} @_method_cache[cache_key] ||= method.call(*args) end end end
  22. module A public static void def lol() 'I am a

    Java! Love me!' end end A.lol #=> "I am a Java! Love me!"
  23. plus = proc { |a, b| a + b }

    plus_one = plus.curry[1] [1, 2, 3, 4].map &plus_one #=> [2, 3, 4, 5]
  24. naturals = 1..Float::INFINITY naturals.lazy .map { |x| x ** 2

    } .take_while { |x| x <= 100 } .reduce(:+) #=> 385
  25. naturals = 1..Float::INFINITY naturals.lazy .map { |x| x ** 2

    } .take_while { |x| x <= 100 } .reduce(:+) #=> 385
  26. class P < BasicObject class << self def method_missing(method, *args,

    &block) ::Proc.new { |object| object.send method, *args, &block } end def to_proc ::Proc.new { |object| object } end end end
  27. f = Fibonacci.new f.calculate(4) #=> 3 f.instance_variable_get('@_method_cache') #=> { #

    [:fib, [2]] => 1, # [:fib, [1]] => 1, # [:fib, [3]] => 2, # [:fib, [4]] => 3 # } f.instance_variable_set('@_method_cache', {[:fib, [4]] => 42}) f.calculate(4) #=> 42
  28. class A private def call_me_if_you_can; 'gj'; end end a =

    A.new a.call_me_if_you_can #=> NoMethodError: private method # `call_me_if_you_can' called
  29. a.call :call_me_if_you_can #=> "gj" a.instance_eval { call_me_if_you_can } #=> "gj"

    A.class_eval { public :call_me_if_you_can } a.call_me_if_you_can #=> "gj"
  30. array = [1] array << 2 array #=> [1, 2]

    array.freeze array << 3 #=> RuntimeError: can't modify frozen Array
  31. array << 3 #=> RuntimeError: can't modify frozen Array array.unfreeze

    array.frozen? #=> false array << 3 array #=> [1, 2, 3]
  32. class Person def initialize(name) @name = name end def likes(*items)

    "I am #{@name}. I like #{items.join(', ')}." end end
  33. ivan = Person.new('Ivan') ivan.likes('cake', 'cats') #=> 'I am Ivan. I

    like cake, cats.' m = ivan.method(:likes) #=> #<Method: Person#likes> m.call('pancakes') #=> 'I am Ivan. I like pancakes.'
  34. patrick = Person.new('Patrick') def patrick.likes '[censored]' end patrick.likes('coffee') #=> '[censored]'

    m.unbind.bind(patrick).call('coffee') #=> 'I am Patrick. I like coffee.'
  35. class Test def f(a, b=2, *args) end end m =

    Test.new.method(:f) m.source_location #=> ["/Users/gangelov/ruby-test.rb", 2] m.parameters #=> [[:req, :a], [:opt, :b], [:rest, :args]]
  36. [[1, [2, 3]], [4, [5, 6]]].each do |a, (b, c)|

    puts a, b, c end #=> 1 2 3 #=> 4 5 6
  37. person = { first_name: "Иван", last_name: "Петров", age: 22, #

    ... } person.using do |first_name, last_name| puts "Здравей, #{first_name} #{last_name}!" end
  38. person = { first_name: "Иван", last_name: "Петров", age: 22, #

    ... } person.using do |first_name, age| puts "#{first_name} е на #{age}!" end
  39. triangles = [ {a: 3, b: 4, c: 5 },

    {a: 5, b: 12, c: 13}, ... ] triangles.select.using do |a, b, c| a**2 + b**2 == c**2 end
  40. $global = 'глобална променлива' local = 'локална променлива' Constant =

    'константа' @instance = 'инстанционна променлива' @@class = 'класова променлива'
  41. doge_class = Class.new do def such 'much' end end doge_class.name

    #=> nil Doge = doge_class doge_class.name #=> 'Doge'
  42. h = Hash.new do |hash, key| hash[key] = Hash.new(&hash.default_proc) end

    h['a'] #=> {} h['a']['b']['c']['d'] = 42 h #=> {"a" => {"b" => {"c" => {"d" => 42}}}}
  43. a_counter = 1 b_counter = 3 c_counter = 9 increment_counters

    a_counter #=> 2 b_counter #=> 4 c_counter #=> 10
  44. require 'binding_of_caller' def increment_counters b = binding.of_caller(1) b.local_variables .select {

    |name| name =~ /_counter$/ }.each do |name| value = b.local_variable_get(name) b.local_variable_set(name, value + 1) end end
  45. set_trace_func proc do |event, file, line, id, binding, cn| printf

    "%8s %s:%-2d %10s %8s\n", event, file, line, id, cn end t = Test.new t.test #=> line prog.rb:11 false #=> c-call prog.rb:11 new Class #=> c-call prog.rb:11 initialize Object #=> c-return prog.rb:11 initialize Object #=> c-return prog.rb:11 new Class #=> line prog.rb:12 false #=> call prog.rb:2 test Test #=> line prog.rb:3 test Test #=> line prog.rb:4 test Test #=> return prog.rb:4 test Test
  46. i = RubyVM::InstructionSequence.compile("Test.new.method") puts i.disassemble #=> 0000 trace 1 (

    1) #=> 0002 getinlinecache 9, <is:0> #=> 0005 getconstant :Test #=> 0007 setinlinecache <is:0> #=> 0009 opt_send_without_block <callinfo!mid:new, argc:0, ARGS_SIMPLE>, <callcache> #=> 0012 opt_send_without_block <callinfo!mid:method, argc:0, ARGS_SIMPLE>, <callcache> #=> 0015 leave
  47. class Person def say(message) "#{message}!" end end person = Spy.new(Person.new)

    person.class #=> Person person.say('hello') #=> They called say with hello #=> 'hello!'
  48. class Spy < BasicObject def initialize(obj) @instance = obj end

    def method_missing(name, *args, &block) $stdout.puts "They called #{name} with (#{args.join(', ')})" @instance.send(name, *args) end end
  49. require 'timecop' new_time = Time.local(2008, 9, 1, 12, 0, 0)

    Timecop.freeze(new_time) sleep 10 new_time == Time.now #=> true
  50. # Seconds will now seem like hours Timecop.scale(3600) Time.now #

    => 2016-02-28 21:23:25 +0200 # A few seconds later... Time.now # => 2016-02-29 06:22:59 +0200