LithoOperators
安装
LithoOperators 通过 CocoaPods 提供使用。要安装它,请简单地将以下行添加到您的 Podfile:
pod 'LithoOperators', git: 'https://github.com/ThryvInc/LithoOperators'
此 pod 包含的内容
此 pod 提供了一些提高生活质量的功能和操作符,使 Swift 中的函数式编程更加简单。
中缀操作符 >?>
此操作符允许你链接具有可选性的函数。例如,假设你有函数 f
,它的输出是 String?
,另一个函数 g
只接受一个 String
。尝试使用 f >>> g
会编译失败,因为不能将 nil
传递给 g
。然而,通过使用 f >?> g
,可以编译通过,因为这个操作符只有在 f
返回非 nil
值时才执行 g
。这真的很不错,与下面定义的 optionalCast
一起使用,它会尝试为您转换对象。例如,假设有一个从 (UIButton) -> Void
类型的函数 f
,但希望能够智能地将其应用于任何传入的 UIView
;那么你可以做 optionalCast >?> f
,编译器会返回一个从 UIView -> Void
类型的函数,如果 UIView
特别是一个 UIButton
,则将 f
应用到它上面。
func optionalCast<T, U>(object: U) -> T?
这是一个非常方便的函数,它会为您转换对象。当与 >?>
配合使用时,编译器将能够确定要转换到哪种类型,而无需您明确说明。
中缀操作符 >|>
这基本上是一个用于柯里化的操作符。它将值 a
放入从 (A, B) -> C
类型的函数 f
的第一个参数位置,并返回一个只接受 B
类型的值的函数。在 Prelude 中,这将是 a |> curry(f)
。
中缀操作符 >||>
与 >|>
类似,但使用第二个值。例如,考虑函数 f: (A, B) -> C
。那么 b >||> f
将 b
放入 f
的第二个参数,并返回一个从 A -> C
类型的函数。我发现这在某些情况下比使用 curry
更方便,因为我不需要交换参数或进行其他操作。这种用法主要用于下面定义的免费用 map
函数。例如,如果你有一个从 Int -> String
类型的函数 f
,并想使用它将 Int
类型的数组转换为 String
类型的数组,你可以这样做:f >||> map
,这将返回一个从 [Int] -> [String]
类型的函数
中缀运算符 >|||>
见上,方便的柯里化,但 参数更多。
中缀运算符 >||||>
见上,方便的柯里化,但 参数更多。
中缀运算符 >|||||>
见上,方便的柯里化,但 参数更多。
中缀运算符 >||||||>
见上,方便的柯里化,但 参数更多。
func voidCurry(_ t: T, _ f: @escaping (T) -> U) -> () -> U
这仅仅返回一个函数,可以在稍后没有参数的情况下调用,并带有预填充的传入值。我经常在使用当反复使用的组件不知道传入类型时使用它,但是在发生动作时需要将其传递给其他代码。
中缀运算符 *>
voidCurry
的运算符版本
前缀运算符 ^
这是一个创建函数的运算符,给定一个类型的关键路径,将返回一个接受该类型对象的函数,并返回该对象的属性值。例如,^\UIViewController.view
将返回一个函数 (UIViewController) -> UIView
。这来自优秀的 PointFree 视频系列。
func union(_ functions: (() -> Void)...) -> () -> Void
在这里,union
将接受多个函数,并返回一个函数,当调用时,将依次调用这些函数。我主要用在 UI 样式上,例如,对于名为 setClipsToBounds
和 setGrayBackground
的两个函数,它们均来自 UIView -> Void
,您可以创建一个新的函数,例如 clipAndGrayBg = union(setClipsToBounds, setGrayBackground)
。
func coalesceNil<T>(with defaultValue: T) -> (T?) -> T
这只是 nil 合并运算符 ??
的函数版本。
func ifExecute<T>(_ t: T?, _ f: (T) -> Void)
此函数在传给它的是非 nil 值时执行 f
。如果有一个仅接受非可选值的函数,但您有一个未包装的变量,这个函数很方便。基本上,此函数为您解决了带有可选类型的自动解包问题。
中缀操作符 ?>
这仅仅是 ifExecute
的操作符版本。
func ifApply(_ condition: Bool, _ function: (Self) -> Self) -> Self
这是一个名为 ConditionalApply
协议的扩展函数。如果条件为真,则将自身传递给给定的函数。我在 iOS 中不是经常使用它,但在 Vapor 创建数据库查询时它非常有用。
func firstElement<T>(_ array: [T]) -> T?
如果元素存在,则返回数组的第一个元素
func map<U, V>(array: [U], f: (U) -> V) -> [V]
map
的自由函数版本。
func map<Value>(_ kp: KeyPath<Element, Value>) -> [Value]
这是在 Sequence
的扩展中,源自于优秀的 PointFree 视频。它允许您使用键路径转换数组。
func compactMap<Value>(_ kp: KeyPath<Element, Value?>) -> [Value]
与前一个相同,但以 compactMap
为基础。
func map<Element, Value>(array: [Element], _ kp: KeyPath<Element, Value>) -> [Value]
带有键路径的 map
的自由函数版本。
func fzip<T, U, V>(_ f: @escaping (T) -> U, _ g: @escaping (T) -> V) -> (T) -> (U, V)
该函数将一些函数的输出组合到元组中。当在创建视图的同时保持两个部分解耦时,非常方便。
此库还包括在PointFree视频中开发的函数式获取器/设置器。因此包括 prop
、get
、set
、over
、mut
、mver
等。
作者
Elliot Schrock
许可
LithoOperators 在 MIT 许可协议下提供。有关更多信息,请参阅 LICENSE 文件。