通过链接的JavaScript函数组合
我已经检查了重复问题的可能性, 也找不到确切的答案 我用JavaScript编写了一些函数链代码,如下所示,效果很好通过链接的JavaScript函数组合,javascript,node.js,Javascript,Node.js,我已经检查了重复问题的可能性, 也找不到确切的答案 我用JavaScript编写了一些函数链代码,如下所示,效果很好 var log = function(args) { console.log(args) return function(f) { return f; }; }; (log('1'))(log('2'))(log('3'))(log('4')); //1 //2 //3 //4 我想做这个懒惰的评估 或编写函数 var log = function
var log = function(args)
{
console.log(args)
return function(f)
{
return f;
};
};
(log('1'))(log('2'))(log('3'))(log('4'));
//1
//2
//3
//4
我想做这个懒惰的评估
或编写函数
var log = function(args)
{
var f0 = function()
{
return console.log(args);
};
return function(f1)
{
return function()
{
f0();
return f1;
};
};
};
var world = (log('1'))(log('2'))(log('3'))(log('4'));
console.log(world);
//should be just a function,
// but in fact
//1
//[function]
world();
//should be
//1
//2
//3
//4
// but in fact
// 2
有些事情很不对劲。
你能修好它吗
谢谢
这个问题已经解决了,但还有进一步的问题
注释讨论中显示的异步问题
当我们有
// unit :: a -> IO a
var unit = function(x)
{
return function()
{
return x;
};
};
// bind :: IO a -> (a -> IO b) -> IO b
var bind = function(x, y)
{
return function()
{
return y(x())();
};
};
// seq :: IO a -> IO b -> IO b
var seq = function(x, y)
{
return function()
{
return x(), y();
};
};
var action = function(x)
{
return function(y)
{
return y ? action(seq(x, y)) : x();
};
};
var wrap = function(f)
{
return function(x)
{
return action(function()
{
return f(x);
});
};
};
var log = wrap(console.log);
// -- runtime --
// HACK: when `world` is modified by passing a function,
// the function will be executed.
Object.defineProperties(window,
{
world:
{
set: function(w)
{
return w();
}
}
});
我们也常常非常希望异步链式反应
var asyncF = function(callback)
{
setTimeout(function()
{
for (var i = 0; i < 1000000000; i++)
{
};
callback("async process Done!");
}, 0);
};
var async = wrap(asyncF(function(msg)
{
world = log(msg);
return msg;
}));
到目前为止还很好,很平滑,现在我们尝试使用bind
world = (log(1))
(bind((async), (log(x))));
//should be
//1
//async process Done!
//3
//in fact
//ReferenceError: x is not defined
请你修改一下以使它工作好吗
关于retrunx,y的更多信息代码>多值
我不明白
// seq :: IO a -> IO b -> IO b
var seq = function(x, y)
{
return function()
{
return x(), y();
};
};
正如图书馆作者所提到的
注意,这在Haskell中是不可能的,因为一个函数不能返回两个结果。而且,依我拙见,它看起来很丑
我同意,但不知道这是怎么回事
返回x(),y()代码>
多重返回值
我在这里搜索,但找不到答案
这是什么
(以防万一,我会选择这个黑客的语法)
谢谢 这是因为您正在返回并返回所有内容
输出中打印了三个内容:
1
function ()
{
f0();
return f1;
}
2
1) 第一次输出:1
这是因为:console.log(args)
在链接中只执行一次,因为f0在最后一次发现args
为1时只执行一次(因为返回每个嵌套函数,最后返回的值是函数f1,当args的值为1时执行f0()。
然后它将1打印到控制台
2) 第二次输出函数f1
返回f1上次返回时执行的代码>(将args作为1传递给函数时返回)
function ()
{
f0();
return f1;
}
回到变量世界,因此只有内部嵌套函数被打印到控制台
3) 第三次产出:2
然后在执行函数world()
时
同样,直接执行函数f1(请参见world
和world()
)之间的细微差别),但这一次是在您将args
作为2
传递时返回的函数
原因:world将只输出函数,world()
将执行函数。
编写world()
时,在上次返回函数f1
时,直接执行args was 2的值
我知道我的回答措辞很糟糕。。但希望这有帮助(希望您理解)让我们看看这里发生了什么:
var log = function(args)
{
var f0 = function()
{
return console.log(args);
};
return function(f1)
{
return function()
{
f0();
return f1;
};
};
};
再加上一点:
var log = function(args) {
return function(f1) {
return function() {
console.log(args);
return f1;
};
};
};
因此,我们返回一个函数f
,它接受一个函数f1
,并返回一个函数g
,该函数执行逻辑并返回f1
。真是太多了!你的问题是你为什么要这么做
(log('1'))(log('2'))(log('3'));
日志1
。我去掉了log('4')
,因为转到3就足以显示您描述的案例。为了回答这个问题,让我们玩编译器和内联游戏吧
(log('1'))(log('2'))(log('3'))
// =>
(
function (f1) {
return function () {
console.log('1');
return f1;
}
}
)(
function (f1) {
return function () {
console.log('2');
return f1;
}
}
)(
function (f1) {
return function () {
console.log('3');
return f1;
}
}
)
简单替换。我获取了log(something)
的每个实例,用函数的内容替换它,用传递的值替换参数。让我们再来一次
(
function () {
console.log('1');
return function (f1) {
return function () {
console.log('2');
return f1;
}
};
}
)(
function (f1) {
return function () {
console.log('3');
return f1;
}
}
)
下面这个有点棘手:我扩展了第一个函数调用。最顶层的函数接收到一个参数f1
,我们只为它提供了一个值,因此我进入该函数并用给定的值替换了f1
的每一次出现(结果是log('2')
),就像log
参数一样
如果您仍然没有遵循,请再次查看此处发生的情况,但我的建议是自己执行:将代码段复制到您最喜欢的代码编辑器中,然后自己进行扩展
现在您可以了解调用log('1')
的原因。我们编译器接下来需要做的就是处理下一个函数调用。你知道吗,该函数的第一行是一个控制台.log
!最好去做
我们能做什么!?
我不知道Haskell或IO Monad,但正如你目前计划的那样,我认为你不能用基本功能做你想做的事情,不是那样的。如果你能说出你想用这个…呃…模式解决什么问题,也许我们能帮上忙 因此,如果我正确理解了这个问题,您希望在JavaScript中链接IO操作。为此,您首先需要定义IO操作是什么。理解IO操作的一种方式是,它只是一个不带参数的函数。例如:
// log :: a -> IO b
function log(x) {
return function () { // IO action
return console.log(x);
};
}
将IO操作表示为不带参数的函数的一个优点是,它与()的表示形式相同。Thunks是在Haskell这样的语言中支持惰性计算的东西。因此你可以免费得到懒惰
现在是作文。如何用JavaScript编写两个IO操作?在Haskell中,您使用>
操作符对IO操作进行排序,通常根据>=
(又称绑定
)定义如下:
// sequence :: [IO a] -> IO [a]
function sequence(array) {
return function () {
var list = array;
var length = list.length;
var result = new Array(length);
var index = 0;
while (index < length)
result[index] = list[index++]();
return result;
};
}
(>>=)::Monad m=>ma->(a->mb)->mb
(>>)::单子m=>MA->MB->MB
x>>y=x>>=\\\->y
用JavaScript为IO操作编写等效的bind
函数很容易:
// bind :: IO a -> (a -> IO b) -> IO b
function bind(x, y) {
return function () {
return y(x())();
};
}
假设您有一个IO操作x::IO a
。因为它只是一个没有参数的函数,所以当您调用它时,它相当于计算IO操作。因此x()::a
。将此结果馈送到函数y::a->IO b
将导致IO操作y(x())::IO b
。请注意,整个操作都包含在一个多余的惰性函数中
类似地,实现>
操作符也同样简单。让我们把它称为“序列”
// seq :: IO a -> IO b -> IO b
function seq(x, y) {
return function () {
return x(), y();
};
}
这里我们计算IO表达式x
,不关心其结果,然后返回IO表达式y
。这正是歌剧院的风格
// unit :: a -> IO a
function unit(x) {
return function () {
return x;
};
}
// sequence :: [IO a] -> IO [a]
function sequence(array) {
return function () {
var list = array;
var length = list.length;
var result = new Array(length);
var index = 0;
while (index < length)
result[index] = list[index++]();
return result;
};
}
var world = sequence([log("1"), log("2"), log("3"), log("4")]);
world();
// 1
// 2
// 3
// 4
function action(x) {
return function (y) {
return y ? action(seq(x, y)) : x();
};
}
// log :: a -> IO b
// log :: a -> IO r -> IO r
function log(x) {
return action(function () {
return console.log(x);
});
}
log("1")(); // :: b
log("1")(log("2")); // :: IO r
var world = (log("1"))(log("2"))(log("3"))(log("4"));
world();
// 1
// 2
// 3
// 4
var newWorld = (world)(log("5"));
newWorld();
// 1
// 2
// 3
// 4
// 5
var world = (log('1'))(log('2'))(log('3'))(log('4'));
if(typeof(arguments[0]) == 'function'){
console.log("Got a neglected argument");
console.log(arguments[0]());
}
2
4
undefined