文章目錄
  1. 1. Evalulation Argunment first
    1. 1.1. Call-By-Value
    2. 1.2. Call-By-Reference
  2. 2. Evaluation Argunment when needed
    1. 2.1. Call-By-Name
      1. 2.1.1. Clousre in Javascript
    2. 2.2. Call-By-Need
    3. 2.3. Call-By-Text

主要分為兩種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 // 這是closure 內的variable

def add(n: => Int) : Int = {
return n;
}

def callAdd() = {
add(array(index)) // 我連著上面的 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; // 改變了closure 內的variable 數值
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; // 這不是closure內的variable
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()); // 1

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());

文章評論

文章目錄
  1. 1. Evalulation Argunment first
    1. 1.1. Call-By-Value
    2. 1.2. Call-By-Reference
  2. 2. Evaluation Argunment when needed
    1. 2.1. Call-By-Name
      1. 2.1.1. Clousre in Javascript
    2. 2.2. Call-By-Need
    3. 2.3. Call-By-Text