- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我是根据我在对这个问题的答案的评论中进行的小型讨论创建这个问题的:design a method returning a value or changing some data but not both
@Kata 指出 OP 感兴趣的模式称为命令-查询分离,并认为这是构建代码的良好模型。
来自 wikipedia :
Command–query separation (CQS) is a principle of imperative computer programming. It was devised by Bertrand Meyer as part of his pioneering work on the Eiffel programming language.
It states that every method should either be a command that performs an action, or a query that returns data to the caller, but not both. In other words, Asking a question should not change the answer.1 More formally, methods should return a value only if they are referentially transparent and hence possess no side effects.
我质疑这个设计原则的合理性,因为通常它会使您的代码显得更加乏味。例如:您不能执行像 next = Queue.Dequeue(); 这样的简单语句,您需要两条指令:一条用于修改数据结构,一条用于读取结果。
@Kata 找到了另一种 Stack 实现,乍一看似乎满足了两全其美:借鉴函数式编程,我们将 Stack 定义为不可变数据结构。每当我们 push(x) 时,我们都会创建一个新的 Stack 节点,该节点保存值 x 并维护指向旧头 Stack 实例的指针。每当我们 pop() 时,我们只是返回指向下一个 Stack 实例的指针。因此我们可以坚持命令-查询分离原则。
示例堆栈实现:https://fsharpforfunandprofit.com/posts/stack-based-calculator/
但是,在这种情况下不清楚的一件事是您如何在保持对堆栈的多个引用同步的同时仍然遵守命令-查询分离原则?我没有看到一个明显的解决方案。因此,出于好奇,我将这个问题提交给社区,看看我们是否能找到令人满意的解决方案:)
编辑:这是问题的一个例子:
s = new Stack();
s2 = s
...
s = s.push(x);
assert(s == s2); // this will fail
最佳答案
在函数式编程 (FP) 风格中,我们经常设计我们的函数,这样我们就不需要保持这些引用同步。
考虑这种情况:您创建一个堆栈 s
,将其注入(inject)到 Client
对象中,然后将一个项目推送到 s
并获得一个新堆栈 s2
:
s = new Stack()
client = new Client(s)
s2 = s.push(...)
因为 s
和 s2
不同步(即,它们是不同的堆栈),在对象 client
中,它仍然看到旧版本的堆栈 (s
) 这是您不想要的。这是客户端
的代码:
class Client {
private Stack stack;
// other properties
public Client(Stack stack) { this.stack = stack; }
public SomeType foo(/*some parameters*/) {
// access this.stack
}
}
为了解决这个问题,函数式方法不使用这种隐式引用,而是将引用作为显式参数传递给函数:
class Client {
// some properties
public SomeType foo(Stack stack, /*some parameters*/) {
// access stack
}
}
当然,有时这会很痛苦,因为函数现在有一个额外的参数。 Client
的每个调用者都必须维护一个堆栈,以便调用 foo
函数。这就是为什么在 FP 中您倾向于看到比在 OOP 中具有更多参数的函数。
但是 FP 有一个概念可以减轻这种痛苦:所谓的 partial application .如果你已经有一个堆栈 s
,你可以写 client.foo(s)
来获得 foo
的“升级”版本,它没有需要一个堆栈,但只需要其他一些参数
。然后,您可以将升级后的 foo
函数传递给不维护任何堆栈的接收器。
不过,值得一提的是,有些人认为这种痛苦实际上是有帮助的。例如,Scott Wlaschin 在他的文章 Functional approaches to dependency injection 中:
The downside of course, is that there are now five extra parameters for the function, which looks painful. (Of course, the equivalent method in the OO version also had these five dependencies, but they were implicit).
In my opinion though, this pain is actually helpful! With OO style interfaces, there is a natural tendency for them to accrete crud over time. But with explicit parameters like this, there is a natural disincentive to have too many dependencies! The need for a guideline such as the Interface Segregation Principle is much diminished.
此外,Mark Seemann -- 这本书的作者 Dependency Injection -- 在 Dependency Rejection 上有一个有趣的系列.
如果你不能忍受那种痛苦,那么就打破 CQS,回到 Stack 的传统实现。毕竟,如果一个函数(比如 pop
/dequeue
)是众所周知的并且很清楚它既返回了一些东西又改变了它的内部数据,那么违反 CQS 是还不错。
即使在这种情况下,某些 FP 语言也提供消息传递机制,以便您可以以不编写代码改变数据(例如,使用赋值符号的代码)的方式实现可变堆栈。 MailboxProcessor在 F# 中就是这样一种机制。
希望这有帮助:)
关于design-patterns - CQS设计原理题: Implementing a Queue,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53237990/
我有两个关于这段代码的问题。 double*** pdata 和 int*** pmask 是什么意思?指向指针的指针?为什么或何时需要这样做? int 和 double 是不同的类型,double*
谁能用英文解释一下这是怎么回事? std::vector cats; //I get that cats is a vector of Cat objects if (std::find(cats.b
在C中,下列声明有区别吗: float DoSomething( const float arr[] ); 对比 float DoSomething( const float* arr ); 一个比另
我到 question 36我认为这很简单。像往常一样,我显然错了。我正在尝试在 Python 中执行此操作(因为我不知道 Python)。我的代码如下。我得到 19 作为输出,这显然是不正确的。我不
我已经通读了 MSDN 上的 Winsock2 文档,但如果有人能提供帮助,我仍然需要澄清一些事情。 我计划做一些类似于您在使用 WSAAsyncSelect() 时获得的设置,但使用一个单独的线程。
#include int main () { int *p = (int *)malloc((100*sizeof(int))); p++; free(p); /* do some
我想提供未知的“对象”并返回其成员之一的值。在 C# 中需要响应。 一般来说,我想我正在寻找这个方法的代码公共(public)静态对象 GetObjectMemberValue (object myO
由异常准确的 AI 提供支持的 20 个问题的简单在线游戏。 他们怎么猜得这么好? 最佳答案 您可以将其视为二进制搜索算法。在每次迭代中,我们都会提出一个问题,该问题应该会消除大约一半的可能单词选择。
拜托,有人可以解释一下吗: 如果文档说 STL std::vector finding element speed performace = O(ln(n)),这是什么意思。 O(ln(n)) - 什
我正在尝试通过遵循 Microsoft 为 ADSI API 和 Windows-RS crate 发布的 c++ 示例来使用 Rust 的事件目录。我不太明白这里发生了什么: https://doc
这是处理具有重复元素的单个列表的 nieve 案例,我在处理一些嵌套列表时遇到了麻烦,所以我想先写简单的案例。 所以我有: (defn packDuplicatesIntoLists [lis
我是新来的。我正在尝试解决此练习 Problem 18只是为了加强我的解决能力。我已经编码了答案。该任务要求“在 1,000,000 以下的质数中,有多少个数位之和等于两周中的天数?” (两周是 14
我正在尝试对POCO类中的某些字段进行索引,并将某些属性装饰为“忽略= true”,并且这些字段不应被索引,而应该被存储。我希望这些字段出现在搜索结果中,但不应作为索引。 我正在尝试对应索引的几个字段
我是编码的新手,正在尝试通过完成 Project Euler 问题来学习 Swift。我似乎有导致大量错误的不同版本的 Swift 代码。如果您对我的问题的格式有任何建议以供将来引用,请告诉我,谢谢。
对于problem statement在 google codejam 2008:第 1A 轮问题 3 In this problem, you have to find the last three
我是一名优秀的程序员,十分优秀!