本文翻译自: Composition in Flutter & Dart

在 Flutter & Dart 中使用组合创建模块化应用程序。

什么是组合?

在dictionary.com 中 composition 的定义为:将部分或者元素组合成一个整体的行为。简单说,组合就像堆乐高积木,我们可以将积木组合成一个结构。

在 FP 中,我们定义了一个简单的通用函数,该函数可以通过组合构成一个复杂的函数,一个函数的输出是另外一个函数的输入,依此类推。输入从一个函数传递到另外一个函数最后返回结果。因此,组合可以认为是数据流动的管道。

组合的数字符号是 f.g。 f(g(x))它从里向外执行。

  1. 首先 x 初始化。
  2. 将 x 作为参数传递给 g,g(x)被初始化。
  3. g(x)被计算并将结果传递给 f 函数,最后 f(g(x))被计算。

在 Dart 中,组合函数可以表示如下:

Compose 是个高阶函数,它接收两个函数并返回一个可接收输入的函数。 组合的执行顺序是从右到左,因此g先执行,然后再执行f

如上图创建了函数shout,它由两个较小的功能函数toUpperexclaim组成。

第 4 行,组合这两个函数创建shout函数.

第 8 行使用了包Dartz中提供的函数composeF

Flutter 中如何使用组合?

Flutter 框架是展示组合功能的最佳示例之一,我们组合控件来进行UI设计。比如你想设置 padding,可以用Padding来组合,你想设置一些装饰,可以用DecoratedBox来进行组合等等。

Flutter 大量使用了组合。控件树就是我们用组合处理 UI 的结果.控件就像乐高积木,小的通用控件可以被组合成复杂的控件或者用户界面。比如,Container就包含了几个控件,如PaddingDecoratedBoxAlignLimitedBox等。

这里偏重介绍组合在实践中应用让读者更深刻理解组合概念,本质上来说Flutter中的控件组合与函数式编程中的组合还是有点区别,两则编程范式不一样,Flutter 控件间组合偏重于面向对象编程,对象是基本单元,控件都是对象;而函数的组合偏重于函数式编程,无状态函数是基本单元。

组合与管道

与 compose 类似,这里介绍另外一个概念:管道。两者区别在于组合执行顺序是从右到左,而管道执行顺序是从左至右

这个区别尤为重要,不要忽视,它间接影响到代码可读性。中国人的阅读习惯是从左到右的,如果你是阿拉伯人可以忽略我说的,哈哈!

在第 14 行,使用了 compose,它的执行顺序是从右至左,函数 g 首先执行,结果传递给 f 。

在第 17 行,使用了管道,它的执行顺序是从左至右,函数 f 先执行,结果传递给 g 。

如果使用 compose,输入 10 先执行increment 增加到 11 然后乘以 2,因此执行结果是 22.

如果使用管道,输入 10 先执行doubler乘以 2 变成 20,然后执行increment递增到 21 并返回。

Example 示例

结合所学的概念,我们可以创建几个函数,实现字符串的变换。

我们需要可以将上述用例相互转换的函数。

就像乐高游戏一样,首先需要乐高积木,在这个例子中我们需要具有一些基础功能的函数。

之前定义的 Compose 函数只接收两个函数作为参数,现在定义一个可以接收 n 个参数的函数。

我们创建了如上代码,接下来可以用它来实现更有意思的函数,这些函数将被使用,通过Github 仓库查找更多信息。

Snake case to Pascal case

接下来将从 Snake case 转换成 camel,pascal 和 kebab cases。

const _pascalCase = 'LoremIpsumDolorSitAmet';

const _snakeCase = 'lorem_ipsum_dolor_sit_amet';

在第 5 行中,定义了_snakeToPascal  函数,它接收一个参数并返回结果。_snakeToPascal由三个小函数组合而成:splitWithUnderscorecapitalizeWords和  joinWithoutSpace 。将“lorem_ipsum_dolor_sit_amet”作为参数传入函数中,compose 是从右至左的执行顺序。因此:

  1. 首先输入字符串先传给splitWithUnderscore,该函数将输入拆分成 [“lorem”, “ipsum”, “dolor”, “sit”, “amet”]

  2. splitWithUnderscore的返回值是一个数组,它将被传递给第二个函数,即capitalizeWords将每个元素的首字母转换成大写并返回列表 [“Lorem”, “Ipsum”, “Dolor”, “Sit”, “Amet”]

  3. capitalizeWords的返回结果将被传递给  joinWithoutSpace,该函数将元素连接在一起并返回结果 “LoremIpsumDolorSitAmet”

还记得我们之前讲的么? 我们通过组合为数据定义一个管道,像上面这样。数据流通过这些管道并返回结果,花些时间来构建一些基础功能函数,组合他们生成更有意义的函数就变得很容易了。

Snake case to Camel case

const _snakeCase = 'lorem_ipsum_dolor_sit_amet';

const _camelCase = 'loremIpsumDolorSitAmet';

第 15 行_snakeToCamel非常简单,第一个与最后一个函数都是与上面转换都是相同的:splitWithUnderscore  和  joinWithoutSpace,将中间函数从capitalizeWords  修改为  capitalizeTail,我们的功能就实现了。原因是 camelCase 的情况下不需要将第一个单词大写。capitalizeTailcapitalizeWords类似,但是它忽略了第一个单词处理,匹配了我们的用例。

Snake case to Kebab case

Snake case 转换成 kebab case 更简单.只需要组合两个函数 (splitWithUnderscore & joinWithHyphen),就可以完成任务。

Camel case to other cases

Kebab case to other cases

Pascal case to other cases

想法

我喜欢将组合视为一种分治技术。组合的主要优点是得到高复用和可定制功能。

文中源码地址  GitHub

太棒了!鼓励自己坚持到底。我希望我为你投入的时间增加了一些价值。

如果觉得文章对你有帮助,点赞、收藏、关注、评论,一键四连支持,你的支持就是我创作最大的动力。

️ 本文原创听蝉 公众号:码里特别有禅 欢迎关注原创技术文章第一时间推送 ️

函数式编程:Flutter&Dart中的组合的更多相关文章

  1. 为什么函数式编程在Java中很危险?

    摘要:函数式编程这个不温不火的语言由来已久.有人说,这一年它会很火,尽管它很难,这也正是你需要学习的理由.那么,为什么函数式编程在Java中很危险呢?也许这个疑问普遍存在于很多程序员的脑中,作者Ell ...

  2. Flutter Dart中的异步

    以下内容从官网得到: https://webdev.dartlang.org/articles/performance/event-loop Even-Looper Dart是单线程模型,也就没有了所 ...

  3. 翻译连载 | 第 11 章:融会贯通 -《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇

    原文地址:Functional-Light-JS 原文作者:Kyle Simpson-<You-Dont-Know-JS>作者 关于译者:这是一个流淌着沪江血液的纯粹工程:认真,是 HTM ...

  4. 关于函数式编程(Functional Programming)

    初学函数式编程,相信很多程序员兄弟们对于这个名字熟悉又陌生.函数,对于程序员来说并不陌生,编程对于程序员来说也并不陌生,但是函数式编程语言(Functional Programming languag ...

  5. 【JS】394- 简明 JavaScript 函数式编程-入门篇

    转载自公众号"程序员成长指北" 写在开头 本文较长,总共分为三大部分:(对于函数式编程以及其优点有一定理解的童鞋,可以直接从 第二部分 开始阅读) 第一部分:首先会通过实际代码介绍 ...

  6. 翻译连载 | 附录 B: 谦虚的 Monad-《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇

    原文地址:Functional-Light-JS 原文作者:Kyle Simpson-<You-Dont-Know-JS>作者 关于译者:这是一个流淌着沪江血液的纯粹工程:认真,是 HTM ...

  7. JavaScript:了解一下函数式编程

    一.简介 在JavaScript中,函数就是第一类公民,它可以像字符串.数字等变量一样,使用var修饰并作为数据使用.它可以作为数值.可以作为参数.还可以作为返回结果.可以说JavaScript就是函 ...

  8. 理解函数式编程中的函数组合--Monoids(二)

    使用函数式语言来建立领域模型--类型组合 理解函数式编程语言中的组合--前言(一) 理解函数式编程中的函数组合--Monoids(二) 继上篇文章引出<范畴论>之后,我准备通过几篇文章,来 ...

  9. Scala 中的函数式编程基础(一)

    主要来自 Scala 语言发明人 Martin Odersky 教授的 Coursera 课程 <Functional Programming Principles in Scala>. ...

  10. 可爱的 Python : Python中的函数式编程,第三部分

    英文原文:Charming Python: Functional programming in Python, Part 3,翻译:开源中国 摘要:  作者David Mertz在其文章<可爱的 ...

随机推荐

  1. Go语言核心36讲19

    你好,我是郝林,今天我们继续分享go语句执行规则的内容. 在上一篇文章中,我们讲到了goroutine在操作系统的并发编程体系,以及在Go语言并发编程模型中的地位和作用等一系列内容,今天我们继续来聊一 ...

  2. [ PHP 内核与扩展开发系列] 内存管理 —— 引用计数

    对于 PHP 这种需要同时处理多个请求的程序来说,申请和释放内存的时候应该慎之又慎,一不小心便会酿成大错.另一方面,除了要安全申请和释放内存外,还应该做到内存的最小化使用,因为它可能要处理每秒钟数以千 ...

  3. UWSGI 安装出现 ModuleNotFoundError: No module named '_ctypes'

    原因:Python3中有个内置模块叫ctypes,它是Python3的外部函数库模块,它提供兼容C语言的数据类型,并通过它调用Linux系统下的共享库(Shared library),此模块需要使用C ...

  4. [排序算法] 冒泡排序 (C++)

    冒泡排序解释: 冒泡排序 BubbleSort 是一种最基础的交换排序.顾名思义,数组中的每一个元素就好像泡泡一样,根据自己的大小不同一点点的向一侧移动. 冒泡排序原理: 每一趟只能确定将一个数归位. ...

  5. JavaEE Day13 Tomcat和Servlet

    之前是web基础,现在是web核心 今日内容: web相关概念的回顾 开源的web服务器软件:Tomcat Servlet:整个web技术的核心[Servlet入门] 一.web相关概念的回顾 1.软 ...

  6. 基于Nginx搭建WebDAV服务

    title: 基于Nginx搭建WebDAV服务 categories: - [IT,网络,服务] tags: - WebDAV - Nginx comments: true date: 2022-1 ...

  7. 【Java难点攻克】「NIO和内存映射性能提升系列」彻底透析NIO底层的内存映射机制原理与Direct Memory的关系

    NIO与内存映射文件 Java类库中的NIO包相对于IO包来说有一个新功能就是 [内存映射文件],在业务层面的日常开发过程中并不是经常会使用,但是一旦在处理大文件时是比较理想的提高效率的手段,之前已经 ...

  8. JAVA学到方法写了一个四则运算计算器,请教一下有什么需要改进的

    package method; /* * 四则运算计算器 * */ import java.util.Scanner; public class Demo07 { public static void ...

  9. 使用pip命令安装库时提示Could not build wheels for six, since package 'wheel' is not installed

    在使用pip命令安装库时提示Could not build wheels for six, since package 'wheel' is not installed 解决以上问题可用 pip in ...

  10. JUC基础学习笔记

    JUC的理解: JUC即java.util .concurrent工具包的简称.从JDK 1.5 开始出现,主要用于处理多线程.高并发问题. 多线程的三大特征解析 原子性.可见性.有序性 1.原子性: ...