问题描述
我想知道为什么使用kestrel收拾代码的副作用部分是如此有用.有人有经验吗?并可以解释真正的动机及其对准确的帮助.
尽管我知道纯函数编程是关于零端效应,因此,该代码的调试和可预测性更好.但是,对于Kestrel,我看不出这是如何真正帮助这样做的?
最好,
mm-
推荐答案
关键是要避免创建您可能不想躺在周围的中间变量,或者避免为您在传递中所做的事情创建一个新的块.让我们假设我们的kestrel如Ruby:
implicit class RubyKestrel[A](val repr: A) extends AnyVal { def tap[B](f: A => B) = { f(repr); repr } }
现在让我们假设我们有一些代码线:
xs.map(_ + 7).filter(foo).take(n)
,我们想在过滤器后打印出调试消息.没有tap我们将该行重构为:
{ val temp = xs.map(_ + 7).filter(foo) println(temp) temp.take(n) }
ugh.现在假设我们有tap:
xs.map(_ + 7).filter(foo).tap(println).take(n)
哇,更好!
让我们假设我们有一个具有添加方法的堆栈,我们想在使用其他地方之前在堆栈中添加一些东西.
def newStack = { val stack = new Stack stack add "whatever" stack }
ugh.但是使用tap:
def newStack = (new Stack).tap(_ add "whatever")
非常方便 - 它实际上只能让您将任何普通的副作用方法变成可以链接的东西.而且由于链式电话通常是较低的样板,所以这通常是一个很大的胜利.
问题描述
I'm wondering why is it so useful to put away the side effect part of a code using Kestrel. Does anyone has experience with it? and can explain the real motivation and how does it help exactly.
Although i understand that Pure functional programing is about zero-side effect and henceforth better debugging and predictability of the code. However in the case of Kestrel, I don't see how it really help to do that ?
Best,
MM-
推荐答案
The point is to avoid creating an intermediate variable that you probably don't want to have lying around, or to avoid having to create a new block for something you're doing in passing. Let's suppose we have the Kestrel as in Ruby:
implicit class RubyKestrel[A](val repr: A) extends AnyVal { def tap[B](f: A => B) = { f(repr); repr } }
Now let's suppose we have some line of code:
xs.map(_ + 7).filter(foo).take(n)
and we want to print out a debugging message after the filter. Without tap we refactor that line to:
{ val temp = xs.map(_ + 7).filter(foo) println(temp) temp.take(n) }
Ugh. Now suppose we have tap:
xs.map(_ + 7).filter(foo).tap(println).take(n)
Whew, way better!
Let's suppose we have a stack that has an add method, and we want to add something to the stack before using it somewhere else.
def newStack = { val stack = new Stack stack add "whatever" stack }
Ugh. But with tap:
def newStack = (new Stack).tap(_ add "whatever")
Pretty handy--it really just lets you turn any normal side-effecting method into something that you can chain calls to. And since chained calls are often lower boilerplate, that's often a big win.