考虑类型Foo
:
class Foo {
var isBaz: Bool {
return false
}
func bar() {
print("some boring print")
}
}
现在假设我要遍历一个类实例的集合并在每个实例上调用一些函数:
let someFoos: [Foo] = [Foo(), Foo(), Foo()]
someFoos.forEach { $0.bar() }
该语法非常紧凑,但感觉有点尴尬。另外,它不能在任何地方使用。例如,在if
语句条件中:
if someFoos.contains { $0.isBaz } {
// compiler error: statement cannot begin with a closure expression
}
if someFoos.contains($0.isBaz) {
// compiler error: anonymous closure argument not contained in a closure
}
if someFoos.contains({ $0.isBaz }) {
// this is correct, but requires extra pair of parentheses
}
理想情况下,写类似
someFoos.forEach(Foo.bar)
但是从Swift 2.1开始,这不是正确的语法。这种引用该函数的方式将类似于以下内容:
func bar2(foo: Foo) -> Void {
print("some boring print")
}
someFoos.forEach(bar2)
有没有更好的方法来引用实例函数?您如何喜欢写这样的表达式?
这里有两个不同的问题。的 拖尾闭合语法 可以在调用函数时,可以使用与最后一个参数是一个闭合,所以
let b1 = someFoos.contains({ $0.isBaz })
let b2 = someFoos.contains { $0.isBaz }
完全等效。但是,在if语句的情况下,尾随闭包语法可能会出现问题:
if someFoos.contains({ $0.isBaz }) { } // OK
if someFoos.contains { $0.isBaz } { } // Compiler error
if (someFoos.contains { $0.isBaz }) { } // OK, as noted by R Menke
我们只能推测第二个为什么不起作用。可能是编译器将第一个{
作为if-body的开始。也许这会在Swift的未来版本中发生变化,但是这不值得付出努力。
另一个问题是关于 咖喱函数 。
someFoos.forEach(bar2)
进行编译,因为bar2
具有类型Foo -> Void
,这正是该forEach()
方法所期望的。Foo.bar
另一方面,是咖喱函数(请参见http://oleb.net/blog/2014/07/swift-instance-methods-curried-functions/),该函数将实例作为第一个参数。它具有类型Foo -> () -> ()
。所以
Foo.bar(someFoo)
是类型为的闭包() -> ()
,并且
Foo.bar(someFoo)()
bar
在someFoo
实例上调用方法。
( 注意: 以下内容并不是实际建议,而只是作为有关咖喱函数和闭包乐趣的演示!)
要Foo.bar
直接作为参数传递给forEach()
我们,我们需要“交换”参数的顺序。Haskell为此具有“翻转”功能,并且在Swift中也是:
func flip<A, B, C>(f: A -> B ->C) -> B -> A ->C {
return { b in { a in f(a)(b) } }
}
然后flip(Foo.bar)
具有类型() -> Foo -> ()
,因此bar
可以应用方法的void参数
flip(Foo.bar)()
得到Foo -> ()
关闭,并且
flip(Foo.bar)()(someFoo)
bar
在someFoo
实例上调用方法。现在我们可以打电话
someFoos.forEach (flip(Foo.bar)())
不使用闭包表达式{ .. }
!
如果isBaz
是 方法 而不是属性
func isBaz() -> Bool { return false }
那么您可以在if-expression中执行相同的操作:
if someFoos.contains(flip(Foo.isBaz)()) {
// ...
}
再次,这仅是示范。此外, 属性 不是咖喱函数,因此无法使用您的isBaz
属性来完成。
问题内容: 我想使用Streams.intRange(int start,int end,int step)实现反向排序的流。但是,似乎java.util.Streams类不再可用(但是它仍在标准库的rt.jar中)。此方法是在其他类中还是被其他方法替代? 问题答案: 实际上,JDK中再也没有这种方法了。您能获得的下一个最接近的位置是,但是只会一步一步走。 一种解决方案是实施您自己的解决方案。例如
我学到了两件事: -操作符创建一个新实例,然后执行声明的connstuctor来初始化该新实例 根据我的理解,这些说法互相反对。 例如,不会创建两个实例,因为-操作符创建一个实例,构造函数调用并创建另一个实例?当然不会,但现在到底是什么创建了一个实例。。。?
我仍然是AnyLogic和JAVA的基本用户,但我遇到了获取服务块剩余时间的问题。我知道服务块嵌入了延迟块,并且有一个用于延迟的函数(getRemainingTime(代理))。是否可以在(代理)main中调用此函数? 我需要获得我的产品将停留在服务块的时间,以导航我的推送过程。我有3个产品(都是个人代理)和一个在服务前装配我的产品和1个原材料(个人代理)的拾取块。显然,剩余时间必须是动态的,并且
问题内容: 如果返回错误,是否仍在调用? 问题答案: 不,延迟功能不会运行。 这是log.Fatal的描述: 致命等同于Print(),然后调用os.Exit(1)。 呼叫,其描述在这里: 退出使当前程序以给定的状态码退出。按照惯例,代码零表示成功,代码零表示错误。程序立即终止;延迟功能未运行。 示范 如果您确实需要在程序完成之前正确关闭资源或执行某些任务,请不要使用。
问题内容: 我正在尝试修复我的一个程序中的错误,我认为这可能是由于Hibernate弄清楚了如何在不调用其默认(或任何其他)构造函数的情况下实例化对象的实例。 问题答案: 实际上,是的,如果使用objenesis为您实例化对象,则可以在实例化对象时绕过构造函数。它执行字节码操作来实现此目的。 反序列化对象也将绕过构造函数。 使用反射无法做到这一点。
问题内容: 是否可以从Java调用COM API(特别是HP / Mercury Quality Center OTA API)?如果是这样,最好的方法是什么? 像JACOB一样合适吗? 代码片段对于基础知识会有所帮助:-) 问题答案: jacob:是的,http://sourceforge.net/projects/jacob- project/ 是一个活跃的项目,可以很好地满足您的目的。 您可