SlideShare a Scribd company logo
OOP,
  metaprogramming,
blocks, iterators, mix-
   ins, duck typing.
       Code style
       Code style
Anton Shemerey
• https://github.com/shemerey
• https://twitter.com/shemerey
• https://www.facebook.com/shemerey
• https://www.linkedin.com/in/shemerey
• shemerey@gmail.com
• etc.
Code style

• https://github.com/bbatsov/ruby-style-guide
• https://github.com/bbatsov/rails-style-guide
• Use two spaces per tab!
• explicit “return” - is evil
OOP - Everything is object,
  not quite but still...
“hello” - this is object too
 1
 2   a = "hello" # instance
 3   b = a.dup   # new object
 4
 5   # instance method (for object)
 6   class << a
                                  1
 7     def to_s
                                  2 def a.to_s
 8       "#{self} world"
                                  3   "#{self} world"
 9     end
                                  4 end
10
                                  5
11     def say_hello
                                  6 def a.say_hello
12       self.to_s
                                  7   self.to_s
13     end
                                  8 end
14   end
                                  9
15
16   a.to_s                              #   =>   "hello world"
17   b.to_s                              #   =>   "hello"
18   a.methods - b.methods               #   =>   [:say_hello]
19   a.class.methods - b.class.methods   #   =>   []
42 - this is object too

• 42.instance_variables # => []
• 42.instance_variable_set(:@hello, 'world')
• 42.instance_variables # => [:@hello]
• 42.object_id # => 85
true - this is object too
• true.instance_variables # => []
• true.instance_variable_set(:@false, true)
• true.instance_variables # => [:@false
• true.object_id # => 2
• false.object_id # => 0
• nil.object_id # => 4
Class
 3   class Point
 4     def initialize(x, y)
 5       @x, @y = x, y
 6     end
 7   end
 8
 9   if __FILE__ == $PROGRAM_NAME
10     puts Point.new(1, 10).inspect #<Point:0x0bf78 @x=1, @y=10>
11   end
attribute reader/writer
 1 class Point           1 class Point
 2   def initialize(x)   2   attr_accessor :x
 3     @x = x            3
 4   end                 4   def initialize(x)
 5                       5     @x = x
 6   def x               6   end
 7     @x                7 end
 8   end                 8
 9
10   def x=(x)
11     @x = x
12   end
13 end
14
1   module ReadWrite
 2     def rw(*params)                               # params = [:x, :y]
 3       params.each do |attr|
 4         define_method attr do                    #    def x
 5           instance_variable_get :"@#{attr}"      #     @x
 6         end                                      #    end
 7
 8         define_method :"#{attr}=(val)" do         #   def x=(val)
 9           instance_variable_set :"@#{attr}=", val #    @x=val
10         end                                       #   end
11       end
12     end
13   end
14
15   class Object
16     extend ReadWrite
17   end
18
19   class Point
20     rw :x, :y
21
22     def initialize(x)
23       @x = x
24     end
25   end
26
Class / Module

•   Module.ancestors
    •   # => [Module, Object, Kernel, BasicObject]

• Class.ancestors
   • # => [Class, Module, Object, Kernel, BasicObject]
class A; end

• new
• inheritance
• include class A - computer says no
• extend class A - computer says no
• computer says no - http://bit.ly/gQX24
module B; end

• new - computer says no
• inheritance - computer says no
• include B
• extend B
• computer says no - http://bit.ly/gQX24
include/extend
 1   module M                        1   module M
 2     def inst_method               2     def cl_method
 3       "instance"                  3       "instance"
 4     end                           4     end
 5   end                             5   end
 6                                   6
 7                                   7
 8   class Point                     8   class Point
 9     include M                     9     extend M
10   end                            10   end
11                                  11
12   if __FILE__ == $PROGRAM_NAME   12   if __FILE__ == $PROGRAM_NAME
13     puts Point.new.inst_method   13     puts Point.cl_method
14   end                            14   end
15                                  15
1   module M
 2     def self.included(base)
 3       base.extend(ClassMethods)
 4     end
 5
 6     # -- instance methods --
 7
 8     module ClassMethods
 9       # -- class methods --
10     end
11   end
12
13
14   class Point
15     include M
16
17     def initialize(x)
18       @x = x
19     end
20   end
Classes and
      Objects
• More information: http://bit.ly/YZBfmp
Ruby Blocks
1   %w[first second third].each do |item|
2       item.capitalize
3   end
4
5   %w[first second third].each { |i| i.upcase }
6
7   %w[first second third].each <<= block
Yield
1   require "ostruct"
 2   Point = Struct.new(:x, :y)
 3
 4   class PointList
 5     def initialize                   13   def each(block = Proc.new)
 6      @data = []                      14     for item in @data
 7     end                              15       block.call(item)
 8                                      16     end
 9     def <<(other)                    17   end
10       @data << other
11     end
12
13     def each                         13   def each(&block)
14       for item in @data              14     for item in @data
15         yield item <<<<<<<<<<<<      15       block.call(item)
16       end                            16     end
17     end                              17   end
18   end
19
20   if __FILE__ == $PROGRAM_NAME
21     list = PointList.new << Point.new(1,3) << Point.new(2,1)
22     list.each do |point|
23       puts point #<struct Point x=1, y=3>, #<struct Point x=2, y=1>
24     end
25   end
Enumerable
http://ru.wikibooks.org/wiki/Ruby/Справочник/Enumerable
 1 require "ostruct"
 2
 3 Point = Struct.new(:x, :y) do
 4   def distance
 5     Math.sqrt(x**2 + y**2)
 6   end
 7 end
 8
 9 class PointList
 include Enumerable <<<<<<<
10   # -- code omitted --
11
12   def each
13     for item in @data
14       yield item
15     end
16   end
17 end
18
19 if __FILE__ == $PROGRAM_NAME
20   list = PointList.new << Point.new(1,3) << Point.new(2,1) << Point.new(2,2)
21   list.sort_by(&:distance)
22   list.sort_by {|e| e.distance }
23 end
Comparable
   <=>
   1, 0, -1
   1, 0, -1
   1, 0, -1
Comparable
 1   require "ostruct"
 2
 3   Point = Struct.new(:x, :y) do
 4     include Comparable <<<<<<
 5
 6     def distance
 7       Math.sqrt(x**2 + y**2)
 8     end
 9
10     def <=>(other)
11       self.distance <=> other.distance
12     end
13   end
14
15   if __FILE__ == $PROGRAM_NAME
16     puts Point.new(1,3) == Point.new(2,1) # false
17     puts Point.new(1,3) == Point.new(3,1) # true
18     puts Point.new(2,3) >= Point.new(1,1) # true
19     puts Point.new(2,3) <= Point.new(1,1) # false
20     puts Point.new(2,2).between? Point.new(2,1), Point.new(2,3) #true
21   end
Mad Ruby
#to_proc (&)
1 class Symbol
2   def to_proc
3     Proc.new { |*args| args.shift.__send__(self, *args) }
4   end
5 end

19 if __FILE__ == $PROGRAM_NAME
20   list = PointList.new << Point.new(1,3) << Point.new(2,1) << Point.new(2,2)
21   list.sort_by(&:distance)
22   list.sort_by {|e| e.distance }
23 end

1 [1, 2, 3].map(&:to_s) # => ["1", "2", "3"]
2 [3, 4, 5].inject(&:*) # => 60
Advanced Examples
 1   File.open('nginx.log', 'r') do |file|    1   ActiveRecord::Base.transaction do
 2     while line = file.gets                 2     # -- code omitted --
 3       puts line                            3   end
 4     end                                    4
 5   end                                      5    # -- possible implementation --
 6                                            6   module ActiveRecord
 7    # -- possible implementation --         7     class Base
 8   class File                               8       def transaction
 9     def open(file, option)                 9         # -- start transaction
10       if block_given?                     10         yield
11         f = fopen(file, option)           11         # -- commit transaction
12         yield f                           12         rescue ActiveRecord::Rollback
13         f.close                           13         # -- roll back transaction
14       end                                 14         ensure
15     end                                   15         # -- close transaction
16   end                                     16       end
                                             17     end
                                             18   end
The End

More Related Content

PDF
Programming JVM Bytecode with Jitescript
ZIP
Refatoração + Design Patterns em Ruby
PDF
Practical JavaScript Programming - Session 6/8
PDF
SfCon: Test Driven Development
PDF
IPC2010SE Doctrine2 Enterprise Persistence Layer for PHP
PPTX
PyconKR 2018 Deep dive into Coroutine
PDF
Beginning Python
PDF
Funkcija, objekt, python
Programming JVM Bytecode with Jitescript
Refatoração + Design Patterns em Ruby
Practical JavaScript Programming - Session 6/8
SfCon: Test Driven Development
IPC2010SE Doctrine2 Enterprise Persistence Layer for PHP
PyconKR 2018 Deep dive into Coroutine
Beginning Python
Funkcija, objekt, python

What's hot (20)

PDF
Functional Algebra: Monoids Applied
DOC
Function Call Optimization
PDF
The Ring programming language version 1.5.1 book - Part 74 of 180
PDF
Lucio Floretta - TensorFlow and Deep Learning without a PhD - Codemotion Mila...
PDF
Practical JavaScript Programming - Session 7/8
PDF
Notes for GNU Octave - Numerical Programming - for Students - 02 of 02 by aru...
PDF
The Ring programming language version 1.6 book - Part 34 of 189
PDF
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
PDF
DevOpsCon 2021: Go Web Development 101
PDF
Joe Bew - Apprendi un nuovo linguaggio sfruttando il TDD e il Clean Code - Co...
PDF
Elixir: the not-so-hidden path to Erlang
PPTX
Lexical environment in ecma 262 5
PDF
entwickler.de Go Day: Go Web Development 101
PPTX
Refactoring group 1 - chapter 3,4,6
PDF
betterCode() Go: Einstieg in Go, Standard-Library und Ökosystem
PDF
Perl6 one-liners
PDF
The Ring programming language version 1.6 book - Part 81 of 189
PDF
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
PDF
SWP - A Generic Language Parser
PDF
PHP7 is coming
Functional Algebra: Monoids Applied
Function Call Optimization
The Ring programming language version 1.5.1 book - Part 74 of 180
Lucio Floretta - TensorFlow and Deep Learning without a PhD - Codemotion Mila...
Practical JavaScript Programming - Session 7/8
Notes for GNU Octave - Numerical Programming - for Students - 02 of 02 by aru...
The Ring programming language version 1.6 book - Part 34 of 189
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
DevOpsCon 2021: Go Web Development 101
Joe Bew - Apprendi un nuovo linguaggio sfruttando il TDD e il Clean Code - Co...
Elixir: the not-so-hidden path to Erlang
Lexical environment in ecma 262 5
entwickler.de Go Day: Go Web Development 101
Refactoring group 1 - chapter 3,4,6
betterCode() Go: Einstieg in Go, Standard-Library und Ökosystem
Perl6 one-liners
The Ring programming language version 1.6 book - Part 81 of 189
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
SWP - A Generic Language Parser
PHP7 is coming
Ad

Similar to Ruby: OOP, metaprogramming, blocks, iterators, mix-ins, duck typing. Code style (20)

PDF
Ruby 程式語言入門導覽
KEY
Module Magic
PDF
Introduction to Ruby Programming Language
PDF
Rapid Development with Ruby/JRuby and Rails
PDF
Designing Ruby APIs
KEY
Why I choosed Ruby
PDF
Ruby on Rails
PDF
Ruby Topic Maps Tutorial (2007-10-10)
PPT
Ruby For Java Programmers
PDF
Introduction to Ruby
KEY
Desarrollando aplicaciones web en minutos
PPT
Advanced Ruby
KEY
jRuby: The best of both worlds
PDF
block
PDF
Ruby and Rails by Example (GeekCamp edition)
PPT
ppt18
PPT
ppt9
PPT
name name2 n
PPT
test ppt
PPT
Ruby for Perl Programmers
Ruby 程式語言入門導覽
Module Magic
Introduction to Ruby Programming Language
Rapid Development with Ruby/JRuby and Rails
Designing Ruby APIs
Why I choosed Ruby
Ruby on Rails
Ruby Topic Maps Tutorial (2007-10-10)
Ruby For Java Programmers
Introduction to Ruby
Desarrollando aplicaciones web en minutos
Advanced Ruby
jRuby: The best of both worlds
block
Ruby and Rails by Example (GeekCamp edition)
ppt18
ppt9
name name2 n
test ppt
Ruby for Perl Programmers
Ad

Ruby: OOP, metaprogramming, blocks, iterators, mix-ins, duck typing. Code style

  • 1. OOP, metaprogramming, blocks, iterators, mix- ins, duck typing. Code style Code style
  • 2. Anton Shemerey • https://github.com/shemerey • https://twitter.com/shemerey • https://www.facebook.com/shemerey • https://www.linkedin.com/in/shemerey • [email protected] • etc.
  • 3. Code style • https://github.com/bbatsov/ruby-style-guide • https://github.com/bbatsov/rails-style-guide • Use two spaces per tab! • explicit “return” - is evil
  • 4. OOP - Everything is object, not quite but still...
  • 5. “hello” - this is object too 1 2 a = "hello" # instance 3 b = a.dup # new object 4 5 # instance method (for object) 6 class << a 1 7 def to_s 2 def a.to_s 8 "#{self} world" 3 "#{self} world" 9 end 4 end 10 5 11 def say_hello 6 def a.say_hello 12 self.to_s 7 self.to_s 13 end 8 end 14 end 9 15 16 a.to_s # => "hello world" 17 b.to_s # => "hello" 18 a.methods - b.methods # => [:say_hello] 19 a.class.methods - b.class.methods # => []
  • 6. 42 - this is object too • 42.instance_variables # => [] • 42.instance_variable_set(:@hello, 'world') • 42.instance_variables # => [:@hello] • 42.object_id # => 85
  • 7. true - this is object too • true.instance_variables # => [] • true.instance_variable_set(:@false, true) • true.instance_variables # => [:@false • true.object_id # => 2 • false.object_id # => 0 • nil.object_id # => 4
  • 8. Class 3 class Point 4 def initialize(x, y) 5 @x, @y = x, y 6 end 7 end 8 9 if __FILE__ == $PROGRAM_NAME 10 puts Point.new(1, 10).inspect #<Point:0x0bf78 @x=1, @y=10> 11 end
  • 9. attribute reader/writer 1 class Point 1 class Point 2 def initialize(x) 2 attr_accessor :x 3 @x = x 3 4 end 4 def initialize(x) 5 5 @x = x 6 def x 6 end 7 @x 7 end 8 end 8 9 10 def x=(x) 11 @x = x 12 end 13 end 14
  • 10. 1 module ReadWrite 2 def rw(*params) # params = [:x, :y] 3 params.each do |attr| 4 define_method attr do # def x 5 instance_variable_get :"@#{attr}" # @x 6 end # end 7 8 define_method :"#{attr}=(val)" do # def x=(val) 9 instance_variable_set :"@#{attr}=", val # @x=val 10 end # end 11 end 12 end 13 end 14 15 class Object 16 extend ReadWrite 17 end 18 19 class Point 20 rw :x, :y 21 22 def initialize(x) 23 @x = x 24 end 25 end 26
  • 11. Class / Module • Module.ancestors • # => [Module, Object, Kernel, BasicObject] • Class.ancestors • # => [Class, Module, Object, Kernel, BasicObject]
  • 12. class A; end • new • inheritance • include class A - computer says no • extend class A - computer says no • computer says no - http://bit.ly/gQX24
  • 13. module B; end • new - computer says no • inheritance - computer says no • include B • extend B • computer says no - http://bit.ly/gQX24
  • 14. include/extend 1 module M 1 module M 2 def inst_method 2 def cl_method 3 "instance" 3 "instance" 4 end 4 end 5 end 5 end 6 6 7 7 8 class Point 8 class Point 9 include M 9 extend M 10 end 10 end 11 11 12 if __FILE__ == $PROGRAM_NAME 12 if __FILE__ == $PROGRAM_NAME 13 puts Point.new.inst_method 13 puts Point.cl_method 14 end 14 end 15 15
  • 15. 1 module M 2 def self.included(base) 3 base.extend(ClassMethods) 4 end 5 6 # -- instance methods -- 7 8 module ClassMethods 9 # -- class methods -- 10 end 11 end 12 13 14 class Point 15 include M 16 17 def initialize(x) 18 @x = x 19 end 20 end
  • 16. Classes and Objects • More information: http://bit.ly/YZBfmp
  • 17. Ruby Blocks 1 %w[first second third].each do |item| 2 item.capitalize 3 end 4 5 %w[first second third].each { |i| i.upcase } 6 7 %w[first second third].each <<= block
  • 18. Yield
  • 19. 1 require "ostruct" 2 Point = Struct.new(:x, :y) 3 4 class PointList 5 def initialize 13 def each(block = Proc.new) 6 @data = [] 14 for item in @data 7 end 15 block.call(item) 8 16 end 9 def <<(other) 17 end 10 @data << other 11 end 12 13 def each 13 def each(&block) 14 for item in @data 14 for item in @data 15 yield item <<<<<<<<<<<< 15 block.call(item) 16 end 16 end 17 end 17 end 18 end 19 20 if __FILE__ == $PROGRAM_NAME 21 list = PointList.new << Point.new(1,3) << Point.new(2,1) 22 list.each do |point| 23 puts point #<struct Point x=1, y=3>, #<struct Point x=2, y=1> 24 end 25 end
  • 21. http://ru.wikibooks.org/wiki/Ruby/Справочник/Enumerable 1 require "ostruct" 2 3 Point = Struct.new(:x, :y) do 4 def distance 5 Math.sqrt(x**2 + y**2) 6 end 7 end 8 9 class PointList include Enumerable <<<<<<< 10 # -- code omitted -- 11 12 def each 13 for item in @data 14 yield item 15 end 16 end 17 end 18 19 if __FILE__ == $PROGRAM_NAME 20 list = PointList.new << Point.new(1,3) << Point.new(2,1) << Point.new(2,2) 21 list.sort_by(&:distance) 22 list.sort_by {|e| e.distance } 23 end
  • 22. Comparable <=> 1, 0, -1 1, 0, -1 1, 0, -1
  • 23. Comparable 1 require "ostruct" 2 3 Point = Struct.new(:x, :y) do 4 include Comparable <<<<<< 5 6 def distance 7 Math.sqrt(x**2 + y**2) 8 end 9 10 def <=>(other) 11 self.distance <=> other.distance 12 end 13 end 14 15 if __FILE__ == $PROGRAM_NAME 16 puts Point.new(1,3) == Point.new(2,1) # false 17 puts Point.new(1,3) == Point.new(3,1) # true 18 puts Point.new(2,3) >= Point.new(1,1) # true 19 puts Point.new(2,3) <= Point.new(1,1) # false 20 puts Point.new(2,2).between? Point.new(2,1), Point.new(2,3) #true 21 end
  • 25. #to_proc (&) 1 class Symbol 2 def to_proc 3 Proc.new { |*args| args.shift.__send__(self, *args) } 4 end 5 end 19 if __FILE__ == $PROGRAM_NAME 20 list = PointList.new << Point.new(1,3) << Point.new(2,1) << Point.new(2,2) 21 list.sort_by(&:distance) 22 list.sort_by {|e| e.distance } 23 end 1 [1, 2, 3].map(&:to_s) # => ["1", "2", "3"] 2 [3, 4, 5].inject(&:*) # => 60
  • 26. Advanced Examples 1 File.open('nginx.log', 'r') do |file| 1 ActiveRecord::Base.transaction do 2 while line = file.gets 2 # -- code omitted -- 3 puts line 3 end 4 end 4 5 end 5 # -- possible implementation -- 6 6 module ActiveRecord 7 # -- possible implementation -- 7 class Base 8 class File 8 def transaction 9 def open(file, option) 9 # -- start transaction 10 if block_given? 10 yield 11 f = fopen(file, option) 11 # -- commit transaction 12 yield f 12 rescue ActiveRecord::Rollback 13 f.close 13 # -- roll back transaction 14 end 14 ensure 15 end 15 # -- close transaction 16 end 16 end 17 end 18 end