You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift4中sequence(first:next:)函数语法错误排查咨询

Swift: Explicit Closure Return Type Causes Out-of-Bounds Error in sequence() for LinkedList Collection Implementation

I've run into this exact edge case before when implementing Collection for custom linked lists—let's break down what's happening here and fix it.

First, let's recap your scenario: you're following Ray Wenderlich's algorithms course to implement a LinkedList conforming to Collection. This implicit closure syntax works fine:

let nodes = sequence(first: lhs.node) { $0?.next }

But when you explicitly specify the closure's return type, you get an "Out of bounds: index >= endIndex" error:

let nodes = sequence(first: lhs.node, next: { aNode -> Node<Value>? in aNode?.next }) // Error here

What's Going Wrong

The issue isn't a syntax error—it's a type inference gotcha with Swift's sequence(first:next:) function. Let's look at the function's core signature to clarify:

func sequence<T>(first: T?, next: @escaping (T) -> T?) -> UnfoldSequence<T, T?>

When you omit the parameter type in your closure, Swift correctly infers T as Node<Value>, so:

  • first: lhs.node is treated as Node<Value>? (matching the T? parameter)
  • The closure receives a non-optional Node<Value> ($0) and returns Node<Value>? (its next property)

But when you only specify the closure's return type (without the parameter type), Swift misinfers T as Node<Value>? instead. Now:

  • The closure receives an optional Node<Value>? (aNode)
  • aNode?.next returns Node<Value>?, which gets wrapped into Node<Value>?? to match the function's expected T? return type
  • This causes the sequence to generate an extra nil element at the end, which clashes with your Collection implementation (where endIndex is nil, and accessing endIndex is invalid)

The Fix: Explicitly Specify the Parameter Type

To fix the error, you need to explicitly define the closure's parameter type as non-optional Node<Value>, which guides Swift to infer the correct T type for the sequence:

let nodes = sequence(first: lhs.node, next: { (aNode: Node<Value>) -> Node<Value>? in aNode.next })

You can even simplify it a bit—since the return type can now be inferred from aNode.next, you don't strictly need to specify it:

let nodes = sequence(first: lhs.node, next: { (aNode: Node<Value>) in aNode.next })

Why This Works

Now T is correctly inferred as Node<Value>, so:

  1. The sequence starts with lhs.node (if it's non-nil)
  2. For each element, the closure receives a non-optional Node<Value> and returns its next property (an optional)
  3. The sequence stops as soon as the closure returns nil, so no extra nil elements are added
  4. This aligns perfectly with your Collection implementation's index logic (where endIndex is nil, and we never try to access it)

内容的提问来源于stack exchange,提问作者black_pearl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:41:56