为什么 Swift 编译器将此标记为错误? [英] Why is the Swift compiler marking this as an error?

查看:52
本文介绍了为什么 Swift 编译器将此标记为错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两种编写相同代码的方法,其中一种似乎不被 Swift 编译器所喜欢.你能解释一下原因吗?

I have two ways of writing the same code, one of which seems to be disliked by the Swift compiler. Can you please explain why?

上下文:

let guaranteedValue: String
let cursorPositionFromEnd: Int

工作代码:

let stringFromEndUntilCursorPosition = String(guaranteedValue.reversed()[0..<cursorPositionFromEnd])

非工作代码:

let reversedOriginalString = guaranteedValue.reversed()
let stringFromEndUntilCursorPosition = String(reversedOriginalString[0..<cursorPositionFromEnd])

编译器错误消息:无法为 ReversedCollection 类型的值加上Range 类型的索引"

Compiler error message: "Cannot subscript a value of type ReversedCollection<String> with an index of type Range<Int>"

其他工作尝试:

let reversedOriginalString = guaranteedValue.reversed()[0..< cursorPositionFromEnd]
let stringFromEndUntilCursorPosition = String(reversedOriginalString)

基本上的想法是,如果您在函数返回时添加索引,则只能下标反向范围{但可能不仅如此},但是如果您首先使用 let 或 var 引用变量然后尝试下标,则这不起作用

Basically the idea is you can only subscript a reversed range {but probably not only} if you add the index at a function return, but that does not work if you first reference the variable with a let or var and then try subscripting it.

我也明白,如果 Range 是 String.Index 类型或任何新的方式,它可能会在非工作代码"中工作.

I also understand that it would probably work in the "non-working code" if the Range would be String.Index type or whatever is the new fashion of doing it.

谁能解释一下为什么?这是 Swift 编译器中已经有足够扭曲"字符串逻辑的错误吗?

Can anyone explain why? Is this a bug in Swift's compiler which already has enough "twisted" string logic?

推荐答案

有几个 reversed() 方法,如 什么问题会给 swift 数组带来 assining reversed()?.

There are several reversed() methods, as explained in What trouble could bring assining reversed() to a swift array?.

在您的第一个代码示例中,

In your first code example,

let stringFromEndUntilCursorPosition = String(guaranteedValue.reversed()[0..<cursorPositionFromEnd])

编译器从上下文(即下标)推断Sequence.reversed() 方法是需要,它返回一个数组.数组由整数索引,因此代码编译.此方法具有 O(n) 复杂度,因为创建包含所有元素的新数组.

the compiler infers from the context (i.e. the subscript) that the Sequence.reversed() method is needed, which returns an array. Arrays are indexed by integers, therefore the code compiles. This method has O(n) complexity because a new array with all elements is created.

let reversedOriginalString = guaranteedValue.reversed()

没有这样的上下文,编译器选择Bidirectional.reversed() 方法.与上面提到的方法相比,这个方法有O(1) 复杂度.它返回一个 ReversedCollection有自己的索引类型,因此

there is no such context, and the compiler chooses the Bidirectional.reversed() method. Compared to the above mentioned method, this one has O(1) complexity. It returns a ReversedCollection which has its own index type, therefore

let stringFromEndUntilCursorPosition = String(reversedOriginalString[0..<cursorPositionFromEnd])

产生观察到的错误消息.

produces the observed error message.

可能的解决方案:

  • 提供上下文以强制创建数组:

  • Provide context to enforce the array creation:

let reversedOriginalString: [Character] = guaranteedValue.reversed()
// Or: let reversedOriginalString: Array = guaranteedValue.reversed()
// Or: let reversedOriginalString = guaranteedValue.reversed() as Array
let stringFromEndUntilCursorPosition = String(reversedOriginalString[0..<cursorPositionFromEnd])

这有效,但缺点是创建了一个临时数组.

This works, but has the disadvantage of creating a temporary array.

对反向集合进行适当的索引计算:

Do the proper index calculations on the reversed collection:

let reversedOriginalString = guaranteedValue.reversed()
let pos = reversedOriginalString.index(reversedOriginalString.startIndex, offsetBy: cursorPositionFromEnd)
let stringFromEndUntilCursorPosition = String(reversedOriginalString[..<pos])

这避免了中间数组,但编写起来很乏味.

This avoids the intermediate array, but is tedious to write.

使用序列的prefix(maxLength:)方法:

let reversedOriginalString = guaranteedValue.reversed()
let stringFromEndUntilCursorPosition = String(reversedOriginalString.prefix(cursorPositionFromEnd))

这篇关于为什么 Swift 编译器将此标记为错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆