热门问题
时间线
聊天
视角

Cuneiform语言

来自维基百科,自由的百科全书

Cuneiform语言
Remove ads

Cuneiform是用于大规模科学数据分析的开源工作流程语言英语Scientific workflow system[2][3]。 它是促进并行计算静态类型纯函数式编程语言。它的特征是有个全功能的外界函数接口英语foreign function interface,允许用户集成来自很多外部编程语言的软件。Cuneiform在组织层面上提供了一些设施,如条件分支通用递归,使其具有图灵完备性

事实速览 编程范型, 設計者 ...
Remove ads

概述

Cuneiform尝试拉近在科学工作流程系统如Apache Taverna英语Apache TavernaKNIME英语KNIMEGalaxy,与大规模数据分析程序模型如MapReducePig Latin之间的间隙,同时提供函数式编程语言的通用性。

Cuneiform是用分布式Erlang实现的。如果运行在分布式模态下,它导出一个遵循POSIX分布式文件系统,如GlusterCeph英语Ceph (software)#CephFS(用FUSE集成某个其他文件系统例如HDFS)。作为替代选择,Cuneiform脚本可以执行在HTCondor英语HTCondorApache Hadoop顶上[4][5][6][7]

Cuneiform受到了Peter Kelly的工作的影响,他提议函数式编程作为科学工作流程执行的模型[8]。 故而,Cuneiform不同于其他的基于数据流程编程的工作流程语言,如并行脚本语言Swift英语Swift (parallel scripting language)[9]

Remove ads

扩展软件集成

外部工具和库(比如RPython库)是通过外界函数接口英语foreign function interface来集成的。通过它可以组合,比如允许通过snippet节点使用外部软件的KNIME英语KNIME,或为集成Java软件提供BeanShell英语BeanShell服务的Apache Taverna英语Apache Taverna。通过定义采用外界语言的任务,就可能使用一个外部工具或库的API。这种方式下,工具可以直接集成而不需要写包装器或重新实现工具[10]

目前支持的外界编程语言有:

计划增加外界语言AWKgnuplot

类型系统

Cuneiform提供简单的、静态检查的类型系统[11]。虽然Cuneiform提供列表作为复合数据类型,它省略了传统的列表访问子(headtail),以避免在访问空列表时,可能引起的运行时间错误的可能性。转而列表只能通过在其上mapfold,以全有或全无方式访问。此外,Cuneiform(在组织层面)省略了算术,这排除了除以零的可能性。省略任何的部份定义运算,允许保证运行时间错误只能在外界代码中引发。

基础数据类型

Cuneiform提供的基础数据类型有布尔值字符串文件。这里的文件被用来以任意格式在外界函数之间交换数据。

记录和模式匹配

Cuneiform提供记录(结构)作为复合数据类型。下面的例子展示定义一个变量r,作为有两个字段a1a2的记录,第一个是字符串,而第二个是布尔值:

let r : <a1 : Str, a2 : Bool> =
  <a1 = "my string", a2 = true>;

记录可以要么通过投影(projection)要么通过模式匹配来访问。下面的例子从记录r,提取两个字段a1a2

let a1 : Str = ( r|a1 );

let <a2 = a2 : Bool> = r;

列表和列表处理

进一步的,Cuneiform提供列表作为复合数据类型。下面的例子展示定义一个变量xs,作为一个有三个元素的一个文件:

let xs : [File] =
  ['a.txt', 'b.txt', 'c.txt' : File];

列表可以通过forfold算子来处理。这里的for算子可以接受多个列表,来逐个元素的处置列表(类似于Racket中的for/listCommon Lisp中的mapcarErlang中的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;
Remove ads

并行执行

Cuneiform是纯函数式语言,就是说它不支持可变引用。作为结论,它可以使用独立子项,将一个程序分解成可并行的各部份。Cuneiform调度器分布这些部份到做工节点。此外,Cuneiform采用传名调用求值策略,值只在它对计算结果有贡献时计算。最后,外界函数应用是记忆化的,用来加速包含以前推导结果的计算。

例如,下列Cuneiform程序允许fg的应用平行的运行,而h是有依赖的,它只在fg二者完成的时候可以开始:

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的构造中,fg的应用是独立的,因此可以并行运行:

let r : <a : File, b : File> =
  <a = f(), b = g()>;
Remove ads

例子

下面是一个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英语SAMtools,处置一个BAM格式的输入文件,并产生一个排序了也是BAM格式的输出文件。

Remove ads

发行历史

更多信息 版本, 出现日期 ...

在2016年4月,Cuneiform的实现语言从Java切换成了Erlang,并且在2018年2月,它的主要发布执行平台从Apache Hadoop变更为分布式Erlang。此外,从2015年到2018年,HTCondor英语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;
Remove ads

版本2

Thumb
基于Swing的编辑器和Cuneiform 2.0.3的REPL

Cuneiform外表语法的第二个草案,首次发表于2015年3月,在Cuneiform的实现语言从JavaErlang的迁移期间,持续使用了三年。求值不同于早期方式,解释器归约一个表达式,而非遍历一个静态图。在外表语法保持使用这段时期,解释器被形式化和简化,这导致了第一个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;
Remove ads

版本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;

引用

Loading related searches...

Wikiwand - on

Seamless Wikipedia browsing. On steroids.

Remove ads