So I've started looking at Ramda / Folktale. I'm having an issue trying to map over an array of Tasks that comes from a directory. I'm trying to parse file contents.
var fs = require('fs');
var util = require('util');
var R = require('ramda');
var Task = require('data.task');
var compose = R.compose;
var map = R.map;
var chain = R.chain;
function parseFile(data) {
console.log("Name: " + data.match(/\$name:(.*)/)[1]);
console.log("Description: " + data.match(/\$description:(.*)/)[1]);
console.log("Example path: " + data.match(/\$example:(.*)/)[1]);
}
// String => Task [String]
function readDirectories(path) {
return new Task(function(reject, resolve) {
fs.readdir(path, function(err, files) {
err ? reject(err) : resolve(files);
})
})
}
// String => Task String
function readFile(file) {
return new Task(function(reject, resolve) {
fs.readFile('./src/less/' + file, 'utf8', function(err, data) {
err ? reject(err) : resolve(data);
})
})
}
var app = compose(chain(readFile), readDirectories);
app('./src/less').fork(
function(error) { throw error },
function(data) { util.log(data) }
);
I'm reading the files in a directory and returning a Task. When this resolves it should go into the readFile function (which returns a new task). Once it reads the file I want it to just parse some bits out of there.
With the following:
var app = compose(chain(readFile), readDirectories);
It gets into the readFile function but 'file' is an array of files so it errors.
With:
var app = compose(chain(map(readFile)), readDirectories);
We never get into fs.readfile(), but 'file' is the actual file name.
I'm pretty stumped on this and the documentation is baffling. Any suggestions welcome.
Thanks
The syntax for the map() method is as follows: arr. map(function(element, index, array){ }, this); The callback function() is called on each array element, and the map() method always passes the current element , the index of the current element, and the whole array object to it.
Definition and Usagemap() creates a new array from calling a function for every array element. map() calls a function once for each element in an array. map() does not execute the function for empty elements. map() does not change the original array.
C++ allows us a facility to create an array of maps. An array of maps is an array in which each element is a map on its own.
'use strict';
const fs = require('fs');
const Task = require('data.task');
const R = require('ramda');
// parseFile :: String -> { name :: String
// , description :: String
// , example :: String }
const parseFile = data => ({
name: R.nth(1, R.match(/[$]name:(.*)/, data)),
description: R.nth(1, R.match(/[$]description:(.*)/, data)),
example: R.nth(1, R.match(/[$]example:(.*)/, data)),
});
// readDirectories :: String -> Task (Array String)
const readDirectories = path =>
new Task((reject, resolve) => {
fs.readdir(path, (err, filenames) => {
err == null ? resolve(filenames) : reject(err);
})
});
// readFile :: String -> Task String
const readFile = filename =>
new Task(function(reject, resolve) {
fs.readFile('./src/less/' + filename, 'utf8', (err, data) => {
err == null ? resolve(data) : reject(err);
})
});
// dirs :: Task (Array String)
const dirs = readDirectories('./src/less');
// files :: Task (Array (Task String))
const files = R.map(R.map(readFile), dirs);
// sequenced :: Task (Task (Array String))
const sequenced = R.map(R.sequence(Task.of), files);
// unnested :: Task (Array String)
const unnested = R.unnest(sequenced);
// parsed :: Task (Array { name :: String
// , description :: String
// , example :: String })
const parsed = R.map(R.map(parseFile), unnested);
parsed.fork(err => {
process.stderr.write(err.message);
process.exit(1);
},
data => {
process.stdout.write(R.toString(data));
process.exit(0);
});
I wrote each of the transformations on a separate line so I could include type signatures which make the nested maps easier to understand. These could of course be combined into a pipeline via R.pipe
.
The most interesting steps are using R.sequence
to transform Array (Task String)
into Task (Array String)
, and using R.unnest
to transform Task (Task (Array String))
into Task (Array String)
.
I suggest having a look at plaid/async-problem if you have not already done so.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With