Tag: 功能编程

喜剧Central iOS App:前沿学习

投资改写 在软件工程领域,没有什么比“重写”更令人恐惧的了。因此,当我们的技术团队提出理由这样做时,您可以想象在管理人员眼中的喜悦。 但是像图片一样,表情符号有时值一千个字… 移动开发发展迅速。 每年秋天,开发人员都会面对其操作系统和新工具的新版本。 加快您的古老代码库的速度变得更具挑战性。 开发团队发现自己正在为过时而战,而不是尝试新功能。 我们支持的一些过时的供应商代码位于Restkit和XML提要之上。 其中一些依赖于NSURLConnection,该类在iOS 7中不推荐使用NSURLSession。如果您提前计划,并且您的应用程序支持良好的抽象水平,则可以缓解此类问题。 但这并非总是如此。 我们设定了一个目标,以构建可满足我们未来需求的可扩展移动应用架构。 我们仔细查看了当前的旧版应用目录。 我们问自己,什么有效,什么无效,什么有效,足以改进和重用。 像许多旧版软件一样,逐个功能也变得复杂。 随之而来的是不断增加的技术债务。 我们的前端软件已接近极限。 我们的Feed架构也在遭受痛苦。 这些主要因素,再加上新的,现代的和灵活的API,巩固了我们的立场。 我们从利益相关者那里获得了绿灯,重新开始。 我们与内部API开发人员和产品经理合作,共同创造了未来的证明。 适合我们自己的技术,生产和业务需求的东西。 迅速还是不迅速? 大约一周前,Swift Evolution邮件列表上一个有趣的话题引起了我的注意。 它在主题行中承诺“认真! 在3.0版发布后将Swift冻结两年!” 我们从Swift 1.1开始我们的项目。 目前,Swift 2.3和3.0(又名“ The Grand Renaming”)正在测试中。 每次发布都很痛苦。 语言经常在我们下面改变。 调试和重构变得更加困难。 并且由于删除了本机方法curring,因此编译时间增加了。 但从积极的方面来说,Swift减少了项目中的文件数量。 简明扼要。 它的类型系统和泛型使我们无法编写大量代码。 它也是函数式反应式编程的重要合作伙伴。 标准的Swift库已经提供了您需要的很多东西。 而且,我们都可以同意,Swift比其冗长的前身Objective-C容易得多。 尝试现代概念和框架 大多数iOS应用程序使用MVC架构模式。 我们的要求使我们走了一条通往MVVM(模型视图ViewModel)的道路。 我们还将功能性反应式编程引入了我们的代码中。 在大多数情况下,我们在数据层中使用了它。 我们采用了Promises,这是并发编程语言(例如Scala)中使用的概念。 PromiseKit和ReactiveCocoa是必不可少的两个库。 PromiseKit是帮助程序功能的实现和集合。 它将Promises的概念引入了iOS,并阐明了复杂代码的意图。 使用干净的语法,可以轻松管理工作单元的顺序和/或并行执行。 它是线程安全的,并带有用于并发管理的出色实用程序。 […]

Swift中的Currying初始化器

成为咖喱厨师IRL 这是我在Kayako上构建应用程序时经常遇到的一种情况-我必须初始化一个对象(或对象数组),并且涉及并行(或根据情况而定)运行的多个API调用。 现在,这似乎很简单。 等待直到所有数据准备就绪(存储在全局变量或其他变量中),然后初始化对象。 对? 是的, 是的。 但是如果我不想写怎么办 令x = Obj(a:1,b:2,c:3,依此类推…..) 而不是创建全局变量。 如果..我想要更快的解决方案? 好吧,这是一个解决方案 通过使用currying部分地初始化对象,并在获得更多信息后进行完全初始化,它可以帮助您(很棒的Swift🔶Developer),编写清晰简洁的代码并从长远来看节省时间。 代码 因此,假设您有一个Car Object。 我们将使用一个结构,因为“ Viva la值类型!”且不变性=❤ 摩托车(或自行车)可被视为发动机+轮胎 //:为简便起见。 另外,命名元组是🔥🔥🔥 typealias TirePair =(前:轮胎,后:轮胎) //:愚蠢的媒介不会让我正确缩进我的代码😡 结构引擎{ let horsePower:整数 让做:字符串 } struct Tire { 允许直径:浮动 } 还有我们的自行车课 struct Bike { let engine:引擎 让轮胎:TirePair //:这是唯一需要的功能 静态函数generateBike(引擎:引擎,轮胎:TirePair)->自行车{ 返回自行车(发动机:发动机,轮胎:轮胎) } } 如果您使用thoughtbot的很棒的库Curry之类的东西来咖喱 让curriedInit = curry(Bike.generateBike) 我们可以像这样部分初始化它 […]

Swift 3高阶函数简介

介绍 今天又是一天。 另一个美好的一天。 另一个迅速行动的好日子。 但不只是其他任何一天。 今天我们要进入丛林。 准备好一些Swift丛林荒野。 我最近在YouTube上观看了一些随机的动物战斗,因此本文发生在丛林中。 保持光线凉爽。 旅行愉快。 我们将讨论的主题是具有map,filter,reduce以及将这三个元素放在一起的高阶函数。 欢迎使用Wild Edition:Lio The Lion 。 前提条件 强烈建议您在开始学习之前对函数和闭包有扎实的了解。如果您确实在本文中遇到任何困扰,希望这些文章对您来说很有价值。 因此,如果您对这些文章还不确定,请务必查阅其中的任何文章。 Swift 3中的主函数 Swift 3中的闭包简介 故事 饥饿的狮子想要食物。 食物枯竭。 他的物种只剩下3个中的1个。 大地,搞砸了。 饥饿的狮子。 o 廖是他的名字。 廖是饥饿的狮子。 他会吃任何东西。 任何人。 躺在一片绿色的丛林中,看上去更像沙漠。 干无叶。 廖闭上双眼冬眠。 左眼睁开……等待中。 等待杀死。 人类也是如此。 Bon来了。 天啊 你在这里做什么? 廖把目标对准了猎物。 肉 他睁开右眼。 看邦。 茎秆 伸展他的背部。 降低他的立场。 向远处左移,落在Bon的视线之后。 廖动。 向前移动。 仍然低而动。 仍然用狙击手的稳定盯着猎物。 […]

突破reduce()

关于如何在需要时reduce() method earlier if you want退出reduce() method earlier if you want reduce()是Swift标准库中非常有用的方法。 它的工作方式类似于for in loop(实际上是一个in),但是它专门用于从集合中的元素中计算单个值。 仅有一个微妙的区别-我们不能这样做: 电脑和智能手机速度很快,但我们不希望它们浪费时间并且表现得像那只狗。 在我们的案例中,我们真正需要的是3次迭代… 在reduce方法的重载(如原始声明中那样)中,我们可以看到我们在重载中实现的nextPartialResult可以引发异常,所以为什么不利用它–在传递条件时引发异常,如此处理它不会逃避我们扩展的范围并返回结果。 为了实现它,我们需要一个符合Error类型,它将一个Result对象传递给catch闭包: 为了完成它,让我们有一个完整的实现,它使我们不仅可以基于部分结果,还可以基于集合的当前元素来做出“破坏它或做出它”的决定(尽管如果有的话)像element == someThing您应该在reduce之前使用prefix(while:) 。 这里是: 它还有另一个变体,如果您希望在给定条件为真的情况下减少收款,则应使用它: 它给出了不同的结果,因此,当您不想包括以上条件的元素时可以使用它(因为until变体才是这种情况): 就是这样了! 希望您喜欢我的第二篇文章。 随时尝试一下,您可以在这里找到示例游乐场。

增强您的功能游戏— Map和FlatMap技巧

Swift已经问世了三年多了,随着我对语言的了解,我尝试将更多的函数式编程技术集成到我的代码中。 来自Objective-C的广泛背景,我承认我在第一次学习Swift时确实不了解map和flatMap 。 最终,我对这些概念很满意,可以开始使用它们来替换我的一些for循环。 直到最近,我才真正认为map和flatMap有用。 直到我参加了Neem Serra的Map和FlatMap Magic演讲,才尝试! 在Swift纽约2017年大会上,我的眼睛向世界展示了map和flatMap的其他伟大用途。 这篇文章中的大部分内容都是基于Neem的介绍,因此请确保在有机会的情况下查看她在Realm Academy上的演讲! 地图 我可以为map提出的最基本定义是,它将数据转换为其他类型。 通常,它用于遍历集合并转换每个元素,因此您可以执行诸如从Int数组创建String数组之类的操作。 平面图 与map一样, flatMap将数据转换为其他类型。 FlatMap还具有“删除图层”的特殊属性。一个示例是删除嵌套层,其中将二维数组“展平”为一维数组。 另一个示例是从填充有可选元素的数组中删除nil元素。 地图和FlatMap基础 设定 就像Neem的演讲一样,我将展示使用纸杯蛋糕的地图和flatMap技术。 这是我们将使用的模型: 如您所见,该模型非常简单。 纸杯蛋糕具有flavor属性,有一种方法可以恢复该风味。 实际上,不需要getFlavor()方法,因为我们可以直接访问flavor属性。 但是对于我们的示例,我们将其保留不变。 接下来,我们将创建一些Cupcake并将其粘贴在cupcakes数组中: 其余示例将使用此基本设置来说明不同的地图和flatMap技术。 文章结尾处还提供了一个游乐场。 地图—旧方法 这段代码看起来熟悉吗? 我知道我第一次学习Swift时就以这种风格编写代码感到内。 在这里,我们将Cupcake的数组转换为String的数组。 地图—新方法 使用map ,我们可以将上面的4行代码简化为一行。 整齐! 地图—错误的方式 您实际上应该只使用map来变换元素。 虽然从技术上讲可以使用map 生成元素,但应尽可能避免这样做的冲动。 一个好的经验法则是注意忽略闭包参数。 如果您正在编写类似.map { _ in … } (请注意下划线 ),则可能是您未正确使用map 。 使用可选的映射 地图也可以用于可选项。 作为参考,让我们看一下在不首先包装它们的情况下尝试使用它们时通常如何表现。 […]

Swift 3中带有数组的高阶函数

从函数式编程中汲取灵感,Swift 3推出了高阶函数。 高阶函数(缩写为HOF)是将函数作为输入和/或产生函数作为输出的函数。 Swift 3引入了几个高阶函数。 本文将演示Swift 3高阶函数中的三个函数的一些易于理解的用法。 地图 降低 过滤 值得一提的是,以上所有HOF均可与Array和Dictionary一起使用。 地图 当您要对字典或数组的每个元素执行特定操作时,可以使用Swift的map函数。 在数组中,映射可以用作: var arrayOfNumbers = [1,2,3,4,5,6,7,8,9,10] 让加工数组= arrayOfNumbers.map {(num)-> Int in 返回num + 1 } 在上面的示例中,我们采用1到10的整数数组。我们的目标是使用map函数将数组中的每个数字加1。 num参数是用于每个元素的标识符,可以用任何有效的Swift标识符替换。 在上面的map方法实现中,我们正在做以下事情 我们从arrayOfNumbers中获取每个元素 我们将该数字分配给num(在第二行代码中) 我们打算为每个元​​素返回一个整数。 这实质上意味着我们的计算将得出一个整数。 由于我们将每个数字加1,因此结果也将是整数。 最后,在块内,我们返回递增的数字。 上面的所有四个步骤将对数组或字典中的所有n个元素进行。 一旦所有元素都被处理,新数组将被存储在processedArray中。 降低 Swift 3中的reduce函数用于将数组或字典的值减少为单个值。 让我们考虑一个示例,在该示例中我们想要获取数组中所有数字的总和。 传统的方法是在元素上循环并在变量中累加和。 var sum = 0 用于arrayOfNumbers中的num { 总和=总和+数字 } print(“ Sum is \(sum)”) […]

Swift 3中的协议简介

嗨,Apple,什么是协议? 协议定义了适合特定任务或功能的方法,属性和其他要求的蓝图。 – 苹果 在我看来: 再次阅读定义,并称之为一天。 – 苹果 因此,我正在写这篇文章来澄清问题。 同时使事情变得有趣。 稍后,我们将在我们的协议中使用UFC战斗机示例,希望最后一切都会有意义。 协议是什么 协议是继承标题的先决条件列表。 那是正式的定义。 如果有一件事可以帮助您记住协议是什么,那就是黑帮的定义: 一个协议就是您需要这个,这个和这个。 被称为这个。 您需要喝酒,聚会和拖延才能被称为刻板印象的大学生。 这就是我记得并向人们解释什么是协议的方式。 协议语法 语法结构类似于类/结构/枚举。 UFC战斗机协议 一天。 醒来。 您只想成为UFC战士。 您上了达纳·怀特(UFC主席),您问我如何成为UFC战斗机? “没问题。 让我们谈谈先决条件,属性和方法。” —达娜·怀特 让我们从properties开始。 要成为UFC战士,您需要做的事情。 您需要有一个确定的名称和一个可选的昵称。 这是什么意思 这意味着您在设置名称后便无法更改它。 但是,您可以在设置昵称后对其进行更改。 昵称也可以为nil。 现在让我们谈谈方法 。 成为UFC战士需要做的事情。 您绝对需要能够在UFC中拳打脚踢。 Aka知道基本知识。 您还可以选择垃圾留言。 这是什么意思 这意味着说垃圾话可能是UFC战斗机的能力。 但是,您不必拥有它。 您可以直接战斗。 我觉得您已经在使用UFC协议了。 如果没有,到最后您会感到更多。 我们已经定义并解释了我们的规格。 现在让我们看看如何定义协议。 定义协议的步骤 1.结构和命名协议 协议UFCFighter { } […]

Swift 4中的闭包简介

苹果,什么是瓶盖? 闭包是可以独立传递的功能块,可以在代码中传递和使用。 – 苹果 别担心,如果那没有道理。 起初,这听起来像: 闭包是一堆自成体系的单词,就像该死的篮球一样。 如果您不知道,操场上可能有一个篮球场。 去看看吧。 – 苹果 目的 在什么,如何以及在什么地方介绍闭包。 什么是封闭 闭包采用以下三种形式之一: 全局功能 嵌套函数 闭包表达 前两个是闭包的特殊情况。 如果您不知道函数如何工作,请在此处为您提供一篇文章: Swift 3中的主函数 当我们谈论Swift中的闭包时,我们经常提到闭包表达式。 如果有一件事可以帮助您记住什么是闭包,就是这样: 闭包是无头功能 。 闭包是没有func关键字和函数名称的函数。 它们也称为匿名函数。 它们本身不能像函数一样调用,因为它们没有名称。 它们结合使用。 封闭语法 由于其语法简单,因此鼓励使用闭包。 功能与关闭 以下是函数和闭包之间要记住的主要区别: 功能 有个名字 具有func关键字 没有关键字 关闭 没有名字 没有func关键字 有关键字 限定 让我们看看如何定义函数与闭包。 func GiveAFunc(){} var GiveNoFunc = {()->()in} 注意:我们的闭包以{开头,以}结尾。 我们将闭包存储在变量内,因此可以调用它。 呼叫 让我们调用一个函数,然后调用一个闭包。 GiveAFunc() […]

面向结果的编程:使用应用函子逐步生成结果

在我以前的故事中,我们探讨了如何使用函数组合逐步构建结果。 我们构建了applyResult函数的三个变体。 将applyResult与flatMap可以使我们采用以下代码: func getTweetDetails(for userId:String) ->结果 { var用户:用户! var tweet:鸣叫! 返回getUser(with:userId) .flatMap {userData-> Result 在 用户=用户数据 返回getLatestTweet(for:userData) } .flatMap { tweetData->结果在 tweet = tweetData 返回getTweetSentiment(for:tweetData) } .flatMap {sentimentData .success(TweetDetails(用户,tweet,sentimentData)) } } 并通过以下方式对其进行改进: func getTweetDetails(for userId:String)->结果 { 让tweetDetails = curry(TweetDetails.init) 返回applyResult(of:getUser(),to:tweetDetails) .flatMap(applyResult(of:getLatestTweet)) .flatMap(applyResult(of:getTweetSentiment)) } 一个好朋友和一位杰出的工程师最近观看了Stephen Celis的一段名为Applicatives and Swift的视频。 阅读我的上一篇文章后,他建议我观看视频。 他认为,通过使用可施加的函子,可以进一步简化解决方案。 我必须承认,在完全掌握这一概念之前,我不得不看了几次视频。 这是一个非常棒的视频,我强烈推荐该视频,即使仅观看Stephen Celis现场直播整个过程。 在Playgrounds中进行实验后,我能够将上述内容简化为非常优雅的内容: func […]

迅速。 功能阵列

Swift为iOS开发带来了很多机会。 其中有一些非常有用的功能挂钩。 有些人立即将函数式编程与复杂的数学和M字相关联,但事实并非如此。 函数是函数编程中的真正力量。 在本文中,我们将介绍如何使用其中的一些功能,以使您的日常Array例程更加舒适,避免仅通过使用函数避免代码重复和不必要的键入。 回顾我的一位同事,我们讨论了下一个功能: 现在该回到我们的摘要了。 在第2行中,我们为将在第3行中使用的函数形成一个元组。因此,在第3行中,只要意识到offerCellReactorFactory参数是元组而不是,就可以使代码更甜美 self.offerCellReactorFactory($ 0.0,$ 0.1) 我们可以写 self.offerCellReactorFactory($ 0,$ 1) 那就对了! 元组的元素是函数的独立参数,因此闭包中不需要丑陋的点符号。 这是真正的魔术发生的地方。 类型推断是语言自动检测表达式类型的能力。 在声明变量时,我们每天都在使用它,但是它具有更强大,更漂亮的应用程序。 还记得我们的UIViewController.viewDidAppear声明吗? 该viewDidAppear变量存储一个函数,Swift能够理解该函数是什么。 很酷,但还有更多。 首先, Array的map函数采用一个非转义的闭包作为参数,因此不需要[unown self]。 现在,注意指针,第三行变成 .map(offerCellReactorFactory) 妈呀 在这里,类型推断为我们完成了所有工作。 Swift能够找出该特定表达式中的所有类型,因为我们的元组为该函数形成正确的参数,并且map本身采用了将元组转换为某种东西的函数。 我们只是节省了自己的打字时间。 此功能具有许多优点,从涉及重命名的较少键入和易于重构开始,到使用类型正确的表达式结束。 希望,这也阐明了为什么类型转换和强制转换很差的问题 。 谈论重命名…让我们将offerCellReactorFactory重命名为makeOfferCellReactor🙂 看看我们如何在第2行和第3行中应用两个映射函数。这种应用称为管道 。 实际上,可以将管道调用应用于某些值的一系列函数。 坦白说,我们的问题是功能的流水线应用。 但是此应用程序被变量声明破坏了。 这不好吗? 不,不是真的,但是Array不仅是像Int这样的普通类型。 数组是容器类型。 它通常封装许多元素,并且该数目在计算过程中可能会发生变化。 这被称为非确定性行为。 为了保留不确定性, 数组类型具有特定的属性。 他们为我们提供了我们刚刚描述的出色的管道应用程序功能。 您是否注意到地图返回了另一个Array ? 这样可以进一步应用诸如map , compactMap , […]