5

考虑下面的工作代码:

var randN = x => () => Math.floor(x*Math.random());
var rand10 = randN(10)
times(rand10, 10) // => [6, 3, 7, 0, 9, 1, 7, 2, 6, 0]

randN是一个函数,它接受一个数字并返回一个 RNG,当被调用时,它将返回一个范围为 [0, N-1] 的随机 int。所以它是特定 RNG 的工厂。

我一直在使用ramda.js并学习函数式编程理论,我的问题是:是否可以randN使用 ramda 以无点风格重写?

例如,我可以写:

var badAttempt = pipe(multiply(Math.random()), Math.floor)

这将满足“无点风格”的要求,但无法表现出与以下相同的方式randN:调用badAttempt(10)只返回一个介于 1 和 10 之间的随机数,而不是在调用时生成一个介于 1 和 10 之间的随机数的函数。

我还没有找到使我能够以无点样式进行重写的 ramda 函数组合。我不知道这是否只是我的失败,还是 using 的特殊之处random,它破坏了引用透明度,因此可能与无点样式不兼容。

更新

在与 Denys 讨论后,我自己对解决方案的细微改动:

randN = pipe(always, of, append(Math.random), useWith(pipe(multiply, Math.floor)), partial(__,[1,1]))
4

3 回答 3

3

这将有助于一个额外的函数来抽象一个函数,以便在每次调用它时重新评估它的参数。

thunk = fn => R.curryN(fn.length, (...args) => () => fn(...args))

fn此函数的唯一目的是在给定函数内引起一些副作用。

一旦我们有了thunk函数,我们就可以randN这样定义:

randN = thunk(R.pipe(S.S(R.multiply, Math.random), Math.floor))

R.times(randN(10), 5) // e.g. [1, 6, 9, 4, 5]

注意:S.S这里是来自 Sanctuary 的 S 组合子,它的作用与R.converge(multiply, [Math.random, identity]).

但是,如果它确实提高了函数的可读性,我只建议使用无点解决方案。

于 2016-03-24T08:09:42.793 回答
2

我不知道使用特定库学习函数式编程是否是一个好主意,因为库的特性和函数范式将不可避免地混合在一起。然而,在实践中,Ramda 非常有用。它在 Javascript 中弥合了命令式现实和功能性Fantasy Land之间的差距:D

这是一种手动方法:

// a few generic, reusable functions:
const comp = f => g => x => f(g(x)); // mathematical function composition
const comp2 = comp(comp)(comp); // composes binary functions
const flip = f => x => y => f(y)(x); // flips arguments
const mul = y => x => x * y; // first class operator function

// the actual point-free function:
const randN = comp2(Math.floor)(flip(comp(mul)(Math.random)));

let rand10 = randN(10); // RNG
for (let i = 0; i < 10; i++) console.log(rand10());

值得一提的是,这randN是不纯的,因为随机数根据定义是不纯的。

于 2016-03-24T13:14:54.303 回答
1

var randN = R.converge(R.partial, [R.wrap(R.pipe(R.converge(R.multiply, [Math.random, R.identity]), Math.floor), R.identity), R.of])
var rand10 = randN(10)
alert(R.times(rand10, 10)) // => [3, 1, 7, 5, 7, 5, 8, 4, 7, 2]
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.19.1/ramda.js"></script>

于 2016-03-23T22:39:19.567 回答