Speaker notes added in italics
"Don't underestimate the human factor."
Ruby is from Japan. Ruby's creator, Yukihiro Matsumoto or "Matz", stresses that code should prioritize human needs, not computers' needs.
Ruby is an outlier if you consider language origin. Is it possible that its origin accounts for some of the things that make it special?
Matz' focus on easily-accessible, human-friendly programming spilled into the Ruby community. tryruby.org is a great example of this. It pays homage to _why, an early Ruby personality.
DHH & Stuff
Ruby on Rails made Ruby famous. Rails was warmly received and remains loved for its dedication to making development fast & easy, for providing smart conventions and for enabling endless customization and specialization.
These days, there are lots of ways to run Ruby code.
name = "Star Wars"
name << ": The Force Awakens"
# => "Star Wars: The Force Awakens"
crew = ["Han Solo", "Chewbacca"]
crew << "Luke Skywalker" << "Ben Kenobi"
# => ["Han Solo", "Chewbacca", "Luke Skywalker", "Ben Kenobi"]
(1..10)
# => 1 .. 10
('a'..'z')
# => "a" .. "z"
started_at = Time.new("2011-01-01")
ended_at = Time.new("2011-12-31")
the_year_2011 = (started_at..ended_at)
# => 2011-01-01 00:00:00 -0800..2011-01-01 00:00:00 -0800
In Ruby, all objects behave basically the same way. This means that once you learn a few Ruby APIs, you know what to expect from new ones.
class Aquarium
attr_accessor :fishes
def initialize(fishes=[])
self.fishes = fishes
end
end
# initialize with an array of fishes
tank = Aquarium.new(["Goldie", "Fishy"])
# add fishes
tank << "Comet"
# combine Aquariums
bowl = Aquarium.new(["Alpha"])
koi_pond = tank + bowl
# find fishes by name
koi_pond["Goldie"]
def +(other_aquarium)
# join fishes together
new_fish = self.fishes +
other_aquarium.fishes
Aquarium.new(new_fish)
end
def <<(fish)
# add a fish to the collection,
# return self
self.fishes << fish
self
end
def [](fish)
# lookup a fish by name
self.fishes.find { |f| f == fish }
end
With Ruby, just imagine how your objects should behave. You can always implement it. Since operators are aliases for methods, your custom objects feel like built-ins.
const_defined?(:Fish) # => true
fish_class = const_get(:Fish)
Fish.ancestors
# => [Fish, Animal, Vertebrate, Object,
# Kernel, BasicObject]
Fish.method_defined?(:swim)
Fish.instance_method(:swim) # => BoundMethod
shiny = Fish.new(name: "Shiny")
shiny.class # => #<class: Fish>
shiny.instance_variable_get("@name")
# => "Shiny"
shiny.is_a?(Fish) # => true
shiny.is_a?(Animal) # => true
shiny.respond_to?(:swim!) # => true
shiny.respond_to?(:walk!) # => false
Your app is made of values and code stored in the VM's memory. Ruby gives you lots of ways to inspect it.
const_defined?(:Fish) # => true
class Fish
def saute
# add oil & heat
end
end
COOKING_METHODS = [:broil, :bake]
class Fish
COOKING_METHODS.each do |cook|
define_method(cook) do |heat, time|
# heat for time, etc
end
end
end
if !const_defined(:Squid)
squid_class = Class.new(Fish)
squid_class.name # => nil
Object.const_set(:Squid, squid_class)
end
Besides inspecting objects in memory, you can modify them and create new ones.
class Fish
end
def method_missing(name, *args, &block)
# last chance, what do you want to do!?
super
end
def self.const_missing(name)
# I'm sure we've got an extra
# `Fish::Head` around here somewhere...
super
end
yummy = Tuna.new(name: nil)
yummy.dolphin_safe?
# => I really can't afford another NoMethodError
if diner.high_class? || diner.russian?
meal = Sturgeon::Caviar
end
# => do we have any of that?
When Ruby looks for some part of your program, but it isn't there, it's not too late. Ruby gives you hooks to handle those cases.
Ruby is wonderful because you have total control to express yourself in your code. You own it; not vice-versa.
Let's talk about another implementation of Ruby: mruby. In fact, this is Matz's current project.
Matz's dream is to lower the barrier of entry to the "internet of things" by using Ruby to connect people to all kinds of computers.
What makes mruby special is that it's great for connecting to a) other applications or b) small computers.
I added this slide in place of the live demo, shoulda been there!
mruby's Hello world consists of:
See it on github
I added this slide in place of the live demo, shoulda been there!
You don't have to ship your code with the mruby parser. You can precompile Ruby code to RiteVM instructions.
Then, your C application can execute the bytecode instructions with the mruby VM.
See it on github
I added this slide in place of the live demo, shoulda been there!
In your C application, you can prepare the mruby VM with values & code that are normally off-limits for Ruby.
How about the timeless example of illuminating LEDs?
I don't have any LEDs, but let's imagine with `FakeLED`.
I added this slide in place of the live demo, shoulda been there!
You can write a Ruby script to control your LEDs
First, wrap the hardware with some mruby-compatible functions
Then, in your application, bind the hardware to the mruby VM by defining classes, methods and constants (github)
Lastly, evaluate your Ruby code with your VM instance (github)
It looks like mruby has some support from Japanese companies.
Ex: forum.mruby.org, Toshiba, CloudWalk.io (not Japanese)
Robert Mosolgo, @rmosolgo
https://github.com/rmosolgo/mruby-examples