考虑 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 的 future 版本中进行更改,但可能不值得
努力。
另一个问题是关于柯里化(Currying)函数。
someFoos.forEach(bar2)
编译是因为 bar2 的类型是 Foo -> Void,这正是
forEach() 方法需要什么。 Foo.bar 另一方面,
是一个 curry 函数(参见 http://oleb.net/blog/2014/07/swift-instance-methods-curried-functions/ ),它将实例作为第一个
争论。它的类型为 Foo -> () -> ()。所以
Foo.bar(someFoo)
是类型为 () -> () 的闭包,并且
Foo.bar(someFoo)()
在 someFoo 实例上调用 bar 方法。
(注意:以下内容并非实际建议, 但仅作为有关柯里化(Currying)函数和乐趣的演示 有闭包!)
要将 Foo.bar 作为参数直接传递给 forEach() 我们需要
“交换”参数的顺序。为此,Haskell 有一个“翻转”功能,
在 Swift 中也是可能的(参见例如 How to write a flip method in 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)
在 someFoo 实例上调用 bar 方法。
现在我们可以调用
someFoos.forEach (flip(Foo.bar)())
不使用闭包表达式 { .. } !!
如果 isBaz 是一个方法而不是一个属性
func isBaz() -> Bool { return false }
那你 可以在 if 表达式中做同样的事情:
if someFoos.contains(flip(Foo.isBaz)()) {
// ...
}
再次声明,这只是一个演示。还有属性
不是 curry 函数,所以这不能用
你的 isBaz 属性。
关于ios - 有没有办法在调用 SequenceType.forEach 时引用实例函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34049116/
我好像记得Lua有类似Ruby的method_missing的东西。还是我记错了? 最佳答案 表的metatable的__index和__newindex可以用于与Ruby的method_missing相同的效果。 关于ruby-难道Lua没有和Ruby的method_missing相媲美的东西吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/7732154/
我有一个奇怪的问题:我在rvm上安装了rubyonrails。一切正常,我可以创建项目。但是在我输入“railsnew”时重新启动后,我有“程序'rails'当前未安装。”。SystemUbuntu12.04ruby-v"1.9.3p194"gemlistactionmailer(3.2.5)actionpack(3.2.5)activemodel(3.2.5)activerecord(3.2.5)activeresource(3.2.5)activesupport(3.2.5)arel(3.0.2)builder(3.0.0)bundler(1.1.4)coffee-rails(
我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击
在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
我正在尝试用ruby中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了
我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin
我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案
这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下
我正在处理旧代码的一部分。beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)endRubocop错误如下:Avoidstubbingusing'allow_any_instance_of'我读到了RuboCop::RSpec:AnyInstance我试着像下面那样改变它。由此beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)end对此:let(:sport_