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.