A slightly-modified version of my IPRUG talk, this time for the BT DevCon5 developer conference at Adastral Park on 25 May 2012.
The main changes are the addition of the Ruby section and the increased number of HHGTTG references in honour of towel day.
6. What is the typing model?
What is the programming model?
How will you interact with it?
What are the decision constructs
and core data structures?
What are the core features that
make the language unique?
7. Java was like having a rich lawyer as a brother. He was
fun when he was younger, but now he’s a black hole
that sucks away all the joy in a 100-mile radius.
14. Blocks & yield
>> 3.times { puts "hello" }
hello
hello
hello
>> File.open "some-file", "w" do |f|
?> f.write "some-data"
>> end
>> def delayed_by seconds
>> sleep seconds
>> yield
>> end
>> delayed_by 5 do
?> puts "At last!"
>> end
At last!
15. Open classes
class NilClass
def blank?
true
end
end
class String
def blank?
empty?
end
end
>> [nil, "", "foo"].map &:blank?
=> [true, true, false]
16. Modules & mixins
module Debug
def info
"#{self.class}[#{object_id}]: #{to_s}"
end
end
class Object
include Debug
end
>> 2.info
=> "Fixnum[5]: 2"
>> "foo".info
=> "String[70107061928320]: foo"
22. Io is a rule bender. He’s young, wicked smart, and easy to
understand but hard to predict. He might give you the ride of
your life, wreck your dad’s car, or both.
24. Objects & Slots
Io> Person := Object clone
==> Person_0x7f922c06ad00:
type = "Person"
Io> Person firstName := "John"
==> John
Io> Person lastName := "Doe"
==> Doe
Io> Person firstName
==> John
26. Prototypal inheritance
Io> Arthur := Person clone
==> Arthur_0x7fd5406cd860:
type = "Arthur"
Io> Arthur name
==> John Doe
Io> Arthur firstName = "Arthur"
Io> Arthur lastName = "Dent"
Io> Arthur name
==> Arthur Dent
Io> Arthur proto
==> Person_0x7fd540693ed0:
firstName = "John"
lastName = "Doe"
name = method(...)
type = "Person"
30. Actors
Io> Slow := Object clone
Io> Fast := Object clone
Io> Slow go := method(
wait(1)
"Slow" println
)
Io> Fast go := method(
"Fast" println
)
Io> Slow @@go; Fast @@go; wait(2)
Fast
Slow
31. Futures
Io> page := URL with(
"http://google.co.uk/") @fetch
Io> "I'm in the foreground" println
I'm in the foreground
Io> page size println
16906
32. Pros
Tiny – ideal for embedded systems
Prototypes and duck typing are very flexible
Concurrency support
Simple, consistent syntax
Raw execution speed
Small user community
Cons
42. Pros
Solving logical and scheduling problems
Natural language processing
Artificial intelligence
Scaling requires deep understanding
Not a general-purpose language
Simple procedural tasks are difficult
Cons
44. He was often awkward, was sometimes amazing, but always had a
unique expression. Sometimes, his scissors let him do incredible things.
Other times, he was awkward and humiliated.
45. Type inference & coercion
scala> "foo"
res0: java.lang.String = foo
scala> 123
res1: Int = 123
scala> 45.6
res2: Double = 45.6
scala> 1 + 2.3
res3: Double = 3.3
scala> "The answer is " + 42
res4: java.lang.String = The answer is 42
46. var & val
scala> var a = 42
a: Int = 42
scala> a = a + 1
a: Int = 43
scala> val earth = "Harmless"
earth: java.lang.String = Harmless
scala> earth = "Mostly Harmless"
<console>:8: error: reassignment to val
earth = "Mostly Harmless"
^
47. Ranges & tuples
scala> val range = 0 to 3
range: scala.collection.immutable.Range.Inclusive
= Range(0, 1, 2, 3)
scala> val range = 0 to 5 by 2
range: scala.collection.immutable.Range
= Range(0, 2, 4)
scala> val tuple = ("Kerry", 42)
tuple: (java.lang.String, Int) = (Kerry,42)
scala> val (name, age) = tuple
name: java.lang.String = Kerry
age: Int = 42
56. Concurrency with actors
case object Stroke
case object Feed
class Cat() extends Actor {
def act() {
loop {
react {
case Stroke => { println("Purr!") }
case Feed => { println("Om nom nom") }
}
}
}
}
scala> val cat = new Cat().start
scala> cat ! Stroke; cat ! Feed; println("Done.")
Done.
Purr!
Om nom nom
57. Pros
A modern version of Java
Mixins, pattern matching, blocks, XML
Concurrency with actors & immutability
Static typing
Compromises with mutable state
Cons
59. Agent Smith was an artificial intelligence program in the matrix that
had an amazing ability to take any form and bend the rules of
reality to be in many places at once. He was unavoidable.
65. Patterns in functions
-module(fact).
-export([fact/1]).
fact(0) -> 1;
fact(N) -> N * fact(N-1).
1> c(fact).
{ok,fact}
3> fact:fact(6).
720
4> fact:fact("foo").
** exception error: bad argument in an arithmetic
expression
in function fact:fact/1 (fact.erl, line 5)
6> fact:fact(10000).
74. Pros
Designed for concurrency & fault tolerance
Flexibility of dynamic typing
Lightweight processes with message passing & monitoring
Build scalable applications with the OTP library
Syntax sometimes a little clumsy
Integration with other languages
Cons
76. His communication style is often inverted and hard to understand.
He seems too small to make a difference, but it quickly becomes
apparent that there is more to Yoda than meets the eye.
91. Agents in the background
user=> (defn slow-twice [x]
(do (Thread/sleep 5000) (* 2 x)))
#'user/slow-twice
user=> (def number (agent 2))
#'user/number
user=> number
#<Agent@4c825cf3: 2>
user=> @number
2
user=> (send number slow-twice)
#<Agent@4c825cf3: 2>
user=> @number
2
user=> @number
4
92. Back to the futures
user=> (def ultimate-answer
(future (do
(Thread/sleep 2.4e17)
42)))
#'user/ultimate-answer
user=> @ultimate-answer
42
93. Pros
A good lisp implementation
Access to Java ecosystem
Concurrency provided by STM
Prefix notation can be confusing
(((((and all those parens don’t help)))))
Some limitations compared to other lisps
Cons
95. Haskell represents purity and freedom, but the power comes at a
price. Think Spock from Star Trek. His character has a single-minded
purity that has endeared him to generations.
96. Type inference
Prelude> :set +t
Prelude> 42
42
it :: Integer
Prelude> "Mostly harmless"
"Mostly harmless"
it :: [Char]
Prelude> "black" == "white"
False
it :: Bool
Prelude> 1/2
0.5
it :: Double
97. Defining functions
Prelude> let double x = x * 2
double :: Num a => a -> a
Prelude> double 4
8
Prelude> double 2.5
5.0
Prelude> let times x y = x * y
times :: Num a => a -> a -> a
Prelude> times 5 6
30
98. Specifying function types
module Main where
double :: Integer -> Integer
double x = 2 * x
Prelude> :load main
[1 of 1] Compiling Main ( main.hs, interpreted )
Ok, modules loaded: Main.
*Main> double 2
4
*Main> double 2.5
<interactive>:1:8:
No instance for (Fractional Integer)
arising from the literal `2.5'
99. Pattern matching & guards
module Main where
factorial :: Integer -> Integer
factorial 0 = 1
factorial x = x * factorial (x - 1)
factorial2 :: Integer -> Integer
factorial2 x
| x > 1 = x * factorial2 (x - 1)
| otherwise = 1
100. Tuples & lists
Prelude> let zaphod = ("Zaphod", "Beeblebrox", "Betelgeuse", 2)
Prelude> let (_, _, _, numberOfHeads) = zaphod
Prelude> let numbers = [1, 2, 3, 4]
Prelude> let (head:tail) = numbers
Prelude> head
1
Prelude> tail
[2,3,4]
Prelude> 1:[2, 3]
[1,2,3]
Prelude> [1, "two"]
<interactive>:1:2:
No instance for (Num [Char])
arising from the literal `1'
Possible fix: add an instance declaration for (Num [Char])
In the expression: 1
In the expression: [1, "two"]
In an equation for `it': it = [1, "two"]
102. List comprehensions
Prelude> let numbers = [1,2,3]
Prelude> [x * 2 | x <- [1, 2, 3]]
[2,4,6]
Prelude> [[x, y] | x <- numbers, y <- numbers]
[[1,1],[1,2],[1,3],[2,1],[2,2],[2,3],[3,1],[3,2],[3,3]]
Prelude> [[x, y] | x <- numbers, y <- numbers, x < y]
[[1,2],[1,3],[2,3]]
Prelude> let more_numbers = [4,5]
Prelude> [(x, y, x * y) | x <- numbers, y <- more_numbers, x < y]
[(1,4,4),(1,5,5),(2,4,8),(2,5,10),(3,4,12),(3,5,15)]
103. Function currying
Prelude> 4 * 5
20
Prelude> (*) 4 5
20
Prelude> :t (*)
(*) :: Num a => a -> a -> a
Prelude> let double = (* 2)
Prelude> :t double
double :: Integer -> Integer
Prelude> double 3
6
105. Type classes
class Eq a where
(==), (/=) :: a -> a -> Bool
-- Minimal complete definition:
-- x/=y x==y
(==) or (/=)
= not(x==y) = not(x/=y)
*Main> :info Integer
data Integer
= integer-gmp:GHC.Integer.Type.S# GHC.Prim.Int#
| integer-gmp:GHC.Integer.Type.J# GHC.Prim.Int#
GHC.Prim.ByteArray#
-- Defined in integer-gmp:GHC.Integer.Type
instance Enum Integer -- Defined in GHC.Num
instance Eq Integer -- Defined in GHC.Classes
instance Integral Integer -- Defined in GHC.Real
instance Num Integer -- Defined in GHC.Num
instance Ord Integer -- Defined in GHC.Classes
instance Read Integer -- Defined in GHC.Read
instance Real Integer -- Defined in GHC.Real
instance Show Integer -- Defined in GHC.Num
106. User-defined types
module Main where
data Shape = Circle Float | Rectangle Float Float
deriving show
area :: Shape -> Float
area (Circle r) = pi * r ^ 2
area (Rectangle x y) = x * y
*Main> let circle = Circle 10
*Main> let rect = Rectangle 6 7
*Main> area circle
314.15927
*Main> area rect
42.0
*Main> [circle, rect]
[Circle 10.0,Rectangle 6.0 7.0]
107. Record syntax
module Main where
data Shape = Circle {radius :: Float}
| Rectangle {width :: Float, height :: Float}
deriving Show
area :: Shape -> Float
area (Circle r) = pi * r ^ 2
area (Rectangle x y) = x * y
*Main> let circle = Circle 10
*Main> let rect = Rectangle 6 7
*Main> [circle, rect]
[Circle {radius = 10.0},Rectangle {width = 6.0, height = 7.0}]
108. Monads
A monad is a construction that, given an underlying type
system, embeds a corresponding type system (called
the monadic type system) into it (that is, each monadic
type acts as the underlying type). This monadic type
system preserves all significant aspects of the
underlying type system, while adding features particular
to the monad.
Monads must obey the following rules:
• (return x) >>= f ≡ f x
• m >>= return ≡ m
• (m >>= f) >>= g ≡ m >>= ( x -> (f x >>= g) )
109. Monads
A monad is a construction that, given an underlying type
system, embeds a corresponding type system (called
the monadic type system) into it (that is, each monadic
type acts as the underlying type). This monadic type
system preserves all significant aspects of the
underlying type system, while adding features particular
to the monad.
Monads must obey the following rules:
• (return x) >>= f ≡ f x
• m >>= return ≡ m
• (m >>= f) >>= g ≡ m >>= ( x -> (f x >>= g) )
110. The maybe monad
data Maybe a = Nothing | Just a
Prelude> case (html doc) of
Nothing -> Nothing
Just x -> case body x of
Nothing -> Nothing
Just y -> paragraph 2 y
instance Monad Maybe where
return = Just
Nothing >>= f = Nothing
(Just x) >>= f = f x
Prelude> Just someWebPage >>= html >>= body
>>= paragraph >>= return
111. Pros
Pure functional language with no side effects
Strong typing with powerful type inference
Laziness reduces need for recursion
Ideal for learning the functional paradigm
Inflexibility and lack of compromise
Small community outside academia
Steep learning curve (especially monads!)
Cons
113. Functional style
def total_price(widgets)
total = 0
widgets.each do |widget|
if widget.red?
total += widget.price
end
end
total
end
def total_price(widgets)
widgets.select{|w| w.red?}.map{|w| w.price}.reduce(&:+)
end
114. JVM or standalone?
• Access to Java libraries
• Deployment environments
• Escape route for Java developers
• Limitations (eg tail recursion)
115. Know what’s out there
• Languages
• Features
• First-class functions
• List comprehensions
• Pattern matching
• Lazy evaluation