Generic Java Functor 發佈首個版本

〇,簡介

Gavator(Generic Java Functor)試圖探索以普通Java語法進行函數式編程的可行性,並儘可能的保證使用的方便性,良好的可讀性和基本的類型安全性

一,功能

所有功能都是類型安全的,無需涉及強制轉型

  • 提供了若干算法:transform/map, select/filter, accumulate/reduce, foreach/enumerate, findfirst等

  • 提供了若干適配器:bind,bind1st, bind2nd等

  • 提供了常用控制結構的函數形式和functor形式:dowhile/whiledo, dountil/untildo, ifelse等

  • 提供了常用邏輯運算結構的函數形式和functor形式:and,or,not等

  • 提供了常用數據結構:filter,pipe等

二,結構

Gavator的結構是層次化的

  • 最核心的是一組接口:分別定義了Procedure,Predicate,Function的零元,一元,二元形式

  • 基於這些接口,以functor的形式提供了常用概念的實現,包括數據結構,控制結構,適配器等,如Filter/Pipe,Bind,And/Or/Not,WhileDo/IfElse等

  • 基於這些結構和適配器,以function的形式實現了使用方便和可讀性好的包裝,如pipe,bind,and/or/not, ifelse等

三,用法

附帶的測試用例可用來簡單說明一下用法;其實所有functor和algorithm都很直觀,看到名稱和參數,即能領會它的用法;並且代碼量非常少,半個小時就能將所有代碼瀏覽一遍

曾經聽說ThoughtWorks的敏捷項目中平均每個函數代碼控制在三行以下,Gavator中每個函數平均只有不到兩行代碼

package gavator.test; 

import static gavator.algorithm.Algorithms.*;

import gavator.datastructure.*;

import junit.framework.*;

 

class ToUpperFilter implements Filter<String> {

     public String eval(String obj) {

         return obj.toUpperCase();

     }

class ToLowerFilter implements Filter<String> {

     public String eval(String obj) {

         return obj.toLowerCase();

     }

class DirtyWordsFilter implements Filter<String> {

     public String eval(String obj) {

         return obj.replace("dirty words", "***");

     }

}

 

public class FilterPipeTest extends TestCase {

 

     private Pipe lowerPipe, upperPipe, dirtyWordsPipe; 

     private String string = "abc"; 

     private String dws = "you said dirty words, so...";

 

     public void testFilter() {

         Assert.assertEquals("ABC", new ToUpperFilter().eval(string));

         Assert.assertEquals("abc", new ToLowerFilter().eval(new ToUpperFilter().eval(string)));

         Assert.assertEquals("you said ***, so...", new DirtyWordsFilter().eval(dws));

     } 

     public void testPipe() {

         lowerPipe = new Pipe<String>(new ToUpperFilter(), new ToLowerFilter());

         upperPipe = new Pipe<String>(new ToLowerFilter(), new ToUpperFilter());

         dirtyWordsPipe = new Pipe<String>(lowerPipe, new DirtyWordsFilter());

 

         Assert.assertEquals("abc", lowerPipe.eval("abc"));

         Assert.assertEquals("ABC", upperPipe.eval("abc"));

 

         Assert.assertEquals("hehe***", dirtyWordsPipe.eval("hehedirty words"));

         Assert.assertEquals("hehe***", pipe("hehedirty words", dirtyWordsPipe));

     } 

}

四,擴展

使用者可以在Gavator結構的任何一次層次對Gavator進行擴充,如擴充functor實現其它設計模式和常用概念,或編寫更多的算法,結合import static,提高客戶代碼的可讀性

目前Gavator to be contributed的是 ContinuationFramework 和 QueryFramework

五,問題

  • Gavator的主要思想來自C++ STL和Apache Common Funtor,我對純粹的函數式語言如Scheme,Haskell並沒有太多經驗,因此Gavator最主要的問題是:它做的是否正確?

  • Gavator還不完整,如尚未將Functor實現爲值語義等

  • 好的名稱有助於減少文檔,促進理解,但同一個概念在不同的社團可能有不同的慣用名稱,如transform和map,select和filter,accumulate和reduce,等等;Gavator選擇了使用STL和Apache Common Functor中的名稱

  • 序列操作的參數應該是Collection還是Iterator ?STL和Apache Common Functor選擇了Iterator,我感覺大部分情況下Collection更方便,就用了Collection

  • 目前Gavator其實並不是很實用,像ifelse等基本是花拳繡腿,關鍵是要基於Gavator,發展出專注於某個應用領域的framework,如Continuation和Query

六、其它

Java語言本身的簡單,造成了對Functional Programming支持的限制,Apache Common Functor至今還是sandbox;這些限制包括:

  • 函數不是first class,不是一等公民,更別提lambda表達式

  • primitive type與class無法完全統一,你試試能否寫一個通用的accumulate支持int集合,long集合,double集合的累加就知道了

  • 不支持操作符重載,當然,這不是本質問題

  • 使用擦拭法實現generic,使你不能對T調用任意函數,無法特化,沒有typedef,只能用繼承來模擬,任何動態特性都將使generic喪失類型安全性,如序列化後反序列化,反射等

  • 甚至不能return void,這使Procedure和Function在實現上無法統一以減少代碼,雖然在概念上它們是獨立的

或許Java平臺上的函數式編程的支持將使用專門的語言來解決

Gavator起源於去年的一個項目,在那個項目裏實現了一個基於Functor的查詢框架,增加一種條件只需實現Condition接口,當然,Condition是一個Predicate,然後就可以和已有的各種Condition通過and,or,not等組合出各種複合查詢,提供服務的一方通過恆定不變的代碼select(Collection, Condition)來滿足任意的查詢;希望接下來實現一個封裝了各種查詢(對象,SQL,XPath/XQuery等)的QueryFramework

另外對Continuation的支持也值得一做,希望得到幫助,mailto:[email protected]

 

發佈了27 篇原創文章 · 獲贊 0 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章