【问题标题】:How to change the value that a template string extrapolates如何更改模板字符串外推的值
【发布时间】:2019-11-20 00:34:27
【问题描述】:

我正在尝试编写一个简单的 Id monad 来玩和学习。

这是我写的:

const util = require('util');

const Id = x => ({
  [util.inspect.custom]: () => `Id(${x})`,
  map: f => Id.of(f(x)),
  flatMap: f => f(x),
  valueOf: () => `Id(${x})`,
});

Id.of = Id;

const foo = Id.of('foo');
const toUpper = str => Id.of(str.toUpperCase());

const fooBoxed = foo.map(toUpper); // Oh oh, should be Id(Id('FOO'));
const FOO = foo.flatMap(toUpper); // Yay, Id('FOO');

console.log(fooBoxed);
console.log(FOO);

fooBoxed 应该注销Id(Id(Foo)),但它会注销Id([object object])。 我尝试修改 valueOfinspect 但两者都不起作用。我怀疑${x} 调用了不同的方法,但我在互联网上找不到那个方法。我需要修改什么,以便 ${x} 为我的嵌套 Id monad 返回正确的字符串?

【问题讨论】:

  • 你想在这里达到什么目的?
  • 不应该valueOf()返回x吗?否则似乎没有办法拆箱。
  • 相关但不能解决您的问题:Symbol.toStringTag

标签: javascript node.js functional-programming template-strings


【解决方案1】:

您需要覆盖toString,而不是valueOf。与字符串连接(或插入模板字符串)会将值强制转换为字符串,并且您的对象继承 Object.prototype.toString 并返回 [object …]

const Id = x => ({
  toString: () => `Id(${x})`,
  map: f => Id.of(f(x)),
  flatMap: f => f(x),
});

Id.of = Id;

const foo = Id.of('foo');
const toUpper = str => Id.of(str.toUpperCase());

const fooBoxed = foo.map(toUpper);
const FOO = foo.flatMap(toUpper);

console.log(fooBoxed.toString()); // Yay, Id(Id('FOO'));
console.log(FOO.toString()); // Yay, Id('FOO');

但是,由于您似乎打算将其用于调试,因此您实际上应该使用 x 值的调试表示。为此,请自己致电util.inspect()

const util = require('util');

const Id = x => ({
  [util.inspect.custom]: () => `Id(${util.inspect(x)})`,
//                                   ^^^^^^^^^^^^
  map: f => Id.of(f(x)),
  flatMap: f => f(x),
  valueOf: () => x,
});
Id.of = Id;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多