Could enums have their rawValue type inferred?


(Eric Miller) #1

automatically cast rawValue when assigning an enum value to

a variable or argument of the type of the enum's raw value

That's exactly what I'm thinking, Leonardo. I was a little bit trying to
avoid specifics because I don't understand the differences between
autocasting and inference.

There's a small miscommunication though--This api works great since it
accepts the enum type, rather than the underlying value type. Signature:

static func fadeIn(view: UIView?, withSpeed: Animate.transitionSpeed =
Animate.transitionSpeed.fast)

The goal was to provide my users with a good default and an easy set of
configurable options at the call site like `.fast`, `.normal`, `.slow`.

(unrelated: +1 on inferring type of function params with default values, I
hit this all the time)

Calling:

Animate.fadeIn(myView, withSpeed: .slow)

Works great.

This library of methods is a facade for CABasicAnimation or UIView
animations which take an NSTimeInterval, and that's where the "autocasting"
would come into play.

···

------------------------------

Message: 31
Date: Fri, 13 May 2016 16:58:06 -0300
From: Leonardo Pessoa <me@lmpessoa.com>
To: Swift-evolution <swift-evolution@swift.org>
Subject: Re: [swift-evolution] Could enums have their rawValue type
        inferred?
Message-ID:
        <CANTOS57wksMRzUAMq0ncf1QAd82vhudf21tnea6wHjhBOFr1PA@mail.gmail.com>
Content-Type: text/plain; charset="utf-8"

Eric, I think I understood your proposal. If I may explain in other words
it would be "to automatically cast rawValue when assigning an enum value to
a variable or argument of the type of the enum's raw value", am I right? I
think this would imply a little more inference and type checking rules from
the compiler and maybe even take a little longer to fully compile code. I'm
not sure it's feasible but from your examples, I can see how it enhances
readability of the code, so I'm +1 for it. My only concern is that you
would still need to fully declare the enum's name where the value of the
enum is used. Taking from your own example

    Animate.fadeIn(view, withSpeed: .fast)

couldn't be called that way if withSpeed expects and NSTimeInterval because
the compiler won't know whether you're refering to transitionSpeed or to
ambientAnimationSpeed. You would still have to call it like

    Animate.fadeIn(view, withSpeed: transitionSpeed.fast)

even if you had only one possible enum value over all declared enums
because that would still force the compiler to search for each value over
all known enums to define where the value you're using comes from and make
sure there are no two enums with the same value.

Aside from that, I good with the idea.

On 13 May 2016 at 15:09, Eric Miller via swift-evolution < swift-evolution@swift.org> wrote:

This might open a larger can of worms than I imagine, but what do you
folks think about using the `rawValue` of an enum when that rawValue is a
fit for the expected type?

Use case.

I'm making an animation facade, and it has some speed presets:

class Animate {
  enum transitionSpeed: NSTimeInterval {
    case fast = 0.15
    case slow = 0.5
  }
  enum ambientAnimationSpeed: NSTimeInterval {
    case fast = 1.0
    case slow = 5.0
  }
  ...
}

I did them with static variables at first but that made the call site
verbose. Compare:

Animate.fadeIn(view, withSpeed: Animate.cfg.transitionFast)
Animate.fadeIn(view, withSpeed: .fast)

So, I like the enum approach better, but my library code has to use
`rawValue` to do anything with the actual value, of course:

static func fadeIn(view: UIView?, withSpeed duration:transitionSpeed =
.fast) {
  ...
  UIView.animateWithDuration(duration.rawValue, animations: { })
}

It's not a serious issue, but the code is more clear and beautiful if it
has just myIntent, rather than myIntent.rawValue.

I've hit this issue when modeling other things, such as:

* server fault codes
* HTTP status codes
* Currency codes
* Days of the week

Would it be appropriate to "autocast" to the rawValue of the enum when the
rawValue's Type matches the type expectation of the API? Or would this
introduce a bunch of type system uncertainty?

Maybe this could be implemented as a protocol? It feels almost like the
convenience of `CustomStringConvertible`'s `description` property.