為你⾃⼰學 系列單元ޒഒላӃFunctional Ruby
View Slide
ޒഒላӃവᏐࣜఔࣜઃܭ'VODUJPOBM1SPHSBNNJOH '1
ޒഒላӃਞྻཫॴ༗తحᏐငҎ೭ޙฒܭࢉશ෦ݩૉ័
ޒഒላӃ+4// JavaScriptconst 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
ޒഒላӃ+4// JavaScriptconst 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
ޒഒላӃ+4// JavaScriptconst list = [1, 2, 3, 4, 5]const oddOnly = (i) => i % 2 === 1const triple = (i) => i * 3const sum = (acc, cv) => acc + cvconst result = list.filter(oddOnly).map(triple).reduce(sum, 0)console.log(result) // 27
ޒഒላӃॄኄੋ'1ʁ
ޒഒላӃఔࣜޠݴయൣ1SPHSBNNJOH1BSBEJHNT
ޒഒላӃ݅ಋఔࣜઃܭ0CKFDU0SJFOUFE1SPHSBNNJOH
ޒഒላӃ෧ঝ&ODBQTVMBUJPO*OIFSJUBODF
ޒഒላӃവᏐࣜఔࣜઃܭ'VODUJPOBM1SPHSBNNJOH
ޒഒላӃവᏐ'VODUJPO
ޒഒላӃॄኄੋവᏐʁ
ޒഒላӃf(x) = 3x + 2
ޒഒላӃവᏐ༌ೖ值ᢛ༌ग़值೭ؒత᮫
ޒഒላӃ७വᏐ1VSF'VODUJPO
ޒഒላӃ1VSF'VODUJPO༌ग़݁Ռ᪑༌ೖ值༗᮫
ޒഒላӃ+4# 不純def one_weeks_laterTime.now + 7.daysend
ޒഒላӃ+4# 比較純def one_weeks_later(current_time)current_time + 7.daysend
ޒഒላӃ1VSF'VODUJPOෆ။㐫ଶվᏓ
ޒഒላӃᔒ༗෭࡞༻/PTJEFFGGFDU
ޒഒላӃ+4# 不純def add_bookBook.create(title: '為你⾃⼰學 Ruby')end
ޒഒላӃ+4# 不純def replace_element(arr, idx, value)arr[idx] = valuearrendlist = [1, 2, 3]result = replace_element(list, 0, "a")p result # ["a", 2, 3]p list # ???
ޒഒላӃ+4# 比較純def replace_element(arr, idx, value)dup_arr = arr.dupdup_arr[idx] = valuedup_arrendlist = [1, 2, 3]result = replace_element(list, 0, "a")p result # ["a", 2, 3]p list # ???
ޒഒላӃෆՄᏓੑ*NNVUBCJMJUZ
ޒഒላӃ+4// JavaScriptconst list = [1, 2, 3]const otherList = listconsole.log(list) // [1, 2, 3]otherList[0] = "a"console.log(list) // ???
ޒഒላӃ+4// Rustfn main() {let list = [1, 2, 3];list[0] = 100; // 預設是不能修改的println!("{:?}", list);}
ޒഒላӃ+4# Elixirlist = [1, 2, 3]list[0] = 100 # 預設是不可修改的
ޒഒላӃ'1JO3VCZ
ޒഒላӃ+4list = [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]
ޒഒላӃ3VCZฒෆࢉੋਅਖ਼త'1-BOHVBHF
ޒഒላӃവᏐੋҰެຽ'JSTU$MBTT$JUJ[FO
ޒഒላӃ3VCZॴ༗త౦ੋ݅&WFSZUIJOHJO3VCZJTBOPCKFDU
ޒഒላӃୠଖመ༗ࠣ౦ฒෆੋ݅
ޒഒላӃᩋํ๏ʮ݅Խʯ
ޒഒላӃ+4# 把⽅法物件化def add(a, b)a + bendm1 = method(:add)m2 = Proc.new { |x, y| add(x, y) }m3 = -> (x, y) { add(x, y) }puts m1.call(1, 2) # 3puts m2.call(3, 4) # 7puts m3.call(5, 6) # 11
ޒഒላӃ+4# Data.define 是 Ruby 3.2 之後才加進來的新功能Location = Data.define(:x, :y)point = Location.new(0, 0)puts point.x, point.ypoint.x = 100 # 錯誤
ޒഒላӃိᴍෳᯑత
ޒഒላӃᐬཬԽ$VSSZJOH
ޒഒላӃݪຊधཁଟݸჩᏐతവᏐҰܥྻཁݸჩᏐతവᏐతաఔ
ޒഒላӃ+4def add_numbers(a, b, c)a + b + cend# 柯⾥化curried_add = -> (x) {-> (y) {-> (z) {add_numbers(x, y, z)}}}
ޒഒላӃ+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)
ޒഒላӃ+4def add_numbers(a, b, c)a + b + cend # 柯⾥化# curried_add = -> (x) {# -> (y) {# -> (z) {# add_numbers(x, y, z)# }# }# }# Ruby 內建的⽅法curried_add = method(:add_numbers).curry
ޒഒላӃภവᏐ1BSUJBM'VODUJPOT
ޒഒላӃ෦份BQQMZݪ࢝വᏐɼઌݻఆവᏐత෦ჩᏐɼճၚडႫᰨჩᏐత৽വᏐ
ޒഒላӃ+4def add_numbers(a, b, c)a + b + cend# Partial Function# 先給 1 個參數add_2 = -> (i, j) { add_numbers(2, i, j) }# 剩下的 2 個參數之後再⼀次給⾜puts add_2.call(3, 5) # 10
ޒഒላӃ+4def add_numbers(a, b, c)a + b + cend# Partial Function# 或是先給 2 個參數add_2_and_3 = -> (k) { add_numbers(2, 3, k) }# 最後 1 個參數之後再給puts add_2_and_3.call(5) # 10
ޒഒላӃ+4def add_numbers(a, b, c)a + b + cend# 利⽤內建的 curry ⽅法partial_fn = method(:add_numbers).curry# 先給 1 個參數add_2 = partial_fn.call(2)# 剩下的參數之後再⼀次給⾜puts add_2.call(3, 5) # 10
ޒഒላӃവᏐ߹'VODUJPO$PNQPTJUJPO
ޒഒላӃઌՃɼ࠶Ճഒɼ࠷ޙ࠶ฏํʂ
ޒഒላӃ+4// JavaScriptconst add_one = (n) => n + 1const double = (n) => n * 2const square = (n) => n * nconsole.log(square(double(add_one(5)))) // 144
ޒഒላӃઢ1JQF
ޒഒላӃ+4# Elixiradd_one = fn x -> x + 1 enddouble = fn x -> x * 2 endsquare = fn x -> x * x endresult = 5 |> add_one.()|> double.()|> square.()IO.inspect result # 144
ޒഒላӃ3VCZᔒ༗Ṝኄํศత౦
ޒഒላӃ+4add_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
ޒഒላӃ+4add_one = -> (n) { n + 1 }double = -> (n) { n * 2 }square = -> (n) { n * n }# 先加 1,再加倍,最後再平⽅composed_fn = add_one >> double >> squareputs composed_fn.call(5) # 144
ޒഒላӃ