我似乎發現,我是不是還沒說明我要做什麼樣的專案阿XD
我想在Julia這個語言上實作Reactive programming這樣的概念。
如果有成功的話,我會進一步把他發展成為一個library,然後放上Github。
我們來想想看reactive programming需要怎樣的元素。
我先貼一段Python的讓大家瞧瞧。
functional.seq([1, 2, 3, 4, 5, 6])
.map(lambda x: x ** 2)
.filter(lambda x: x > 10)
.to_list()
基本上物件導向語言在實作reactive programming的時候都會用上的就是functional programming,其中我認為會用到的應該是在functional language裡面的functor。
那就來介紹一下functor吧!
functor原本是一種數學概念,大概在代數拓樸或是範疇論中可以找到他。
雖然數學領域的名字聽起來很嚇人,但是概念卻很簡單。
他有點像是你把值用糖果紙包起來,當值要通過一個函數做運算之後,外面包的那層紙還在,但是裡面的值已經被偷天換日了。
所以假設有個函數可以做到把運算式跟要運算的值做結合,那我們就完工了!
基本上概念如下
fmap: (<A -> B>, F(A)) -> F(B)
這是一個稱為fmap
的函式,他接受兩個參數,第一個參數是一個函式,他可以把A
值運算成為B
值,第二個參數則是要運算的值,他是一個有糖果紙包著的值F(A)
,最後這個fmap
他會回傳F(B)
給我,很神奇吧!
我們這邊同時實作也要求俱備可擴充性。
import Base: get, map, filter # 要擴充原有的function功能的話要先把他們import進來
abstract Functor # 宣告一個Functor是抽象型別,這樣以後繼承這個型別的人就都可以用
function get(f::Functor) # 宣告一個空的get介面,來取得繼承Functor的型別裡的值
end
function map{T <: Functor}(f::Function, x::T) # 接受第一個參數型別是function,第二個參數型別要是Functor的子型別
x_ = get(x) # 先取得x當中的值
return T(f(x_)) # 塞進f之後在把他用原型別包起來
end
function filter{T <: Functor}(f::Function, x::T)
x_ = get(x)
if f(x_)
return xs
end
end
到這邊我都把介面跟行為都定義好了,接下來就是實作了!
type Foo <:Functor
value
end
function get(x::Foo)
return x.value
end
ㄟ?實作只有這樣嗎?
嗯!對阿!Julia很優雅吧!
a = Foo(5)
map(x -> x+5, a) # Foo(10)
filter(x -> x > 5, a) # nothing
filter(x -> x > 5, map(x -> x+5, a)) # Foo(10)
我就寫到這邊囉~~~其他留給大家自己看吧!