问题描述
我已经添加了我的代码的两张图片,解释了这两种情况在第一种情况下,下标的工作方式与它应该工作的完全一样,有两行代码
I've add two pictures of my code , that explain both Scenariosat the first scenario the subscript work exactly like its supposed to work, with Two lines of code
在第二种情况下,代码应该与两行相同,但由于某种原因我收到错误
at the secound scenario , the code should evaluate same as the two line, but im getting an error for some reason
你能帮我弄清楚为什么吗?
can you help me figure out WHY?
工作图片:工作图片
错误图片:错误图片
完整代码:
class SomeClass {
var dic = Dictionary<String,(()->String) -> String>()
subscript(_ s:String) -> (()->String) -> String {
get{
return dic[s]!
}set{
dic[s] = newValue
}
}
}
func createClass(_ s:String) -> SomeClass {
func foo(_ str:()->String) ->String {
return str() + " AND " + "Two"
}
let sc = SomeClass()
sc["0"] = foo
return sc
}
// WORKING TWO LINES
let someClass = createClass("someStr")["0"]
let str = someClass{"One"} // everything work fine, no errors // prints 'One AND Two'
// ERROR ONE LINE
let str = createClass("someStr")["0"]{"One"}
// WHY?
推荐答案
你的例子:
let str = createClass("someStr")["0"]{"One"}
正在使用尾随闭包语法.
尾随闭包语法的工作原理是将尾随闭包作为函数调用的附加参数包含在内.对数组进行下标实际上是一个函数调用(到一个名为 subscript
的函数),并且 Swift 试图将该闭包作为第二个参数传递给下标调用,这就是错误所解释的:
Trailing closure syntax works by including the trailing closure as an additional parameter to a function call. Subscripting an array is really a function call under the hood (to a function called subscript
), and Swift is trying to pass that closure as a second parameter to the subscripting call, which is what the error is explaining:
不能使用类型为(String, () -> String)"的参数对类型为SomeClass"的值进行下标.
换句话说,你不能同时将 "0"
和闭包 {"One"}
传递给下标函数.
In other words, you can't pass both "0"
and the closure {"One"}
to the subscripting function.
至少有 3 种方法可以解决此问题,但仍将其放在一行中:
There are at least 3 ways to fix this and still put it on one line:
选项 1:使用显式调用来传递闭包,而不是使用尾随闭包语法
将闭包包裹在 ()
中以明确调用:
Wrap the closure in ()
to make the call explicit:
let str1 = createClass("someStr")["0"]({"One"})
print(str1)
选项 2:将 createClass("someStr")["0"]
括在括号中
Option 2: Wrap the createClass("someStr")["0"]
in parentheses
这让 Swift 知道下标只获取 "0"
作为参数,并允许尾随闭包语法按预期工作:
That lets Swift know the subscripting only gets "0"
as a parameter and allows trailing closure syntax to work as expected:
let str2 = (createClass("someStr")["0"]){"One"}
print(str2)
选项 3:在尾随闭包语法之前将 .self
添加到结果中:
Option 3: Add .self
to the result before the trailing closure syntax:
再次完成下标调用并避免混淆.
That again finishes the subscripting call and avoids the confusion.
let str3 = createClass("someStr")["0"].self {"One"}
print(str3)
就我个人而言,我会选择选项 1,因为尾随闭包语法是不必要的语法糖,显然在这里不起作用.
Personally, I would choose Option 1, because trailing closure syntax is unnecessary syntactic sugar that clearly is not working here.
在我问的评论中:
我同意尾随闭包语法很可能是他们可以修复的错误,但我不明白您为什么坚持在这里使用尾随闭包语法.即使只是为了解决 Swift 中的错误,将闭包包装在 () 中以使调用显式化有什么令人反感的地方?
您回复:
坚持的原因是我想解决一个挑战.实际上,这个返回闭包的函数只是它的一方面事情是这样的
func Challenge() {
// Do not edit below this line
XCTAssertEqual(foo("str1")["str2"]{ "654321" }, "123456")
}
我们已经确定尾随闭包语法将最终的闭包与索引操作配对,所以诀窍是设计一个带有索引操作的闭包的类:
We've already established that trailing closure syntax is pairing the final closure with the indexing operation, so the trick is to design a class that takes a closure with its indexing operation:
class SomeClass {
subscript(_ s: String, closure: () -> String) -> String {
return String(closure().reversed())
}
}
func foo(_ str: String) -> SomeClass {
return SomeClass()
}
func Challenge() {
// Do not edit below this line
XCTAssertEqual(foo("str1")["str2"]{ "654321" }, "123456")
}
这篇关于相同的下标代码,当用两条单独的行构建它时它工作正常,当用一行代码构建它时,我收到错误,为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!