on
Functional Lens in Swift
Swift Language က Lens အကြောင်း အခြေခံလေးပါ
ထားပါတော့ ကျွန်တော်တို့မှာ Employee
ဆိုတဲ့ type ရှိတယ်ပေါ့။ ကျွန်တော်တို့က အဲ့ဒီ Employee
ရဲ့ Designation
တစ်ခုပဲပါတဲ့ View တစ်ခုဖန်တီးချင်တယ်ပေါ့။ အဲ့ဒီ Designation
ကနေ title
ဆိုတဲ့ value ကို get လုပ်ပြီးပြချင်တယ်ပေါ့။ နောက် project ရဲ့တစ်နေရာရာမှာ အဲ့ဒီ title ကို ပြင်ချင်တာမျိုးရှိလာနိုင်တယ် ပြီးတော့ အဲ့ဒီ Employee
တစ်ခုလုံးကို update လုပ်တာမျိုးပေါ့။ အဲ့တော့ Code အနေနဲ့ကြည့်ရအောင်…
struct Employee {
let name: String
let designation: Designation
}
struct Designation {
let title: String
let department: String
}
အဲဒီမှာ Employee ရဲ့ title ကိုယူတာကတော့ရှင်းပါတယ်။ employee.designation.title
ဆိုပြီးခေါ်လိုက်ရုံပဲ။ အဲ့ဒီ value ကို update လုပ်ဖို့ကျနည်းနည်းရှုပ်သွားပြီ။ ဘာလို့လဲဆိုတော့ ကျွန်တော်တို့က Employee
နဲ့ Designation
တို့ကို immutable structs အနေနဲ့ declare လုပ်ထားခဲ့လို့။ တစ်ကယ်လို့သာ mutable ဖြစ်ရင်တော့လွယ်လွယ် update လုပ်လိုက်လို့ရတာပေါ့။
အဲ့ဒီနေရာမှာ Lens funtion က အသုံးဝင်လာတာပါပဲ။ Lens ကို လွယ်လွယ်ပြောရရင်
getter နဲ့ setter ပေါင်းထားတာပါပဲ။ ကျွန်တော်တို့ ဥပမာကိုပဲ ပြောရရင် - employee
ရဲ့ designation
ကို ယူမယ် ပြီးရင် သူ့ title
ကို update လုပ်ပြီး updated လုပ်ထားပြီးသား Designation
နဲ့ Employee
value အသစ် create လုပ်ပေးမယ်။ Code အနေနဲ့ကြည့်ရအောင် -
struct Lens<A,B> {
let from : (A) -> B
let to : (B, A) -> A
}
ကျွန်တော်တို့ Designation
ရဲ့ title
ကို update လုပ်ဖို့ Lens function ကိုဒီလိုမျိုးရေးလို့ရမယ် -
let title : Lens<Designation,String> = Lens(from: { $0.title }, to:{
Designation(title: $0, department: $1.department)
})
ပြီးရင် title ကို update လုပ်ဖို့ ဒီလိုမျိုးသုံးလို့ရမယ် -
let newDesignation = title.to("Mobile Developer", oldDesignation)
တစ်ကယ်လို့ Lens မသုံးခဲ့ဘူးဆိုရင် code ကဒီလိုမျိုးဖြစ်မယ် -
let newDesignation = Designation(title: "Mobile Developer", department: "Engineering")
ဒီတိုင်းဆို ဘာမှသိပ်မထူးခြားသေးသလိုပဲ။ အဲ့ဒီတော့ ကျွန်တော်တို့ composing lens တွေကို ဆက်ကြည့်ရအောင်။ ခုနက Designation ရဲ့ title ကို update လုပ်ဖို့ ရေးခဲ့တယ်၊ Employee ရဲ့ Designation ကို update လုပ်မယ်ဆိုလည်း တူတူပဲ။ ဒါပေမယ့် Employee ရဲ့ Designation ရဲ့ Title ကို update လုပ်မယ်ဆိုရင်ရော? Code အနေနဲ့ကြည့်ကြည့်ရအောင် -
infix operator =>
func =><A,B,C>(l: Lens<A,B>, r: Lens<B,C>) -> Lens<A,C> {
return Lens(from: { r.from(l.from($0)) }, to: { (c, a) in
l.to(r.to(c,l.from(a)), a)
})
}
ကျွန်တော်တို့ ဖတ်လို့ပိုကောင်းအောင် infix operator လေးနဲ့သုံးကြည့်မယ်
let employeeTitle = designation => title
Getter အနေနဲ့ဆိုရင် -
let john = Employee(name: "John", designation: Designation(title: "Programmer", department: "Engineering"))
print(employeeTitle.from(john)) // Programmer
Update လုပ်မယ်ဆိုရင် -
let john2 = employeeTitle.to("Mobile Engineer", john)
print(john2.designation.title) // Mobile Engineer