Cuneiform語言
編程範型 | 純函數式, 數據流程 |
---|---|
設計者 | Jörgen Brandt |
面市時間 | 2013年 |
當前版本 |
|
型態系統 | 簡單類型 |
實作語言 | Erlang |
操作系統 | Linux, Mac OS |
許可證 | Apache許可證 2.0 |
文件擴展名 | .cfl |
網站 | cuneiform-lang |
啟發語言 | |
Swift (並行腳本語言) |
Cuneiform是用於大規模科學數據分析的開源工作流程語言[2][3]。 它是促進並行計算的靜態類型的純函數式編程語言。它的特徵是有個全功能的外界函數接口,允許用戶集成來自很多外部編程語言的軟件。Cuneiform在組織層面上提供了一些設施,如條件分支和通用遞歸,使其具有圖靈完備性。
概述
Cuneiform嘗試拉近在科學工作流程系統如Apache Taverna、KNIME或Galaxy,與大規模數據分析程序模型如MapReduce或Pig Latin之間的間隙,同時提供函數式編程語言的通用性。
Cuneiform是用分布式Erlang實現的。如果運行在分布式模態下,它導出一個遵循POSIX的分布式文件系統,如Gluster或Ceph(用FUSE集成某個其他文件系統例如HDFS)。作為替代選擇,Cuneiform腳本可以執行在HTCondor或Apache Hadoop頂上[4][5][6][7]。
Cuneiform受到了Peter Kelly的工作的影響,他提議函數式編程作為科學工作流程執行的模型[8]。 故而,Cuneiform不同於其他的基於數據流程編程的工作流程語言,如並行腳本語言Swift[9]。
擴展軟件集成
外部工具和庫(比如R或Python庫)是通過外界函數接口來集成的。通過它可以組合,比如允許通過snippet節點使用外部軟件的KNIME,或為集成Java軟件提供BeanShell服務的Apache Taverna。通過定義採用外界語言的任務,就可能使用一個外部工具或庫的API。這種方式下,工具可以直接集成而不需要寫包裝器或重新實現工具[10]。
目前支持的外界編程語言有:
類型系統
Cuneiform提供簡單的、靜態檢查的類型系統[11]。雖然Cuneiform提供列表作為複合數據類型,它省略了傳統的列表訪問子(head
和tail
),以避免在訪問空列表時,可能引起的運行時間錯誤的可能性。轉而列表只能通過在其上map
或fold
,以全有或全無方式訪問。此外,Cuneiform(在組織層面)省略了算術,這排除了除以零的可能性。省略任何的部份定義運算,允許保證運行時間錯誤只能在外界代碼中引發。
基礎數據類型
Cuneiform提供的基礎數據類型有布爾值、字符串和文件。這裡的文件被用來以任意格式在外界函數之間交換數據。
記錄和模式匹配
Cuneiform提供記錄(結構)作為複合數據類型。下面的例子展示定義一個變量r
,作為有兩個字段a1
和a2
的記錄,第一個是字符串,而第二個是布爾值:
let r : <a1 : Str, a2 : Bool> =
<a1 = "my string", a2 = true>;
記錄可以要麼通過投影(projection)要麼通過模式匹配來訪問。下面的例子從記錄r
,提取兩個字段a1
和a2
:
let a1 : Str = ( r|a1 );
let <a2 = a2 : Bool> = r;
列表和列表處理
進一步的,Cuneiform提供列表作為複合數據類型。下面的例子展示定義一個變量xs
,作為一個有三個元素的一個文件:
let xs : [File] =
['a.txt', 'b.txt', 'c.txt' : File];
列表可以通過for
和fold
算子來處理。這裡的for
算子可以接受多個列表,來逐個元素的處置列表(類似於Racket中的for/list
、Common Lisp中的mapcar
或Erlang中的zipwith
)。
下面的例子展示如何在一個單一的列表上map
,結果是一個文件列表:
for x <- xs do
process-one( arg1 = x )
: File
end;
下面的例子展示如何zip
兩個列表,結果也是一個文件列表:
for x <- xs, y <- ys do
process-two( arg1 = x, arg2 = y )
: File
end;
最後,列表可以使用fold
算子來做聚集。下面的例子合計一個列表的元素:
fold acc = 0, x <- xs do
add( a = acc, b = x )
end;
並行執行
Cuneiform是純函數式語言,就是說它不支持可變引用。作為結論,它可以使用獨立子項,將一個程序分解成可並行的各部份。Cuneiform調度器分布這些部份到做工節點。此外,Cuneiform採用傳名調用求值策略,值只在它對計算結果有貢獻時計算。最後,外界函數應用是記憶化的,用來加速包含以前推導結果的計算。
例如,下列Cuneiform程序允許f
和g
的應用平行的運行,而h
是有依賴的,它只在f
和g
二者完成的時候可以開始:
let output-of-f : File = f(); let output-of-g : File = g(); h( f = output-of-f, g = output-of-g );
下列Cuneiform程序通過將函數f
映射到一個三元素列表,創建了三個並行應用:
let xs : [File] = ['a.txt', 'b.txt', 'c.txt' : File]; for x <- xs do f( x = x ) : File end;
類似的,在記錄r
的構造中,f
和g
的應用是獨立的,因此可以並行運行:
let r : <a : File, b : File> =
<a = f(), b = g()>;
例子
下面是一個hello-world腳本:
def greet( person : Str ) -> <out : Str>
in Bash *{
out="Hello $person"
}*
( greet( person = "world" )|out );
這個腳本定義了採用Bash的一個任務greet
,它對其字符串實際參數person
預加上"Hello "
。這個函數產生具有一個單一字符串字段的記錄out
。應用greet
,綁定實際參數person
到字符串"world"
,產生記錄<out = "Hello world">
。將這個記錄投影為它的字段out
,求值出字符串"Hello world"
。
可以通過定義採用Bash的一個任務來集成命令行工具:
def samtoolsSort( bam : File ) -> <sorted : File>
in Bash *{
sorted=sorted.bam
samtools sort -m 2G $bam -o $sorted
}*
在這個例子中定義了任務samtoolsSort
。它調用了工具SAMtools,處置一個BAM格式的輸入文件,並產生一個排序了也是BAM格式的輸出文件。
發行歷史
版本 | 出現日期 | 實現語言 | 發布平台 | 外界語言 |
---|---|---|---|---|
1.0.0 | 2014年5月 | Java | Apache Hadoop | Bash, Common Lisp, GNU Octave, Perl, Python, R, Scala |
2.0.x | 2015年3月 | Java | HTCondor, Apache Hadoop | Bash, BeanShell, Common Lisp, MATLAB, GNU Octave, Perl, Python, R, Scala |
2.2.x | 2016年4月 | Erlang | HTCondor, Apache Hadoop | Bash, Perl, Python, R |
3.0.x | 2018年2月 | Erlang | 分布式Erlang | Bash, Erlang, Java, MATLAB, GNU Octave, Perl, Python, R, Racket |
在2016年4月,Cuneiform的實現語言從Java切換成了Erlang,並且在2018年2月,它的主要發布執行平台從Apache Hadoop變更為分布式Erlang。此外,從2015年到2018年,HTCondor曾被作為可替代執行平台來維護。
Cuneiform的外表語法修訂過兩次,這反映在主版本號上。
版本1
在2014年5月發布的最初草案中,Cuneiform密切關聯於Make,它構造解釋器在執行期間要遍歷的靜態數據依賴圖。與後來版本的主要區別,是缺乏條件、遞歸或靜態類型檢查。區分文件和字符串,是通過同波浪號~
形成一個單一引用的字符串。腳本的查詢表達式,通過target
關鍵字來介入。Bash是缺省外界語言。函數應用必須使用apply
形式來完成,它接受task
作為第一個關鍵字實際參數。一年之後,這種外表語法被一種精簡卻類似的版本所替代。
下面的例子腳本從一個FTP服務器下載一個參考genome:
declare download-ref-genome; deftask download-fa( fa : ~path ~id ) *{ wget $path/$id.fa.gz gunzip $id.fa.gz mv $id.fa $fa }* ref-genome-path = ~'ftp://hgdownload.cse.ucsc.edu/goldenPath/hg19/chromosomes'; ref-genome-id = ~'chr22'; ref-genome = apply( task : download-fa path : ref-genome-path id : ref-genome-id ); target ref-genome;
版本2
Cuneiform外表語法的第二個草案,首次發表於2015年3月,在Cuneiform的實現語言從Java到Erlang的遷移期間,持續使用了三年。求值不同於早期方式,解釋器歸約一個表達式,而非遍歷一個靜態圖。在外表語法保持使用這段時期,解釋器被形式化和簡化,這導致了第一個Cuneiform的語義規定。語法特徵是有了條件。但是,布爾值被編碼為列表,再度利用空列表為布爾值false
,非空列表為布爾值true
。遞歸後來作為形式化的副產品而增加。但是,靜態類型檢查,只在後來的版本3中介入。
下列腳本解壓一個壓縮文件,並把它分解為大小均勻的劃分:
deftask unzip( <out( File )> : zip( File ) ) in bash *{ unzip -d dir $zip out=`ls dir | awk '{print "dir/" $0}'` }* deftask split( <out( File )> : file( File ) ) in bash *{ split -l 1024 $file txt out=txt* }* sotu = "sotu/stateoftheunion1790-2014.txt.zip"; fileLst = split( file: unzip( zip: sotu ) ); fileLst;
版本3
Cuneiform外表語法的當前版本,比較於早期的草案,是嘗試拉近與主流函數式編程語言的間隙。它的特徵是簡單的靜態檢查的類型系統,並在列表之外介入記錄作為第二個複合數據結構類型。布爾值獨立為基礎數據類型。
下列腳本解包一個文件,結果為一個文件列表:
def untar( tar : File ) -> <fileLst : [File]> in Bash *{ tar xf $tar fileLst=`tar tf $tar` }* let hg38Tar : File = 'hg38/hg38.tar'; let <fileLst = faLst : [File]> = untar( tar = hg38Tar ); faLst;
引用
- ^ Release 3.0.5. 2022年5月27日 [2023年3月19日].
- ^ 存档副本. [2021-03-03]. (原始內容存檔於2021-03-18).
- ^ Brandt, Jörgen; Bux, Marc N.; Leser, Ulf. Cuneiform: A functional language for large scale scientific data analysis (PDF). Proceedings of the Workshops of the EDBT/ICDT. 2015, 1330: 17–26 [2021-03-03]. (原始內容 (PDF)存檔於2020-02-17).
- ^ Scalable Multi-Language Data Analysis on Beam: The Cuneiform Experience by Jörgen Brandt. Erlang Central. [28 October 2016]. (原始內容存檔於2 October 2016).
- ^ Bux, Marc; Brandt, Jörgen; Lipka, Carsten; Hakimzadeh, Kamal; Dowling, Jim; Leser, Ulf. SAASFEE: scalable scientific workflow execution engine (PDF). Proceedings of the VLDB Endowment. 2015, 8 (12): 1892–1895 [2021-03-03]. doi:10.14778/2824032.2824094. (原始內容 (PDF)存檔於2020-11-25).
- ^ Bessani, Alysson; Brandt, Jörgen; Bux, Marc; Cogo, Vinicius; Dimitrova, Lora; Dowling, Jim; Gholami, Ali; Hakimzadeh, Kamal; Hummel, Michael; Ismail, Mahmoud; Laure, Erwin; Leser, Ulf; Litton, Jan-Eric; Martinez, Roxanna; Niazi, Salman; Reichel, Jane; Zimmermann, Karin. Biobankcloud: a platform for the secure storage, sharing, and processing of large biomedical data sets (PDF). The First International Workshop on Data Management and Analytics for Medicine and Healthcare (DMAH 2015). 2015 [2021-03-03]. (原始內容 (PDF)存檔於2018-10-01).
- ^ Scalable Multi-Language Data Analysis on Beam: The Cuneiform Experience. Erlang-factory.com. [28 October 2016]. (原始內容存檔於2020-07-12).
- ^ Kelly, Peter M.; Coddington, Paul D.; Wendelborn, Andrew L. Lambda calculus as a workflow model. Concurrency and Computation: Practice and Experience. 2009, 21 (16): 1999–2017. doi:10.1002/cpe.1448. Barseghian, Derik; Altintas, Ilkay; Jones, Matthew B.; Crawl, Daniel; Potter, Nathan; Gallagher, James; Cornillon, Peter; Schildhauer, Mark; Borer, Elizabeth T.; Seabloom, Eric W. Workflows and extensions to the Kepler scientific workflow system to support environmental sensor data access and analysis (PDF). Ecological Informatics. 2010, 5 (1): 42–50 [2021-03-03]. doi:10.1016/j.ecoinf.2009.08.008. (原始內容 (PDF)存檔於2022-02-25).
- ^ Di Tommaso, Paolo; Chatzou, Maria; Floden, Evan W; Barja, Pablo Prieto; Palumbo, Emilio; Notredame, Cedric. Nextflow enables reproducible computational workflows. Nature Biotechnology. 2017, 35 (4): 316–319. PMID 28398311. doi:10.1038/nbt.3820.
- ^ A Functional Workflow Language Implementation in Erlang (PDF). [28 October 2016]. (原始內容 (PDF)存檔於2022-02-25).
- ^ Brandt, Jörgen; Reisig, Wolfgang; Leser, Ulf. Computation semantics of the functional scientific workflow language Cuneiform. Journal of Functional Programming. 2017, 27. S2CID 6128299. doi:10.1017/S0956796817000119.