Currying是把接受多個(gè)參數(shù)的函數(shù)變換成接受一個(gè)單一參數(shù)(最初函數(shù)的第一個(gè)參數(shù))的函數(shù)爽柒,并且返回接受余下的參數(shù)而且返回結(jié)果的新函數(shù)的技術(shù).
在某些情況下如暖,你可能會(huì)用某個(gè)相同的參數(shù)重復(fù)調(diào)用某個(gè)方法赔退,那么利用柯里化會(huì)使代碼更易于維護(hù),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特性已經(jīng)在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>
(函數(shù)的 currying 特性的使用場(chǎng)景并不大枣接,但他會(huì)增加很多語(yǔ)言的復(fù)雜性,所以需要?jiǎng)h除它)
?Well,你高興就好,如果我們可能有需求要用到這個(gè)缺谴,怎么辦但惶?
其實(shí)也是有類似的寫(xiě)法的:
func caculate(_ num1: Int)->(Int)->Int{ return { num2 in num1 + num2} }
let caculateOne = caculate(5)
caculateOne(2)//7
caculateOne(3)//8
所以,昨天改造了一下之前寫(xiě)過(guò)的代碼湿蛔,寫(xiě)了一點(diǎn)閉包柯里化的東西(我知道函數(shù)的你們肯定都會(huì)寫(xiě)榆骚!):
復(fù)制替換掉ViewController就可以直接用,但是肯定報(bào)錯(cuò)因?yàn)橐獡Q一張圖片:]
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
}
}
}
通過(guò)對(duì)factor
這個(gè)閉包的柯里化和正常寫(xiě)法可以發(fā)現(xiàn)煌集,柯里化會(huì)很快增加代碼的復(fù)雜程度,但同時(shí)又稍微提升了一點(diǎn)閱讀性捌省。
然而對(duì)于下面的三參數(shù)閉包transformWithM34
苫纤,代碼就已經(jīng)變得復(fù)雜多了。很多的括號(hào)看起來(lái)快比上if
嵌套了纲缓。但是不知道親愛(ài)的讀者你們有沒(méi)有發(fā)現(xiàn)卷拘,
let transformWithM34:(CGFloat)->(CGFloat)->(CGFloat)->CATransform3D
并沒(méi)有指定形參名,也就是依次傳入3個(gè)CGFloat類型的參數(shù)就可以收獲一個(gè)CATransform3D的返回值祝高。
那么
考慮參數(shù)的傳入順序栗弟,同樣可以達(dá)到簡(jiǎn)化代碼的目的,比如我們可以將比較固定的參數(shù)先傳入工闺,將變化的參數(shù)寫(xiě)在后面乍赫,這樣當(dāng)需要代碼復(fù)用的時(shí)候,會(huì)比較方便陆蟆。 舉個(gè)??:
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("要回家")
動(dòng)作相對(duì)于某一天來(lái)說(shuō)雷厂,時(shí)間是固定的,動(dòng)作是變化的叠殷。我們?nèi)绻胼敵瞿且惶斓娜魏蝿?dòng)作只需要actionPrint("xxx")
就可以了改鲫。還是很方便的。
??(本來(lái)是想寫(xiě)個(gè)年月日的例子林束,后來(lái)感覺(jué)可能沒(méi)有這個(gè)有說(shuō)服力像棘,結(jié)果參數(shù)忘了改了,輸出有點(diǎn)奇怪??)??
最后想說(shuō)的是壶冒。
?最好不要在需要和很多UI控件交互的地方用這種多參數(shù)柯里化的閉包或者函數(shù)缕题。。你懂得依痊。
這種代碼適用范圍估計(jì)也就是那些小巧或者即將變得小巧的工具方法了吧??
感謝您為閱讀這篇文章付出了時(shí)間避除,謝謝怎披。