Subtitles section Play video
[Applause]
[掌聲]
Hi!
你好!
First of all,
首先
I just want to give a big shout-out to the organizers of this conference.
我只想向這次會議的主辦單位表达致意
I feel like this has been a fantastic smooth experience from start to finish,
我覺得從開始到尾, 這都是非常棒的體驗
so...
所以
[Applause]
[掌聲]
Amazing job.
真棒
Hi! I'm Anjana Vakil.
大家好!我是Anjana Vakil
I am an English teacher turned computational linguist
我是一名英語老師 後成為計算語言學家
turned software developer
然後再轉為軟件開發人員
and as I mentioned a little bit earlier today,
正如我剛才提到的
about six months ago, I knew nothing about functional programming
大約六個月前, 我對函式編程一無所知
and very little about JavaScript.
只略知小許JavaScript
So, what I want to do today is kind of
今天想做的
take you guys along on some of the things I've learned
帶你們走一遍 看看我學過的東西
about doing functional programming in JavaScript
關於使用JavaScript進行函式編程
and I am not an expert in any of this,
我不是這方面的專家
so this is going to be me taking you along on my learning journey
所以這將是我帶你們 一起走過我的學習旅程
and nothing more.
僅此而已
I'm going to try and save a little time for questions at the end,
到最後,我會盡量擠出一些時間 來回答一些問題
but we'll see how that turns out.
看看等下如何吧
So, how did I end up standing here
那 我為什麼會站在這
talking to you guys about functional programming in JavaScript?
與你們分享有關JavaScript函式編程?
About six months ago in the fall of 2015,
大約六個月前, 在2015年秋季
I went to a programming community in New York City
我去找了紐約的一個編程團體
called The Recurse Center
叫做 The Recurse Centre
which quick plug
它的快宣傳會
is probably the best programming community I've ever experienced
應該是我參加最棒的一個編程團體經驗
and it's a programming retreat
是個編程退修會
where you can go and learn about
你可以去那裡學習
whatever is interesting to you in the world of computer science
在計算機科學界對你來說有趣的事
and so I got there
所以我到了那裡
and a lot of people were talking about functional programming,
很多人在談論函式編程
functional programming, Haskell, Clojure, all this cool stuff,
函式編程,Haskell、Clojure, 所有這些很棒的東西
a lot of people were working in JavaScript getting into node
很多正在使用JavaScript的人開始進入節點
and these were some really interesting topics
這些都是一些非常有趣的話題
and so I started talking to people there
所以我開始和那裡的人聊了起來
and finding out what is all this stuff.
想知道這些東西是什麼
So, what is functional programming?
那函式編程是什麼?
Few different ways that question can be answered.
這個問題可以用幾種不同的方式回答
First of all, it's a programming paradigm.
首先,這是一個編程範例
Some other paradigms are like imperative programming
其他範例包括命令式編程
where you say do this and then do that
像是一直說 做這個 然後做那個
or object-oriented programming
或面向對象的編程
which maybe a lot of you write object-oriented JavaScript
也許你們當中很多人 編寫了面向對象的JavaScript
where you have objects and they have methods on them
你有對象, 而它們上有方式
and you change them, etc., etc.
然後你更改它們 等等
Functional programming is also a paradigm
函式編程也是一種範式
where functions are king
函式為王
and we'll talk about what that means in a little bit.
我們稍後會討論 這意味著什麼
It's also a style of coding,
這也是一種編碼風格
of organizing your code,
組織代碼
writing your code,
編寫代碼
style of approaching projects
接近項目的風格
and really more than that it's kind of a mindset you can get into,
不僅限於此, 是個可進入的一種心態
a way of thinking about a problem,
一種思考問題的方式
a way of approaching a task
一種接近任務的方式
and it's also a really sexy trend
這也是一個非常有趣的趨勢
with lots of buzzwords that'll make you super popular
有很多流行詞
when you're talking with people at the pre-conference party or whatever it is.
當會前聚會時與人交談或其他場合 會讓你超受歡迎
No, just kidding.
我開玩笑的
But it is something that's gotten a lot of attention
但這引起了很多關注
and, so yeah, I thought it was important
所以我認為這是很重要的一點
to find out why everybody was so excited about it.
去找出每個人都對此 感到如此興奮的原因
So, why do functional programming in JavaScript specifically?
為什麼要專門使用JavaScript進行函式編程呢?
Well, I don't know about for all of you,
我不知道你們是否有相似經驗
perhaps more experienced JavaScript developers,
也許對更有經驗的JavaScript開發人員
but when I started learning JavaScript
但我開始學JavaScript時
having had some object-oriented programming experience with Java, C-Sharp,
有些面向對象編程經驗在Java,C-Sharp
that kind of thing,
那些東西
I found object-oriented JavaScript super confusing,
我發現面向對象的JavaScript 非常令人困惑
prototypal inheritance, how does that work?
原型繼承, 如何運作?
How many of you guys, quick show of hands,
你們當中幾個人, 舉舉手來看
have ever run into a bug or a problem or something unexpected with this,
誰曾經遇到過錯誤, 問題或意外情況
doing something...
做某事...
Yeah, exactly. Right?
是咯,對吧?
So, I found that really tricky and confusing
我發現那確實很棘手和令人困惑
and so I thought, all right, I know I want to get more into JavaScript
所以我想,好吧, 我知道我想進一步了解JavaScript
but let me set aside the object orientation
但讓我放開對象方向
and try to think about things in a functional way
嘗試用函式去思考問題
which is maybe simpler in some ways
在某些方面可能更簡單
and avoid some of these problems
而避免其中一些問題
like bugs introduced by binding this to the wrong thing.
因為把這與錯的東西綁定 而造成了錯誤
So, functional JavaScript to me at least is a bit safer,
因此至少對我而言 函式JavaScript更安全一些
a bit less tricky,
沒那麼棘手
a bit easier to debug
比較容易調試
but easier to maintain as you're building a project
但在構建項目時 更易於維持
and we'll take a look at some of the features
我們稍後會看一些功能
that make that easier in a bit.
會變得容易
Also, there is already a huge community of developers
而且,已經有一個龐大的開發者團體
who are doing JavaScript in a functional style,
他們以函式風格編寫JavaScript
so there's a lot of libraries out there
外面很多程序庫
to help you write functional JavaScript.
幫助你編寫函式JavaScript
There's a lot of people out there that are experts in this,
有很多人是專家
for example, there was a talk in the next room over earlier today on Ramda
例如,在隔壁庭有個 關於Ramda的演講
and there are people here you can talk to
這裡也有人可以與你交談
that probably know a lot more about functional JavaScript than I do,
而他們可能會比我 更加了解函式JavaScript
but the point is there's already a community,
但關鍵是已經有一個團體
so this isn't necessarily something you'd be doing on your own,
所以這不一定需要你憑一己之力完成的事
grappling you versus JavaScript,
與JavaScript搏鬥
there's other people to support you,
還有其他人支持你
which I found really helpful.
而我發現這真的很有幫助
Okay.
好的
So, hopefully by now I've convinced you
希望到現在我已經說服了你
that functional programming is at least interesting
函式編程至少有趣
and that we could do it in JavaScript to avoid these headaches, etc.
並且我們可以使用JavaScript來編
How can we do it?
我們要怎麼做?
What does it mean?
這是什麼意思?
This is what I was asking myself.
這就是我在問自己的問題
So, the main thing
最主要的
and maybe it sounds like a tautology or obvious is that
也許聽起來像是重言式或顯而易見的是
in functional programming
在函式編程中
you want to do everything with functions,
你會想用函式來做所有事情
so we want to express everything in our program in terms of functions.
所以我們想用函式來表達 程序中的所有內容
And a function of course is just something
當然,函式只是一個
that takes an input and gives an output.
接受輸入並給出輸出的東西
So, we want to be thinking about
所以 我們要想的是
kind of the flow of data of inputs and outputs through the program,
程序輸入和輸出的數據流的種類
instead of thinking about objects and how they interact
而不是考慮對象及其相互作用
and how they manipulate
以及它們如何操縱
or thinking about steps in a recipe like in an imperative style.
或想食譜上的步驟 比較命令式的步驟
Here we're really thinking about how we can express everything
在這,我們在考慮如何表達這一切
in terms of functions,
以函式來說
taking inputs, giving outputs.
接受輸入,提供輸出
So, for example,
舉例說
this would be a non-functional way for me to get the text
這將是一種非函式性的方式取得文字
“Hi, I'm Anjana” to appear on the screen.
屏幕上出現 “嗨,我是Anjana”
I could assign a variable, I call it “name”
我可以分配一個變量 我稱之為“名稱”
and have it store the text “Anjana.”
並存儲文字 “Anjana”
I could have a greeting like “Hi, I'm” or “Hello, I'm”, whatever,
我可以有個招呼, 例如 “嗨,我是” 或 “你好,我是”,什麼的
and then I could log that to the console.
然後將其記錄到控制台
This is sort of an imperative style.
這是一種命令式風格
First do this, then do that, then do this other thing,
先做這,後做那,再後做這其他的
we don't have functions here,
這裡沒有函式
we're not expressing this in terms of how inputs are transformed into outputs.
我們不是在以 如何輸入會轉換為輸出 來表達這一點
So, maybe a more functional way of doing the same thing
也許是一種更實用的方法來做同樣的事情
and this is a really simple example, just for the sake of it,
這是一個非常簡單的例子
is to define a function called greet
是定義一個叫做greet的函式
which takes a parameter name
帶有參數名稱
and returns a string which adds “Hi, I'm”
並返回一個字串, 其中添加 “嗨,我是”
to the beginning of that name.
到該名稱的開頭
So, for example, if I type greet,
舉例來說, 如果我輸入greet
the string Anjana,
字串Anjana
feeding that as input
作為輸入
then I get the output “Hi, I'm Anjana”,
然後我得到輸出 “嗨,我是Anjana”
that's a more functional way expressing this in terms of functions.
這是一種從函式上 表達此函式的方法
Okay. So, another...
好,所以...
maybe the main thing about functional programming
也許關於函式編程的主要問題
is to avoid side effects
就是避免副作用
and instead to use pure functions.
而是使用純函式
So, what does that mean?
那是什麼意思呢?
A side effect is anything that a function might do
副作用是函式可能會做的任何事情
that isn't computing its output from the inputs you've given
沒有在用你的輸入 來計算它的輸出
and returning that output.
以及返回該輸出
So, for example,
例如
printing something to the console is not returning an output,
在控制台上打印一些內容 不是返回輸出
it's doing something else,
它在做其他事情
something that's on the side of the function
函式副面的東西
or if you have a function that uses some globally defined variable
或者如果你的函式使用一些全局定義的變量
to compute its output
來計算其輸出
that doesn't depend only on the input to that function,
這不僅僅取決於該函式的輸入
so that's not pure.
所以那不是純的
It's taking something from outside the function
它從函式外部獲取了一些東西
and involving it in some way in what the function does.
並以某種方式將其 包含在函式的功能中
So, this is just a really quick explanation of what a pure function
那只是對什麼是純函式的快速解釋
that avoids side-effects would do.
可以避免副作用就好
For more information on that
有關更多信息
there's excellent Wikipedia articles on these sorts of things,
Wikipedia上有很多關於這類事情的文章
but basically the idea is that
但基本上
you want your function to do nothing
你想要你的函式什麼都不做
except take its input, use that and only that
除了接受輸入, 僅使用那個輸入來
to compute an output
計算輸出
and then return it.
然後返回
That's pure.
那才是純的
So, for example, this function here,
例如,此函式
we have this globally defined variable name
我們有這個全局定義的變量名
which gets used in the function
會在函式中使用
as you can see in the last line there,
你在這 最後一行所看到的
it gets used, so there's no input,
它被使用了,所以沒有輸入
we don't have name as an argument to this function,
我們沒有名稱作為此函式的參數
it's just reading something in from the global state.
它只是從全局狀態中 讀取一些信息
That's not pure.
那不是純的
Also, not pure because
它不純的原因是因為
the return value of this function here isn't what we care about,
而這個函式的返回值不是我們所在乎的
we care about doing something,
我們在乎做某事
changing the world in some way
以某種方式改變世界
other than the return value,
除了返回值
in this case, printing to the console.
在這種情況下, 打印至控制台
So, this is a not pure function here.
這不是一個純函式
A pure function might look like this.
一個純函式可能會長這樣
Here we have,
在這裡
the only thing that matters
對此輸出唯一重要的
to the output of this function is its input,
是它的輸入
the argument that we pass to it
我們傳遞給它的論點
and the only thing that it does is return its output.
它唯一要做的就是返回其輸出
Okay, so I've been talking for a while now about pure functions
我好像說了很多純函式
that's because this is really like a key thing at least for me,
因為至少對我而言, 這確實是一件關鍵的事情
something I've taken as one of the key parts of functional programming
一件我當成函式編程的關鍵部分
is thinking about things as purely as possible.
就是以最純粹的方式去思考問題
Another key point would be using higher-order functions.
另一個關鍵點是 使用高階函式
So, this means functions that can take as inputs other functions
因此,這在指一些可以 納其他函數為輸入的函式
or a function that can return a function as its output.
一個可以返回函式為輸出的函數
So, basically, we're treating functions kind of as objects themselves.
基本上就是將函式本身視為對象
They can be passed to other functions.
它們可以傳遞給其他函式
You can have layers of functions within functions within functions, etc.,
你可以在函式中有層層的函式
and these are what's called higher-order functions,
這就是所謂的高階函式
they come up a lot in functional programming.
在函式編程中經常出現
This is a bit of a random example,
這是一個隨機的例子
but let's say we have this function at the top here,
假設我們在這有此函式
makeAdjectifier
makeAdjectifier
where we give it an adjective
我們給它一個形容詞
and it returns actually a function.
它實際上給回一個函式
It doesn't return a string or a number or anything like that,
它不會給回字串,數字或類似的東西
it returns us a function
它給回我們一個函式
which adds that adjective to a string that you give it.
這會將形容詞添加到 你提供的字串中
So, for example, I can use the makeAdjectifier function
例如,我可以使用makeAdjectifier函式
feed it the input “cool”
輸入 “cool”
and get a function that's called coolifier.
並獲得一個稱為coolifier的函式
So, now when I pass a string to coolifier,
當我將字串傳遞給coolifier時
I get “cool” added to that string.
該字串中就會添加 “cool” 字
So, if I pass conference, I get cool conference.
如果我寫 "會議" conference), 我會得到"很棒的會議" (cool conference )
So, the idea here is that we have a higher-order function
概念就是我們有一個高階函式
which returns a function.
給回一個函式
And this kind of wrapping your head around this
大概消化一下這個概念
at least for me
至少對於我來說
is one of the key things to being able to write in a functional style
是能夠以函式風格進行寫碼的關鍵之一
because as we'll see a bit later,
因為我們之後會看到
we need these higher-order functions
我們需要這些高階函式
in order to avoid some of the tricks
為了避免一些花招
that we're used to using from other paradigms.
我們習慣於從其他範例中使用
So, learning the thing to get into that functional mindset
想融入函式性思維要學習的
for me really involved wrapping my head around this concept.
對我而言就是 儘快熟悉這個概念
Okay.
好
So, one of these things that we're going to avoid
我們要避免的其中一個東西是
that we're used to doing is iterating,
我們習慣做的是迭代
using like “for” or “while”, these sort of things.
使用像 “for” 或 “while” 之類的東西
We're used to going over lists and doing things to all the items in it.
我們習慣於遍歷列表 並對其中的所有項目執行操作
Instead, in a functional style,
以函式風格
we might use higher-order functions like Map or Reduce or Filter
我們可能會使用高階函式, 例如地圖 (Map) 或減少 (Reduce) 或過濾 (Filter)
which often take as an input
通常作為輸入
not only the list that you want to do something to in some way
不僅是某種方式做某事的列表
but also a function that then you're going to apply to it.
但也是要應用的函式
In the interest of time I'm not going to go into too much detail
為了時間的關係, 我不仔細贅述
about what Map, Reduce, and Filter do,
Map,Reduce和Filter的功能
but I found and also thanks to my colleague Khalid up there,
但因為我的同事Khalid, 我找到了
a really cool graphic that I think expresses Map and Reduce pretty well,
一個很酷的圖, 適當的解釋Map和Reduce
maybe you guys have seen it before,
也許你們以前看過
the MapReduce Sandwich, everyone!
大家,MapReduce 三明治!
So, the idea here is that let's say you have a list,
這裡的想法是, 假設你有一個列表
in this case, a bunch of vegetables.
在這種情況下,一堆蔬菜
They're whole vegetables.
未切過的,整體的蔬菜
We got some bread in there too
這裡也有麵包
and we want to transform that data in some way.
我們想以某種方式轉換數據
So, for example, let's say we want to slice that data
舉例來說, 我們想對數據進行切片
and we have a function 'slice up' or 'cut up' or 'chop'
我們有一個 “切片” 或 “切” 或 “剁” 函式
which we can apply to each item in that list.
將其應用於該列表中的每個項目
Now, usually I would do “for vegetable in sandwich ingredients,”
通常我會用 “用於三明治中的蔬菜”
do all of this,
完成這些
do all this chopping,
這些剁碎啊
but in a functional style we'd use Map,
但我們會以函式性風格使用Map
give it the list of ingredients and give it the function 'chop'
給它材料列表後 給 “剁” 這個函式
and I would get out a new list where everything has been chopped.
而我就會得到一個新的列表 所有材料已經被剁碎了
Then we have a Reduce function
然後我們有一個減少 (Reduce) 函式
which basically combines all of the items in a list in a certain way,
基本上將列表中的所有項目組合在一起
in this case, layering
在這種情況下,分層
to make a delicious sandwich,
來配成一個美味的三明治
and Filter let's say
以及Filter吧
could be if you hate cucumbers,
可能你討厭黃瓜
you could have a Filter function
你可以有一個過濾 (Filter) 函式
which makes sure that
確保
only things that are not cucumbers get through the filter.
只有非黃瓜的蔬菜才能通過過濾器
So, these are the ways we use these higher-order functions
這是我們使用的方式 這些高階函式
to get around the type of “for” or “while” iteration
來熟悉 “for” 或 “while” 這類型的迭代
that we're used to doing in functional programming,
在函式編程中習慣做的
instead we're going to feed functions to higher-order functions
我們將函式提供給高階函數
like Map, Reduce, and Filter
如Map,Reduce和Filter
to get the sandwich that we want.
得到我們想要的三明治
And again, this is not intended to be a totally clear explanation
重申,這並不是一個完全清楚方式
of how Map, Reduce, and Filter work,
來解釋 Map,Reduce 和 Filter 的操作
but there's plenty of information on that online.
但網上很多關於這的資料
The idea is that we want to use these instead of “for.”
我們要使用這些而不是 “for”
So, another thing that we want to do is
我們要做的另一件事是
we want to avoid mutating data, |avoid mutability.
我們要避免變異數據, 避免變異
Mutation in the sense I just mean changing objects in place.
變異指在某個放置更改對象
So, when we have something that's immutable,
當我們有個不可變的東西時
I'm sure a lot of you guys are familiar with the term,
我相信很多人都熟悉這個詞
it's something data that can't be changed in place.
這是數據放置無法更改的
Once we've set it it's there forever.
一旦設置好, 它將永遠存在
It's never going to change.
它永遠不會改變
So, let's take a look at an example.
我們來看個例子
Just because for me
因為對我來說
this was another thing that required a little head wrapping.
這是另一件需要 稍微更努力理解的事
So, this would be an example of mutation which is non-functional.
這是非函式突變的一個例子
We have a rooms variable which stores a list,
我們有一個房間的變量 來存儲列表
so “H1,” “H2,” and “H3,”
“H1”、“H2” 和 “H3”
because that's what we thought the rooms were,
因為我們認為房間是那樣
at least that's what I thought the relevant rooms were,
至少那是我以為 相關的房間所在
and then we say no no no actually it's not “H3,” it's “H4”.
後來發覺不是的 實際上不是 “H3” 而是 “H4”
So, let's replace the thing at index [2] in rooms with “H4.”
所以讓我們將房間中索引[2]處 的內容替換為 “H4”
And so, then we have rooms has actually changed,
因此,我們的房間實際上已經改變
we went from [“H1,” “H2,” “H3”]
我們從 [“H1”、“H2”、“H3”]
to [“H1,” “H2,” “H4”].
換成了 [“H1”、“H2”、“H4”]
So, that is still stored in the variable rooms
它仍然存儲在變量 “房間” 中
but we've actually changed something in place
但實際上我們已經改變了一些放置
and this is something that functional programming avoids
而这是函式编程避免的
because this can cause a lot of problems
因為這可以引起很多問題
and this is part of the reason why we get into trouble with this
這也是為何我們特別注意 這一點的原因之一
and with these sort of object-oriented approaches,
並通過這類面向對象的方法
sometimes you can change things in a way that you didn't intend,
有時候你可以 以意想不到的方式改變事物
so that what you thought you were dealing with
你以為你在處理的
if I thought that rooms meant [“H1,” “H2,” “H3”]
如果我以為房間意味著 ["H1", "H2", "H3"]
and I didn't know that somewhere else in my code
而我不知道我代碼中的其他地方
I had replaced something in the rooms array
我已更換了房間數組中的某個東西
I could run into trouble.
我可能會遇到麻煩
I could end up introducing bugs into my code
我最終可能會在代碼中引入錯誤
and having a really hard time tracking them down
並且很難追踪它們
because rooms here is the right thing,
因為這裡的房間是對的
rooms there is the wrong thing,
那裡的房間是錯的
ah! what happened? Where did this go wrong?
啊!發生了什麼事? 到底哪裡出錯了?
Oh! my God!
我的天啊!
You end up crying in front of your computer.
然後在電腦面前哭
No, just me.
不是啦,那只是我
So, a better way to go about things
所以更好的方法
is to think of all data as immutable, never changing.
就是將所有數據視為不變的, 永不改變
For example,
例如
with no mutation we still have our rooms which has the wrong
即使沒有變化, 我們仍然有錯誤的房間
[“H1,” “H2,” “H3”]
[“H1”、“H2”、“H3”]
but instead of changing it in place
但與其改變它的位置
I'm going to make a new rooms array
我要整理出一個新房間數組
using this map function
使用此Map函式
that we talked about a little bit earlier
就是我們剛才有提到的
where I'm mapping,
我要映射的地方
I'm feeding a function into this map,
我正在向地圖中添加函式
which looks at each room in the list
它會查看列表中的每個房間
and if it's “H3”,
那如果是 “H3”
oops! I have a missing = sign there,
唉!我少了個 = 符號
last-minute slides,
臨時做的幻燈片就這樣...
if the room is “H3” it returns “H4” instead of “H3”,
如果房間為 “H3”, 則返回 “H4” 而不是 “H3”
otherwise it returns whatever the room was.
否則返回的是房間原型
Okay. Understanding this specific example is not crucial
好,了解此示例並不重要
but the point is that once I've assigned this new rooms variable,
但是關鍵是, 一旦我分配了這個新的房間變量
new rooms has the correct values I expect “H1,” “H2,” and “H4”.
新房間有正確值 應該是 “H1”、“H2” 和 “H4”
But rooms is the same as it always was,
但是房間和以前一樣
it hasn't changed at all.
根本沒有改變
So, this is thinking about rooms as being immutable,
這在視房間為不變的
we're not changing it
我們不會改變它
and that's something that's really important for functional programming
這對於函式編程非常重要
because as I said,
正如我所說
it helps you avoid a lot of headaches, a lot of bugs.
它可以幫你避免很多麻煩 很多錯誤
So, how much time do I have?
我還有多少時間?
Okay. Good.
好
We have a little time to talk about persistent data structures, yey!
我們有些時間聊持久化數據結構
The problem with immutability is that
不變性的問題在於
when you're treating arrays and things like that as immutable,
當你把數組和像此的事物視為不變
what you end up doing is making new copies of everything.
你最終會做的是 製作所有內容
So, if I want to change my one room in this list
如果我想在此列表中更改一個房間
I have to make a whole new array
我必須做一個全新的數組
and when you're dealing with short little things like this
當你處理像這樣的矮小事情時
maybe that's not a big deal,
也許那沒什麼大不了的
but as your objects get bigger, more complex,
但是隨著物體變大, 越來越複雜,
this can give you efficiency problems
這會帶來效率問題
because if you have to copy over everything,
因為如果你要複製所有內容
even the things that didn't change,
甚至沒有改變的事情
every time you make one little adjustment
每次你進行一個小調整
and you want to make a new copy,
你想要有個新副本
a slightly different copy of your array,
數組的副本略有不同
it takes you a lot of time,
會費你很多時間
you have to go through everything in the list to copy it over,
必須仔細閱讀列表中的所有內容 才能將其複制
you end up using a lot of space
最終會佔用很多空間
that maybe once the objects start getting bigger and bigger
也許一旦物體開始變得越來越大
becomes a problem.
就成了問題
And so, one thing that's very popular in the functional world
在函式世界中非常流行的一件事
as a way of getting around these efficiency issues
解決這些效率問題的一種方法
is to use persistent data structures.
就是使用持久化數據結構
This was something introduced sort of theoretically by Phil Bagwell,
這是Phil Bagwell從理論上介紹的
he wrote a paper called Ideal Hash Trees.
他寫了一篇名為《理想哈希樹》的論文
I can put a link in the slide to that later
之後我可以在幻燈片中放一個鏈接
and then Rich Hickey who invented the language Clojure
發明語言Clojure的Rich Hickey
implemented the data structures using Bagwell's ideas
使用Bagwell的想法 實現了數據結構
to make Clojure really efficient for these immutable data structures
使Clojure對於這些不變的數據結構更加有效
and for these functional operations.
以及這些函式操作
Okay.
好
So, the way persistent data structures work if I may,
持久化數據結構操作方式
if you will indulge me,
若你們縱容我
I'm going to step back to the chalkboard right here.
我就要用這黑板
We're getting retro. Yeah, it's happening.
我們走復古型了 是的,這正在發生
Okay.
好
So, if we have like an array where we had H1, H2, H3,
如果我們有一個數組, 其中有H1,H2,H3
typically what I do in a mutable world is just get rid of this
通常我會在一個可變的世界裡 所做的就是擺脫這個
and replace it with H4,
並用H4代替
but as we said we want to avoid that.
但是正如我們所說, 我們希望避免這種情況
So, instead, if I copy it over into a new array,
如果我將其複製到新數組中
I copy H1,
我複制H1
I copy H2
複制H2
and I replace, instead of copying H3 I put in H4.
然後我替換, 不是複制H3,而是放入H4
Great!
很棒!
But now I have to store two arrays,
但是現在我必須存儲兩個數組
taking up a lot of time,
費了很多時間
look how long that took me to do all of that.
看看我花了多長時間來完成所有這些
Terrible. Right?
很糟吧?
I know you guys feel as upset about this as I do.
我知道你們和我一樣對此感到很不滿
I can see it in your faces.
你們的表情告訴了我
What if instead we represented this array right here as a tree,
相反的,如果我們把這個數組 表示為樹
such that each leaf node of the tree
這樹的每個葉子節點
is one of the things that I'm trying to store
是我想存的東西之一
or perhaps 2 of the things or 3 or 32 or some number of the things
或許是兩個或三個 甚至32個東西之一
and if I want to change something,
如果我想改變一些東西
I don't need to replace the entire array,
我不需要把整個數組替換掉
I can just make a new node over here, like H4,
我只需要新建一個節點,像這H4
and now I can make a new tree
我就可以做一棵新樹
which instead of repeating H1 and H2
與其重複H1和H2
I can reuse those same things and just make a new node
我可以使用同樣的東西, 只建新節點
which connects them to my new element over here,
將它們連接到這個新元素
so that now I have here a data structure which contains H1, H2 and H4
所以現在我有個數據結構 裡面包含了H1,H2 和 H4
but I didn't need to make a whole new thing.
但就是不需要重新建過
I just needed to make my one little part.
我只需要改一小部分
I can reuse the old structure of the list.
及重用列表的舊結構
So, this idea, this sort of topic is called structural sharing
這種概念或主題, 稱為結構共享
because we can share parts of the old versions with the new versions,
因為我們可以與新舊版本 共享某些部分
so we have much more efficient operations for adding,
使我們有更高效率地進行添加
changing things or moving things from vectors, for example, or arrays
從矢量或數組 更改或移動事物
and this can also be done for maps, for hash maps that sort of thing
這也可以用於地圖,哈希地圖之類的事情
and it basically makes the world of functional programming bust wide open
基本上使函式編程世界展開
so that we don't have to go through these long time
所以我們不需浪費時間
and expensive space operations
和昂貴的空間運作
to update our immutable data all the time.
去一直更新我們的不變數據
So, to do this in JavaScript,
所以,要在JavaScript中做到這一點
there are a couple of libraries that are really popular.
有幾個非常受歡迎的程序庫
One which I like to use is called Mori
我特比喜歡Mori
which I'll show you the link for in a little bit
一會兒把鏈結給你們看
which actually uses ClojureScript
它其實使用ClojureScript
which has these type of data structures natively,
本身俱有這類數據結構
it ports them over to JavaScript,
後將它們移植到JavaScript
so you can use them right from JavaScript
直接從JavaScript使用它們
and it's great.
這很棒
It has a lot of also like general functional programming helpers
它也有很多通用 函式編程的助手
like Map and Reduce and lots of other things.
例如Map和Reduce 以及許多其他東西
There's also another popular library called Immutable.js
還有一個出名的庫叫做Immutable.js
which Facebook put out
是Facebook推出的
which is JavaScript through and through.
就是完完全全的JavaScript
I haven't worked as much with that
本身沒什麼經驗
but I know a lot of people like that as well.
但我知道很多人也喜歡它
And yeah, so these are ways
是的,所以這些是
you can try out using these immutable data structures
你可以嘗試使用的 不變的數據結構
if that is something you feel like you can't wait to do now.
如果你覺得迫不及待了
I know.
我理解
I can just feel the excitement. Yeah, that's great.
我能感覺到你們的興奮 是的,太好了
Okay. Moving on.
好,我們繼續
If you're ready to try it out,
如果你準備好嘗試
like I said, we have Mori and Immutable.js,
如我所說, 我們有Mori和Immutable.js
links there to those libraries.
那些庫的鏈結
There's also a lot of utility libraries
還有很多實用程序庫
which don't focus so much on this persistent data structure thing,
不會太注重此持久化數據結構
but instead give you a lot of helper functions like Map, Reduce, etc.
反而給你很多幫助函式 例如Map,Reduce等
So, Underscore, Lodash, for example.
例如Underscore,Lodash
Today I found out that Ramda is a thing
今天我發現Ramda是一回事
because there was a talk on it the other day
因為前幾日有個關於Ramda的演講
and there are many more.
還有更多
And in fact, JavaScript has some built-in functions,
實際上,JavaScript 具有一些內置函式
like for example, arrays have a built in Map, Reduce functions.
例如,數組具有 內置的Map,Reduce函式
So, a few slides ago we saw this rooms.map,
幾張幻燈片之前, 我們看到了這 room.map
that's because the array prototype has these functions Map, Reduce, etc.
這是因為數組原型具有 這些函式Map,Reduce等
So, you can even do some functional programming in pure vanilla JavaScript
你甚至可以使用純JavaScript 進行一些函式編程
without using any of these libraries.
無需使用任何程序庫
Okay.
好
So, if you are sitting there thinking,
如果你坐在那 想著
What? Huh? I didn't really get that something about immutability,
什麼? 我並沒了解不變性
side effects, pure functions. What now, huh?
副作用,純函式 現在呢?
If you want to learn a bit more about all these buzzwords,
如果你想進一步了解 所有的這些流行詞
like I said, all these sexy buzzwords
就像我說的, 所有這些吸引的流行詞
that I've been throwing at you for the last 20 minutes,
也是我過去二十分鐘一直向你扔的詞
I highly recommend a nice gentle introductory article called
我極力推薦一篇不錯的介紹文章 名為
“An introduction to functional programming”
“函式編程簡介”
by Mary Rose Cook
以 瑪麗·羅斯·庫克(Mary Rose Cook)所寫
who is a former facilitator at The Recurse Center
之前在The Recurse Center的一位促進者
that I keep talking about.
就是我一直在提的
The link is up there,
鏈接在那
but basically this is a really nice introduction
但基本上 這是一個非常好的介紹
that kind of goes into a little bit more depth
又有一些些深度
in some of the “commandments” of functional programming
對於函式編程的一些 “戒律”
that I've mentioned today.
我今天也提到的
So, if you are a little intrigued
如果你有點好奇
but not quite clear on this stuff that I've been mentioning,
但在我有提到的東西上並不清楚的
I highly recommend you check it out.
我強烈建議你看看
So, I think that's it for my talk.
我猜我演講就到這吧
We have a couple of minutes for questions, I suppose,
我們應該還有幾分鐘來回答問題吧
eight minutes by my account,
大概八分鐘吧
but first of all I just wanted to say thank you guys very much.
但首先我真的很想對你們致謝
I'm Anjana Vakil.
我是 Anjana Vakil
Anjana Vakil on Twitter
Twitter上也是Anjana Vakil
and has link there to my GitHub.
在那有我GitHub的鏈結
So, would love to keep in touch
很想保持聯繫
if anybody else is out there also learning
如果有人也在學習
functional JavaScript as a newbie like myself,
函式性JavaScript, 如我這樣的新手
definitely reach out,
歡迎與我聯繫哦
we could stick together,
可以互相支持
but first of all I want to give a huge thanks
我想特別致謝於
to again the JSUnconf organizers,
JSUnconf 主辦單位
especially the diversity sponsors.
尤其是這些多元性贊助家
I'm here on a diversity ticket myself
我也是被贊助而來的
and wouldn't have been able to come without that awesome program
沒有那麼棒的議程也應該來不了
and all of you and the sponsors who sponsored those tickets
還有所有贊助商, 贊助了這些票
and also a huge huge thank you to The Recurse Center
特別特別感謝 The Recurse Center
and some of the alumni there who have helped me learn all this stuff
以及幫助我學到那麼多東西的校友
including Khalid at the back there
包括後面那位,Khalid
and Sal Becker, another alum,
還有另一位校友Sal Becker
who explained a lot of this stuff to me
向我解釋了很多有關這的東西
over several long caffeine-fueled conversations at The Recurse Center
在The Recurse Center 經過很多談話
and if any of you are interested in spending time
如果你們有興趣花時間
on self-directed educational programming retreat in New York City
在紐約自導教育性編程修會
definitely check out recurse.com,
一定要去看看recurse.com
it's an amazing community.
是一個了不起的團體
Okay, that's it for me. Thanks.
好吧,就這樣了 謝謝
[Applause]
[掌聲]
Thank you very much.
非常感謝你們
Yes, _____
是的,_____
Does anybody have any questions about functional programming?
有沒有人對函式編程有任何疑問?
Don't know if I'll be able to answer them but I can try.
不曉得我是否能夠回答, 但我可以嘗試
Yeah.
是
Actually, always the professors at my faculty
其實,我系的教授們
always said that object-oriented programming
總是說面向對象編程
is better than functional programming
比函式編程好
and I was thinking that is it better
我在想那會更好
or is it you think that we should use
還是你認為我們應該使用
functional programming only on JavaScript
僅在JavaScript上進行函式編程
or also on other programming languages like C _____
或其他編程語言 例如C _____
So, I think that's a great question
我認為這是一個很好的問題
and it kind of gets into a little bit of the,
有點進入了
what I think of as kind of the philosophy of programming paradigms.
我認為這是一種編程範例哲學
So, as I was learning about functional programming
當我在學函式編程
I started even wondering what is a programming paradigm
我甚至開始懷疑 什麼是編程範例
and why do people fight about them,
人們為何要為它們爭論
why do people say object orientation sucks,
為什麼人們都說面向對像很爛
we have to do everything functional
我們必須以函式來做
and why do people say no, functional programming sucks,
為什麼人們都 嫌棄函式編程
we need object orientation.
我們需要面向對象
And the conclusion that I came to is that
我得到的結論是
no one paradigm is better or worse than other paradigms.
沒有一個範例比其他 範例更好或更糟
They just have different advantages and disadvantages
它們只是有不同的優點和缺點
and they have different situations
和不同的情況
in which they're going to be kind of the best tool
它們將成為最佳工具
for that particular problem.
來解決那個問題
So, for example, if you just want to really quickly write up a script
例如,如果你想快速地編寫腳本
that just does something on your computer once really fast,
就在你電腦上很快地做過一次
you're probably just going to do it in an imperative style,
你可能會以命令式的方式進行操作
do this, then do that, then do the other thing.
做這個,然後做那個, 然後做另一件事
If you don't need to maintain it,
如果你不需要維護它
if you just need it to happen right there,
只需要它在那發生
imperative programming is a totally legit paradigm for that.
命令式編程是完全合理的範例
If you're trying to model real world objects
如果你要建模真實物體
and how they interact
以及它們如何互動
and how they go around and things you can do,
它們怎麼運作和你能辦到的
like if you're trying to model, I don't know,
像是要建模, 我不曉得...
books in a library
圖書館的書
or classes with teachers and students
或與老師和學生一起上課
and how they all interrelate that sort of thing,
以及它們如何相互關聯
maybe thinking about it in an object-oriented way makes most sense
也許以面向對象的方式 考慮它是最合理的
because that's exactly the problem you're trying to solve,
因為那就是你想解決的問題
is modeling objects
正在建模對象
and that's why that paradigm came about.
就是這種範例的來歷
But if you're trying to avoid some of those problems
但如果你想避免其中一些問題
that I was talking about
那就是我說的
when you have maybe a situation
當你可能有些情況
that doesn't actually refer to real-world objects,
並不涉及現實物體的情況
where you're using objects just because you have to
就是因為需要才用物體的那些情況
and that's introducing all kinds of side effects and weird bugs
而這會帶來各種副作用和怪異的錯誤
that are hard to track down,
也很難追踪的
maybe you want to consider thinking about it
那可能你要再考慮
in terms of functions on your data
在數據上的函式
and things being pipelined through multiple functions
通過多種函式 傳遞東西
and undergoing various transformations,
並經歷了各種轉變
not in the sense that the data is being mutated
並不是說數據正在突變
but in the sense that we're getting new outputs
然而是根據舊的輸入
based on old inputs,
我們正在獲得新的輸出
then functional programming is probably the way to go
那麼函式編程可能就是辦法
and it has a lot of advantages such as being nicely,
而且它有很多優點, 例如
you can break things down into small functions that only do one thing.
你可以將事情分解 為只做一件事的小函式
So, if you want to change something
如果你想更改某些東西
you don't have to change an entire class structure,
你不必更改整個類的結構
you can just change the one little function
只需更改一個小函式
that does the thing you want to change.
那功能就是負責做你想改的東西
So, I think it has advantages, it has disadvantages.
我想這定有它的好壞處
I definitely wouldn't say it's better than object orientation in all cases
也不會說在所有情況下 它比面向對象更好
and I definitely wouldn't say object orientation is better in all cases either,
但我也不會說在所有情況下 面向對象是更好
it really depends on your situation.
這真的取決於你的情況
Also, very good introduction of programming philosophy.
也是很好地介紹了編程原理
I used to be a philosophy major, so that might be why.
我曾經是哲學專業的, 可能是這個原因吧
Any other questions?
還有其他問題嗎?
You mentioned Map function
你提到了地圖函式
and the Map function is not working,
並且Map函式無法正常工作
so do you mix it...
那你會混合嗎...
Before that, I come from object-oriented programming style
之前,我比較熟悉面向對象的編程風格
and not so much into functional.
而不是過多地投入函式
That's cool too.
那也挺酷的
The professors really just test our functions
教授只是測試我們的函式
and can avoid the concurrency
也可以避免並發
that the Map function could possibly introduce.
Map函式可能會引入的功能
Non-blocking and concurrency and promises
非阻塞,並發和承諾
are all things that I do not feel qualified to talk about right here.
都是我覺得我沒資格在這裡談論的
I would love to turn that question over to the audience though.
我想把這個問題交給聽眾
Anybody want to respond?
有人要回應嗎?
_____
_____
Fight fight fight.
打架,打架,打架
Just kidding.
開玩笑啦
Just kidding, just kidding.
開玩笑,我只是在開玩笑
That would be against the code of conduct, you guys.
會違反規矩噢
_____
_____
I would also guess that perhaps it's blocking
我猜想 它可能蠻妨礙這裡的談話話題
but we can discuss this later in a small room or outside.
但我們稍後可以在 外面或找個小房間討論
[Laughter]
[笑聲]
Thank you for the conversation starter question though.
謝謝你的開話問題
Excellent question
那是個好問題
and I would love to know the answer.
我也很想知道答案
Look forward to talking you guys more.
期待與你們有更多交流
I guess...
我猜...
I guess we are done with the talks, the big talks now.
我想我們今天的演講就到此了
Thank you.
謝謝大家
Thank you. - Again.
再次,謝謝
[Applause]
[掌聲]