如何使用 Ramda 将代码从 Lisp (MIT Schema) 翻译成 JavaScript?

How to translate code from Lisp (MIT Schema) into JavaScript using Ramda?

我目前正在自学函数式编程。

我正在尝试翻译以下内容:

(define a 3)
(define b (+ a 1))

(* (cond ((> a b) a)
         ((< a b) b)
         (else -1))
   (+ a 1))

变成 JavaScript (使用 Ramda)。

可以使用嵌套的三元组,但我喜欢使用 Ramda 的 cond 函数。这是我所做的:

const a = 3;
const b = 3 + 1;

cond([[() => a > b, () => a], [() => a < b, () => b], [T, () => -1]])() * (a + 1)

我遇到的问题是我必须使用这些函数(例如 () => 3)而不仅仅是它们的值(例如 a)。

有什么办法可以避免这些功能吗?或者在 JavaScript 中是否有另一种更好的方法(甚至可能没有 Rambda)?

我想避免使用 ifforswitch.

等语句

另一种解决方法是使用:

import gt from "ramda/src/gt";
import lt from "ramda/src/lt";

const a = () => 3;
const b = () => a() + 1;


cond([[gt(a, b), a], [lt(a, b), b], [T, () => -1]])() * (a() + 1);

这使 ab 变得复杂,因为它们总是必须被调用(参见 a() + 1)。

编辑:

出于某种原因,我将 ab 定义为函数的最后一段代码不起作用

Ramda 是自动柯里化的,因此您可以使用一些参数调用该函数,并返回一个新函数。例如:

const { pipe, cond, gt, lt, T, always, identity, multiply } = R

const a = 3
const b = 3 + 1

const fn = (a) => pipe(
  cond([
    [gt(a), always(a)],
    [lt(a), identity],
    [T, always(-1)]
  ]),
  multiply(a + 1)
)

const result = fn(a)(b)

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>

在 Scheme 中不必将所有内容都包装在 thunk(即不带参数的函数)中的原因是因为 cond 是一个扩展为嵌套 if 的宏,在你的情况:

(if (> a b) a
  (if (< a b) b
    -1))

所以不,如果你想避免三元运算符并将所有内容包装在 thunk 中,你对 vanilla JS 没有太多选择。

如果您不介意使用非标准 JS,您可以使用 Sweet.js...

的宏来实现 cond

我认为您是在有点误解的情况下工作的。 cond旨在给你一个功能。它实际上不是为为表达式创建标量值而设计的。它当然可以这样做,只需立即调用它生成的函数即可。但这不是重点。此外,它实际上并不意味着使用空函数进行调用(默认情况下传递 T 的情况除外。)。同样,您可以这样做,但它违背了该工具的宗旨。

尽管 Ramda 从 LISP 风格和 ML 风格的函数式语言中汲取灵感,虽然我个人更喜欢前者,但 Ramda 更接近 ML 世界,尤其是 Haskell。所以它主要activity支持的是通过组合其他函数来构建函数。

如果我要解决这个问题,我可能不会使用任何 Ramda,选择这样的东西:

const larger = (a, b) => (a > b) ? a : (b > a) ? b : -1
const foo = (a, b) => (a + 1) * larger(a, b)

foo(3, 4) //=> 16
foo(6, 3) //=> 42
foo(3, 3) //=> -4

或者,如果我不需要重用 larger,我可能会像这样内联它:

const foo = (a, b) => (a + 1) * ((a > b) ? a : (b > a) ? b : -1)

当然我可以用 Ramda 写这个,而且是无意义的方式:

const larger = cond([[gt, unapply(head)], [lt, unapply(last)], [T, always(-1)]])
const foo = converge(multiply, [inc, larger])

或者,我可能会内联 larger,或者将 unapply(head) 替换为 nthArg(0),将 unapply(last) 替换为 nthArg(1)

但是 none 这些选项与原始选项一样可读。 Ramda 在这里没有添加任何我能看到的内容。请注意,我是 Ramda 的忠实粉丝;我创办了这个图书馆,并且是它的主要作者之一。但我不认为它应该用于所有问题。