iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 13
0
自我挑戰組

Julia語言—從入門到專案系列 第 13

[Day 13] 前哨站--functional patterns

我似乎發現,我是不是還沒說明我要做什麼樣的專案阿XD
我想在Julia這個語言上實作Reactive programming這樣的概念。
如果有成功的話,我會進一步把他發展成為一個library,然後放上Github。

Reactive programming需要的元素

我們來想想看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吧!

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)

我就寫到這邊囉~~~其他留給大家自己看吧!


上一篇
[Day 12] Asynchronous programming--連結起來
下一篇
[Day 14] Reactive programming--實作bridge
系列文
Julia語言—從入門到專案31

尚未有邦友留言

立即登入留言