使用Stack&;函数式编程中的队列(javascript)

使用Stack&;函数式编程中的队列(javascript),javascript,functional-programming,Javascript,Functional Programming,我读过一些关于函数式编程的文章,其中一个标准是“给定相同的输入,它们总是产生相同的输出”。根据这条规则,我如何在javascript中调用push/pull/shift/unshift,因为结果应该总是变化的?另外,如果需要将用户输入存储到数组中,您能否建议如何应用堆栈/队列或解决方法。谢谢 stack: [] recordData(value) { stack.push(value) ...... } “相同的输入相同的输出” 对Array.prototype.push是一

我读过一些关于函数式编程的文章,其中一个标准是“给定相同的输入,它们总是产生相同的输出”。根据这条规则,我如何在javascript中调用push/pull/shift/unshift,因为结果应该总是变化的?另外,如果需要将用户输入存储到数组中,您能否建议如何应用堆栈/队列或解决方法。谢谢

stack: []

recordData(value) {
    stack.push(value)
    ......
}
“相同的输入相同的输出”

Array.prototype.push
是一种破坏性功能,它会改变输入。您的堆栈/队列需要使用纯函数实现——显然,这些函数不会改变底层数据结构


具有约束力的协议

在继续之前,让我们先看一下
堆栈
合同

// stack contract
stackIsEmpty(emptyStack)               => true
stackIsEmpty(stackPush(x, emptyStack)) => false
stackPop(stackPush(x, emptyStack))     => [x, emptyStack]
这些函数的任何其他用途都是未定义的行为

  • 您必须
    stackPush
    将第一个值推送到
    emptyStack
  • 在调用堆栈上的
    stackPop
    之前,必须验证堆栈是否为空
您在下面看到的实现只是一个可能的实现。关键是只要合同得到履行,
Stack
的实现就无关紧要


“但是它是不变的吗?”

是的,当然,但是如果你必须看到它才能相信它,那就自己看看吧。我们创建一个示例堆栈,
s
,然后对其调用两次
stackPop
每个调用的结果都是相同的,因为我们实现了一个不可变的数据结构

//堆栈数据抽象
常量emptyStack={}
常量stackPush=(x,xs)=>f=>f(x,xs)
常量stackPop=s=>s((x,xs)=>[x,xs])
const stackIsEmpty=s=>s==emptyStack
//stackPush不会变异为emptyStack
设s=stackPush(1,清空堆栈)
log(stackIsEmpty(emptyStack))//true
//stackPop不会变异为s
让[test1,stack1]=stackPop(s)
log(test1,stack1)//1{}
//stackPop为相同的输入返回相同的值,s
让[test2,stack2]=stackPop(s)

log(test2,stack2)//1{}
您可以返回一个新的堆栈/队列。关于第二个问题,根据您如何实现堆栈/队列,它可能已经是一个数组了。@torazaburo,谢谢您的回答。但它必须违反“相同输入相同输出”的规则,例如,在第一次:stack.push(1),输出为[1];第二次:stack.push(1),输出为[1,1]。我怎样才能解决这个矛盾呢?Thanks@torazaburo,此外,另一个规则是“保持变量不变”,但堆栈和队列似乎会导致变量“Stack”始终更改。因此,我不知道我可以在函数式编程下使用它们吗?Thanks@Phil您不参与函数式编程标记。我想知道你为什么投票决定结束这个问题,因为你显然没有仔细研究给定的问题?堆栈的实现是故意刁钻的。它可以很容易地使用本机
数组实现,但我正在尝试从堆栈本身移除焦点。只要合同有效,
Stack
的具体实现是多么的不重要,这一点我说得太清楚了。非常有用,谢谢!!这个评论只是告诉我函数式编程对我来说是陌生的。我花了一段时间努力理解代码片段。你能推荐一个资源来探索如何使用函数式编程实现传统的数据结构吗?@KibongeMurphy当你在一个对象上设置属性或切片一个数组时,你会考虑如何执行这些操作吗?当你上车时,转动点火开关上的钥匙,踩下油门并转动方向盘,你会想到油泵、喷油器和动力转向马达吗?所有的汽车都以完全相同的方式实现这些功能吗?抽象的要点是从最终用户那里删除这些细节和关注点。作为司机,我们只关心汽车在汽油被踩下时打开并向前移动,在刹车被踩下时停止,等等。(续)你可能会从阅读中受益。在这个网站上,我也有一些帖子。
// stack contract
stackIsEmpty(emptyStack)               => true
stackIsEmpty(stackPush(x, emptyStack)) => false
stackPop(stackPush(x, emptyStack))     => [x, emptyStack]