设为首页 加入收藏

TOP

Scalaz(26)- Lens: 函数式不可变对象数据操作方式(一)
2017-10-10 12:13:23 】 浏览:2964
Tags:Scalaz Lens 函数 可变 对象 数据 操作 方式

  scala中的case class是一种特殊的对象:由编译器(compiler)自动生成字段的getter和setter。如下面的例子:

 1 case class City(name:String, province: String)  2 case class Address(street: String, zip: String, city: City)  3 case class Person(name: String, age: Int, phone: String, address: Address)  4 val Peter = Person("Peter Chan",20,"4806111",Address("13 baoan road","40001",City("ShenZhen","GuangDong")))  5                                                   //> Peter : Exercises.LensDemo.Person = Person(Peter Chan,20,4806111,Address(13  6                                                   //| baoan road,40001,City(ShenZhen,GuangDong)))
 7 val John = Person("John Woo",43,"3602011",Address("33 fada road","51001",City("GuangZhou","GuangDong")))  8                                                   //> John : Exercises.LensDemo.Person = Person(John Woo,43,3602011,Address(33 fa  9                                                   //| da road,51001,City(GuangZhou,GuangDong)))
10 val Ming = Person("Fang Ming",23,"3682412",Address("6 jiefang da dao","51012",City("GuangZhou","GuangDong"))) 11                                                   //> Ming : Exercises.LensDemo.Person = Person(Fang Ming,23,3682412,Address(6 ji 12                                                   //| efang da dao,51012,City(GuangZhou,GuangDong)))

这里我们可以看到:Person是个多层次对象,包含多层嵌入属性对象(multi-layer embeded objects)。如果需要更改Person类型实例中的任何字段时,我们可以直接用行令方式(imperative style):

1 case class City(var name:String, province: String) 2 Peter.address.city.name = "DongGuan"
3 Peter                              //> res0: Exercises.LensDemo.Person = Person(Peter Chan,20,4806111,Address(13 ba 4                                    //| oan road,40001,City(DongGuan,GuangDong)))

注意:我必须把case class 属性City的name字段属性变成var,而且这时peter已经转变了(mutated)。既然我们是在函数式编程中,强调的是纯函数代码,即使用不可变对象(immutable objects),那么函数式编程方式的字段操作又可以怎样呢?

1 al peterDG = peter.copy( 2       address = peter.address.copy( 3     city = peter.address.city.copy(name = "DongGuan"))) 4                                                   //> peterDG : Exercises.LensDemo.Person = Person(Peter Chan,20,4806111,Address( 5                                                   //| 13 baoan road,40001,City(DongGuan,GuangDong)))
6 peter                                             //> res0: Exercises.LensDemo.Person = Person(Peter Chan,20,4806111,Address(13 ba 7                                                   //| oan road,40001,City(ShenZhen,GuangDong)))
8 peterDG                                           //> res1: Exercises.LensDemo.Person = Person(Peter Chan,20,4806111,Address(13 ba 9                                                   //| oan road,40001,City(DongGuan,GuangDong)))

我们可以使用case class的自带函数copy来实现字段操作。但是随着嵌入对象层次的增加,将会产生大量的重复代码。scalaz的Lens type class的主要功能之一就可以解决以上问题。我们先来看看scalaz Lens的用例:

 1 //定义Lens实例
 2 val nameL = Lens.lensu[Person, String]((p,n) => p.copy(name=n), _.name)  3                                                   //> nameL : scalaz.Lens[Exercises.LensDemo.Person,String] = scalaz.LensFunction  4                                                   //| s$$anon$5@5f375618
 5 val ageL = Lens.lensu[Person, Int]((p,a) => p.copy(age=a), _.age)  6                                                   //> ageL : scalaz.Lens[Exercises.LensDemo.Person,Int] = scalaz.LensFunctions$$a  7                                                   //| non$5@1810399e
 8 val addrL = Lens.lensu[Person,Address]((p,a) => p.copy(address=a), _.address)  9                                                   //> addrL : scalaz.Lens[Exercises.LensDemo.Person,Exercises.LensDemo.Address] 10                                                   //| = scalaz.LensFunctions$$anon$5@32d992b2
11 val zipL = Lens.lensu[Address,String]((a,z) => a.copy(zip=z), _.zip) 12                                                   //> zipL : scalaz.Lens[Exercises.LensDemo.Address,String] = scalaz.LensFunctio 13                                                   //| ns$$anon$5@215be6bb
14 val cityL = Lens.lensu[Address,City]((a,c) => a.copy(city=c), _.city) 15                                                   //> cityL : scalaz.Lens[Exercises.Le
编程开发网
首页 上一页 1 2 3 4 5 6 7 下一页 尾页 1/7/7
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Gatling实战(三) 下一篇Scalaz(25)- Monad: Monad Tr..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

array(4) { ["type"]=> int(8) ["message"]=> string(24) "Undefined variable: jobs" ["file"]=> string(32) "/mnt/wp/cppentry/do/bencandy.php" ["line"]=> int(214) }