$30 off During Our Annual Pro Sale. View Details »

Functional Ruby

Functional Ruby

高見龍

June 27, 2023
Tweet

More Decks by 高見龍

Other Decks in Technology

Transcript

  1. 為你⾃⼰學 系列單元
    ޒഒላӃ
    Functional Ruby

    View Slide

  2. ޒഒላӃ
    വᏐࣜఔࣜઃܭ
    'VODUJPOBM1SPHSBNNJOH '1

    View Slide

  3. ޒഒላӃ
    ೺ਞྻཫॴ༗తحᏐ
    ငҎ೭ޙฒܭࢉશ෦ݩૉ័࿨

    View Slide

  4. ޒഒላӃ
    +4
    // JavaScript


    const list = [1, 2, 3, 4, 5]


    const odd_numbers = []


    // 挑出奇數


    for (let i = 0; i < list.length; i++) {


    const el = list[i]


    if (el % 2 === 1) {


    odd_numbers.push(el)


    }


    }


    const triple_numbers = []


    // 乘 3 倍


    for (let i = 0; i < odd_numbers.length; i++) {


    triple_numbers.push(odd_numbers[i] * 3)


    }


    let total = 0


    // 計算總和


    for (let i = 0; i < triple_numbers.length; i++) {


    total += triple_numbers[i]


    }


    console.log(total) // 27

    View Slide

  5. ޒഒላӃ
    +4
    // JavaScript


    const list = [1, 2, 3, 4, 5]


    const result = list.filter(i => i % 2 === 1)


    .map(i => i * 3)


    .reduce((acc, cv) => acc + cv, 0)


    console.log(result) // 27

    View Slide

  6. ޒഒላӃ
    +4
    // JavaScript


    const list = [1, 2, 3, 4, 5]


    const oddOnly = (i) => i % 2 === 1


    const triple = (i) => i * 3


    const sum = (acc, cv) => acc + cv


    const result = list.filter(oddOnly)


    .map(triple)


    .reduce(sum, 0)


    console.log(result) // 27

    View Slide

  7. ޒഒላӃ
    ॄኄੋ'1ʁ

    View Slide

  8. ޒഒላӃ
    ఔࣜޠݴయൣ
    1SPHSBNNJOH1BSBEJHNT

    View Slide

  9. ޒഒላӃ
    ෺݅ಋ޲ఔࣜઃܭ
    0CKFDU0SJFOUFE1SPHSBNNJOH

    View Slide

  10. ޒഒላӃ
    ෧᧋៺ঝ
    &ODBQTVMBUJPO*OIFSJUBODF

    View Slide

  11. ޒഒላӃ
    വᏐࣜఔࣜઃܭ
    'VODUJPOBM1SPHSBNNJOH

    View Slide

  12. ޒഒላӃ
    വᏐ
    'VODUJPO

    View Slide

  13. ޒഒላӃ
    ॄኄੋവᏐʁ

    View Slide

  14. ޒഒላӃ
    f(x) = 3x + 2

    View Slide

  15. ޒഒላӃ
    വᏐ༌ೖ值ᢛ༌ग़值೭ؒత᮫܎

    View Slide

  16. ޒഒላӃ
    ७വᏐ
    1VSF'VODUJPO

    View Slide

  17. ޒഒላӃ
    1VSF'VODUJPO
    ༌ग़݁Ռ୞᪑༌ೖ值༗᮫

    View Slide

  18. ޒഒላӃ
    +4
    # 不純


    def one_weeks_later


    Time.now + 7.days


    end

    View Slide

  19. ޒഒላӃ
    +4
    # 比較純


    def one_weeks_later(current_time)


    current_time + 7.days


    end

    View Slide

  20. ޒഒላӃ
    1VSF'VODUJPO
    ෆ။଄੒㐫ଶվᏓ

    View Slide

  21. ޒഒላӃ
    ᔒ༗෭࡞༻
    /PTJEFFGGFDU

    View Slide

  22. ޒഒላӃ
    +4
    # 不純


    def add_book


    Book.create(title: '為你⾃⼰學 Ruby')


    end

    View Slide

  23. ޒഒላӃ
    +4
    # 不純


    def replace_element(arr, idx, value)


    arr[idx] = value


    arr


    end


    list = [1, 2, 3]


    result = replace_element(list, 0, "a")


    p result # ["a", 2, 3]


    p list # ???

    View Slide

  24. ޒഒላӃ
    +4
    # 比較純


    def replace_element(arr, idx, value)


    dup_arr = arr.dup


    dup_arr[idx] = value


    dup_arr


    end


    list = [1, 2, 3]


    result = replace_element(list, 0, "a")


    p result # ["a", 2, 3]


    p list # ???

    View Slide

  25. ޒഒላӃ
    ෆՄᏓੑ
    *NNVUBCJMJUZ

    View Slide

  26. ޒഒላӃ
    +4
    // JavaScript


    const list = [1, 2, 3]


    const otherList = list


    console.log(list) // [1, 2, 3]


    otherList[0] = "a"


    console.log(list) // ???

    View Slide

  27. ޒഒላӃ
    +4
    // Rust


    fn main() {


    let list = [1, 2, 3];


    list[0] = 100; // 預設是不能修改的


    println!("{:?}", list);


    }

    View Slide

  28. ޒഒላӃ
    +4
    # Elixir


    list = [1, 2, 3]


    list[0] = 100 # 預設是不可修改的

    View Slide

  29. ޒഒላӃ
    '1JO3VCZ

    View Slide

  30. ޒഒላӃ
    +4
    list = [1, 2, 3, 4, 5]


    double_list = list.map { |n| 2 * n }


    odd_numbers = list.filter { |n| n.odd? }


    p double_list # [2, 4, 6, 8, 10]


    p odd_numbers # [1, 3, 5]

    View Slide

  31. ޒഒላӃ
    3VCZฒෆࢉੋਅਖ਼త'1-BOHVBHF

    View Slide

  32. ޒഒላӃ
    വᏐੋҰ౳ެຽ
    'JSTU$MBTT$JUJ[FO

    View Slide

  33. ޒഒላӃ
    +4
    // JavaScript


    const list = [1, 2, 3, 4, 5]


    const oddOnly = (i) => i % 2 === 1


    const triple = (i) => i * 3


    const sum = (acc, cv) => acc + cv


    const result = list.filter(oddOnly)


    .map(triple)


    .reduce(sum, 0)


    console.log(result) // 27

    View Slide

  34. ޒഒላӃ
    3VCZॴ༗త౦੢౎ੋ෺݅
    &WFSZUIJOHJO3VCZJTBOPCKFDU

    View Slide

  35. ޒഒላӃ
    ୠଖመ༗ࠣ౦੢ฒෆੋ෺݅

    View Slide

  36. ޒഒላӃ
    ᩋํ๏ʮ෺݅Խʯ

    View Slide

  37. ޒഒላӃ
    +4
    # 把⽅法物件化


    def add(a, b)


    a + b


    end


    m1 = method(:add)


    m2 = Proc.new { |x, y| add(x, y) }


    m3 = -> (x, y) { add(x, y) }


    puts m1.call(1, 2) # 3


    puts m2.call(3, 4) # 7


    puts m3.call(5, 6) # 11

    View Slide

  38. ޒഒላӃ
    ෆՄᏓੑ
    *NNVUBCJMJUZ

    View Slide

  39. ޒഒላӃ
    +4
    # Data.define 是 Ruby 3.2 之後才加進來的新功能


    Location = Data.define(:x, :y)


    point = Location.new(0, 0)


    puts point.x, point.y


    point.x = 100 # 錯誤

    View Slide

  40. ޒഒላӃ
    ိᴍෳᯑత

    View Slide

  41. ޒഒላӃ
    ᐬཬԽ
    $VSSZJOH

    View Slide

  42. ޒഒላӃ
    ೺ݪຊधཁଟݸჩᏐతവᏐ
    ᫚׵੒Ұܥྻ୞ཁݸჩᏐతവᏐతաఔ

    View Slide

  43. ޒഒላӃ
    +4
    def add_numbers(a, b, c)


    a + b + c


    end


    # 柯⾥化


    curried_add = -> (x) {


    -> (y) {


    -> (z) {


    add_numbers(x, y, z)


    }


    }


    }

    View Slide

  44. ޒഒላӃ
    +4
    # 分開寫


    add_2 = curried_add.call(2)


    add_3 = add_2.call(3)


    result = add_3.call(5)


    puts result


    # 或串在⼀起寫


    puts curried_add.call(2).call(3).call(5)

    View Slide

  45. ޒഒላӃ
    +4
    def add_numbers(a, b, c)


    a + b + c


    end



    # 柯⾥化


    # curried_add = -> (x) {


    # -> (y) {


    # -> (z) {


    # add_numbers(x, y, z)


    # }


    # }


    # }


    # Ruby 內建的⽅法


    curried_add = method(:add_numbers).curry

    View Slide

  46. ޒഒላӃ
    ภവᏐ
    1BSUJBM'VODUJPOT

    View Slide

  47. ޒഒላӃ
    ෦份BQQMZݪ࢝വᏐɼઌݻఆവᏐత෦෼
    ჩᏐɼճၚ઀डႫᰨჩᏐత৽വᏐ

    View Slide

  48. ޒഒላӃ
    +4
    def add_numbers(a, b, c)


    a + b + c


    end


    # Partial Function


    # 先給 1 個參數


    add_2 = -> (i, j) { add_numbers(2, i, j) }


    # 剩下的 2 個參數之後再⼀次給⾜


    puts add_2.call(3, 5) # 10

    View Slide

  49. ޒഒላӃ
    +4
    def add_numbers(a, b, c)


    a + b + c


    end


    # Partial Function


    # 或是先給 2 個參數


    add_2_and_3 = -> (k) { add_numbers(2, 3, k) }


    # 最後 1 個參數之後再給


    puts add_2_and_3.call(5) # 10

    View Slide

  50. ޒഒላӃ
    +4
    def add_numbers(a, b, c)


    a + b + c


    end


    # 利⽤內建的 curry ⽅法


    partial_fn = method(:add_numbers).curry


    # 先給 1 個參數


    add_2 = partial_fn.call(2)


    # 剩下的參數之後再⼀次給⾜


    puts add_2.call(3, 5) # 10

    View Slide

  51. ޒഒላӃ
    വᏐ߹੒
    'VODUJPO$PNQPTJUJPO

    View Slide

  52. ޒഒላӃ
    ઌՃɼ࠶Ճഒɼ࠷ޙ࠶ฏํʂ

    View Slide

  53. ޒഒላӃ
    +4
    // JavaScript


    const add_one = (n) => n + 1


    const double = (n) => n * 2


    const square = (n) => n * n


    console.log(square(double(add_one(5)))) // 144

    View Slide

  54. ޒഒላӃ
    ؅ઢ
    1JQF

    View Slide

  55. ޒഒላӃ
    +4
    # Elixir


    add_one = fn x -> x + 1 end


    double = fn x -> x * 2 end


    square = fn x -> x * x end


    result = 5 |> add_one.()


    |> double.()


    |> square.()


    IO.inspect result # 144

    View Slide

  56. ޒഒላӃ
    3VCZᔒ༗Ṝኄํศత౦੢

    View Slide

  57. ޒഒላӃ
    +4
    add_one = -> (n) { n + 1 }


    double = -> (n) { n * 2 }


    square = -> (n) { n * n }


    # 先加 1,再加倍,最後再平⽅


    composed_fn = add_one.compose(double)


    .compose(square)


    puts composed_fn.call(5) # 144

    View Slide

  58. ޒഒላӃ
    +4
    add_one = -> (n) { n + 1 }


    double = -> (n) { n * 2 }


    square = -> (n) { n * n }


    # 先加 1,再加倍,最後再平⽅


    composed_fn = add_one >> double >> square


    puts composed_fn.call(5) # 144

    View Slide

  59. ޒഒላӃ
    ޻঎෰຿

    View Slide