Jul 03, 2015
以下純屬
Update to date
• JDK 7 Features updated ! Plan B
has apparently been approved
– http://www.baptiste-wicht.com/2010/09/jdk-7-features-updated-plan-b-is-apparently-here/
• 2011 Java SE 7 沒有 Closure … Orz
• 2012 Java SE 8 才有 Closure ... XD
• 2012 世界末日才有 Closure … 囧rz
議程 • lambda
• closure
• 動靜之間
• 沒有 lambda/closure 的 Java
• Java SE 7 lambda/closure 提案
/lambda/
What is
http://en.wikipedia.org/wiki/Lambda
In programming languages such as
Lisp and Python, lambda is an
operator used to denote
anonymous functions or closures
從 Java…呃!JavaScript 來認識起…
function doSome(param) {
// 作些事
}
var doSome = function(param) {
// 作些事
};
function(param) {
// 作些事
};
function(param) {
// 作些事
};
* Function literal
* Function 實例
* new Function('param', '函式本體');
* Anonymous function
既然函式是物件,那麼可以作什麼?
• 指定給別的變數
• 這跟樓下的是一樣的 …
function foo(arg) {
document.write(arg , '<br>');
}
var zzz = foo;
zzz('demo');
var foo = function(arg) {
document.write(arg , '<br>');
};
var zzz = foo;
zzz('demo');
既然可以指定給別的變數,就可以…
• 作為引數傳入函式中
• 這跟樓下的是一樣的 …
function show(element) {
document.write(element + '<br>');
}
[1, 2, 3, 4, 5].forEach(show);
var show = function(element) {
document.write(element + '<br>');
};
[1, 2, 3, 4, 5].forEach(show);
文化 與
風格
走訪陣列
var array = [1, 2, 3, 4, 5];
for(var i = 0; i < array.length; i++) {
doucment.write(array[i] + '<br>');
}
[1, 2, 3, 4, 5].forEach( function(element) {
doucment.write(element + '<br>');
} );
可作為引數傳入函式?那就可以設計 callback 函式..
• 實作 forEach
Array.prototype.forEach = function(callback) {
for(var i = 0; i < this.length; i++) {
callback(this[i]);
}
};
[1, 2, 3, 4, 5].forEach( function(element) {
doucment.write(element + '<br>');
} );
當函式是物件時
• 可以根據需要傳遞給另一個名稱參考
• 不再被動呼叫,可主動指導別的函式動作
• 流程中不同演算,設計callback函式代換
簡化的語法
不同的設計
closure?
What is
Closure
• 文言文….
–函式物件建立時,自由變數(Free variable
)綁定了當時作用範圍中的變數,使被綁定的變數之作用範圍跟隨著被建立的函式物件
• 白話文 就是….
r2
心愛的跟別人跑了…XD
網頁資源載入完成後執行一次
這是一個區域變數
function init() {
var local = 10;
setInterval(
function() {
alert(new Date() + ': ' + local);
local++;
},
3000);
}
window.onload = init;
function() {
alert(new Date() + ': ' + local);
local++;
}, 自由變數(Free variable)
• local這樣的變數對函式實字部份的宣告來說,稱為自由變數(Free variable)
• 自由變數真正的意義,必須結合函式實字以外的環境才可以得知
你說過要跟我海枯石爛啊啊啊啊…
init 函式…
r2
實際的應用呢?…
• 在 JavaScript 中模擬私用性…
function Account(money) {
var balance = money;
this.getBalance = function() {
return balance;
};
this.deposit = function(money) {
if(money > 0) {
balance += money;
}
};
}
var account = new Account(1000);
account.deposit(500);
account.balance = 1000;
var account = new Account(1000);
var account = {};
Account.call(account, 1000); function Account(money) {
var balance = money;
this.getBalance = function() {
return balance;
};
this.deposit = function(money) {
if(money > 0) {
balance += money;
}
};
}
* 函式是物件 * 物件可以擁有方法
Closure 綁定的是自由變數本身,而不是其值!
正確的說法叫腳踏兩(多)條船…XD
環環相扣
def max(m, n):
return m if m > n else n
print(max(10, 3)) # 顯示 10
maximum = max
print(maximum(10, 3)) # 顯示 10
max = lambda m, n: m if m > n else n
print(max(10, 3)) # 顯示 10
My name is Python ….
function max(m, n) {
if(m > n) {
return m;
}
return n;
}
def max(m, n):
return m if m > n else n
function(m, n) {
if(m > n) {
return m;
}
return n;
};
lambda m, n: m if m > n else n
函式定義
匿名函式
從函式傳回函式 import math
def prepare_factor(max):
# 一些建立質數表的過程,需要一些時間與資源
primes = [i for i in range(2, max) if prime[i] == 1] # 質數表
def factor(num):
# 利用質數表進行因式分解的過程
while primes[i] ** 2 <= num:
if num % primes[i] == 0:
list.append(primes[i])
num //= primes[i]
else:
i += 1
return factor # 傳回函式
factor = prepare_factor(1000)
print(factor(100)) # 顯示 [2, 2, 5, 5]
Closure
當函式是物件時
• 可以根據需要傳遞給另一個名稱參考
• 不再被動呼叫,可主動指導別的函式動作
• 流程中不同演算,設計callback函式代換
• 可以形成 Closure 綁定自由變數(資源)
• 可以從函式中傳回函式
Python 只作「半套」?。。XD
18 1
• 變數無需宣告就可以直接使用並指定值
• 除非特別使用global或nonlocal指明(Python 3),否則變數範圍(Scope)總在指定值時建立
def func():
x = 10
def getX():
return x
def setX(n):
x = n
return (getX, setX)
getX, setX = func()
getX() # 10
setX(20)
getX() # 10
def func():
x = 10
def getX():
return x
def setX(n):
nonlocal x = n
return (getX, setX)
getX, setX = func()
getX() # 10
setX(20)
getX() # 20
def max(m: Int, n: Int): Int = {
if (m > n)
m
else
n
}
val max: (Int, Int) => Int = (m: Int, n: Int) => if(m > n) m else n
函式定義
匿名函式
def max(m: Int, n: Int): Int = {
if (m > n)
m
else
n
}
val max: (Int, Int) => Int = (m: Int, n: Int) => if(m > n) m else n
函式定義
匿名函式
動態定型語言 • 型態資訊是在資料本身而不是變數
• 變數本身的型態是在執行時期運算得知,也同一變數可以參考至各種型態的資料。
function max(m, n) { if(m > n) {
return m;
}
return n;
}
def max(m, n):
return m if m > n else n
function(m, n) {
if(m > n) {
return m;
}
return n;
};
max2 = lambda m, n: m if m > n else n
靜態定型語言
• 根據資料的型態資訊,將變數及運算式進行分類,型態資訊是在宣告的變數上
• 在執行時期變數的型態資訊無法改變,資料只能被指定至同一種型態的變數
def max(m: Int, n: Int): Int = {
if (m > n)
m
else
n
}
val max: (Int, Int) => Int = (m: Int, n: Int) => if(m > n) m else n
語法上的冗長
如果要設計callback函式…
def selection(number: Array[Int], order: (Int, Int) => Boolean) {
...
val o = order(a, b)
…
}
val arr = Array(2, 5, 1, 7, 8)
selection(arr, (a: Int, b: Int) => a > b)
val arr = Array(2, 5, 1, 7, 8)
selection(arr, (a, b) => a > b)
val arr = Array(2, 5, 1, 7, 8)
selection(arr, (_: Int) > (_: Int))
val arr = Array(2, 5, 1, 7, 8)
selection(arr, _ > _)
類型推斷 type inference
終於輪到我登場了嗎?。。XD
目前 Java 沒有 lambda/closure
List<String> list = new ArrayList<String>();
list.add("Justin");
...
Collections.sort(list, new Comparator<String>() {
public int compare(String s1, String s2) {
return -s1.compareTo(s2);
}
…
});
假設 Java 有 lambda/closure
Collections.sort(list, (s1, s2) => -s1.compareTo(s2));
借一下 Scala 的語法
目前 Java 沒有 lambda/closure
• 所以無法設計 callback 函式
• 目前由 callback 物件來實現
語法上的冗長
也不僅是語法上的冗長
public void doSome() {
final int res = 10;
ISome o = new ISome() {
public void doIt() {
int result = res * 10;
….
}
}
}
編譯器強迫你要加上 final
表面上…你綁定了res
事實上...編譯器只是建立一個區域變數res
把外部res指定
給區域變數res
所以編譯器強迫你要加上 final
就像 Python 只作「半套」?。。XD
18 1
Lambdas in Java Preview
• http://stronglytypedblog.blogspot.com/2010/06/lambdas-in-java-preview-part-1-basics.html
• http://stronglytypedblog.blogspot.com/2010/07/lambdas-in-java-preview-part-2.html
• http://stronglytypedblog.blogspot.com/2010/07/lambdas-in-java-preview-part-3.html
• http://stronglytypedblog.blogspot.com/2010/07/lambdas-in-java-preview-part-4-proposal.html
• http://stronglytypedblog.blogspot.com/2010/07/lambdas-in-java-preview-part-5-apache.html
int doubler(int x) {
return 2 * x;
}
...
doubler(3);
#int(int, int) sum = #(int x, int y)(x+y);
int sum(int x, int y) {
return x + y;
}
#int(int) doubler = #(int x)(2*x);
doubler.(3)
max = lambda m, n: m if m > n else n
max(10, 3)
val max: (Int, Int) => Int = (m, n) => if(m > n) m else n
max(10, 3);
#int(int, int) max = #(int x, int y) {
if (x >= y) return x;
else return y;
};
max.(10, 3);
Python
Scala
Java
void selection(int[] array, #boolean(int, int) order) {
...
boolean o = order.(a, b);
…
}
…
selection(arr, #(int a, int b)(a > b));
def selection(number: Array[Int], order: (Int, Int) => Boolean) {
...
val o = order(a, b)
…
}
…
selection(arr, (a, b) => a > b)
Scala
Java
目前 Java 沒有 lambda/closure
List<String> list = new ArrayList<String>();
list.add("Justin");
...
Collections.sort(list, new Comparator<String>() {
public int compare(String s1, String s2) {
return -s1.compareTo(s2);
}
…
});
假設 Java 有 lambda/closure
Collections.sort(list,
#(String s1, String s2)(-s1.compareTo(s2)));
##int(int)(int) sum = #(int x)(#(int y)(x+y)); ##int(int)(int) sum = #(int x)(#(int y)(x+y));
傳回函式 #int(int)
新的提案
• http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-2.html
– No more function types
– More type inferencing
– Scala-like syntax
void selection(int[] array, #boolean(int, int) order) {
...
boolean o = order.(a, b);
…
}
…
selection(arr, #(int a, int b)(a > b));
void selection(int[] array, Order order) {
...
boolean o = order.compare(a, b);
…
}
…
selection(arr, (a, b) -> {a > b});
public interface Order {
public boolean compare(int a, int b);
}
Function type
SAM(Single Abstract Method) type
More type inferencing
Scala-like syntax
Much Better!!
val arr = Array(10, 20, 30)
var sum = 0
arr.foreach(i => sum += i)
println(sum)
int[] = {10, 20, 30};
int sum = 0;
arr.foreach(i -> { sum += i });
System.out.println(sum);
我們需要?
• Lambda/Closure
• 類型推斷
• 單一抽象方法形態(SAM types)
• 可利用現存的 API
• 更多程式設計風格