Клинопись (язык программирования)
![]() | |
![]() | |
Парадигма | функциональный , научный рабочий процесс |
---|---|
Разработано | Йорген Брандт |
Впервые появился | 2013 |
Стабильная версия | 3.0.4
/ 19 ноября 2018 г. |
Дисциплина набора текста | статические , простые типы |
Язык реализации | Эрланг |
ТЫ | Линукс , Мак ОС |
Лицензия | Лицензия Апач 2.0 |
Расширения имен файлов | .cfl |
Веб-сайт | клинопись-язык |
Под влиянием | |
Swift (язык параллельных сценариев) |
Cuneiform — с открытым исходным кодом. язык рабочих процессов для крупномасштабного анализа научных данных. [1] [2] Это статически типизированный функциональный язык программирования, способствующий параллельным вычислениям . Он имеет универсальный интерфейс внешних функций , позволяющий пользователям интегрировать программное обеспечение со многих внешних языков программирования. На организационном уровне Cuneiform предоставляет такие возможности, как условное ветвление и общая рекурсия, что делает его полным по Тьюрингу . В этом смысле Cuneiform — это попытка сократить разрыв между системами научных рабочих процессов, такими как Taverna , KNIME или Galaxy, и моделями программирования крупномасштабного анализа данных, такими как MapReduce или Pig Latin, предлагая при этом универсальность функционального языка программирования.
Cuneiform реализован на распределенном Erlang . При запуске в распределенном режиме он управляет POSIX, распределенной файловой системой, совместимой с такой как Gluster или Ceph (или интеграцией FUSE какой-либо другой файловой системы, например, HDFS ). Альтернативно сценарии Cuneiform можно выполнять поверх HTCondor или Hadoop . [3] [4] [5] [6]
Cuneiform находится под влиянием работ Питера Келли, который предлагает функциональное программирование в качестве модели выполнения научного рабочего процесса. [7] [8] В этом Cuneiform отличается от родственных языков рабочих процессов, основанных на программировании потоков данных, таких как Swift . [9]
Внешняя интеграция программного обеспечения
[ редактировать ]Внешние инструменты и библиотеки (например, библиотеки R или Python ) интегрируются через внешний интерфейс функций . В этом он напоминает, например, KNIME , который позволяет использовать внешнее программное обеспечение через узлы фрагментов, или Taverna , которая предлагает BeanShell сервисы для интеграции программного обеспечения Java . Определив задачу на иностранном языке, можно использовать API внешнего инструмента или библиотеки. Таким образом, инструменты можно интегрировать напрямую, без необходимости написания оболочки или повторной реализации инструмента. [10]
В настоящее время поддерживаются следующие иностранные языки программирования:
Поддержка иностранных языков для AWK и gnuplot является запланированным дополнением.
Типовая система
[ редактировать ]Cuneiform предоставляет простую, статически проверяемую систему типов. [11] Хотя Cuneiform предоставляет списки как составные типы данных, в нем отсутствуют традиционные средства доступа к спискам (голова и хвост), чтобы избежать ошибок во время выполнения, которые могут возникнуть при доступе к пустому списку. Вместо этого доступ к спискам осуществляется по принципу «все или ничего», путем их сопоставления или свертывания. Кроме того, в Cuneiform отсутствует (на организационном уровне) арифметика, что исключает возможность деления на ноль. Пропуск какой-либо частично определенной операции позволяет гарантировать, что ошибки времени выполнения могут возникнуть исключительно во внешнем коде.
Базовые типы данных
[ редактировать ]В качестве базовых типов данных Cuneiform предоставляет логические значения, строки и файлы. Здесь файлы используются для обмена данными в произвольном формате между внешними функциями.
Записи и сопоставление с образцом
[ редактировать ]Cuneiform предоставляет записи (структуры) как составные типы данных. В примере ниже показано определение переменной. r
запись с двумя полями a1
и a2
, первая из которых является строкой, а вторая — логическим значением.
let r : <a1 : Str, a2 : Bool> =
<a1 = "my string", a2 = true>;
Доступ к записям можно получить либо через проекцию, либо через сопоставление с образцом . В приведенном ниже примере извлекаются два поля a1
и a2
из записи r
.
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 можно задать несколько списков для их поэлементного использования (аналогично for/list
в Рэкет , mapcar
в Common Lisp или zipwith
в Эрланге ).
В приведенном ниже примере показано, как сопоставить один список, результатом которого является список файлов.
for x <- xs do
process-one( arg1 = x )
: File
end;
В приведенном ниже примере показано, как сжать два списка, в результате чего также будет список файлов.
for x <- xs, y <- ys do
process-two( arg1 = x, arg2 = y )
: File
end;
Наконец, списки можно агрегировать с помощью оператора свертывания. В следующем примере суммируются элементы списка.
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
путем сопоставления f
над списком из трех элементов:
let xs : [File] = ['a.txt', 'b.txt', 'c.txt' : File]; for x <- xs do f( x = x ) : File end;
Аналогично, приложения f
и g
независимы при построении записи r
и, таким образом, может выполняться параллельно:
let r : <a : File, b : File> =
<a = f(), b = g()>;
Примеры
[ редактировать ]Скрипт приветствия, мир:
def greet( person : Str ) -> <out : Str>
in Bash *{
out="Hello $person"
}*
( greet( person = "world" )|out );
Этот скрипт определяет задачу greet
в Bash, который добавляет "Hello "
к его строковому аргументу person
.
Функция создает запись с одним строковым полем. 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 г. | Ява | Апач Хадуп | Bash, Common Lisp, GNU Octave, Perl, Python, R, Scala |
2.0.х | март 2015 г. | Ява | HTCondor , Apache Hadoop | Bash, BeanShell, Common Lisp, MATLAB, GNU Octave, Perl, Python, R, Scala |
2.2.х | апрель 2016 г. | Эрланг | HTCondor , Apache Hadoop | Баш, Перл, Питон, R |
3.0.х | февраль 2018 г. | Эрланг | Распределенный Эрланг | Bash, Erlang, Java, MATLAB, GNU Octave, Perl, Python, R, Racket |
В апреле 2016 года язык реализации Cuneiform переключился с Java на Erlang , а в феврале 2018 года его основная платформа распределенного выполнения изменилась с Hadoop на распределенный Erlang. Кроме того, с 2015 по 2018 год HTCondor поддерживался в качестве альтернативной платформы выполнения.
Поверхностный синтаксис Cuneiform дважды пересматривался, что отражено в основном номере версии.
Версия 1
[ редактировать ]В своем первом проекте, опубликованном в мае 2014 года, Cuneiform был тесно связан с Make тем, что создавал статический граф зависимостей данных, который интерпретатор проходил во время выполнения. Основным отличием от более поздних версий было отсутствие условий, рекурсии или статической проверки типов. Файлы отличались от строк путем сопоставления строковых значений в одинарных кавычках с тильдой. ~
. Выражение запроса скрипта было представлено в target
ключевое слово. Bash был иностранным языком по умолчанию. Применение функции должно было выполняться с использованием apply
форму, принявшую task
в качестве первого аргумента ключевого слова. Год спустя этот поверхностный синтаксис был заменен упрощенной, но похожей версией.
Следующий пример сценария загружает эталонный геном с FTP-сервера.
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 года, использовался в течение трех лет, пережив переход с Java на Erlang в качестве языка реализации Cuneiform. Оценка отличается от более ранних подходов тем, что интерпретатор сокращает выражение запроса вместо обхода статического графа. За то время, пока использовался поверхностный синтаксис, интерпретатор был формализован и упрощен, что привело к первой спецификации семантики 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;
Ссылки
[ редактировать ]- ^ «Йорген7/Клинопись» . Гитхаб . 14 октября 2021 г.
- ^ Брандт, Йорген; Букс, Марк Н.; Лезер, Ульф (2015). «Клинопись: функциональный язык для крупномасштабного анализа научных данных» (PDF) . Материалы семинаров EDBT/ICDT . 13:30 : 17–26.
- ^ «Масштабируемый многоязычный анализ данных на луче: опыт клинописи Йоргена Брандта» . Эрланг Центральный . Архивировано из оригинала 2 октября 2016 года . Проверено 28 октября 2016 г.
- ^ Букс, Марк; Брандт, Йорген; Липка, Карстен; Хакимзаде, Камаль; Даулинг, Джим; Лезер, Ульф (2015). «SAASFEE: масштабируемая система выполнения научных рабочих процессов» (PDF) . Труды Фонда VLDB . 8 (12): 1892–1895. дои : 10.14778/2824032.2824094 .
- ^ Бессани, Алиссон; Брандт, Йорген; Букс, Марк; Кого, Виниций; Димитрова, Лора; Даулинг, Джим; Голами, Али; Хакимзаде, Камаль; Хаммель, Майкл; Исмаил, Махмуд; Лора, Эрвин; Лезер, Ульф; Литтон, Ян-Эрик; Мартинес, Роксанна; Ниязи, Салман; Райхель, Джейн; Циммерманн, Карин (2015). «Biobankcloud: платформа для безопасного хранения, совместного использования и обработки больших наборов биомедицинских данных» (PDF) . Первый международный семинар по управлению данными и аналитике для медицины и здравоохранения (DMAH 2015) .
- ^ «Масштабируемый многоязычный анализ данных на луче: опыт клинописи» . Erlang-factory.com . Проверено 28 октября 2016 г.
- ^ Келли, Питер М.; Коддингтон, Пол Д.; Вендельборн, Эндрю Л. (2009). «Лямбда-исчисление как модель рабочего процесса». Параллелизм и вычисления: практика и опыт . 21 (16): 1999–2017. дои : 10.1002/cpe.1448 . S2CID 10833434 .
- ^ Барсегян, Дерик; Алтинтас, Илкай; Джонс, Мэтью Б.; Ползучий, Дэниел; Поттер, Натан; Галлахер, Джеймс; Корнильон, Питер; Шильдхауэр, Марк; Борер, Элизабет Т.; Сиблум, Эрик В. (2010). «Рабочие процессы и расширения системы научных рабочих процессов Kepler для поддержки доступа и анализа данных датчиков окружающей среды» (PDF) . Экологическая информатика . 5 (1): 42–50. дои : 10.1016/j.ecoinf.2009.08.008 . S2CID 16392118 .
- ^ Ди Томмазо, Паоло; Чацу, Мария; Флоден, Эван В.; Барха, Пабло Прието; Палумбо, Эмилио; Нотредам, Седрик (2017). «Nextflow обеспечивает воспроизводимые вычислительные процессы». Природная биотехнология . 35 (4): 316–319. дои : 10.1038/nbt.3820 . ПМИД 28398311 . S2CID 9690740 .
- ^ «Реализация функционального языка рабочих процессов в Erlang» (PDF) . Проверено 28 октября 2016 г.
- ^ Брандт, Йорген; Райзиг, Вольфганг; Лезер, Ульф (2017). «Вычислительная семантика функционального языка научного рабочего процесса Cuneiform». Журнал функционального программирования . 27 . дои : 10.1017/S0956796817000119 . S2CID 6128299 .