5
\$\begingroup\$

I started learning functional programming with JavaScript and I have the basic idea of Functors, container types and etc. I was trying to experiment with arrays but I don't know how to solve the problem of a function call that iterates over a array and returns returns another array. So the first call ends up with an array with 4 elements which are nested nested arrays of promises.

const iterate = p =>
Promise.all(p
.map(f=>({localPath:f.localPath,RelativePathFromDistLibrary:f.RelativePathFromDistLibrary}))
.map(f=>getsubfolders(f.localPath)
  .map(async _f=>({
    RelativeDistLibraryUrlAfterDomain: env.spDistLibraryAbsoluteUrlArray.slice(1).join(''),
    RelativeDistFolder:`${env.spDistFolderAbsoluteUrlArray.slice(3).join('')}${f.RelativePathFromDistLibrary}${_f}`,
    ModifiedTimeInMs: (await readStat(`${f.localPath}${_f}`)).mtimeMs
  }))
))
.then(x=>Promise.all(x.flat(Infinity)))
.then(x=>x.map(z=>console.log(z.ModifiedTimeInMs)))

The first call for iterate we pass an array of four objects. The first map just transforms each object, the second one gets all subfolders for each directory.

Example:

iterate([{RelativePathFromDistLibrary: '/src', localPath: './src'}]))

Then we map over all the results (first nested map). We wrap all in a promise.all since it will return a array of promises. We flatten the resulting array and wrap in a promise all again, then we can access the props.

Any tips that can help me better understand FP or solve the issues from this code would be super helpful.

\$\endgroup\$
  • \$\begingroup\$ @Drew and Billal, indentation and formatting is perfectly reviewable. Don't modify the code, write an answer instead. \$\endgroup\$ – Mast Jul 31 at 7:11
  • \$\begingroup\$ @Mast Fair enough, readability is a valid part of a code review. Will keep this in mind. \$\endgroup\$ – Drew Reese Jul 31 at 7:14
  • \$\begingroup\$ @DrewReese Thank you. You can still find your edit in the edit history. It would be the start of a good review, if you compare the changes to the original and point out why yours is better compared to the original. Feel free to do so. \$\endgroup\$ – Mast Jul 31 at 7:16
  • \$\begingroup\$ The current question title, which states your concerns about the code, applies to too many questions on this site to be useful. The site standard is for the title to simply state the task accomplished by the code. Please see How to Ask for examples, and revise the title accordingly. \$\endgroup\$ – Mast Jul 31 at 7:17
  • \$\begingroup\$ This looks like it could be a fun review, but only if you change your title and body a bit to answer these questions: What are you trying to achieve with this code? Does the provided example work? Are there any bugs or parts of the code that you don't understand and need help with? Right now, all I can say for sure is that you need to be more consistent with your indentation :) \$\endgroup\$ – Maanlamp Aug 6 at 13:34
0
\$\begingroup\$

I decided to go with the solution below.

By using Tasks I don't need to put all the logic right there, I can just pass the Task anywhere and map/chain over it to add extra functionality. I can even just fork it after I have all the data and get the List inside which I can also map and more.

Also with the function "getsubfolders" from the questions I can use to get the array of the paths and just wrap it in a List as I am doing in readDir.

So what I mean is that, although the structure is different, this way is way more flexible and readable (I can still derive all the above objects from the result).

I am noew trying to convert the getsubfolders to async and functional as well, for the sake of learning.

/* eslint-disable import/extensions */
/*
taken from 
https://mostly-adequate.gitbooks.io/mostly-adequate-guide/content/ch08.html#asynchronous-tasks
 */
import fs from 'fs'
import {Task, traverse,concat,compose,chain,map, prop, List, } from './shared/functional.js';

// readDir :: String -> Task Error (List String)
const readDir = path => new Task((reject, result) => {
  fs.readdir(path, (err, data) => (err ? reject(err) : result(new List(data))));
});

// readDir :: String -> Task Error (Stat)
const readStat = filename => new Task((reject, result) => {
  fs.stat(filename, (err, data) => (err ? reject(err) : result(data)));
});

const dirList = dir => 
chain(
  traverse(Task.of, compose(readStat, concat(dir))),
  readDir(dir),
);

dirList('./shared/').fork(console.error, map(compose(console.log, prop('mtimeMs'))));
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.