从没有数组的功能链中提取数据 [英] Extracting data from a function chain without arrays

查看:87
本文介绍了从没有数组的功能链中提取数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是的高级主题

如何存储功能数据单项列表链?

我非常确定我们可以以某种方式从功能链中提取数据,而无需使用存储数据的数组. 基本结构是:

I am pretty sure we can somehow extract data from a function chain without using an array storing data. The basic structure is :

L = a => L

非常简单,但是此结构会生成一个列表:

very simple, but this structure generates a list:

L(1)(2)(3)(4)(5)(6)()

这可能与 什么是DList? ,但这种结构严格地仅依赖于功能链.

This may be related to What is a DList? , but this structure strictly depends on function chain only.

那么,提取所有值的方法是什么? 我目前的成就仅仅是拔出头和尾巴,我不知道该如何解决.

So, what is the way to pull out the whole values? Current achievement of mine merely pulling out the head and tail, and I don't know how to fix this.

我忘了说我想做的事

操作.

因此,如果选择f作为Array.concat,则意味着您可以将数据提取为数组,但是折叠并不仅仅限于数组串联.和f可以加/加等.

So, if one choses f as Array.concat which means you can extract data as an array, but simply fold is not limited to array concatenation. and f can be add/sum etc.

因此,到目前为止,从某种意义上讲,到目前为止,我可以将内部行为可视化,我将log编写为f.

So, currently, so far, to visualize the internal behavior, in a sense, I write log as f.

EDIT2

我必须澄清更多.可以显示该规范:

I must clarify more. The specification can be presented:

const f = (a) => (b) => a + b;//binary operation

A(a)(b)(f) = f(a)(b)  // a + b

A(a)(b)(c)(f) = f(f(a)(b))(c) // a + b + c

这完全是

(a b c).reduce(f)

事物以及何时

f = (a) => (b) => a.concat(b)

结果将为[a, b, c].

Array.concat仅仅是广义二进制运算f的成员.

Array.concat is merely a member of generalized binary operations f.

起初,对我而言,这项挑战很容易,但结果却很难,并觉得最好问一个更聪明的编码器.

At first this challenge is easy for my skill, but turned out hard and felt it's better to ask smarter coder.

谢谢.

const A = a => {

    const B = b => (b === undefined)
        ? (() => {
            log("a " + a);
            return A();
        })()
        : c => (c === undefined)
            ? (() => {
                log("b " + b);
                return B()();
            })()
            : B;

    return B;

};
 

A(1)(2)(3)(4)(5)(6)()

function log(m)  {
    console.log((m)); //IO
    return m;
};

b 6
a 1
a undefined

推荐答案

给出一个类似A(a)(b)(f)的表达式,其中f是一个函数,因此无法知道是否应该将f添加到列表中或是否这是归约功能.因此,我将描述如何编写与[a, b].reduce(f, x)等价的A(a)(b)(f, x)之类的表达式.这使我们可以根据您提供的参数来区分列表何时结束:

Given an expression like A(a)(b)(f) where f is a function, it's impossible to know whether f is supposed to be added to the list or whether it's the reducing function. Hence, I'm going to describe how to write expressions like A(a)(b)(f, x) which is equivalent to [a, b].reduce(f, x). This allows us to distinguish when the list ends depending upon how many arguments you provide:

const L = g => function (x, a) {
    switch (arguments.length) {
    case 1: return L(k => g((f, a) => k(f, f(a, x))));
    case 2: return g((f, a) => a)(x, a);
    }
};

const A = L(x => x);

const xs = A(1)(2)(3)(4)(5);

console.log(xs((x, y) => x + y, 0));        // 15
console.log(xs((x, y) => x * y, 1));        // 120
console.log(xs((a, x) => a.concat(x), [])); // [1,2,3,4,5]

它可以继续工作.每次添加新元素时,我们都会累积CPS函数.每个CPS功能都调用先前的CPS功能,从而创建一个CPS功能链.当我们为该CPS功能链提供基本功能时,它将展开该链并允许我们减少它. 传感器

It works due to continuations. Every time we add a new element, we accumulate a CPS function. Each CPS function calls the previous CPS function, thereby creating a CPS function chain. When we give this CPS function chain a base function, it unrolls the chain and allows us to reduce it. It's the same idea behind transducers and lenses.

编辑: user633183的解决方案非常出色.它使用使用右折对列表进行教会编码来减轻连续性的需要,从而用更容易理解的简单代码.这是她的解决方案,经过修改后使foldr看起来像foldl:

user633183's solution is brilliant. It uses the Church encoding of lists using right folds to alleviate the need for continuations, resulting in simpler code which is easy to understand. Here's her solution, modified to make foldr seem like foldl:

const L = g => function (x, a) {
    switch (arguments.length) {
    case 1: return L((f, a) => f(g(f, a), x));
    case 2: return g(x, a);
    }
};

const A = L((f, a) => a);

const xs = A(1)(2)(3)(4)(5);

console.log(xs((x, y) => x + y, 0));        // 15
console.log(xs((x, y) => x * y, 1));        // 120
console.log(xs((a, x) => a.concat(x), [])); // [1,2,3,4,5]

此处g是到目前为止已累积的教会编码列表.最初,它是空列表.调用g会将其从右侧折叠.但是,我们也从右侧构建列表.因此,由于我们编写列表的方式,似乎我们正在构建列表并将其从左侧折叠.

Here g is the Church encoded list accumulated so far. Initially, it's the empty list. Calling g folds it from the right. However, we also build the list from the right. Hence, it seems like we're building the list and folding it from the left because of the way we write it.

如果所有这些功能使您感到困惑,那么user633183真正在做什么:

If all these functions are confusing you, what user633183 is really doing is:

const L = g => function (x, a) {
    switch (arguments.length) {
    case 1: return L([x].concat(g));
    case 2: return g.reduceRight(x, a);
    }
};

const A = L([]);

const xs = A(1)(2)(3)(4)(5);

console.log(xs((x, y) => x + y, 0));        // 15
console.log(xs((x, y) => x * y, 1));        // 120
console.log(xs((a, x) => a.concat(x), [])); // [1,2,3,4,5]

如您所见,她正在向后构建列表,然后使用reduceRight向后折叠后向列表.因此,看起来您正在构建列表并将其向前折叠.

As you can see, she is building the list backwards and then using reduceRight to fold the backwards list backwards. Hence, it looks like you're building and folding the list forwards.

这篇关于从没有数组的功能链中提取数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆