Swift3.0 Currying
Currying是把接受多個引數的函式變換成接受一個單一引數(最初函式的第一個引數)的函式,並且返回接受餘下的引數而且返回結果的新函式的技術.
在某些情況下,你可能會用某個相同的引數重複呼叫某個方法,那麼利用柯里化會使程式碼更易於維護,Ex:
func sum(a: Int)(b: Int) -> Int {
return a + b
}
var sumWithFive = sum(5)
sumWithFive(b: 5)
sumWithFive(b: 10)
sumWithFive(b: 15)
但是,Curring特性已經在Swift3.0中被remove了,The reason was:</br>
Curried function declaration syntax func foo(x: Int)(y: Int) is of limited usefulness and creates a lot of language and implementation complexity. We should remove it.</br>
(函式的 currying 特性的使用場景並不大,但他會增加很多語言的複雜性,所以需要刪除它)
�Well,你高興就好,如果我們可能有需求要用到這個,怎麼辦?
其實也是有類似的寫法的:
func caculate(_ num1: Int)->(Int)->Int{ return { num2 in num1 + num2} }
let caculateOne = caculate(5)
caculateOne(2)//7
caculateOne(3)//8
所以,昨天改造了一下之前寫過的程式碼,寫了一點閉包柯里化的東西(我知道函式的你們肯定都會寫!):
複製替換掉ViewController就可以直接用,但是肯定報錯因為要換一張圖片:]
class ViewController: UIViewController
{
private lazy var postCardView:UIImageView =
{
let postCardView = UIImageView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
postCardView.center = self.view.center
postCardView.image = UIImage(named: "1.jpg")
postCardView.layer.cornerRadius = 5.0
postCardView.clipsToBounds = true
return postCardView
}()
override func viewDidLoad()
{
super.viewDidLoad()
setUp()
}
func setUp()
{
view.layer.shadowColor = UIColor.black.cgColor
view.layer.shadowOffset = CGSize(width: 0, height: 10)
view.layer.shadowRadius = 10.0
view.layer.shadowOpacity = 0.3
view.addSubview(postCardView)
view.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(panInCard(sender:))))
}
func panInCard(sender:UIPanGestureRecognizer)
{
let point = sender.location(in: view)
let factor:(CGFloat)->(CGFloat)->CGFloat =
{
point in
{
length in
min(1, max(-1, (point - length * 0.5) / length * 0.5))
}
}
// let factor:(CGFloat,CGFloat)->CGFloat = { point,length in min(1, max(-1, (point - length * 0.5) / length * 0.5)) }
let transformWithM34:(CGFloat)->(CGFloat)->(CGFloat)->CATransform3D =
{
m34 in
{
xf in
{
yf in
var t = CATransform3DIdentity
t.m34 = m34
t = CATransform3DRotate(t, CGFloat(M_PI/9) * xf, 0, 1, 0)
t = CATransform3DRotate(t, CGFloat(M_PI/9) * yf, -1, 0, 0)
return t
}
}
}
switch sender.state
{
case .changed:
let (xFactor,yFactor) = (factor(point.x)(view.bounds.size.width),factor(point.y)(view.bounds.size.height))
postCardView.layer.transform = transformWithM34(1.0 / -400)(xFactor)(yFactor)
case .ended:
UIView.animate(withDuration: 0.2, animations:{
self.postCardView.layer.transform = CATransform3DIdentity
})
default:
break
}
}
}
通過對factor
這個閉包的柯里化和正常寫法可以發現,柯里化會很快增加程式碼的複雜程度,但同時又稍微提升了一點閱讀性。
然而對於下面的三引數閉包transformWithM34
,程式碼就已經變得複雜多了。很多的括號看起來快比上if
巢狀了。但是不知道親愛的讀者你們有沒有發現,let transformWithM34:(CGFloat)->(CGFloat)->(CGFloat)->CATransform3D
並沒有指定形參名,也就是依次傳入3個CGFloat型別的引數就可以收穫一個CATransform3D的返回值。
那麼
考慮引數的傳入順序,同樣可以達到簡化程式碼的目的,比如我們可以將比較固定的引數先傳入,將變化的引數寫在後面,這樣當需要程式碼複用的時候,會比較方便。 舉個?:
let datePrint:(Int)->(Int)->(String)->Void =
{
month in
print("\(month)月")
return{
day in
print("\(day)日")
return{
action in print("\(action)")
}
}
}
let actionPrint = datePrint(2016)(11)
actionPrint("要出去玩")
actionPrint("要回家")
動作相對於某一天來說,時間是固定的,動作是變化的。我們如果想輸出那一天的任何動作只需要actionPrint("xxx")
就可以了。還是很方便的。
⬇️(本來是想寫個年月日的例子,後來感覺可能沒有這個有說服力,結果引數忘了改了,輸出有點奇怪?)⬇️
最後想說的是。
�最好不要在需要和很多UI控制元件互動的地方用這種多引數柯里化的閉包或者函式。。你懂得。
這種程式碼適用範圍估計也就是那些小巧或者即將變得小巧的工具方法了吧?
感謝您為閱讀這篇文章付出了時間,謝謝。
相關文章
- Javascript中currying的實現JavaScript
- Js中Currying的應用JS
- Javascript currying柯里化詳解JavaScript
- 高階函式應用--currying函式
- 前端之函式柯里化Currying前端函式
- 搶先看Swift3.0Swift
- Swift3.0 - 遇到的坑Swift
- 從Object-C -> Swift3.0ObjectSwift
- Swift3.0整合極光推送Swift
- Swift3.0 -- 建構函式Swift函式
- swift3.0後的for in寫法Swift
- iOS Swift3.0 UIView動畫詳解iOSSwiftUIView動畫
- Swift3.0 已出坑-適配 iOS10,專案遷移 Swift3.0 問題總結SwiftiOS
- 函數語言程式設計之Currying&partial application函數程式設計APP
- Swift3.0語言教程使用URL字串Swift字串
- Swift3.0 Delegate和Block的實現SwiftBloC
- Swift3.0語言教程組合字串Swift字串
- Swift3.0 呼叫C函式-_silen_nameSwift函式
- Swift3.0語言教程使用路徑字串Swift字串
- Swift3.0語言教程替換子字串Swift字串
- 在swift3.0中列印物件的地址資訊Swift物件
- Swift3.0語言教程獲取C字串Swift字串
- Swift3.0語言教程獲取字串長度Swift字串
- Swift3.0語言教程比較、判斷字串Swift字串
- Swift3.0語言教程字串大小寫轉化Swift字串
- swift3.0與OC的互動注意事項Swift
- Swift2.3升級到Swift3.0小記Swift
- Swift3.0 -- didSet(OC中重寫setter方法)Swift
- Swift3.0專案升級到4.2遇到問題Swift
- Swift3.0語言教程分割字串與擷取字串Swift字串
- Swift3.0語言教程字串轉換為數字值Swift字串
- 記錄專案中Swift3.0的語法變化Swift
- Swift3.0語言教程獲得一個公共的字首Swift
- Swift3.0語言教程查詢字符集和子字串Swift字串
- Swift3.0 -- 閉包的迴圈引用與OC的對比Swift
- Swift3.0語言教程刪除字元與處理字元編碼Swift字元
- Swift3.0語言教程字串與檔案的資料轉換Swift字串
- Swift3.0語言教程使用字串建立和初始化字串Swift字串