Java 8 Lambda 捕获外部变量

可能会把捕获外部变量的 Lambda 表达式称为闭包,那么 Java 8 的 Lambda 可以捕获什么变量呢?

  1. 捕获实例或静态变量是没有限制的(可认为是通过 final 类型的局部变量 this 来引用前两者)
  2. 捕获的局部变量必须显式的声明为 final 或实际效果的的 final 类型

回顾一下我们在 Java 8 之前,匿名类中如果要访问局部变量的话,那个局部变量必须显式的声明为  final,例如下面的代码放在 Java 7 中是编译不过的

java7-annymous-capture-local-variable

Java 7 要求 version 这个局部变量必须是 final  类型的,否则在匿名类中不可引用。 阅读全文 >>

Java 8 Stream 如何还原为集合

由于 Java 对集合的函数式操作并非原生态的,必须对得到的 stream() 进行过滤等操作,之后还是一个 stream(),一般我们最后返回给调用者需还原为相应的集合。这无法与 Scala 的 for ... yield 操作相比。例如下面在使用 Stream API 过滤获得所有大于 3 的数字之后,方法的返回值还应该还原为 List<Integer>, 这个需求非常自然

我们这儿的问题就是如何把上面的 streamOfInteger 转换为 List<Integer>, 有以下几种办法 阅读全文 >>

Java 8 Lambda 写法与简化

Java 8 的 Lambda 表达式的实现方式还是基于已有的字节码指令,由 Lambda 表达式的方法签名结合上下文并经由 SAM 推断出正确的类型来。Java 8 的 Lambda 完整书写格式是

(type parameter1 [type parameter2, ...type parametern]) -> { statements here }

这种标准格式所表示的就是方法签名。

虽不及其他语言的 Lambda 表达式,像 Swift, Scala 可省略参数部分,可用默认参数名 $0, $1, 或 _, 但 Java 8 的 Lambda 还是可以进行酌情简化

  1. 参数类型总是可省略   --     (x, y) -> { x + y; }
  2. 参数为一个时,参数括号可省略  --    x -> { System.out.println(x); }
  3. 语句为一条时,可省略大括号, 并且语句后不要分号 --  x -> System.out.println(x)
  4. 上面更进一步,如果是单条 return 语句,必须把 return 关键字去掉  --  x -> "Hello " + x
  5. 就差一点,参数部分总是不能省,无参必须写成 () -> System.out.println("hi")
  6. Java 8 中若要近似的实现无参数部分写法,那就是方法引用了 -- System.out::println

阅读全文 >>

Mac OS X 下不能 brew update 的问题

我在 Mac OS X 下执行 brew update 出错

➜   brew update
error: Your local changes to the following files would be overwritten by merge:
    Library/Formula/abcde.rb
    Library/Formula/acpica.rb
    ............
    Library/Formula/pypy.rb
    Library/For
error: The following untracked working tree files would be overwritten by merge:
    Library/Aliases/actor-framework
    Library/Formula/aescrypt-packetizer.rb
    ............
    Library/Formula/stlink.rb
    Library/Formula/with-readline.rb
Please move or remove them before you can merge.
Aborting
Error: Failure while executing: git pull -q origin refs/heads/master:refs/remotes/origin/master 阅读全文 >>

Swift 学习笔记(对象和类)

类的最基本特性就是封装, Swift 的类可以想见就是把 let 的常量, var 的变量, func 的方法写在 class 定义里。在此之上就涉及变、常量的初始,实例的初始化。Swift 的类定义与 Java 相比还是有些特别的地方,如属性不存在默认值,必须在构造函数中初始化; 构造函数还是沿用了 Objective-C 的方式,名称都是 init; 实例化时不需要 new 等等。

Swift 的类终于不用像 Objective-C 那样接口定义和实现分开来写了。

下面尽量用一个类声明来说明 Swift 类和对象更多的问题 阅读全文 >>

Swift 学习笔记(@autoclosure 与 call-by-name)

咋一眼看到 Swift @autoclosure 自动闭包便不由自主的联想到 Scala 的 Call-By-Name 求值策略。既然主要话题是关于 Swift 的,那还是 Swift 的 @autoclosure 先入为主,下面例子中的 greet(name: () -> String) 接收一个闭包作为参数

greet(_:) 的函数调用不断简化,最后简化为 greet{"Swift}。总而言之大括号是甩不了了,有大括号的围绕才叫闭包。

同时我们依据闭包的简化规则倒退发现:给任何一个表达式两边加上大括号 {},就构成了一个闭包,它是无参数的闭包,返回值可有可无。例如 {1+2}, {foo(10)+5}, {print("Hello")}, {array.removeAtIndex(0)} 等等

至此,我们还未死心,思考能不能对 greet{"Swift"} 的写法进一步简化,这就要请出 @autoclosure 隆重登场, 对 greet() 的 name 参数前加上  @autoclosure, 就是 阅读全文 >>

Swift 学习笔记(闭包)

谈到函数式编程,恐怕最不能放过的就是闭包。闭包的定义总是不那么清晰,好像每种语言都有小许的差别。通常说的是可以捕获(访问)外部变量语句块,Swift 的闭包类似于 Objective-C 的 Block 或其他语言的 Lambda 表达式。所以闭包同 Lambda 基本上是同义词。

现在还没完, Swift 认为全局函数(有名字的,不能捕获外部变量)和嵌套函数(有名字,可捕获外部变量)也认为是特殊的闭包。闭包表达式(无名字的闭)才是真正意义上的闭包,它用最简洁的方式来书写一个函数。因此它尽了最大的可能的作了约定性的简化,例如参数与返回类型的推断,return 的省略,无参或只有一个参数的简化。

闭包的语法形式

   { (parameters) -> return type in
        statements
    }

闭包中可用常量参数(let),变量参数(var), inout 参数,甚至是可变个数参数,但是不能用默认参数。说白了,闭包也就是无名函数的另一种写法。 阅读全文 >>

Swift 学习笔记(函数第一等)

正好前段时间在发力理解函数式编程,学习 Swift 至今就想看看 Swift 对函数式编程的支持如何。从变量声明用 let, 以及函数参数的 let 和 var 都非常适合于函数式编程,它们对实例保护的很好。let 和 var 类型的函数参数保证了函数内部操作的是传入参数的深拷贝。

在 Objective-C 中要调用一个函数,除了通过对像为媒介,还能 perform 一个  selector, selector 其实也是定位函数的方式,这更像是反射。其实 C/C++ 的函数指针概念更不错,用于直接定位函数。

所以进一步,函数要成为第一等公民,它本身可以很容易的作为参数传入或作为返回值,即能构成高阶函数。这在 Swift 也是没问题的,我们可以定义函数类型的变量,例如:

阅读全文 >>

Swift 学习笔记(函数)

由于 Swift 出自于名门 Apple,与 Objective-C 共同服务于 iOS/Mac OS X 平台,因而看得出它更像是脱胎于 Objective-C。现在来学习它的函数相关的知识,Swift 函数定义有些像 Scala,只是用 func  替代了 def, 返回类型的指定用的是 -> 而不是 =, 格式如下:

当然函数无参数就是空括号(不能省略空括号),无返回值的话就无需 -> 指定类型了,比如 func greet() { print("Hello")},从形式上看不出是否有副作用(纯函数)

调用函数时和 Objective-C 是一样的,除第一个参数不需要指定形参名,其他参数必须指定形参名,并且顺序是要和函数定义时完全一样的。我们知道在 Objective-C 中一般约定把第一次参数包含在方法名中,如 阅读全文 >>

Swift 学习笔记(基本语法)

因为是本人学习 Swift 的笔记,是基于所掌握的其他语言来认识 Swift 的,所以并非详尽的 Swift ABC,也就显得凌乱不堪。
 
不会自动转型,强型转型的方式是 String(变量值), 括号不是括住类型

let 为常量, var 为变量, 类型的指定方式与  Scala 一样,如果不让它自动推断或无法推断时,这样指定类型


阅读全文 >>