HTTPS SSH

Cookery

Cookery is a framework for designing Domain Specific Languages for scientific applications. It is developed in Ruby programming language (requires Ruby 2.0).

How does it work

Cookery is inspired by cooking recipes and it allows to develop scientific applications with plain English. In order to develop an application, first an environment has to be established. It consist three kinds components:

  1. Action
  2. Condition
  3. Subject

Action

Action is a pair: name and procedure. Name_ is a reference to created action and can be used in a place of action (see syntax). Procedure is a block of code that takes one argument - subject. During the execution, action receives a reference to a subject specified be a user.

Communication between actions is done using channels. They can be accessed using function channel_put(<channel_name>, <value>) and channel_get(<channel_name>) (available in action's blocks).

Condition

Condition is very similar to action. It has a name and procedure. They should have longer, descriptive names and be designed in a way that can cooperate with many actions.

Subject

Subject is built from four elements: name, regular expression, type and procedure.

  • name is a reference to a subject
  • regular expression is used to parse subject's arguments, all elements captured by a regular expression are available as arguments in a block
  • type (or protocol) points to an implementation of subject's backend, backend provides methods that can be used in a procedure to specify protocol's parameters (e.g. path)
  • procedure - block of Ruby code where all the parameters specific to a protocol can be specified using functions provided by a protocol implementation

Syntax

These components define named entities - keywords that can be used in a following syntax:

Action subject (context) - condition condition ... condition.

Then, during the execution, framework passes subject with arguments specified by a user ((context)) and references to conditions.

Example

In a following example we show an application that counts words in a compressed text file. (file file-operations.rb in a repository).

Setting up environment

First, all the required components have to be defined, a subject:

subject(:file, /(.+)/, :file) do |f|
  path f
end

Action that puts content of a file to a channel (specified by a subject)

action(:read) do |subject|
  puts "in action"

  channel_put(:foo, subject)
end

Condition that decompresses a string

condition("with zip compression") do |data|
  puts "in condition"
  gz = Zlib::GzipReader.new(StringIO.new(data))
  result = gz.read
  gz.close
  result
end

Example, empty condition:

condition("with nothing") do |data|
  data
end

Action print_result prints result to standard output

action(:print_result) do
  puts "RESULT: #{channel_get(:bar)}"
end

Action count_words counts word in string.

action(:count_words) do |subject, conditions|
  channel_put(:bar, channel_get(:foo).split.length)
end

Application

In a following code we use available components from a previous paragraph to construct a full application.

Read file /tmp/test_data.gzip - with zip compression, with nothing.
Count words.
Print result.