Just...
look around you!
Have you worked out what we're looking for?
invented by Moses Schönfinkel
"Nothing in math is named after the person that discovered it"
(discovered by Hubert Kennedy)
First, you need a function
add = lambda do |x, y|
x + y
end
add.call(5, 6)
More tersely,
add = -> x, y { x + y }
add[5, 6]
Now, instead of returning the value, wrap the value in a lambda.
add = lambda do |x, y|
lambda do
x + y
end
end
add.call(5, 6).call
Now, just move the argument from the outer lambda to the inner lambda!
add = lambda do |x|
lambda do |y|
x + y
end
end
add.call(5).call(6)
Y'all are curry masters!
foo = lambda do |x|
2 * x + 1
end
bar = lambda do |x|
x ** 2
end
(foo * bar).call(x) == foo.call(bar.call(x))
Ruby doesn't have a function composition operator...
... yet!!
class Proc
def *(other)
lambda do |x|
self.call(other.call(x))
end
end
end
Bash pipes!
# How many classes are defined in your app?
$ cat **/*.rb | grep "^class" | wc -l
# Using the * style:
$ (wc -l * grep "^class" * cat)( **/*.rb )
$ wc -l ( grep "^class" ( cat ( **/*.rb ) ) )
Those Unix commands are partially applied!
$ wc -l **/*.rb
$ grep "^class" **/*.rb
$ cat **/*.rb
Unfortunately, Ruby doesn't have the pipe composition operator...
... yet!
class Proc
def |(other)
lambda do |x|
other.call(self.call(x))
end
end
end
function update(index, item) {
App.data[index] = item;
}
function renderItems() {
return App.data.map(function (item, index) {
return new Item(item, update.bind(this, index));
});
}
function update(index) {
return function (item) {
App.data[index] = item;
}
}
function renderItems() {
return App.data.map(function (item, index) {
return new Item(item, update(index));
});
}
let update = index => item => App.data[index] = item;
function renderItems() {
return App.data.map(
(item, index) => new Item(item, update(index))
);
}
Language | Implemented |
---|---|
Ruby |
|
Java |
|
Haskell |
|
Math | $add : \mathbb{Z} \rightarrow \mathbb{Z} \rightarrow \mathbb{Z}$ $ add(x, y) = x + y $ |
a transformation from something to some other thing
represented like: $$ A \rightarrow B $$
where $A$ is the type of the original thing, and $B$ is the type of the new thing, and the arrow ($\rightarrow$) represents the transformation
Ruby is Object Oriented, not Lambda or Function Oriented.
Is there an equivalence? How can we translate these ideas?
RCaaF -- startup idea!
(this is kinda out there so please stop me and ask questions if you want)
How to make a Ruby class like a function?
$$ f : A \rightarrow B $$Where:
Class#new
A Duck is the methods we care about on some object.
class F
attr_reader :b
def initialize(object)
@b = object.a
end
end
Objects from F
have the duck b
, and it's input argument has the duck a
class G
attr_reader :a
def initialize(object)
@a = object
end
end
Objects from G
have the duck a
, and it's input argument doesn't have a duck
>> F.new( G.new( 5 ) ).b
=> 5
I wrote the gem Beethoven
to make this sort of thing easier
The following are equivalent:
F.new(G.new(5)).b
(F * G).new(5).b
(G | F).new(5).b
[G, F].reduce(&:|).new(5)
Single argument functions are boring...
lambda do |x, y|
x + y
end.call(5, 6)
to
lambda do |x|
lambda { |y| x + y }
end.call(5).call(6)
Class#new
class Add
def initialize(x)
@x = x
end
def new(y)
@y = y; return self
end
def value
@x + @y
end
end
>> Add.new(5).new(6).value
=> 11
class Map
def initialize(func)
@func = func
end
def new(object)
@list = object.list; self
end
def list
@list.map(&@func)
end
end
class Filter
def initialize(func)
@func = func
end
def new(object)
@list = object.list; self
end
def list
@list.filter(&@func)
end
end
class Reduce
def initialize(func)
@func = func
end
def new(object)
@list = object.list; self
end
def value
@list.reduce(&@func)
end
end
List = Struct.new(:list)
list = List.new( (1..100).to_a )
Reduce.new(-> sum, next { sum + next }).new(
Map.new(-> x { x + 10 }).new(
Filter.new(-> x { x.even? }).new(list)
)
).value
=> 3050
Pipeline = Filter.new(-> x { x.even? })
| Map.new(-> x { x + 10 })
| Reduce.new(-> sum, next { sum + next })
Pipeline.new(list).value
=> 3050
even = -> x { x.even? }
add_ten = -> x { x + 10 }
add = -> x, y { x + y }
Pipeline = Filter.new(even)
| Map.new(add_ten)
| Reduce.new(add)
Pipeline.new(list).value
=> 3050
even = -> x { x.even? }
add = -> x, y { x + y }.curry
Pipeline = Filter.new(even)
| Map.new(add.call(10))
| Reduce.new(add)
Pipeline.new(list).value
=> 3050
Ruby and JavaScript @
(we're they're hiring!)
Now, Haskell @ Layer 3 Communications