partial.lenses: how to use asynchronous operations in optics with L.collect?
I understand that partial.lenses isn't necessarily the best solution to the following problem and that's besides the point in this question. I was trying to list files from a directory using L.collect from the partial.lenses library. Goal is just to get a flattened array of file names.
Problem: instead of using fs.readdirSync I would like to make use of asynchronous, Promise returning versions of the Node's fs API, in my optics.
The following would be the promisified version of the readdir:
const util = require('util')
const fs = require('fs')
const readdirAsync = util.promisify(fs.readdir)
Below is the actual implementation. I would like to know how I can replace the synchronous fs.readdirSync in the readdir function with an asynchronous version.
const L = require("partial.lenses")
const fs = require("fs")
const path = require("path")
const _ = require("lodash")
const basePath = path.basename(`${__dirname}/..`)
const isDirectory = dirent => {
return dirent instanceof fs.Dirent ? dirent.isDirectory() : false
}
const readDir = path => () => {
return fs.readdirSync(path, { withFileTypes: true })
}
const leafs = nodePath => {
return L.cond(
[
_.isArray,
L.lazy(() => [
L.elems,
L.choose(({ name }) => leafs(path.join(nodePath, name)))
])
],
[
isDirectory,
L.lazy(() => [
readDir(nodePath),
L.elems,
L.choose(({ name }) => leafs(path.join(nodePath, name)))
])
],
[L.identity]
)
}
const listFiles = async () =>
L.collect(
leafs(basePath),
fs.readdirSync(basePath, { withFileTypes: true })
)
node.js partial-lenses
add a comment |
I understand that partial.lenses isn't necessarily the best solution to the following problem and that's besides the point in this question. I was trying to list files from a directory using L.collect from the partial.lenses library. Goal is just to get a flattened array of file names.
Problem: instead of using fs.readdirSync I would like to make use of asynchronous, Promise returning versions of the Node's fs API, in my optics.
The following would be the promisified version of the readdir:
const util = require('util')
const fs = require('fs')
const readdirAsync = util.promisify(fs.readdir)
Below is the actual implementation. I would like to know how I can replace the synchronous fs.readdirSync in the readdir function with an asynchronous version.
const L = require("partial.lenses")
const fs = require("fs")
const path = require("path")
const _ = require("lodash")
const basePath = path.basename(`${__dirname}/..`)
const isDirectory = dirent => {
return dirent instanceof fs.Dirent ? dirent.isDirectory() : false
}
const readDir = path => () => {
return fs.readdirSync(path, { withFileTypes: true })
}
const leafs = nodePath => {
return L.cond(
[
_.isArray,
L.lazy(() => [
L.elems,
L.choose(({ name }) => leafs(path.join(nodePath, name)))
])
],
[
isDirectory,
L.lazy(() => [
readDir(nodePath),
L.elems,
L.choose(({ name }) => leafs(path.join(nodePath, name)))
])
],
[L.identity]
)
}
const listFiles = async () =>
L.collect(
leafs(basePath),
fs.readdirSync(basePath, { withFileTypes: true })
)
node.js partial-lenses
1
There is no need to use Lodash here. You can replace that dependency by switching_.isArraytoArray.isArray.
– toastal
Nov 18 '18 at 16:20
add a comment |
I understand that partial.lenses isn't necessarily the best solution to the following problem and that's besides the point in this question. I was trying to list files from a directory using L.collect from the partial.lenses library. Goal is just to get a flattened array of file names.
Problem: instead of using fs.readdirSync I would like to make use of asynchronous, Promise returning versions of the Node's fs API, in my optics.
The following would be the promisified version of the readdir:
const util = require('util')
const fs = require('fs')
const readdirAsync = util.promisify(fs.readdir)
Below is the actual implementation. I would like to know how I can replace the synchronous fs.readdirSync in the readdir function with an asynchronous version.
const L = require("partial.lenses")
const fs = require("fs")
const path = require("path")
const _ = require("lodash")
const basePath = path.basename(`${__dirname}/..`)
const isDirectory = dirent => {
return dirent instanceof fs.Dirent ? dirent.isDirectory() : false
}
const readDir = path => () => {
return fs.readdirSync(path, { withFileTypes: true })
}
const leafs = nodePath => {
return L.cond(
[
_.isArray,
L.lazy(() => [
L.elems,
L.choose(({ name }) => leafs(path.join(nodePath, name)))
])
],
[
isDirectory,
L.lazy(() => [
readDir(nodePath),
L.elems,
L.choose(({ name }) => leafs(path.join(nodePath, name)))
])
],
[L.identity]
)
}
const listFiles = async () =>
L.collect(
leafs(basePath),
fs.readdirSync(basePath, { withFileTypes: true })
)
node.js partial-lenses
I understand that partial.lenses isn't necessarily the best solution to the following problem and that's besides the point in this question. I was trying to list files from a directory using L.collect from the partial.lenses library. Goal is just to get a flattened array of file names.
Problem: instead of using fs.readdirSync I would like to make use of asynchronous, Promise returning versions of the Node's fs API, in my optics.
The following would be the promisified version of the readdir:
const util = require('util')
const fs = require('fs')
const readdirAsync = util.promisify(fs.readdir)
Below is the actual implementation. I would like to know how I can replace the synchronous fs.readdirSync in the readdir function with an asynchronous version.
const L = require("partial.lenses")
const fs = require("fs")
const path = require("path")
const _ = require("lodash")
const basePath = path.basename(`${__dirname}/..`)
const isDirectory = dirent => {
return dirent instanceof fs.Dirent ? dirent.isDirectory() : false
}
const readDir = path => () => {
return fs.readdirSync(path, { withFileTypes: true })
}
const leafs = nodePath => {
return L.cond(
[
_.isArray,
L.lazy(() => [
L.elems,
L.choose(({ name }) => leafs(path.join(nodePath, name)))
])
],
[
isDirectory,
L.lazy(() => [
readDir(nodePath),
L.elems,
L.choose(({ name }) => leafs(path.join(nodePath, name)))
])
],
[L.identity]
)
}
const listFiles = async () =>
L.collect(
leafs(basePath),
fs.readdirSync(basePath, { withFileTypes: true })
)
node.js partial-lenses
node.js partial-lenses
asked Nov 16 '18 at 7:35
Esko LahtiEsko Lahti
1812
1812
1
There is no need to use Lodash here. You can replace that dependency by switching_.isArraytoArray.isArray.
– toastal
Nov 18 '18 at 16:20
add a comment |
1
There is no need to use Lodash here. You can replace that dependency by switching_.isArraytoArray.isArray.
– toastal
Nov 18 '18 at 16:20
1
1
There is no need to use Lodash here. You can replace that dependency by switching
_.isArray to Array.isArray.– toastal
Nov 18 '18 at 16:20
There is no need to use Lodash here. You can replace that dependency by switching
_.isArray to Array.isArray.– toastal
Nov 18 '18 at 16:20
add a comment |
1 Answer
1
active
oldest
votes
This is an interesting question in the sense that Partial Lenses can work on
asynchronous problems like this, but the library currently only provides a
little bit of direct support for asynchronous operations out-of-the-box. In the
future the library could certainly be extended to provide more support for
performing asynchronous operations.
Traversals in Partial Lenses build
applicative operations. By
using different applicatives different kinds of operations, like collecting
elements, computing a minimum of elements, or computing a new version of the
data structure, can be performed.
Many operations, like collecting elements or computing minimums, have an
underlying monoid. Any monoid, like array
concatenation
const ConcatArray = {empty: () => , concat: (l, r) => l.concat(r)}
can be converted to an applicative. In Partial Lenses the
L.concat and
L.concatAs
operations do that internally.
So, for collecting elements asynchronously, we could use an asynchronous version
of a concatenating monoid. We can get there by creating a function that
converts any monoid to an asynchronous monoid:
const asyncMonoid = m => ({
empty: async () => m.empty(),
concat: async (l, r) => m.concat(await l, await r)
})
We can now define an asynchronous version of
L.collect as follows:
const collectAsync = L.concatAs(
async x => [x],
asyncMonoid(ConcatArray)
)
One more thing we need for solving this problem is a way to get the result of an
asynchronous operation so that we can zoom into it using optics. For that we
could define a new primitive optic
function that awaits
for the focus before passing it forward in the optic composition:
const awaitIt = async (x, i, F, xi2yF) => xi2yF(await x, i)
Using the above awaitIt optic, we can now define asynchronous traversals over
the files in a file system given a suitable asynchronous readDirectory
function:
const filesUnderEntries = L.lazy(() => [
awaitIt,
L.elems,
L.ifElse(L.get('isDir'), ['path', filesUnderDirectory], 'path')
])
const filesUnderDirectory = [L.reread(readDirectory), filesUnderEntries]
We can use the above traversals to examine a directory structure and select
files from under it. We can also further compose operations to read those files
and examine data from those files. For example
collectAsync(
[
filesUnderDirectory,
L.when(R.test(/.my$/)),
L.reread(readFile),
awaitIt
]
)
defines an asynchronous operation that traverses a directory tree and produces
the contents of files with the .my extension under the directory tree.
Here is a playground with full code and examples using faked file system
operations.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53333345%2fpartial-lenses-how-to-use-asynchronous-operations-in-optics-with-l-collect%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
This is an interesting question in the sense that Partial Lenses can work on
asynchronous problems like this, but the library currently only provides a
little bit of direct support for asynchronous operations out-of-the-box. In the
future the library could certainly be extended to provide more support for
performing asynchronous operations.
Traversals in Partial Lenses build
applicative operations. By
using different applicatives different kinds of operations, like collecting
elements, computing a minimum of elements, or computing a new version of the
data structure, can be performed.
Many operations, like collecting elements or computing minimums, have an
underlying monoid. Any monoid, like array
concatenation
const ConcatArray = {empty: () => , concat: (l, r) => l.concat(r)}
can be converted to an applicative. In Partial Lenses the
L.concat and
L.concatAs
operations do that internally.
So, for collecting elements asynchronously, we could use an asynchronous version
of a concatenating monoid. We can get there by creating a function that
converts any monoid to an asynchronous monoid:
const asyncMonoid = m => ({
empty: async () => m.empty(),
concat: async (l, r) => m.concat(await l, await r)
})
We can now define an asynchronous version of
L.collect as follows:
const collectAsync = L.concatAs(
async x => [x],
asyncMonoid(ConcatArray)
)
One more thing we need for solving this problem is a way to get the result of an
asynchronous operation so that we can zoom into it using optics. For that we
could define a new primitive optic
function that awaits
for the focus before passing it forward in the optic composition:
const awaitIt = async (x, i, F, xi2yF) => xi2yF(await x, i)
Using the above awaitIt optic, we can now define asynchronous traversals over
the files in a file system given a suitable asynchronous readDirectory
function:
const filesUnderEntries = L.lazy(() => [
awaitIt,
L.elems,
L.ifElse(L.get('isDir'), ['path', filesUnderDirectory], 'path')
])
const filesUnderDirectory = [L.reread(readDirectory), filesUnderEntries]
We can use the above traversals to examine a directory structure and select
files from under it. We can also further compose operations to read those files
and examine data from those files. For example
collectAsync(
[
filesUnderDirectory,
L.when(R.test(/.my$/)),
L.reread(readFile),
awaitIt
]
)
defines an asynchronous operation that traverses a directory tree and produces
the contents of files with the .my extension under the directory tree.
Here is a playground with full code and examples using faked file system
operations.
add a comment |
This is an interesting question in the sense that Partial Lenses can work on
asynchronous problems like this, but the library currently only provides a
little bit of direct support for asynchronous operations out-of-the-box. In the
future the library could certainly be extended to provide more support for
performing asynchronous operations.
Traversals in Partial Lenses build
applicative operations. By
using different applicatives different kinds of operations, like collecting
elements, computing a minimum of elements, or computing a new version of the
data structure, can be performed.
Many operations, like collecting elements or computing minimums, have an
underlying monoid. Any monoid, like array
concatenation
const ConcatArray = {empty: () => , concat: (l, r) => l.concat(r)}
can be converted to an applicative. In Partial Lenses the
L.concat and
L.concatAs
operations do that internally.
So, for collecting elements asynchronously, we could use an asynchronous version
of a concatenating monoid. We can get there by creating a function that
converts any monoid to an asynchronous monoid:
const asyncMonoid = m => ({
empty: async () => m.empty(),
concat: async (l, r) => m.concat(await l, await r)
})
We can now define an asynchronous version of
L.collect as follows:
const collectAsync = L.concatAs(
async x => [x],
asyncMonoid(ConcatArray)
)
One more thing we need for solving this problem is a way to get the result of an
asynchronous operation so that we can zoom into it using optics. For that we
could define a new primitive optic
function that awaits
for the focus before passing it forward in the optic composition:
const awaitIt = async (x, i, F, xi2yF) => xi2yF(await x, i)
Using the above awaitIt optic, we can now define asynchronous traversals over
the files in a file system given a suitable asynchronous readDirectory
function:
const filesUnderEntries = L.lazy(() => [
awaitIt,
L.elems,
L.ifElse(L.get('isDir'), ['path', filesUnderDirectory], 'path')
])
const filesUnderDirectory = [L.reread(readDirectory), filesUnderEntries]
We can use the above traversals to examine a directory structure and select
files from under it. We can also further compose operations to read those files
and examine data from those files. For example
collectAsync(
[
filesUnderDirectory,
L.when(R.test(/.my$/)),
L.reread(readFile),
awaitIt
]
)
defines an asynchronous operation that traverses a directory tree and produces
the contents of files with the .my extension under the directory tree.
Here is a playground with full code and examples using faked file system
operations.
add a comment |
This is an interesting question in the sense that Partial Lenses can work on
asynchronous problems like this, but the library currently only provides a
little bit of direct support for asynchronous operations out-of-the-box. In the
future the library could certainly be extended to provide more support for
performing asynchronous operations.
Traversals in Partial Lenses build
applicative operations. By
using different applicatives different kinds of operations, like collecting
elements, computing a minimum of elements, or computing a new version of the
data structure, can be performed.
Many operations, like collecting elements or computing minimums, have an
underlying monoid. Any monoid, like array
concatenation
const ConcatArray = {empty: () => , concat: (l, r) => l.concat(r)}
can be converted to an applicative. In Partial Lenses the
L.concat and
L.concatAs
operations do that internally.
So, for collecting elements asynchronously, we could use an asynchronous version
of a concatenating monoid. We can get there by creating a function that
converts any monoid to an asynchronous monoid:
const asyncMonoid = m => ({
empty: async () => m.empty(),
concat: async (l, r) => m.concat(await l, await r)
})
We can now define an asynchronous version of
L.collect as follows:
const collectAsync = L.concatAs(
async x => [x],
asyncMonoid(ConcatArray)
)
One more thing we need for solving this problem is a way to get the result of an
asynchronous operation so that we can zoom into it using optics. For that we
could define a new primitive optic
function that awaits
for the focus before passing it forward in the optic composition:
const awaitIt = async (x, i, F, xi2yF) => xi2yF(await x, i)
Using the above awaitIt optic, we can now define asynchronous traversals over
the files in a file system given a suitable asynchronous readDirectory
function:
const filesUnderEntries = L.lazy(() => [
awaitIt,
L.elems,
L.ifElse(L.get('isDir'), ['path', filesUnderDirectory], 'path')
])
const filesUnderDirectory = [L.reread(readDirectory), filesUnderEntries]
We can use the above traversals to examine a directory structure and select
files from under it. We can also further compose operations to read those files
and examine data from those files. For example
collectAsync(
[
filesUnderDirectory,
L.when(R.test(/.my$/)),
L.reread(readFile),
awaitIt
]
)
defines an asynchronous operation that traverses a directory tree and produces
the contents of files with the .my extension under the directory tree.
Here is a playground with full code and examples using faked file system
operations.
This is an interesting question in the sense that Partial Lenses can work on
asynchronous problems like this, but the library currently only provides a
little bit of direct support for asynchronous operations out-of-the-box. In the
future the library could certainly be extended to provide more support for
performing asynchronous operations.
Traversals in Partial Lenses build
applicative operations. By
using different applicatives different kinds of operations, like collecting
elements, computing a minimum of elements, or computing a new version of the
data structure, can be performed.
Many operations, like collecting elements or computing minimums, have an
underlying monoid. Any monoid, like array
concatenation
const ConcatArray = {empty: () => , concat: (l, r) => l.concat(r)}
can be converted to an applicative. In Partial Lenses the
L.concat and
L.concatAs
operations do that internally.
So, for collecting elements asynchronously, we could use an asynchronous version
of a concatenating monoid. We can get there by creating a function that
converts any monoid to an asynchronous monoid:
const asyncMonoid = m => ({
empty: async () => m.empty(),
concat: async (l, r) => m.concat(await l, await r)
})
We can now define an asynchronous version of
L.collect as follows:
const collectAsync = L.concatAs(
async x => [x],
asyncMonoid(ConcatArray)
)
One more thing we need for solving this problem is a way to get the result of an
asynchronous operation so that we can zoom into it using optics. For that we
could define a new primitive optic
function that awaits
for the focus before passing it forward in the optic composition:
const awaitIt = async (x, i, F, xi2yF) => xi2yF(await x, i)
Using the above awaitIt optic, we can now define asynchronous traversals over
the files in a file system given a suitable asynchronous readDirectory
function:
const filesUnderEntries = L.lazy(() => [
awaitIt,
L.elems,
L.ifElse(L.get('isDir'), ['path', filesUnderDirectory], 'path')
])
const filesUnderDirectory = [L.reread(readDirectory), filesUnderEntries]
We can use the above traversals to examine a directory structure and select
files from under it. We can also further compose operations to read those files
and examine data from those files. For example
collectAsync(
[
filesUnderDirectory,
L.when(R.test(/.my$/)),
L.reread(readFile),
awaitIt
]
)
defines an asynchronous operation that traverses a directory tree and produces
the contents of files with the .my extension under the directory tree.
Here is a playground with full code and examples using faked file system
operations.
answered Nov 16 '18 at 7:58
polytypicpolytypic
1913
1913
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53333345%2fpartial-lenses-how-to-use-asynchronous-operations-in-optics-with-l-collect%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
There is no need to use Lodash here. You can replace that dependency by switching
_.isArraytoArray.isArray.– toastal
Nov 18 '18 at 16:20