[swift-evolution] Proposal: Allow #if to guard switch case clauses

Joe Groff jgroff at apple.com
Wed May 10 13:44:57 CDT 2017


Seems reasonable to me.


> On May 10, 2017, at 1:32 AM, rintaro ishizaki via swift-evolution <swift-evolution at swift.org> wrote:
> 
> Hi evolution community,
> 
> This proposal allows you to enclose switch cases with #if directive.
> Implementation: https://github.com/apple/swift/pull/9457
> This is one of the oldest SR issue:
> https://bugs.swift.org/browse/SR-2
> https://bugs.swift.org/browse/SR-4196
> 
> Thanks!
> Rintaro
> 
> 
> Allow #if to guard switch case clauses
> 
> 	• Proposal: SE-NNNN
> 	• Authors: Rintaro Ishziaki
> 	• Review Manager: TBD
> 	• Status: Awaiting review
> Introduction
> 
> This proposal adds ability to guard switch case clauses with #if directives.
> 
> Swift-evolution thread: Not yet
> 
> Motivation
> 
> When you want to switch cases only for certain compilation condition, say switching #if os(Linux) guarded enum cases, right now you have to write switch twice:
> 
> enum Operation
>  {
>   
> case output(String
> )
> #
> if os(Linux
> )
>   
> case syscall
> (Syscall)
> #
> endif
> 
> }
> 
> 
> func execute(operation
> : Operation) {
> #
> if !os(Linux
> )
>    
> switch
>  operation {
>    
> case .output(let str):
> 
>        
> print
> (str)
>    }
> #
> else
> 
>    
> switch
>  operation {
>    
> case .output(let str):
> 
>        
> print
> (str)
>    
> case .syscall(let call):
> 
>        call.
> execute
> ()
>    }
> #
> endif
> 
> }
> 
> This is annoying and error prone.
> 
> Proposed solution
> 
> This proposal allows #if to guard switch case clauses.
> 
> func execute(operation
> : Operation) {
>     
> switch
>  operation {
>     
> case .output(let str):
> 
>         
> print
> (str)
> #
> if os(Linux
> )
>     
> case .syscall(let call):
> 
>         call.
> execute
> ()
> #
> endif
> 
>     }
> }
> 
> Detailed design
> 
> This change shouldn't affect existing #if directives within case clauses. This code should works as expected:
> 
> func foo(x
> : MyEnum) {
>     
> switch
>  x {
>     
> case .some(let str):
> 
>         
> doSomething
> (str)
> #
> if
>  PRINT_SOME
>         
> print
> (str)
> #
> endif
> 
>     
> case .other:
> 
>         
> doOther
> ()
>     }
> }
> 
> Only if the next token after #if is case or default, the Parser treat it as guarding case clauses.
> 
> func foo(x
> : MyEnum) {
>     
> switch
>  x {
>     
> case .some(let str):
> 
>         
> doSomething
> (str)
> #
> if
>  HAS_OTHER
>     
> case .other:
> 
>         
> doOther
> ()
>     }
> #
> endif
> 
> }
> 
> func foo(x
> : MyEnum) {
>     
> switch
>  x {
>     
> case .some(let str):
> 
>         
> doSomething
> (str)
> #
> if
>  HAS_OTHER
>     
> default:
> 
>         
> break
> 
> #
> endif
> 
> }
> 
> Error cases:
> 
>     switch
>  x {
>     
> case .some(let str):
> 
>         
> doSomething
> (str)
> #
> if
>  HAS_OTHER
>     
> case .other:
> 
>         
> doOther
> ()
> #
> else
> 
>         
> doMore() // error: all statements inside a switch must be covered by a 'case' or 'default'
> #endif
> 
>     }
> 
>     switch
>  x {
>     
> case .some(let str):
> 
>         
> doSomething
> (str)
> #
> if
>  HAS_OTHER
>         
> doMore
> ()
>     
> case .other:
> 
>         
> doOther() // error: 'case' label can only appear inside a 'switch' statement
> #else
> 
>     }
> 
> You can guard multiple cases as long as it is guarding whole clauses:
> 
>     switch
>  x {
>     
> case .some(let str):
> 
>         
> doSomething
> (str)
> #
> if
>  HAS_OTHERS
>     
> case .other:
> 
>         
> doOther
> ()
>     
> case .more:
> 
>         
> doMore
> ()
> #
> else
> 
>     }
> 
> 
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution



More information about the swift-evolution mailing list