Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/409.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何使用Ramda.js重构这个组合函数?_Javascript_Node.js_Functional Programming_Ramda.js - Fatal编程技术网

Javascript 如何使用Ramda.js重构这个组合函数?

Javascript 如何使用Ramda.js重构这个组合函数?,javascript,node.js,functional-programming,ramda.js,Javascript,Node.js,Functional Programming,Ramda.js,我正在使用ramda和data.task编写一个小实用程序,它从目录中读取图像文件并输出其大小。我让它像这样工作: const getImagePath = assetsPath => item => `${assetsPath}${item}` function readImages(path) { return new Task(function(reject, resolve) { fs.readdir(path, (err, images) => {

我正在使用
ramda
data.task
编写一个小实用程序,它从目录中读取图像文件并输出其大小。我让它像这样工作:

const getImagePath = assetsPath => item => `${assetsPath}${item}`

function readImages(path) {
  return new Task(function(reject, resolve) {
    fs.readdir(path, (err, images) => {
      if (err) reject(err)
      else resolve(images)
    })
  })
}

const withPath = path => task => {
  return task.map(function(images) {
    return images.map(getImagePath(path))
  })
}

function getSize(task) {
  return task.map(function(images) {
    return images.map(sizeOf)
  })
}

const getImageSize = dirPath => compose(getSize, withPath(dirPath), readImages)
问题在于
withPath
函数将正确的图像路径添加到图像文件名,但强制api传入directoryName两次:一次用于读取文件,第二次用于读取路径。这意味着我必须调用
getImageSize
函数,如下所示:

const portfolioPath = `${__dirname}/assets/`

getImageSize(portfolioPath)(portfolioPath).fork(
  function(error) {
    throw error
  },
  function(data) {
    console.log(data)
  }
)
有没有办法只将
dirname
作为参数传递一次?我希望api的工作方式如下:

getImageSize(portfolioPath).fork(
  function(error) {
    throw error
  },
  function(data) {
    console.log(data)
  }
)
module.exports = (function getImageSize(dirPath) {
  return compose(getSize, withPath, readImages)
})()
getImageSize(portfolioPath).fork(
  function(error) {
    throw error
  },
  function(data) {
    console.log(data)
  }
)

我通过将
任务
解析传递给单个对象来解决此问题,如下所示:

function readImages(path) {
  return new Task(function(reject, resolve) {
    fs.readdir(path, (err, images) => {
      if (err) reject(err)
      else resolve({ images, path })
    })
  })
}

const withPath = task => {
  return task.map(function({ images, path }) {
    return images.map(getImagePath(path))
  })
}
…然后将其从任务负载中销毁,现在我的compose函数如下所示:

getImageSize(portfolioPath).fork(
  function(error) {
    throw error
  },
  function(data) {
    console.log(data)
  }
)
module.exports = (function getImageSize(dirPath) {
  return compose(getSize, withPath, readImages)
})()
getImageSize(portfolioPath).fork(
  function(error) {
    throw error
  },
  function(data) {
    console.log(data)
  }
)
我的api调用如下所示:

getImageSize(portfolioPath).fork(
  function(error) {
    throw error
  },
  function(data) {
    console.log(data)
  }
)
module.exports = (function getImageSize(dirPath) {
  return compose(getSize, withPath, readImages)
})()
getImageSize(portfolioPath).fork(
  function(error) {
    throw error
  },
  function(data) {
    console.log(data)
  }
)

您不应该像那样手动构建路径

Node的一个更好的api是———我建议将您的
readImages
包装器设置为通用
readdir
包装器,并解析一组“d”文件路径

const readdir = dir =>
  new Task ((reject, resolve) =>
    fs.readdir (dir, (err, files) =>
      err
        ? reject (err)
        : resolve (files.map (f => path.resolve (dir, f)))


const getImagesSizes = dir =>
  readdir (dir) .map (R.map (sizeOf))
包装节点继续传递样式的API只是为了返回一个
任务
会很麻烦,不是吗

const taskify = f => (...args) =>
  Task ((reject, resolve) =>
    f (...args, (err, x) =>
      err ? reject (err) : resolve (x)))

const readdir = (dir, ...args) =>
  taskify (fs.readdir) (dir, ...args)
    .map (R.map (f => path.resolve (dir, f)))

const getImagesSizes = dir =>
  readdir (dir) .map (R.map (sizeOf))

您可能还应该注意将作为目录的文件路径归档,除非您的
sizeOf
实现能够处理这一问题,因为我现在在手机上,所以无法进行真正的测试,但您可以查看函数的工作原理:
chain(f,g)(x)=>f(g(x),x)
。Hey@ScottSauyet-希望引起您的注意。我解决了这个问题,但我仍然想了解在这种情况下我将如何使用链。拉姆达的
chain
不就是
flatmap
?这在这里是如何应用的?我在想,您可能可以将
withPath
切换到
task=>path=>…
,然后使用
chain(withPath,readImages)
组合
getSize
。至于
chain
如何处理函数,Scott Christopher提供了一个.Ok。我想尝试一下,我认为对于大多数刚开始编写函数的程序员来说,把所有问题都看成是
comp
position问题是很常见的——别担心;这会随着时间的推移而改变,但你所展示的也是一种构图模式,不是吗?你能进一步阐述你的批评吗?我是FP的相对初学者,学习FP主要是作为一系列函数组合。Amit,谢谢你强调了一个模糊性——我想区分“[函数]组合”和
组合
函数本身——你可以将所有复合函数视为较小函数的组合,但请记住,并非所有函数组合都是使用
compose
函数编写的–因此,是的,
readdir
是一个组合,但在这种情况下,
compose
函数并不能帮助我们更好地表达该组合–大多数初学者都会说“我需要一个组合”,然后使用
compose
函数,然后想知道为什么他们的最终计划会感到尴尬。