50
Ruby

Write more understandable code in less lines Free (Very open license) Extensible Dynamic languages such as Ruby can be very productive in specific

Embed Size (px)

Citation preview

Page 2: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

Write more understandable code in less lines

Free (Very open license) Extensible Dynamic languages such as Ruby can be

very productive in specific areas, such as prototyping, web development or for gluing various applications together.

Why Ruby?

Page 3: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

Dynamic programming languages are often referred to as 'weakly typed' which means that variables are not bound to a particular type until runtime.

It typically features "dynamic typing," which gives the programmer more freedom to pass parameters at runtime without having to define them beforehand.

This dynamic typing is accomplished by using an interpreted language, rather than a compiled language.

Dynamic Programming Language

Page 4: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

A scripting language is a programming language that allows control of one or more software applications. "Scripts" are distinct from the core code of the application, which is usually written in a different language, and are often created or at least modified by the end-user. Scripts are often interpreted from source code whereas the applications they control are traditionally compiled.

The name "script" is derived from the written script of the performing arts, in which dialogue is set down to be spoken by human actors.

A Scripting language

Page 5: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

interpreted (no linking or compilation) less efficient to run faster to develop (factor of 5 to 10) high level – a single statement is more powerful no type declarations, typeless powerful built-in types can generate and interpret source code at run time

(via eval) interface to underlying operating system – can call

operating system commands plays well with others – glue systems together rarely used for complex algorithms or data structures. Examples: javascript, perl, php, smalltalk, ruby,

vbscript, groovy, emacslisp, awk, python, tcl, unix shell.

Characteristics of Scripting Language

Page 6: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

Japanese Design Aesthetics Shine Through Focus on human factors Principle of Least Surprise: when two

elements of an interface conflict, or are ambiguous, the behavior should be that which will least surprise the human user or programmer at the time the conflict arises.

Principle of Succinctness

Principles of Ruby

Page 7: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

The supreme design goal of RubyMakes programmers happy and makes Ruby easy to learn

Examples What class does an object belong to ? – can ask

o.class (returns the class object) Is it Array#size or Array#length?

Either one - same method – they’re aliased Is this good or bad design? Array operators? – if it makes sense, they are

defined.diff = ary1 – ary2 (removes elements of ary2 from ary1)union = ary1 + ary2 (concatenate arrays)

intersection = ary1 & ary2 (elements common to both)

The Principle of Least Surprise

Page 8: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

also known as the Principle of Least EffortMotivation… We don’t like to waste time The quicker we program, the more we

accomplishSounds reasonable enough, right?

Less code means less bugs Common needs are built-in.

Principle of Succinctness

Page 9: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

All classes derived from Object including Class (like Java) but there are no primitives (not like Java at all). EVERYTHING is an Object.

Ruby uses single-inheritance What are the dangers of multiple inheritance? Mixins give you the power of multiple inheritance

without the headaches Modules allow addition of behaviors to a class Reflection is built in along with lots of other

highly dynamic metadata features Things like ‘=‘ and ‘+’ that you might think are

operators are actually methods (like Smalltalk)

Ruby is Truly Object-Oriented

Page 10: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

a mixin is a class that is mixed with a module. In other words the implementation of the class and module are joined, intertwined, combined, etc.

a module as a degenerate abstract class. A module can’t be instantiated and no class can directly extend it but a module can fully implement methods.

Mixin

Page 11: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

# Convert a integer value to English.02.module Stringify03.  # Requires an instance variable

@value04.  def stringify05.    if @value == 106.      "One"07.    elsif @value == 208.      "Two"09.    elsif @value == 310.      "Three"11.    end12.  end13.end

Module (dependent of implementation class) so must be instance method Stringify makes use

of a @value instance variable.

The class that will be mixed with this module needs to define and set a @value instance variable

a module could invoke methods defined not in the module itself but in the class that it will be mixed with.

Page 12: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

# A Math module akin to Java Math class.2.module Math3.  # Could be called as a class, static,

method4.  def add(val_one, val_two)5.    BigInteger.new(val_one + val_two)6.  end7.end

Module (self contained) and so can be class method.

Page 13: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

# Base Number class02.class Number03.  def intValue04.    @value05.  end06.end07. 08.# BigInteger extends Number09.class BigInteger < Number10. 11.  # Add instance methods from Stringify12.  include Stringify // mix methods at the instance level13. 14.  # Add class methods from Math15.  extend Math // mix methods at the class level16. 17.  # Add a constructor with one parameter18.  def initialize(value)19.    @value = value20.  end21.end

mixin BigInteger

Page 14: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

# Call class method extended from Mathbigint2 = BigInteger.add(-2, 4)puts bigint2.intValue   # --> 2

# Call a method included from Stringifyputs bigint2.stringify   # --> 'Two'

Using it…

Page 15: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

# Format a numeric value as a currency module CurrencyFormatter   def format     "$#{@value}"   end end# Add the module methods to.# this object

instance, only!bigint2.extend (CurrencyFormatter)puts bigint2.format   # --> '$2'

Run time extend (add new or override existing methods)

Page 16: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

Method Chaining – applies methods from left to rightprint array.uniq.sort.reverse

Method Names include ! and ?ary.sort!

? returns a true or false ◦examples: defined? equal?

! changes the object that calls the method (do it here!)

Iterators and Blocks vs. Loopsfiles.each { |file| process(file) }

Case usage: ◦ Class names begin with a Capital letter◦ Constants are ALL_CAPS◦ Everything else - method call or a local variable

Convention in naming: Under_score instead of camelCase

Some Coding Conventions

Page 17: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

0.upto(9) do |x|    print x, " " end Produces: 0 1 2 3 4 5 6 7 8 9

[ 1, 1, 2, 3, 5 ].each {|val| print val, " " } Produces: 1 1 2 3 5

songList.each do |aSong|    aSong.play end

Iterators

Page 18: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

Duck TypingBased on signatures, not class inheritance

In Ruby, we rely less on the type (or class) of an object and more on its capabilities.

Duck Typing is a type of dynamic typing in which the object’s current set of methods and properties determines the valid semantics, rather than its inheritance from a particular class or implementation of a specific interface.

The name of the concept refers to the duck test, attributed to James Whitcomb Riley which may be phrased as follows:

"when I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck."

Dynamic Programming

Page 19: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

# Check whether the object defines the to_str method  

puts ('A string'.respond_to? :to_str) # => true  puts (Exception.new.respond_to? :to_str) # => true  puts (4.respond_to? :to_str) # => false  

The above example is the simplest example of Ruby's philosophy of "duck typing:" if an object quacks like a duck (or acts like a string), just go ahead and treat it as a duck (or a string). Whenever possible, you should treat objects according to the methods they define rather than the classes from which they inherit or the modules they include.

Duck Typing

Page 20: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

class Duck def quack 'Quack!' end def swim 'Paddle paddle paddle...' end end class Goose def honk 'Honk!' end def swim 'Splash splash splash...' end end class DuckRecording def quack play end def play 'Quack!' end end

Duck Typing Example

If you are calling “quack”, Duck and DuckRecording are interchangeable

If you are calling “swim”, Duck and Goose are interchangeable.

Method isn’t expecting a specific type JUST one with the needed functionality.

Page 21: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

Dynamic DispatchA key concept of OOP: methods are actually messages that are sent to an object instance

It is a runtime decision to decide which code to execute Can’t be determined statically (method could have been

overridden dynamically)foobar = Array.new foobar.class # => Array foobar.size # => 0

Conceptually: First we search for “size” in Array. If it isn’t there, we look to Object to define size. If the method isn’t found at the top of the hierarchy, we have a “method_missing” message.

Dynamic Language

Page 22: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

The regular search path:

The new search path

foobar = Array.new def foobar.size // Adds a size method ONLY for the instance “Infinity and beyond" ;end

Page 23: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

Languages with weak or no typing systems often carry a dispatch table as part of the object data for each object. This allows instance behavior as each instance may map a given message to a separate method.

Languages with strong (static) typing use a virtual table which defines method to code mapping. Instances of the type store a pointer to this table.

Dynamic Language Implementation

Page 24: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

Suppose a program contains several classes in an inheritance hierarchy: a superclass Cat, and two subclasses, HouseCat and Lion. Class Cat defines a virtual function named speak, so its subclasses may provide an appropriate implementation (e.g. either meow or roar).

When a Cat variable calls speak, we need to be able to tell which method to call.

dispatch table contains addresses of methods

Use same layout for type-compatible methods – so we look for address at a constant offset

Dynamic Dispatch in C++

Page 25: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

Dynamic Behavior◦ Reflection◦ Scope Reopening (Kind of like AOP)◦ Eval◦ Breakpoint debugger

Dynamic Language

Page 26: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

One of the many advantages of dynamic languages such as Ruby is the ability to introspect---to examine aspects of the program from within the program itself. Some call this feature reflection.

We might discover: ◦ what objects it contains, ◦ the current class hierarchy, ◦ the contents and behaviors of objects, and ◦ information on methods.

Reflection

Page 27: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

Everything is an object EVEN the class. 5.class #=> Fixnum "hello".class #=> String class Foo end Foo.class #=> Class Foo is a constant known to the system as a

class

Reflection

Page 28: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

Have you ever craved the ability to traverse all the living objects in your program? Ruby lets you perform this trick with ObjectSpace::each_object .

For example, to iterate over all objects of type Numeric, you'd write the following.

a = 102.7 b = 95 # Won't be returned c = 12345678987654321 # Won't be returned count = ObjectSpace.each_object(Numeric) {|x| p x } puts "Total count: #{count}“Produces:102.73.141592653589792.718281828459042.22044604925031e-161.79769313486232e+3084.9e-324Total count: 6

Hey, where did those last numbers come from? We didn't define them in our program. The Math module defines constants for e and PI; since we are examining all living objects in the system, these turn up as well.

Looking at Objects

Page 29: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

To get ObjectSpace to work from Netbeans use option –X+O (O as in Oreo)

Right click on Project name, Select Properties Click Run Define Ruby Option

Page 30: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

For instance, we can get a list of all the methods to which an object will respond.

r=1..10 num = 14 list = r.methods list.length # 60 list[0..3] # [exclude_end?, to_a, include?, member?] r.respond_to?("frozen?") #>> true r.respond_to?("hasKey") #>> true num.instance_of? Fixnum #>> true

Looking Inside Objects

Page 31: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

one_class = Fixnum begin    print one_class     one_class  = one_class .superclass    print " < " if one_class  end while one_class  puts p Fixnum.ancestors puts self.class # scripts are automatically in Objectputs 3.class # numbers are Fixnum

ProducesFixnum<Integer<Numeric<Object[Fixnum, Integer, Precision, Numeric, Comparable, Object, Kernel]Object Fixnum

Looking at Classes

Page 32: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

trane="John Coltrane".method(:length)miles="Miles Davis".method("sub")puts trane.callputs miles.call(/iles/,'.')trane=%q{"John Coltrane".length}miles=%q{"Miles Davis".sub(/iles/,'.')}puts eval traneputs eval milesproduces 14 M. Davis 14 M. Davis

Method can be passed around as objects (%q is a single quoted string)

Page 33: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

class CoinSlot def initialize(amt) @amt=amt $here=binding endenda=CoinSlot.new(35)eval ("puts @amt", $here) # 35eval ("puts @amt” ) # nil

ScopeAt instance variable begins with @

and its scope is confined to whatever object self refers to

A global variable begins with $It can be referred to from anywhere in the program

Page 34: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

class CoinSlot def initialize(amt) @amt=amt $here=binding endenda=CoinSlot.new(35)eval ("puts @amt", $here) # 35eval ("puts @amt” ) # nileval "@amt=23.92", $here eval "puts @amt", $here # 23.92

Scope

We can even modify variables in original scope

Page 35: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

One nice feature of globals, is that they can be traced; you can specify a procedure which is invoked whenever the value of the variable is changed.

trace_var :$here, proc{print "$here is now", $here, "\n"}

Tracing…

Page 36: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

class Demo def initialize(secret) @secret = secret end def getBinding return binding() end end

k1 = Demo.new(99) b1 = k1.getBinding k2 = Demo.new(-3) b2 = k2.getBinding

puts eval("@secret", b1) #=> 99 puts eval("@secret", b2) #=> -3 puts eval("@secret") #=> nil

Scoping (again)

Page 37: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

caller is a Ruby method of the Kernel class, which all objects inherit.

It returns an array of strings representing the call stack.

Getting the call stack

Page 38: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

class Demo def initialize(secret) @secret = secret @other = 2*@secret $here = binding end def aA puts caller.join("\n") end def aB aA end def aC aB end def getBinding return binding() end end k1 = Demo.new(99) k1.aC # prints call stack

Call StackProduces: C\cs4700\simple_ruby_application\lib\

Scoping.rb:25:in `aB' C:\cs4700\simple_ruby_application\

lib\Scoping.rb:28:in `aC' C:\cs4700\simple_ruby_application\

lib\Scoping.rb:49

Page 39: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

Java features the ability to serialize objects, letting you store them somewhere and reconstitute them when needed. You might use this facility, for instance, to save a tree of objects that represent some portion of application state, save it, and recreate is later.

Ruby calls this kind of serialization marshalling. Marshal: Def: To arrange or place (troops, for

example) in line for a parade, maneuver, or review.

Can be used to create a distributed object system.

Marshalling

Page 40: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

Marshallingclass Note attr :value def initialize(val) @value = val end def to_s @value.to_s endend

class Chord def initialize(arr) @arr = arr end def play @arr.join('-') endend

c = Chord.new( [ Note.new("G"), Note.new("Bb"), Note.new("Db"), Note.new("E") ] )

File.open("posterity", "w+") do |f| Marshal.dump(c, f)end

File.open("posterity") do |f| chord = Marshal.load(f) puts chord.play #» G-Bb-Db-E

end

Page 41: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

the format used by Marshal has changed a few times in the past.

it's Ruby-only. AFAIK nothing else can read data serialized with Marshal.

serializing objects with Marshal exposes implementation details.

The basic problem with Marshal is that it serializes an object by saving the name of its class and all its instance variables

Makes interoperability harder – encoding may change and implementation details are leaked by default.

Problems with marshalling

Page 42: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

Using Ruby's alias it is possible to reopen a class, override a method and still call the original.

class ClockRadio def on! @on = true end def on? @on endend

Clock Radio is complete,Sometime later we can redefine methods and add new ones:

class ClockRadio alias :old_on! :on!

def on! old_on! # Calling original code @display_time = true end

def display_time? @display_time endend

Scope Reopening

Page 43: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

The advantage you gain from being able to reopen classes is that you can patch the framework you’re using unobtrusively in order to fix bugs or improve performance.

Advantages

Page 44: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

Violates OO principle by allowing anyone to add members and methods to an existing class, even outside of the original class definition.

The methods thus added have full access to all other members and methods, including private ones.

This is a “violation of the Open/Closed Principle,” in that the original class is not kept closed against modifications.

It certainly isn’t pure. There really isn’t a Grand Unifying Idea. It clearly copies features from very different languages and allows for a variety of programming styles.

Scope reopening OO criticism

Page 45: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

A closure is a nameless function. It has code to run (the executable) It has state around the code (the scope)

You capture the environment (the local variables) in the closure.

Even after the function has returned, and its local scope has been destroyed, the local variables remain in existence as part of the closure object.

Local variables are shared between the closure and the method. It's a real closure. It's not just a copy. (This is a Perl feature that is copied.)

Closure

Page 46: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

You can reconvert a closure back into a block, so a closure can be used anywhere a block can be used.

Often, closures are used to store the status of a block into an instance variable, because once you convert a block into a closure, it is an object that can be referenced by a variable.

And of course closures can be used like they are used in other languages, such as passing around the object to customize behavior of methods.

Closure – what can you do with them?

Page 47: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

The important thing to remember about Ruby is that there isn't a big difference between ``compile time'' and ``runtime.‘’ This allows:

adding code to a running process. redefining methods on the fly, change their

scope from public to private, and so on. altering basic types, such as Class and

Object.

Compile Time? Runtime? Anytime!

Page 48: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

eval "puts 2+2" # => 4eval "'hello world!'.upcase “# => HELLO WORLD

Useful: Tutoring – allows users to run their code in a protected

environment evaluating math expression (like in spreadsheet) more flexible than a parser as can call functions that

were just created. implemented with the same interpreter as normal code

Eval - you pass in some Ruby code in a string, and it’ll evaluate it.

Characteristic of scripting languages

Page 49: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

Dangers: input = # ... read from some form

eval inputWhat if they input 'rm -rf *‘ ?

Slow – string must be parsed

Eval -

Page 50: Write more understandable code in less lines  Free (Very open license)  Extensible  Dynamic languages such as Ruby can be very productive in specific

Side Effects: As an everyday example, the statement x = gets

reads a line and sticks it into x just like you’d probably expect, but it also has the side effect of sticking the line into the global variable $_.

Ruby also blurs the line between names of variables, classes, and methods.  Some languages allow the same identifier to be both a class and a variable, but context distinguishes. Ruby does not.

Ruby delights in the bizarre usage of operator overloading. ”<<” normally means “left shift”, but it also means ”here document follows,” “append to string,” and “extend array.” Other operators have similar illogical overloadings; for example, the ”<" operator not only means "less than" but also "is a subclass of."

Criticisms of Ruby