微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

打印咖喱函数不显示捕获的参数

如何解决打印咖喱函数不显示捕获的参数

如果我像这样定义一个柯里化函数

const gt = x => y => y > x

我希望 gt(5) 返回 y => y > 5

gt(5)(或gt(5).toString())返回y => y > x

如何获取捕获的参数?

解决方法

我希望 gt(5) 返回 y => y > 5

JavaScript 不是这样工作的。 gt(5) 返回的函数代码是 y => y > x,只是该代码在标识符 x 解析为具有值 5 的绑定的环境中执行,因为这是对该环境的关闭。函数上的 toString 返回函数源代码的字符串版本(或 [ native code ] 周围的函数声明)(spec),因此您仍然会看到 y => y > xtoString 返回的字符串不包括该代码运行的环境。

另见:


正如 @VLAZa comment 中指出的那样,您可以覆盖函数的默认 toString 以赋予它您想要的行为。如果您不介意重复(这几乎不可避免地会导致维护问题):

const gt = x => {
    const fn = y => y > x;
    fn.toString = () => `y => y > ${x}`;
    return fn;
};
console.log(String(gt(5)));

...或者如果您想定义 toString 与原型上的版本具有相同的可枚举性等:

Object.defineProperty(fn,"toString",{
    value: () => `y => y > ${x}`,writable: true,configurable: true,});

在一般情况下这样做需要一个合适的 JavaScript 解析器来进行替换。

,

仅仅打印在闭包中捕获的变量是不可能的,但是对于 curry 有一个解决方法。我将参考 Brian Lonsdorf 在 Medium Debugging Functional 上的文章,其中详细介绍了 curry 和 compose。我衷心建议阅读文章本身,因为我只会使用必需品。

Brian Lonsdorf 提出了通用 curry 函数的自定义实现。原始版本取自an article by Erin Swenson-Healy

这是修改后的版本:

function fToString(f) {
  return f.name ? f.name : `(${f.toString()})`;
}

function curry(fx) {
  var arity = fx.length;

  function f1() {
    var args = Array.prototype.slice.call(arguments,0);
    if (args.length >= arity) return fx.apply(null,args);

    function f2() {
      return f1.apply(null,args.concat(Array.prototype.slice.call(arguments,0))); 
    }

    f2.toString = function() {
      return fToString(fx)+'('+args.join(',')+')';
    }
    return f2;
  };

  f1.toString = function() { return fToString(fx); }
  return f1;
}

const gt = curry((x,y) => y > x);
const sum3 = curry((x,y,z) => x + y + z);
const ltUncurried = (x,y) => y < x;

const lt = curry(ltUncurried);

console.log(gt(1));      // ((x,y) => y > x)(1)
console.log(sum3(1));    // ((x,z) => x + y + z)(1)
console.log(sum3(1,2)); // ((x,z) => x + y + z)(1,2)
console.log(sum3(1)(2)); // ((x,2)

console.log(lt(1));      // ltUncurried(1)

(为了更好的可读性,我修改了 fToString() 以在 f.toString() 周围包含括号)

这非常灵活,因为它允许对任何函数进行柯里化,而且还提供了对所述函数的更好记录。如果您认为最重要的细节需要,可以修改 toString 实现。

,
const gt = x => y => y > x
gt(1);

如果您只传递了 1 个参数,例如 gt(1),并且如果您在控制台中检查,x = 1,此时 y 不可用。因此,执行上下文(调用堆栈)将仅显示 x 参数,而对于 gt() 方法,它将仅显示代码 (y > x)。

下面给了我们一个提示,gt(1) 将首先将 x 绑定到 1,然后 返回一个新函数 f(y) = y > x = y > 1

你没有第二次传递第二个参数,这意味着现在函数 f(y) = 1 + y 被执行了,这一次,它会在 y 不可用的时候检查 y。并且参数 x 的值 1 仍然通过 Closure 保留在上下文中

它看起来和下面的闭包函数一样:-

function add(x) {
    return function (y) {
        return y > x
    }
}

var d = add(1)(2); ===>>>> true

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?