# Allow conditional inclusion of elements in array/dictionary literals?

**URL:** <https://forums.swift.org/t/allow-conditional-inclusion-of-elements-in-array-dictionary-literals/16171>\
**Category:** Pitches\
**Created:** [September 14, 2018, 4:38pm UTC](https://forums.swift.org/t/allow-conditional-inclusion-of-elements-in-array-dictionary-literals/16171 "2018-09-14T16:38:45Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![johnno1962](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/johnno1962/32/6805_2.png) [@johnno1962](https://forums.swift.org/u/johnno1962)\
**Post date:** [September 14, 2018, 4:38pm UTC](https://forums.swift.org/t/allow-conditional-inclusion-of-elements-in-array-dictionary-literals/16171/1 "2018-09-14T16:38:45Z")

</div>

Was wondering if there would be any interest in being able to do the following in Swift:

```
let a = [
  1,
  #if something
  2,
  #endif
  3,
]

```

Would this sneak under the wire as bug fix or require a full blown proposal?

---

<div class="post-metadata">

**Author:** ![Chris\_Lattner3](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/chris_lattner3/32/348_2.png) [@Chris\_Lattner3](https://forums.swift.org/u/Chris_Lattner3)\
**Post date:** [September 14, 2018, 4:53pm UTC](https://forums.swift.org/t/allow-conditional-inclusion-of-elements-in-array-dictionary-literals/16171/2 "2018-09-14T16:53:53Z")

</div>

My personal opinion is that this would not require a full blown proposal, I'd suggest driving the discussion to develop evidence that no one is obviously concerned or opposed to this though.

---

<div class="post-metadata">

**Author:** ![johnno1962](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/johnno1962/32/6805_2.png) [@johnno1962](https://forums.swift.org/u/johnno1962)\
**Post date:** [September 14, 2018, 5:17pm UTC](https://forums.swift.org/t/allow-conditional-inclusion-of-elements-in-array-dictionary-literals/16171/3 "2018-09-14T17:17:29Z")

</div>

Just as well really, I don’t think I have another proposal cycle in me for the moment. Putting it another way then does anybody have any objections or can they think of any potential pitfalls/refinements?

---

<div class="post-metadata">

**Author:** ![Jon\_Shier](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jon_shier/32/921_2.png) [@Jon\_Shier](https://forums.swift.org/u/Jon_Shier)\
**Post date:** [September 14, 2018, 6:46pm UTC](https://forums.swift.org/t/allow-conditional-inclusion-of-elements-in-array-dictionary-literals/16171/4 "2018-09-14T18:46:33Z")

</div>

I'm generally in favor of expanding the usability `#` statements, as there are a few areas where they can't be used at the moment.

---

<div class="post-metadata">

**Author:** ![Karl](https://avatars.discourse-cdn.com/v4/letter/k/34f0e0/32.png) [@Karl](https://forums.swift.org/u/Karl)\
**Post date:** [September 14, 2018, 8:45pm UTC](https://forums.swift.org/t/allow-conditional-inclusion-of-elements-in-array-dictionary-literals/16171/5 "2018-09-14T20:45:01Z")

</div>

I can see this being particularly useful for SwiftPM package manifests. So +1 from me.

```swift
let package = Package(
  ...
  targets: [
      .target(...),
      .target(name: "Clib", sources: [
         "src/common.c",
         #if os(iOS) || os(macOS) // can't do this right now
         "src/platform/darwin.c",
         #else if os(linux)
         "src/platform/linux.c",
         #endif
         ...]),
    ],
...
)

```

---

<div class="post-metadata">

**Author:** ![Ponyboy47](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ponyboy47/32/2605_2.png) [@Ponyboy47](https://forums.swift.org/u/Ponyboy47)\
**Post date:** [September 14, 2018, 9:48pm UTC](https://forums.swift.org/t/allow-conditional-inclusion-of-elements-in-array-dictionary-literals/16171/6 "2018-09-14T21:48:22Z")

</div>

Yes inline conditional compilation for array/dictionary literals would be useful. I can't think of any reason why this would be harmful.

> **Right now I do something like this in some of my Package.swift files:**
>
> ```swift
> // Common dependencies
> var dependencies: [(name: Target.Dependency, package: Package.Dependency)] = [
> (name: "Number1", package: .package(url: "https://github.com/Dependency/Number1", from: "1.0.0"))
> ]
> 
> #if os(Linux)
> dependencies.append(/* Linux-only dependencies */)
> #else
> dependencies.append(/* Darwin-only dependencies */)
> #endif
> 
> let package = Package(
> dependencies: dependencies.map({ $0.package }),
> targets: [
> .target(...
> dependencies: dependencies.map({ $0.name })
> )
> ],
> )   
> 
> ```

---

<div class="post-metadata">

**Author:** ![Aciid](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/aciid/32/429_2.png) [@Aciid](https://forums.swift.org/u/Aciid)\
**Post date:** [September 14, 2018, 11:12pm UTC](https://forums.swift.org/t/allow-conditional-inclusion-of-elements-in-array-dictionary-literals/16171/7 "2018-09-14T23:12:17Z")

</div>

Note: Using `#if` in Package.swift manifest file is not the direction that we want our users to take in the long term. It forces you to write the manifest in a non-declarative manner and it won't really work when cross-compling because manifest will most likely be evaluated using the host platform.

---

<div class="post-metadata">

**Author:** ![Braden\_Scothern](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/braden_scothern/32/1580_2.png) [@Braden\_Scothern](https://forums.swift.org/u/Braden_Scothern)\
**Post date:** [September 15, 2018, 12:10am UTC](https://forums.swift.org/t/allow-conditional-inclusion-of-elements-in-array-dictionary-literals/16171/8 "2018-09-15T00:10:32Z")

</div>

Along the same lines until 4.2 you couldn't have code like this:

```swift
switch someInt {
case 1:
    // do stuff
case 2:
    // do other stuff

// This used to give a compiler error
#if os(linux)
case 3:
    // do some linux stuff
#endif
}

```

But now that this works (much to my happiness and surprise) it makes a lot of sense that you could use `#if` directives in an array or dictionary literal.

I'm all for making `#if` more useful in the cases where it doesn't currently work.

---

<div class="post-metadata">

**Author:** ![Ponyboy47](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ponyboy47/32/2605_2.png) [@Ponyboy47](https://forums.swift.org/u/Ponyboy47)\
**Post date:** [September 15, 2018, 4:50am UTC](https://forums.swift.org/t/allow-conditional-inclusion-of-elements-in-array-dictionary-literals/16171/9 "2018-09-15T04:50:27Z")

</div>

Is there a preferred way to make a Package.swift cross-compilable then? Can we have a Package.swift for each platform? That seems like it would require a lot of boilerplate though..

---

<div class="post-metadata">

**Author:** ![AlexanderM](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/alexanderm/32/9781_2.png) [@AlexanderM](https://forums.swift.org/u/AlexanderM)\
**Post date:** [September 15, 2018, 5:46am UTC](https://forums.swift.org/t/allow-conditional-inclusion-of-elements-in-array-dictionary-literals/16171/10 "2018-09-15T05:46:40Z")

</div>

This is absolutely something I would use. Often, I found myself using something like:

```
let a = [
    1,
    condition ? 2 : nil,
    3,
].flatMap { $0 }

```

Or worse:

```
var a = [1]
if condition { a += [2] }
a += [3]

```

I'm not a fan of the use of `#if`/`#end` for this purpose though. I think it's too wordy, and needing both a start and end token is tedious, imo. I would prefer an approach that just used some token before or after an element.

---

<div class="post-metadata">

**Author:** ![Torust](https://avatars.discourse-cdn.com/v4/letter/t/f17d59/32.png) [@Torust](https://forums.swift.org/u/Torust)\
**Post date:** [September 15, 2018, 6:40am UTC](https://forums.swift.org/t/allow-conditional-inclusion-of-elements-in-array-dictionary-literals/16171/11 "2018-09-15T06:40:10Z")

</div>

@AlexanderM I think you’re proposing a different feature. What’s being described here is _compile-time_ conditionals within array literals (which I’m +1 on; it seems like it should already work), whereas you want _runtime_ conditionals. I don’t think your request is unreasonable, but it _is_ a different topic, and is significantly more difficult to design.

---

<div class="post-metadata">

**Author:** ![hartbit](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/hartbit/32/738_2.png) [@hartbit](https://forums.swift.org/u/hartbit)\
**Post date:** [September 16, 2018, 2:05pm UTC](https://forums.swift.org/t/allow-conditional-inclusion-of-elements-in-array-dictionary-literals/16171/12 "2018-09-16T14:05:09Z")

</div>

I don't want to speak for Ankit, but I think that the idea is for SwiftPM to allow declaratively define conditional settings ( **mock syntax** ):

```swift
let package = Package(
  ...
  targets: [
      .target(...),
      .target(name: "Clib", sources: [
         "src/common.c",
         "src/platform/darwin.c".condition(os: [.iOS, .macOS]),
         "src/platform/linux.c".condition(os: .linux)
       ]),
    ],
...
)

```

---

<div class="post-metadata">

**Author:** ![Ponyboy47](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ponyboy47/32/2605_2.png) [@Ponyboy47](https://forums.swift.org/u/Ponyboy47)\
**Post date:** [September 16, 2018, 3:54pm UTC](https://forums.swift.org/t/allow-conditional-inclusion-of-elements-in-array-dictionary-literals/16171/13 "2018-09-16T15:54:19Z")

</div>

I wonder then, how will other conditional compilation blocks work then if cross-compiling uses the host system? It is VERY common for projects that support multiple OS’s to use `#if os(Linux/macOS)`. It would seem that all of these projects could not be cross-compiled then. I think even swift-foundation may use some of these, but it has been a while since i looked at its code.

Edit: After re-reading @Aciid’s message it seems that only the package.swift will be compiled using the host system and the rest of the code will not. Can someone confirm or deny this assumption for me?

---

<div class="post-metadata">

**Author:** ![Aciid](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/aciid/32/429_2.png) [@Aciid](https://forums.swift.org/u/Aciid)\
**Post date:** [September 16, 2018, 4:42pm UTC](https://forums.swift.org/t/allow-conditional-inclusion-of-elements-in-array-dictionary-literals/16171/14 "2018-09-16T16:42:04Z")

</div>

> [@Ponyboy47](#):
>
> Edit: After re-reading @Aciid’s message it seems that only the package.swift will be compiled using the host system and the rest of the code will not. Can someone confirm or deny this assumption for me?

Right, I was talking about the `Package.swift` manifest file, not the actual source code.

---

<div class="post-metadata">

**Author:** ![Karl](https://avatars.discourse-cdn.com/v4/letter/k/34f0e0/32.png) [@Karl](https://forums.swift.org/u/Karl)\
**Post date:** [September 16, 2018, 4:44pm UTC](https://forums.swift.org/t/allow-conditional-inclusion-of-elements-in-array-dictionary-literals/16171/15 "2018-09-16T16:44:27Z")

</div>

Yeah I was wondering that - surely if you have a cross-compilation toolchain, the swift compiler can parse the manifest in the foreign platform's context. The compiler can still run on the host platform (obviously) - it's only the binary products which cannot be executed on that platform.

AFAIK, parsing a Package.swift file does not depend on executing any binary products, so it should be totally do-able.

EDIT: Oh, no, it does execute code - like if you do `package.targets.append(...)`. So I guess it wouldn't work :/

---

<div class="post-metadata">

**Author:** ![Aciid](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/aciid/32/429_2.png) [@Aciid](https://forums.swift.org/u/Aciid)\
**Post date:** [September 16, 2018, 4:58pm UTC](https://forums.swift.org/t/allow-conditional-inclusion-of-elements-in-array-dictionary-literals/16171/16 "2018-09-16T16:58:45Z")

</div>

No, the manifests are currently parsed by executing the actual code. We could compile them for different platforms but we'd need to use simulators or emulators to execute them with the current parsing mechanism. We would also need to compile the PackageDescription library for each supported platform. Instead of all that, one possibility is to introduce some declarative APIs to allow you to conditionalize the contents of the manifest file (see @hartbit's post above).

Anyway, I think OP's suggested enhancement is orthogonal and makes sense regardless of what we end up doing for the manifest file.

---

<div class="post-metadata">

**Author:** ![rintaro](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/rintaro/32/568_2.png) [@rintaro](https://forums.swift.org/u/rintaro)\
**Post date:** [September 20, 2018, 8:57am UTC](https://forums.swift.org/t/allow-conditional-inclusion-of-elements-in-array-dictionary-literals/16171/17 "2018-09-20T08:57:58Z")

</div>

Why it's only for array/dictional literals? What's the rationale for that?  
How about tuples, calling arguments, or other comma separated lists?  
Why not `#if ... #endif` guarded decl attributes?

```swift
#if os(macOS)
@objc
#endif
func foobar() {...

```

or accessors

```swift
var value: Int {
  get { ... }
#if swift(>=5.0)
  modify { yield ... }
#else
  set { ... }
#endif
}

```

I think the community should discuss more deeply about the _policy_ where `#if` can appear. Currently, conditional block must enclose whole decls/statements (or switch-cases).

---

<div class="post-metadata">

**Author:** ![johnno1962](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/johnno1962/32/6805_2.png) [@johnno1962](https://forums.swift.org/u/johnno1962)\
**Post date:** [September 20, 2018, 11:33am UTC](https://forums.swift.org/t/allow-conditional-inclusion-of-elements-in-array-dictionary-literals/16171/18 "2018-09-20T11:33:02Z")

</div>

There is no rationale. I bought this up because I can already think of a use case for container literals which is making particular tests conditional and I’m sure there are other use cases. Having already looked at [the implementation](https://github.com/apple/swift/pull/19347), as it happens extending the scope to include most things that are lists would not be that difficult but I don’t think we should “go to town” just yet and try to implement every conceivable place conditionals could be used unless someone paid to do this is prepared to take it on. It’s just a matter of where to draw the line. A more ambitious scope can still be tackled later.

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jrose/32/408_2.png) [@jrose](https://forums.swift.org/u/jrose)\
**Post date:** [September 20, 2018, 3:59pm UTC](https://forums.swift.org/t/allow-conditional-inclusion-of-elements-in-array-dictionary-literals/16171/19 "2018-09-20T15:59:11Z")

</div>

I'm with John on this one. Collection literals are a place where it's very clear what the `#if` does, whereas allowing it in, say, arbitrary expression positions might be something the community or core team decides it doesn't want because it can lead to harder-to-understand code. Let's not worry about scope-creeping this proposal right away.

---

<div class="post-metadata">

**Author:** ![rintaro](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/rintaro/32/568_2.png) [@rintaro](https://forums.swift.org/u/rintaro)\
**Post date:** [September 21, 2018, 5:04pm UTC](https://forums.swift.org/t/allow-conditional-inclusion-of-elements-in-array-dictionary-literals/16171/20 "2018-09-21T17:04:26Z")

</div>

Okay. I agreed to move forward on this.

Now I have a question in the design. Sorry for bikeshedding but the following example is legal?

```swift
[
#if FLAG
  42
#endif
]

```

if so, how about:

```swift
[
#if FLAG
  42
#endif

#if !FLAG
  12
#endif
]

```

If you think of `#if .. #endif` as C like pre-processing directive, this expression ends up with

```swift
[
  42

]

```

or

```swift
[

  12
]

```

So it should be legal. But I think this is error prone for developers because requirement for `, ` relies on the flags or platform conditions.

So, to keep things simple, my proposal here is: "trailing comma is _mandatory_ in `#if` block in collection literal regardless of the position in the literal"  
What do you think?

[Next page](https://forums.swift.org/t/allow-conditional-inclusion-of-elements-in-array-dictionary-literals/16171.md?page=2)
