美文网首页
04. So You Want to be a Function

04. So You Want to be a Function

作者: ngugg | 来源:发表于2018-10-30 20:48 被阅读5次

    相关链接:

    https://medium.com/@cscalfani/so-you-want-to-be-a-functional-programmer-part-4-18fbe3ea9e49

    Taking that first step to understanding Functional Programming concepts is the most important and sometimes the most difficult step. But it doesn’t have to be. Not with the right perspective.

    • 采用第一步来理解功能编程概念是最重要的,有时也是最困难的步骤。 但它不一定是。 没有正确的观点。

    If you remember from Part 3, the reason that we were having problems composing mult5 and add (in ) is because mult5 takes 1 parameter and addtakes 2.

    • 如果你记得第3部分,我们在编写mult5和add(in)时遇到问题的原因是因为mult5方法需要1个参数,add方法需要2个。

    We can solve this easily by just restricting all functions to take only 1 parameter.

    • 我们可以通过将所有函数限制为仅采用1个参数来轻松解决此问题。

    Trust me. It’s not as bad as it sounds.

    • 相信我。 它没有听起来那么糟糕。

    We simply write an add function that uses 2 parameters but only takes 1 parameter at a time. Curried functions allow us to do this.

    • 我们只需编写一个使用2个参数的add函数,但一次只需要1个参数。 *** Curried ***功能允许我们这样做。

    A Curried Function is a function that only takes a single parameter at a time.

    • Curried Function是一个一次只接受一个参数的函数。

    This will let us give add its first parameter before we compose it with mult5. Then when mult5AfterAdd10 is called, add will get its second parameter.

    • 这将让我们在用mult5编写它之前给add方法传递它的第一个参数。 然后当调用mult5AfterAdd10时,add将获得其第二个参数。

    In Javascript, we can accomplish this by rewriting add:

    • 在Javascript中,我们可以通过重写add来实现这一点:

    var add = x => y => x + y

    This version of add is a function that takes one parameter now and then another one later.

    • 这个版本的add是一个函数,它现在接受一个参数,然后再接受另一个参数。

    In detail, the add function takes a single parameter, x, and returns a function that takes a single parameter, y, which will ultimately return the result of adding x and y.

    • 详细地说,add函数接收一个参数x,并返回一个接收一个参数y的函数,该参数将最终返回添加x和y的结果。

    Now we can use this version of add to build a working version of mult5AfterAdd10:

    • 现在我们可以使用这个版本的add来构建mult5AfterAdd10的工作版本:

    var compose = (f, g) => x => f(g(x));
    var mult5AfterAdd10 = compose(mult5, add(10));

    The compose function takes 2 parameters, f and g. Then it returns a function that takes 1 parameter, x, which when called will apply f after g to x.

    • compose函数有两个参数f和g。 然后它返回一个接收参数x的函数,该函数在被调用时将x传递给g方法,之后从g方法返回的结果传递给f方法。

    So what did we do exactly? Well, we converted our plain old add function into a curried version. This made add more flexible since the first parameter, 10, can be passed to it up front and the final parameter will be passed when mult5AfterAdd10 is called.

    • 那我们到底做了什么? 好吧,我们将普通的add方法转换为curried version.。 这使得add 方法更加灵活,因为第一个参数10可以预先传递给它,最后一个参数将在调用mult5AfterAdd10时传递。

    At this point, you may be wondering how to rewrite the add function in Elm. Turns out, you don’t have to. In Elm and other Functional Languages, all functions are curried automatically.

    • 此时,您可能想知道如何在Elm中重写add函数。 事实证明,你不必这么做。 在Elm和其他功能语言中,所有功能都会自动进行。(所有功能都自动调整)

    So the add function looks the same:

    • 所以add函数看起来是一样的:
    image.png

    This is how mult5AfterAdd10 should have been written back in Part 3:

    • 这就是mult5AfterAdd10应该在第3部分中写回的方式:
    image.png

    Syntactically speaking, Elm beats Imperative Languages like Javascript because it’s been optimized for Functional things like currying and composition.

    • 从语法上讲,Elm击败了像Javascript这样的命令式语言,因为它已经针对像currying和composition这样的功能性事物进行了优化。
    image.png

    Another time currying shines is during refactoring when you create a generalized version of a function with lots of parameters and then use it to create specialized versions with fewer parameters.

    • 另一个时间是在重构期间,当您创建具有大量参数的函数的通用版本时,然后使用它来创建具有较少参数的专用版本。

    For example, when we have the following functions that put brackets and double brackets around strings:

    • 例如,当我们有以下函数将括号和双括号放在字符串周围时:
    image.png

    Here’s how we’d use it:

    • 以下是我们如何使用它:
    image.png

    We can generalize bracket and doubleBracket:

    • 我们可以概括括号和doubleBracket:
    image.png

    But now every time we use generalBracket we have to pass in the brackets:

    • 但是现在每次我们使用generalBracket时我们都要传递括号:
    image.png

    What we really want is the best of both worlds.

    • 我们真正想要的是两全其美。

    If we reorder the parameters of generalBracket, we can create bracket and doubleBracket by leveraging the fact that functions are curried:

    • 如果我们重新排序generalBracket的参数,我们可以通过利用函数curried的事实来创建括号和doubleBracket:
    image.png

    Notice that by putting the parameters that were most likely to be static first, i.e. prefix and suffix, and putting the parameters that were most likely to change last, i.e. str, we can easily create specialized versions of generalBracket.

    • 请注意,通过首先放置最可能是静态的参数,即前缀和后缀,并放置最有可能最后改变的参数,即str,我们可以轻松地创建generalBracket的专用版本。

    Parameter order is important to fully leverage currying.
    Also, notice that bracket and doubleBracket are written in point-free notation, i.e. the str parameter is implied. Both bracket and doubleBracket are functions waiting for their final parameter.

    • 参数顺序对于充分利用currying非常重要。
      另请注意,括号和doubleBracket是以无点表示法编写的,即str参数是隐含的。 括号和doubleBracket都是等待其最终参数的函数。

    Now we can use it just like before:

    • 现在我们可以像以前一样使用它:
    image.png

    But this time we’re using a generalized curried function, generalBracket.

    • 但这一次我们使用的是广义curried函数generalBracket。

    Common Functional Functions

    • 常用功能
    image.png

    Let’s look at 3 common functions that are used in Functional Languages.

    • 我们来看一下Functional Languages中使用的3个常用函数。

    But first, let’s look at the following Javascript code:

    • 但首先,让我们看看以下Javascript代码:
    image.png

    There’s one major thing wrong with this code. It’s not a bug. The problem is that this code is boilerplate code, i.e. code that is written over and over again.

    • 这段代码有一个重大问题。 这不是一个错误。 问题是这段代码是样板代码,即一遍又一遍地写的代码。

    If you code in Imperative Languages like Java, C#, Javascript, PHP, Python, etc., you’ll find yourself writing this boilerplate code more than any other.

    • 如果您使用诸如Java,C#,Javascript,PHP,Python等命令式语言进行编码,您将发现自己编写的样板代码比其他任何代码都要多。

    That’s what’s wrong with it.

    • 这就是它的错误。

    So let’s kill it. Let’s put it in a function (or a couple of functions) and never write a for-loop again. Well, almost never; at least until we move to a Functional Language.

    • 所以,让我们杀了它。 让我们把它放在一个函数(或几个函数)中,永远不要再写一个for循环。 好吧,几乎没有; 至少在我们转向功能语言之前。

    Let’s start with modifying an array called things:

    • 让我们从修改一个名为thing的数组开始:
    image.png

    UGH!! Mutability!

    • 啊!!可变性!

    Let’s try that again. This time we won’t mutate things:

    • 让我们再试一次。 这次我们不会改变事情:
    image.png

    Okay, so we didn’t mutate things but technically we mutated newThings. For now, we’re going to overlook this. We are in Javascript after all. Once we move to a Functional Language, we won’t be able to mutate.

    • 好吧,所以我们没有改变事物,但从技术上讲,我们改变了新事物。 现在,我们将忽略这一点。 毕竟我们在Javascript中。 一旦我们转向函数式语言,我们将无法改变。

    The point here is to understand how these functions work and help us to reduce noise in our code.

    • 这里的要点是了解这些功能如何工作并帮助我们减少代码中的噪音。

    Let’s take this code and put it in a function. We’re going to call our first common function map since it maps each value in the old array to new values in the new array:

    • 让我们把这段代码放在一个函数中。 我们将调用我们的第一个公共函数映射,因为它将旧数组中的每个值映射到新数组中的新值:
    image.png

    Notice the function, f, is passed in so that our map function can do anything we want to each item of the array.

    • 请注意,函数f被传入,以便我们的map函数可以对数组的每个项执行任何操作。

    Now we can call rewrite our previous code to use map:

    • 现在我们可以调用重写前面的代码来使用map:
    image.png

    Look ma. No for-loops. And much easier to read and therefore reason about.

    • 看马。 没有for循环。 而且更容易阅读,因此推理。

    Well, technically, there are for-loops in the map function. But at least we don’t have to write that boilerplate code anymore.

    • 嗯,从技术上讲,map函数中有for循环。 但至少我们不必再写那个样板代码了。

    Now let’s write another common function to filter things from an array:

    • 现在让我们编写另一个常用函数来过滤数组中的东西:
    image.png

    Notice how the predicate function, pred, returns TRUE if we keep the item or FALSE if we toss it.

    • 注意如果我们保留项目,谓词函数pred如何返回TRUE,如果我们丢弃它,则返回FALSE。

    Here’s how to use filter to filter odd numbers:

    • 以下是使用过滤器过滤奇数的方法:
    image.png

    Using our new filter function is so much simpler than hand-coding it with a for-loop.

    • 使用我们的新过滤器功能比使用for循环手动编码要简单得多。

    The final common function is called reduce. Typically, it’s used to take a list and reduce it to a single value but it can actually do so much more.

    • 最后的常用函数叫做reduce。 通常,它用于获取列表并将其减少为单个值,但它实际上可以做得更多。

    This function is usually called fold in Functional Languages.

    • 此功能通常在功能语言中称为折叠。
    image.png

    The reduce function takes a reduction function, f, an initial start value and an array.

    • reduce函数采用缩减函数f,初始起始值和数组。

    Notice that the reduction function, f, takes 2 parameters, the current item of the array, and the accumulator, acc. It will use these parameters to produce a new accumulator each iteration. The accumulator from the final iteration is returned.

    • 请注意,缩减函数f需要2个参数,即数组的当前项和累加器acc。 它将使用这些参数在每次迭代时生成一个新的累加器。 返回最后一次迭代的累加器。

    An example will help us understand how it works:

    • 一个例子将帮助我们理解它是如何工作的:
    image.png

    Notice that the add function takes 2 parameters and adds them. Our reduce function expects a function that takes 2 parameters so they work well together.

    • 请注意,add函数接受2个参数并添加它们。 我们的reduce函数需要一个带有2个参数的函数,以便它们能很好地协同工作

    We start with a start value of zero and pass in our array, values, to be summed. Inside the reduce function, the sum is accumulated as it iterates over values. The final accumulated value is returned as sumOfValues.

    • 我们从一个零的起始值开始,并传入我们的数组值,进行求和。 在reduce函数内部,总和在迭代值时累积。 最终累计值以sumOfValues的形式返回。

    Each of these functions, map, filter and reduce let us do common manipulation operations on arrays without having to write boilerplate for-loops.

    • 这些函数中的每一个,map,filter和reduce都让我们在数组上进行常见的操作操作,而无需编写样板for循环。

    But in Functional Languages, they are even more useful since there are no loop constructs just recursion. Iteration functions aren’t just extremely helpful. They’re necessary.

    • 但是在Functional Languages中,它们甚至更有用,因为没有循环结构只是递归。 迭代函数不仅非常有用。 他们是必要的。

    Enough for now.

    • 够了。

    In subsequent parts of this article, I’ll talk about Referential Integrity, Execution Order, Types, and more.

    • 在本文的后续部分中,我将讨论参考完整性,执行顺序,类型等。

    相关文章

      网友评论

          本文标题:04. So You Want to be a Function

          本文链接:https://www.haomeiwen.com/subject/qfkgtqtx.html