我尝试使用node.js 实现一个读取FileSystem目录树的列表结构
DIR/文件结构:
DIR1
DIR2R
file1
file2
file3
…
->列表结构:
("DIR1" ("DIR2" "file1" "file2" "file3" …))
DIR() //looks like a C function
file //looks like an Atom value
因此,例如,给定的UNIX根目录DIR:
root bin cd
ls
lib file1
file2
opt
usr file3
file4
相当于一个列表:
("root" ("bin" ("cd" "ls")
"lib" ("file1" "file2")
"opt" ()
"usr" ("file3")
"file4"
)
)
话虽如此,我想用一些惰性异步序列(流/无限列表?)来实现这段代码。
node.js fs.readdir递归目录搜索是一个很好的参考
node.js有许多优秀的库,如file.walk等,但这是一个非常有趣的主题,事实上,有很多代码示例。
换句话说,一个好的主题是学习懒惰异步序列的基本概念(流/无限列表?),并且代码可以是一个好库,我想从头开始实现。
substack/stream手册介绍了如何编写node.js的基本知识带有流的程序。真正优秀的文章
因此,以下是我对这个主题的思考-递归目录树处理:
本主题涉及递归搜索,有两种方法:async和sync,由于各种原因,我选择了异步方法。
搜索结果相当于列表结构,其中函数式编程范式确实很重要(Lisp/Scheme)。
对于JavaScript函数式编程,有一些库,如underline.js和最近的lazy.js惰评估(也称为延迟执行),其中似乎优于underline.js。
lazy.js也将流处理封装在Node.js中。我还发现stream.js说:有无限多的元素。它们的力量来自于懒惰的评估,简单地说,这意味着它们可以包含无限的项目。
流数据(无限列表)实现了反应式功能编程(FRP)范式。lazy.js实际上演示了一个鼠标事件FRP实现。RxJS是一个FRP库:RxJS或JavaScript的Reactive Extensions是一个用于转换、组合和查询数据流的库
async这个主题的方法是一个FRP主题。
因此,懒惰评估是更快列表处理功能编程的核心因素,它将列表扩展到无限列表(流),该列表将异步/事件集成到流数据源,以在功能编程范式(FunctionalReactiveProgramming)中进行处理。
node lazy Introduction明确指出:当您需要像列表一样处理事件流时,lazy非常方便。目前最好的用例是从异步函数返回一个惰性列表,并通过事件将数据注入其中。在异步编程中,你不能因为还没有数据就只返回一个常规列表。到目前为止,通常的解决方案是提供一个回调,当数据可用时调用它。但这样做会失去链接函数和创建管道的能力,从而导致接口不那么好。(请参阅下面的第二个示例,了解它如何改进我的一个模块中的接口。)
最后,这是我关于这个主题的问题-递归目录树处理:
是否有任何示例代码专门以懒惰评估或FRP方式实现此主题
我知道lazy.js、stream.js或linq.js是基于懒惰评估的,但它们中的任何一个都不能将node.js fs.readdr定义为异步处理(FRP)的流数据。根据http://danieltao.com/lazy.js/docs/AsyncSequence.html,它还没有实现,对吗?
RxJS可能可以,但我不知道怎么做。
谷歌rx.ObsObservable fs.readdir什么都不点击。
有什么想法吗?
以下是基于https://gist.github.com/edygar/ee0945a73c79182367df
给定一个目录,它会生成一个子目录列表。
(咖啡文字)
Rx = require "rx"
fs = require "fs"
readdir = Rx.Observable.fromNodeCallback fs.readdir
stat = Rx.Observable.fromNodeCallback (pathName, cb) ->
fs.stat pathName, (err, stats) ->
stats.pathName = pathName
cb err, stats
dirObservable = (dirPath) ->
readdir dirPath
.flatMap (items) -> Rx.Observable.from items
.flatMap (item) -> stat item
.filter (stats) -> stats.isDirectory()
.map (stats) -> stats.pathName
module.exports = dirObservable
if not module.parent
path = require "path"
dirobs = dirObservable path.resolve __dirname, ".."
dirobs.subscribe (data) -> console.log data