unnamed enum, local to func

Is there a way to declare an unnamed local enum?

The kind of enum that can only be used as a parameter or a return value of a specific func.


I could use an Int. Or could use an optional<Bool> to handle three diferent cases. But these are too unspecific.

The other option would be to declare a global enum, or a class enum. But those are ugly and cumbersome.


I would instead, like to do something like:

func makeDinner() -> enum(case: Ready, Ruinned, Cooking) {     
     return .Ready
}

if makeDinner() == .Ruinned {
     apologiseToClients()
}


And something like:

func drawPolygon( polytype: enum(case: Triangle, Square, Elipse) ) {
     switch polytype {
          case .Triangle: drawTriangle()
          case .Square: drawSquare()
          case .Ellipse: drawElipse()
     }
}

drawPolygon(.Square)


But as far as I could find,


I can only do:

enum makeDinner_FuncEnum {  // Can be a very long and weird enum name
     case Ready, Ruinned, Cooking
}

func makeDinner() -> makeDinner_FuncEnum {    // enum will not be used anywhere else
     return .Ready
}

or,

func makeDinner() -> Int {    
     return 0 //utterly unspecific
}

if makeDinner() == 1 { //what does 1 mean??
     apologiseToClients()
}

Accepted Reply

Is there a way to declare an unnamed local enum?

It should be clear by now that, no, there’s no way to do this currently. If you want to change this in the future, you should raise it on the swift-evolution mailing list. Before you do that I recommend that you check out the previous threads (here and here) on this topic.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Replies

Imagine you have 2 enums with the .Square. How would the compiler differentiate ?


The name may be very short, declared inside the class, so what is the problem.

What do your mean by 2 enums? Could you please post an example?


I not agree that the name may be very small, because then it becomes completely unprecise as to what its is. I simple do not like that solution at all. It is almost like saying that a lambda/block/closure is the same as function.

imagine you define another enum for another func : signature is different because enum is different.

drawPolygon(otherPolytype: enum(case: Lozange, Square, Parallelogram)


and call


drawPolygon(.Square)


How would you make the difference between the 2 ?


Are short names less significant than no name at all ? Short such as Shape or Form are very significant.

Ok, I see.

I suppose the simple solution would be that those two funcs, since they would have the same exact signature, they could not coexist.

In other words, any unnamed enum would provide the same signature as any other unnamed enum, irrespective of its clauses.

So the programmer would be forced to provide a parameter label to differentiate between them.



As for the short name... The specific hypothetical example I gave, could perhaps be given such a short name, but then, on so many other cases, that would not work well for me. I guess it's a matter of taste.

In fact, there's no conflict betweeh having ".square" cases in two different enums. (Note that enum cases are lowercased by convention in Swift 3.) The compiler infers the correct type from the type of the parameter to the call.


The real problem is that you're prepared to have a global function (which has a unique name in the global namespace) but you're not prepared to have a matching global enum. Why not? You'll pollute the global namespace once but not twice?


In practice, you'll often avoid a global function in one of two ways:


1. The function is actually an instance method of some class. The enum can be declared as a subtype of the class.


2. The function is made to be a static method of some class, invented for the purpose if necessary. The enum can be declared as a subtype of the class.

I guess I didn't answer the original question head on:


>> Is there a way to declare an unnamed local enum?

>> The kind of enum that can only be used as a parameter or a return value of a specific func.


This isn't an impossible idea as far as it goes, but the problem is that it prevents the client (caller) from using the enum outside of the function call. Specifically, it prevents things like testing if dinner is ready or ruined (except by calling the function twice, which may be undesirable).


Encapsulation of behavior within a class seems like a better solution.

These were meant only to be simple examples of usage, to showcase the concept, nothing else.

So, no, I am not prepared to pollute the global name space. And I very rarely do so.

I would most likely declare instance or class methods such as these.


The idea is to free us from having to come up with new names all the time for stuff we don't really have an easy name for.

And also to free us from having to declare an enum by the side of the func.


I mean, really... the simplest example I can think of are closures.

If to you guys declaring a new selector/func is the same as a closure, then I don't know...


To me, the freedom and the readability that closures brought me, is just too too precious.

These unnamed enums would mean less Ints and Bools with weird and unspecific, parameter and return names, plaguing my code without me being aware.


I know there are alternatives like the ones you guys mention, but they are all too cumbersome, like errortypes, and etc. I only use that stuff seldomly, when it really is needed, otherwise it's just too much of an hassle.

Call me human.

For instance, I cannot brag that I ever really took good care of nils on objc "old" times, despite my very best efforts. Why? because it places a huge amount of effort on our humble human minds, as if they were not already heavily loaded enough! I for that, consider Optionals to be the greatest of all blessings.


If there was a God I would call it OptionalClosure and create a church in his name.


Good languages make good, lazy, programmers.

Ok.

So then, if it is not an impossible idea, and it does not currently exist, then I guess the right thing for me to do would be to file a radar on the bug reporter for a new Swift feature.


Do you happen to know if:

Is this the correct procedure to ask for new Swift features?

Out of the top of my head, I would agree with you, that such enums should probably not be able to be checked outside the caller.

Although I do not see such limitation as a problem.


However I don't necessarily so quickly agree that it can't be done.

I mean, that it can't be checked outside of the caller.

For I can easily imagine something like a AnyEnum type that would refer to any of these kind of simple enums.

However then, it would be the job of the compiler and of the programmer, to make sure they know what they are dealing with.


Under the rug, Swift could be declaring a regular enum with some gibberish name. And as such Swift would very well know its definition.

From our side, it would be as dealing with a superclass called AnyEnum, and only Swift knowing what hidden selectors it had declared in it.

Xcode code completion would then be the one to tell us what the cases were, for us to test against.

Or we could use code navigation, (cmd+click) to dig down the tree, till we find our enum().


Something like:

class Cook {
    func makeDinner() -> enum(case: ready, ruinned, cooking) {
        return .ready
    }
  
    func doYourJob() -> AnyEnum
        let state = makeDinner()
  
        if state == .ruinned {
            apologiseToClients()
        }
        return state
    }
}
class LousyManager {
    func dinnerTime() {
        let dinnerState = Cook().doYourJob()
      
        if dinnerState == .ruinned {
            startYelling()
        }
    }
}
// Again. This is merely meant as a simple example.
// So please, I dont need you guys to tell me that I could simply name the enum DinnerState. I know that.


By the way I don't intend for these AnyEnum to have more than simple cases; So no rawValues, nor funcs, nor anything that our beloved full-fledged Swift enums can accomplish.

Is there a way to declare an unnamed local enum?

It should be clear by now that, no, there’s no way to do this currently. If you want to change this in the future, you should raise it on the swift-evolution mailing list. Before you do that I recommend that you check out the previous threads (here and here) on this topic.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Ok. Thanks.

I didn't find those places you say.

Thanks for telling me where to place the request.


Yes, it is of course clear by now that, no, there’s no way to do this currently.

Still it was good to discuss the issue here.

As other users forced me question the idea.