By
Jason Liu
更新日期:
主要分為兩種Evalulation first, or Evaluation when needed
Evalulation Argunment first
Call-By-Value
最common 的做法,先計算parameter 的value,然後把value copy 進function內
不會影響出面的數值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #include <iostream>
using namespace std;
void addOne(int n){ n = n + 1; }
int main(){ int x = 5; cout << "before function is called: " << x << endl; addOne(x); cout << "after function is called: " << x << endl;
return 0; }
Output: before function is called: 5 after function is called: 5
|
Call-By-Reference
把呼叫者(caller)的variable 直接在function內使用, 但叫第二個名字(Reference)
可以有side effect 出面的數值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #include <iostream>
using namespace std;
void addOne(int &n){ n = n + 1; }
int main(){ int x = 5; cout << "before function is called: " << x << endl; addOne(x); cout << "after function is called: " << x << endl;
return 0; }
Output: before function is called: 5 after function is called: 6
|
Evaluation Argunment when needed
Call-By-Name
用的時侯才把parameter evaluate
在passing as parameter是產生closure (enclosing environement) 裝著evaluation所需的variable
以下add function 中的n 是call-by-name的,
n
是array(index), 當中的index
是記憶著上面的index
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| object CallByName { var array = Array(0, 1, 2, 3) var index = 0 def add(n: => Int) : Int = { return n; } def callAdd() = { add(array(index)) } }
defined object CallByName
scala> CallByName.callAdd res2: Int = 0
|
所以如果closure 內的variable數值被外內改變
會影響evaluation的結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| object CallByName { var array = Array(0, 1, 2, 3) var index = 0 def add(n: => Int) : Int = { index = 1; return n; } def callAdd() = { add(array(index)) } }
defined object CallByName
scala> CallByName.callAdd res3: Int = 1
|
改變local variable 是沒有作用的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| object CallByName { var array = Array(0, 1, 2, 3) var index = 0 def add(n: => Int) : Int = { var index = 1; return n; } def callAdd() = { add(array(index)) } }
defined object CallByName
scala> CallByName.callAdd res2: Int = 0
|
Clousre in Javascript
利用javascript 達成類似call-by-name的效果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| function CallByName(){ var array = [0, 1, 2, 3]; var index = 0;
this.add = function(f){ index = 1; return f(); }
this.callAdd = function(){ return this.add(function(){ return array[index]; }); } }
var callByName = new CallByName(); console.log(callByName.callAdd());
|
Call-By-Need
Call-By-Name + memorized the evaluation result, evalute argunment 後把結果儲起來
就算之後改變argunment也不會影響evaluation的結果
Call-By-Text
類似Call-By-Name ,但passing as parameter時沒有closure 裝著所需的variable
到evaluation 時才找所需的variable
個人認為javascript內的eval 是類似效果?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| function CallByText(){ var array = [0, 1, 2, 3]; var index = 0;
this.add = function(n){ var index = 1; return eval(n); }
this.callAdd = function(){ return this.add('array[index]'); } }
var callByText = new CallByText(); console.log(callByText.callAdd());
|