# \[Closed\] Pitch: Explicit marker for autoclosure parameters

**URL:** <https://forums.swift.org/t/closed-pitch-explicit-marker-for-autoclosure-parameters/65092>\
**Category:** Pitches\
**Tags:** lazy, closure, autoclosure\
**Created:** [May 19, 2023, 8:45pm UTC](https://forums.swift.org/t/closed-pitch-explicit-marker-for-autoclosure-parameters/65092 "2023-05-19T20:45:07Z")\
**Posts on this page:** 20\
**Page:** 2

<div class="post-metadata">

**Author:** ![Tino](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tino/32/1073_2.png) [@Tino](https://forums.swift.org/u/Tino)\
**Post date:** [May 20, 2023, 5:59pm UTC](https://forums.swift.org/t/closed-pitch-explicit-marker-for-autoclosure-parameters/65092/21 "2023-05-20T17:59:11Z")

</div>

Imo this might be yet another issue that is better solved in the tooling rather than in the language: If @autoclosure is really a problem, why not just set the default style for such parameters to bold red in the editor?

---

<div class="post-metadata">

**Author:** ![tera](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tera/32/38201_2.png) [@tera](https://forums.swift.org/u/tera)\
**Post date:** [May 20, 2023, 6:05pm UTC](https://forums.swift.org/t/closed-pitch-explicit-marker-for-autoclosure-parameters/65092/22 "2023-05-20T18:05:43Z")

</div>

> [@GreatApe](#):
>
> but why not just abolish @autoclosure then and require
> 
> ```swift
> foo { 5 > 2 }
> 
> ```

It's not so nice looking for the non-trailing closure parameters:

```
foo({ 5 > 2 }, 2) { 3 } // vs
foo(closure 5 > 2, 2, closure 3)

```

But this is indeed a possibility (see the alternatives 2 & 3).

> [@GreatApe](#):
>
> What purpose will @autoclosure serve in a world where your pitch has been accepted?`

Basically, if you allow for an alternative syntax for making closures that doesn't involve nesting, e.g. this:

```swift
    foo({ foo(42) }) <--> foo(closure foo(42))

```

and do a special exceptional treatment for short-circuiting bool operations then `@autoclosure` feature is not needed. I guess that's what other languages are doing for bool operators (I'm not so sure what do they do for things like logs, etc to conditionally evaluate parameters).

> [@Tino](#):
>
> Imo this might be yet another issue that is better solved in the tooling rather than in the language: If @autoclosure is really a problem, why not just set the default style for such parameters to bold red in the editor?

I'm 99.9% IDE user so that would definitely work for me. Do you mean this is already possible?

---

<div class="post-metadata">

**Author:** ![Tino](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tino/32/1073_2.png) [@Tino](https://forums.swift.org/u/Tino)\
**Post date:** [May 20, 2023, 6:09pm UTC](https://forums.swift.org/t/closed-pitch-explicit-marker-for-autoclosure-parameters/65092/23 "2023-05-20T18:09:03Z")

</div>

> [@tera](#):
>
> Do you mean this is already possible?

I don't think so — and afair, the plug-in capabilities of Xcode are not that great 🫣.

---

<div class="post-metadata">

**Author:** ![bbrk24](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/bbrk24/32/27370_2.png) [@bbrk24](https://forums.swift.org/u/bbrk24)\
**Post date:** [May 20, 2023, 6:50pm UTC](https://forums.swift.org/t/closed-pitch-explicit-marker-for-autoclosure-parameters/65092/24 "2023-05-20T18:50:58Z")

</div>

> [@tera](#):
>
> and do a special exceptional treatment for short-circuiting bool operations

Well, we’d also have to account for `??`, but operators aside `@autoclosure` has its place.

`assert` and `precondition` have already been brought up, but even if those were specially handled it would break `XCTAssertThrows` in a way that’s impossible to circumvent. And if we privilege that, how many third-party libraries do something similar?

---

<div class="post-metadata">

**Author:** ![tera](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tera/32/38201_2.png) [@tera](https://forums.swift.org/u/tera)\
**Post date:** [May 20, 2023, 6:56pm UTC](https://forums.swift.org/t/closed-pitch-explicit-marker-for-autoclosure-parameters/65092/25 "2023-05-20T18:56:58Z")

</div>

Could be this for asserts / etc, or do you think that's too much hassle?

```swift
my_assert { condition }
my_assert { condition } message: { "some expensive message \(here)" }

```

---

<div class="post-metadata">

**Author:** ![beccadax](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/beccadax/32/34217_2.png) [@beccadax](https://forums.swift.org/u/beccadax)\
**Post date:** [May 20, 2023, 7:53pm UTC](https://forums.swift.org/t/closed-pitch-explicit-marker-for-autoclosure-parameters/65092/26 "2023-05-20T19:53:25Z")

</div>

`@autoclosure` is a feature that requires some discipline on the part of API designers. I think this has always been true and usually been understood by everyone involved. When it is used with discipline, though, it is very powerful and useful. I don’t think we should make the good uses worse to help control the rare abuses of the feature.

---

<div class="post-metadata">

**Author:** ![tera](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tera/32/38201_2.png) [@tera](https://forums.swift.org/u/tera)\
**Post date:** [May 20, 2023, 10:38pm UTC](https://forums.swift.org/t/closed-pitch-explicit-marker-for-autoclosure-parameters/65092/27 "2023-05-20T22:38:56Z")

</div>

Three questions for you:

1. if we prefer brevity over clarity when passing autoclosure parameters why don't we do the same for `&` and `@` parameters? ("@autoinout" / "@autobinding")

2. if we didn't have @autoclosure parameters now (just the short-circuiting behaviour for bool operations and using explicit closures for asserts, etc), would we introduce them now?

3. why don't other languages (old, and more importantly new that were created after Swift) have autoclosure equivalents?

---

<div class="post-metadata">

**Author:** ![michelf](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/michelf/32/1180_2.png) [@michelf](https://forums.swift.org/u/michelf)\
**Post date:** [May 21, 2023, 12:36am UTC](https://forums.swift.org/t/closed-pitch-explicit-marker-for-autoclosure-parameters/65092/28 "2023-05-21T00:36:45Z")

</div>

> [@tera](#):
>
> - why don't other languages (old, and more importantly new that were created after Swift) have autoclosure equivalents?

Not porting judgement on anything but...

D has the same concept ([lazy parameters](https://dlang.org/spec/function.html#lazy-params)) and it's likely that it was the inspiration for Swift because it works exactly the same.

C/C++/Objective-C use macros that look like functions to achieve the same effect.

Rust also uses macros for this (see [`assert!`](https://doc.rust-lang.org/std/macro.assert.html)), with a more hygienic macro system. I suppose the `!` at the end of a macro name in Rust would satisfy your requirement of being clear at the call site that something special is happening.

There is definitely a need for this lazy evaluation feature, even though the implementation isn't always through closures.

---

<div class="post-metadata">

**Author:** ![anon9791410](https://avatars.discourse-cdn.com/v4/letter/a/9fc348/32.png) [@anon9791410](https://forums.swift.org/u/anon9791410)\
**Post date:** [May 21, 2023, 9:15am UTC](https://forums.swift.org/t/closed-pitch-explicit-marker-for-autoclosure-parameters/65092/29 "2023-05-21T09:15:17Z")

</div>

> [@beccadax](#):
>
> When it is used with discipline, though, it is very powerful and useful. I don’t think we should make the good uses worse to help control the rare abuses of the feature.

Something like `@autoclosure` \*could be a great feature, but it has always been half-baked:

> <https://stackoverflow.com/questions/34699576/use-logical-operator-as-combine-closure-in-reduce>

I think maybe the conflation of what it does with closures was not the right way to go. All of this compiles:

```swift
func ƒ(_: () -> Void) { }
func ƒ(autoclosure: @autoclosure () -> Void) { }
func ƒƒ(_: (() -> Void) -> Void) { }
func ƒƒ(autoclosured: (@autoclosure () -> Void) -> Void) { }

ƒƒ(ƒ)
ƒƒ(ƒ(autoclosure:))
ƒƒ(autoclosured: ƒ)
ƒƒ(autoclosured: ƒ(autoclosure:))

```

---

<div class="post-metadata">

**Author:** ![GreatApe](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/greatape/32/2640_2.png) [@GreatApe](https://forums.swift.org/u/GreatApe)\
**Post date:** [May 21, 2023, 9:46am UTC](https://forums.swift.org/t/closed-pitch-explicit-marker-for-autoclosure-parameters/65092/30 "2023-05-21T09:46:10Z")

</div>

What you are suggesting is like first adding @autoinout so that we can write

```swift
func reduce(state: inout State, _ action: Action) { }
...
var state
reduce(&state, action)

```

as

```swift
func reduce(state: @autoinout State, _ action: Action) { }
...
var state
reduce(state, action)

```

and then you pitch requiring call site notation to turn that into something like

```swift
var state
reduce(inout state, action)

```

I can understand if you want to get rid of autoclosure, but what is the point of keeping it and requiring a special annotation? Then what you are actually pitching is nothing more or less than a new notation for closures.

---

<div class="post-metadata">

**Author:** ![rayx](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/rayx/32/12204_2.png) [@rayx](https://forums.swift.org/u/rayx)\
**Post date:** [May 21, 2023, 1:06pm UTC](https://forums.swift.org/t/closed-pitch-explicit-marker-for-autoclosure-parameters/65092/31 "2023-05-21T13:06:30Z")

</div>

Instead of introducing a new keyword, how about allowing user to pass a closure explicitly?

This is @tera's proposal:

```swift
baz(autoclosure foo(42))

```

This is mine:

```swift
baz(foo(42)) // this works
baz { foo(42) } // how about allowing this too?

```

This will give user a choice when they have to use the baz() API but find it's confusing. And it's unlikely to break existing code.

---

<div class="post-metadata">

**Author:** ![ksluder](https://avatars.discourse-cdn.com/v4/letter/k/eada6e/32.png) [@ksluder](https://forums.swift.org/u/ksluder)\
**Post date:** [May 21, 2023, 1:18pm UTC](https://forums.swift.org/t/closed-pitch-explicit-marker-for-autoclosure-parameters/65092/32 "2023-05-21T13:18:15Z")

</div>

The question is still, “Why?” `@autoclosure` exists to give API designers the power to defer evaluation of argument expressions. What is gained by giving clients the ability to spell these expressions as closures, and why is that gain worth introducing the ambiguity of whether the client-provided closure itself is then wrapped in an automatic closure?

---

<div class="post-metadata">

**Author:** ![tera](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tera/32/38201_2.png) [@tera](https://forums.swift.org/u/tera)\
**Post date:** [May 21, 2023, 7:17pm UTC](https://forums.swift.org/t/closed-pitch-explicit-marker-for-autoclosure-parameters/65092/33 "2023-05-21T19:17:59Z")

</div>

> [@michelf](#):
>
> D has the same concept ([lazy parameters](https://dlang.org/spec/function.html#lazy-params)) and it's likely that it was the inspiration for Swift because it works exactly the same.

Interestingly they used `"lazy"` even if "lazy argument can be executed 0 or more times". 🤔

> [@GreatApe](#):
>
> What you are suggesting is like first adding @autoinout

It's about consistency and established precedents. I'm applying the same line of reasoning used to defend `@autoclosure` feature existence in its current form ("brevity matters more than clarity at the point of use", "it requires discipline, but it is powerful", "let's not punish good users because of a few abusers", "if we didn't have this feature by now we'd introduce it now" to the similar features `@autoinout` and `@autobinding`. If the line of reasoning good for the former it should be as good for the latter, right?

> [@ksluder](#):
>
> `@autoclosure` exists to give API designers the power to defer evaluation of argument expressions.

Not autoclosures - that's what `closures` do by themselves. `@autoclosures` merely allow to disguise the call site by not having the `{` `}` symbols that we'd have to put otherwise:

```swift
precondition(denominator != 0, "Can't divide \(numerator) by zero")
logger.info("Starting division of \(numerator) by \(denominator)…")

vs

precondition { denominator != 0 } message: { "Can't divide \(numerator) by zero" }
logger.info { "Starting division of \(numerator) by \(denominator)…" }

```

---

<div class="post-metadata">

**Author:** ![GreatApe](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/greatape/32/2640_2.png) [@GreatApe](https://forums.swift.org/u/GreatApe)\
**Post date:** [May 21, 2023, 7:47pm UTC](https://forums.swift.org/t/closed-pitch-explicit-marker-for-autoclosure-parameters/65092/34 "2023-05-21T19:47:14Z")

</div>

> `@autoclosures` merely allow to disguise the call site by not having the `{` `}` symbols that we'd have to put otherwise

Precisely. That's why it makes no sense to keep autoclosure if you require the call site to be annotated.

---

<div class="post-metadata">

**Author:** ![tera](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tera/32/38201_2.png) [@tera](https://forums.swift.org/u/tera)\
**Post date:** [May 21, 2023, 7:52pm UTC](https://forums.swift.org/t/closed-pitch-explicit-marker-for-autoclosure-parameters/65092/35 "2023-05-21T19:52:48Z")

</div>

I am not disagreeing with that, and suggesting that in alternatives #2 and #3.

---

<div class="post-metadata">

**Author:** ![michelf](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/michelf/32/1180_2.png) [@michelf](https://forums.swift.org/u/michelf)\
**Post date:** [May 21, 2023, 8:15pm UTC](https://forums.swift.org/t/closed-pitch-explicit-marker-for-autoclosure-parameters/65092/36 "2023-05-21T20:15:39Z")

</div>

> [@tera](#):
>
> Interestingly they used `"lazy"` even if "lazy argument can be executed 0 or more times". 🤔

It shouldn't be that surprising: `lazy` has an existing meaning in Swift where the initializer is run once on demand the first time the value is requested while D is a different language unencumbered by this precedent. Given `lazy` in D is older than Swift itself, it's likely Swift designers knew about it but found having two different meanings for `lazy` would be confusing and went for `@autoclosure` instead.

---

<div class="post-metadata">

**Author:** ![anon9791410](https://avatars.discourse-cdn.com/v4/letter/a/9fc348/32.png) [@anon9791410](https://forums.swift.org/u/anon9791410)\
**Post date:** [May 22, 2023, 4:15am UTC](https://forums.swift.org/t/closed-pitch-explicit-marker-for-autoclosure-parameters/65092/37 "2023-05-22T04:15:44Z")

</div>

> [@ksluder](#):
>
> “Why?”

`@autoclosure` should be a [parameter wrapper](https://github.com/apple/swift-evolution/blob/main/proposals/0293-extend-property-wrappers-to-function-and-closure-parameters.md#call-site-semantics). It's just a representation of a `get` accessor (with additional complexity from `rethrows` that I'm not going to address here). If it were used like this…

```swift
@propertyWrapper public struct Get<Value> {
  public var wrappedValue: Value { projectedValue() }
  public var projectedValue: () -> Value

  public init(wrappedValue: @autoclosure @escaping () -> Value) {
    projectedValue = wrappedValue
  }

  public init(projectedValue: @escaping () -> Value) {
    self.projectedValue = projectedValue
  }
}

func and(_ bool0: Bool, @Get _ bool1: Bool) -> Bool {
  bool0 && bool1
}

```

…then we would have the ability to _choose_ how to utilize the `get`/value duality, which `@autoclosure` does not allow:

```swift
func expensive() -> Bool { .init() }
_ = and(true, expensive())
_ = and(true, $_: expensive)

```

However "projected parameter syntax" (or whatever that's called) cannot be used with operators (yet), and `init(wrappedValue:)` still requires the `@autoclosure` we have.

---

<div class="post-metadata">

**Author:** ![ensan-hcl](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ensan-hcl/32/15186_2.png) [@ensan-hcl](https://forums.swift.org/u/ensan-hcl)\
**Post date:** [May 22, 2023, 6:44am UTC](https://forums.swift.org/t/closed-pitch-explicit-marker-for-autoclosure-parameters/65092/38 "2023-05-22T06:44:35Z")

</div>

Considering the reasoning for explicit marker for `@autoclosure` parameters, in @tera's opinion, `@Wrapper` parameters should also be explicitly marked, right?

---

<div class="post-metadata">

**Author:** ![tera](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tera/32/38201_2.png) [@tera](https://forums.swift.org/u/tera)\
**Post date:** [May 22, 2023, 8:13pm UTC](https://forums.swift.org/t/closed-pitch-explicit-marker-for-autoclosure-parameters/65092/40 "2023-05-22T20:13:00Z")

</div>

The more I think about it the more alternative #2 is appealing ("Prohibit `autoclosure` parameters altogether"). Operators aside (which, btw, do not need `@autoclosure` feature as well, which I can expand later on), consider these examples:

```swift
precondition(denom != 0)
precondition{denom != 0}

precondition(denom != 0, "Can't divide \(num) by zero")
precondition { denom != 0 } message: { "Can't divide \(num) by zero" }

logger.info("Starting division of \(num) by \(denom)…")
logger.info{"Starting division of \(num) by \(denom)…"}

c.horizontalSizeClassValue(regular: foo(), compact: bar(), otherwise: baz())
c.horizontalSizeClassValue { foo() } compact: { bar() } otherwise: { baz() }

```

All we are gaining by having auto closures here is that we write the first lines instead of the second, and numerous of drawbacks mentioned above (lack of clarity at the point of use, potential for abuse, extra complexity in the compiler, etc). Doesn't look a win overall.

---

<div class="post-metadata">

**Author:** ![Avi](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/avi/32/2962_2.png) [@Avi](https://forums.swift.org/u/Avi)\
**Post date:** [May 23, 2023, 11:50am UTC](https://forums.swift.org/t/closed-pitch-explicit-marker-for-autoclosure-parameters/65092/41 "2023-05-23T11:50:55Z")

</div>

The declaration for `precondition()` is

```swift
public func precondition(_ condition: @autoclosure () -> Bool, _ message: @autoclosure () -> String = String(), file: StaticString = #file, line: UInt = #line)

```

Note that the last two parameters are not autoclosures, nor is there any reason for them to be, since no one should ever be passing them.

[Previous page](https://forums.swift.org/t/closed-pitch-explicit-marker-for-autoclosure-parameters/65092.md?page=1)

[Next page](https://forums.swift.org/t/closed-pitch-explicit-marker-for-autoclosure-parameters/65092.md?page=3)
