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

Ruby is Magic: Black Magic

Ruby is Magic: Black Magic

This time @tisba and I talked about some more or less esoteric features of Ruby like Continuations. As usual the talk is in German, because we gave it at the Cologne Ruby usergroup (Cologne.rb).

Copyright Notice: My Little Pony - Friendship is Magic is Property of Hasbro and The Hub.

9d42f431f092fd96fec44ae936f25e84?s=128

Dirk Breuer

May 15, 2013
Tweet

More Decks by Dirk Breuer

Other Decks in Programming

Transcript

  1. Brony User Group Cologne hosted by 15.05.2013

  2. Ruby #666 Black Magic

  3. None
  4. Continuations, Fibers and friends Black Magic aka

  5. Continuations callcc { |cc| $keynote = cc }

  6. Ich stehe vor dem Kühlschrank und möchte mir gern ein

    Sandwich machen.
  7. Als erstes erzeuge ich eine Continuation…

  8. Ich hole Käse, Butter, Mayo, Schinken und das Brot aus

    dem Kühlschrank.
  9. Ich mache mir das Sandwich, alle Zutaten sind verarbeitet.

  10. Ich rufe die Continuation auf.

  11. Ich stehe vor dem Kühlschrank und möchte mir gern ein

    Sandwich machen.
  12. Der Kühlschrank ist leer, aber da liegt ja ein fertiges

    Sandwich auf dem Tisch.
  13. None
  14. Quasi deprecated in Ruby 1.9 (müssen explizit geladen werden) Es

    gibt eine Klasse Continuation Continuations sind ein bisschen wie goto-Statements Können nur nach “hinten” springen Können den lokalen Scope verlassen – Der Stack zum Zeitpunkt der Definition wird wieder hergestellt
  15. require 'continuation' @counter = 0 def foo puts "foo: #{caller.inspect}"

    bar end def bar callcc { |cc| $ref = cc } puts "bar: #{caller.inspect}" puts "counter: #{@counter}" end def callme $ref.call if @counter < 2 puts "callme: #{caller.inspect}" end foo @counter += 1 callme # foo: ["cont_stack.rb:21:in `<main>'"] # bar: ["cont_stack.rb:7:in `foo'", "cont_stack.rb:21:in `<main>'"] # counter: 0 # bar: ["cont_stack.rb:7:in `foo'", "cont_stack.rb:21:in `<main>'"] # counter: 1 # callme: ["cont_stack.rb:25:in `<main>'"]
  16. Beispiele Seaside - Webframework in Smalltalk Wee - Seaside-ähnliches Webframework

    in Ruby
  17. None
  18. $keynote.call

  19. Continuations, Fibers and friends Black Magic aka

  20. Fiber

  21. Kernel.throw :throw

  22. Continuations, Fibers and friends Black Magic aka

  23. Kernel.throw “Transfers control to the end of the active catch

    block waiting for tag”
  24. def foo puts "foo: #{caller.inspect}" catch :lvl3 do throw :lvl1

    end end def bar puts "bar: #{caller.inspect}" catch :lvl2 do foo end end def callme puts "callme: #{caller.inspect}" catch :lvl1 do bar end puts "callme: #{caller.inspect}" end catch :lvl0 do callme end
  25. Warden Sinatra Rack Testing von verschachtelten Blöcken Beispiele für Kernel.throw

  26. Kernel.throw :fibers

  27. Fiber

  28. Fibers "light weight cooperative concurrency" - Ruby Doc cooperative multitasking

    vs preemptive scheduling Keine echte Nebenläufigkeit, daher automatisch Thread-Safe Gibt es seit 1.9 Haben einen eigenen Stack
  29. @counter = 0 def party puts "party: #{caller.inspect}" end def

    create_fiber puts ">: #{caller.inspect}" f = Fiber.new do puts "fiber: #{caller.inspect}" @counter += 1 puts "counter: #{@counter}" party end.resume puts "counter: #{@counter}" puts "<: #{caller.inspect}" f end def bar create_fiber end def foo bar end def callme puts "callme: #{caller.inspect}" foo puts "callme after foo: #{caller.inspect}" end puts "counter: #{@counter}" callme # party: ["fiber_stack.rb:15:in `block in create_fiber'"] # >: ["fiber_stack.rb:23:in `bar'", "fiber_stack.rb:27:in `foo'", "fiber_stack.rb:32:in `callme'", "fiber_stack.rb:37:in `<main>'"] # fiber: [] # counter: 1 # counter: 1 # <: ["fiber_stack.rb:23:in `bar'", "fiber_stack.rb:27:in `foo'", "fiber_stack.rb:32:in `callme'", "fiber_stack.rb:37:in `<main>'"] # callme: ["fiber_stack.rb:37:in `<main>'"] # callme after foo: ["fiber_stack.rb:37:in `<main>'"] # counter: 0
  30. Wofür?

  31. sequence = Enumerator.new do |yielder| number = 0 loop do

    number += 1 yielder.yield number end end Fiber!
  32. require 'eventmachine' require 'em-http' require 'fiber' def async_fetch(url) f =

    Fiber.current http = EventMachine::HttpRequest.new(url).get :timeout => 10 http.callback { f.resume(http) } http.errback { f.resume(http) } return Fiber.yield end EventMachine.run do Fiber.new{ puts "Setting up HTTP request #1" data = async_fetch('http://www.google.com/') puts "Fetched page #1: #{data.response_header.status}" EventMachine.stop }.resume end # Setting up HTTP request #1 # Fetched page #1: 302
  33. class Integer # The bottles def drink; self - 1;

    end end class << song = nil attr_accessor :wall def bottles (@bottles.zero? ? "no more" : @bottles).to_s << " bottle" << ("s" unless @bottles == 1).to_s end def of(bottles) @bottles = bottles (class << self; self; end).module_eval do define_method(:buy) { bottles } end self end def sing(&step) puts "#{bottles.capitalize} of beer on the wall, #{bottles} of beer." if @bottles.zero? print "Go to the store buy some more, " step = method :buy else print "Take one down and pass it around, " end @bottles = step[@bottles] puts "#{bottles} of beer on the wall." puts "" or wall.call unless step.kind_of? Method end end callcc { |song.wall| song.of(99) }.sing { |beer| beer.drink }
  34. Continuations sind ein nettes Instrument, um sich mal richtig schön

    verwirren zu lassen …sonst vermutlich eher weniger relevant in der Praxis Fibers sind durchaus nützlich (async APIs)
  35. One More Thing …

  36. None
  37. <Insert Shameless Plug here!>

  38. None
  39. ✓Alle Getränke inklusive ✓Professionelle Reinigung ✓Hochwertige Büromöbel ✓100 Mbit Breitband-Internet

    ✓Nutzung von Drucker etc. ✓Erstklassiger Kaffee * inkl. 19% UmSt für pro Monat 359 € *
  40. http://home-office-cologne.de @ HomeOfficeCGN

  41. $keynote.call

  42. Ruby #666 Black Magic

  43. Kernel.throw :faq

  44. Thanks! Q & A? Dirk Breuer / @railsbros_dirk Sebastian Cohnen

    / @tisba ? “My Little Pony” © Hasbro Studios and DHX Media Vancouver rubyismagic.de