Bitshift operators


(Brent Royal-Gordon) #1

While I was watching WWDC videos today, I noticed that there's a bit of annoying boilerplate in OptionSet specifications, and set out to get rid of it. Basically, what I'd like to do is this:

  extension OptionSet where RawValue: Integer {
      init(bit bits: RawValue...) {
          self.init(rawValue: bits.reduce(0) { $0 | (1 << $1) })
      }
  }

  struct FooOptions: OptionSet {
      let rawValue: Int
      
      static let bar = FooOptions(bit: 0)
      static let baz = FooOptions(bit: 1)
  }

However, this was thwarted by the fact that the << operator is not in Integer. Or BitwiseOperations. Or any protocol, in fact.

From what I understand, this is a long-known issue we were planning to address in the Integer redesign, but I'm not sure what the status of that is at this point. I would guess that we're facing one of three situations:

1. An Integer redesign is still planned for Swift 3, but hasn't been reviewed yet.
2. An Integer redesign has been deferred, but an incremental improvement (like adding bitshifting to BitwiseOperations) would be welcome.
3. An Integer redesign has been deferred, and an incremental improvement is either not desired or too late at this point.

Can anyone share the status of this? If we're in #2, I'd be happy to put together a quick proposal to patch this particular issue up in time for Swift 3. (I assume that `OptionSet.init(bit:)` would be considered a "new feature" and thus out of scope.)

···

--
Brent Royal-Gordon
Architechies


(Dave Abrahams) #2

A proposal is imminent.

···

on Wed Jun 15 2016, Brent Royal-Gordon <swift-evolution@swift.org> wrote:

While I was watching WWDC videos today, I noticed that there's a bit
of annoying boilerplate in OptionSet specifications, and set out to
get rid of it. Basically, what I'd like to do is this:

  extension OptionSet where RawValue: Integer {
      init(bit bits: RawValue...) {
          self.init(rawValue: bits.reduce(0) { $0 | (1 << $1) })
      }
  }

  struct FooOptions: OptionSet {
      let rawValue: Int

      static let bar = FooOptions(bit: 0)
      static let baz = FooOptions(bit: 1)
  }

However, this was thwarted by the fact that the << operator is not in
Integer. Or BitwiseOperations. Or any protocol, in fact.

From what I understand, this is a long-known issue we were planning to
address in the Integer redesign, but I'm not sure what the status of
that is at this point.

--
-Dave


(Ben Rimmington) #3

Brent Royal-Gordon wrote:

While I was watching WWDC videos today, I noticed that there's
a bit of annoying boilerplate in OptionSet specifications, and
set out to get rid of it. Basically, what I'd like to do is this:

  extension OptionSet where RawValue: Integer {
      init(bit bits: RawValue...) {
          self.init(rawValue: bits.reduce(0) { $0 | (1 << $1) })
      }
  }

  struct FooOptions: OptionSet {
      let rawValue: Int

      static let bar = FooOptions(bit: 0)
      static let baz = FooOptions(bit: 1)
  }

However, this was thwarted by the fact that the << operator is
not in Integer. Or BitwiseOperations. Or any protocol, in fact.

Alternatively, using binary integer literals:

  struct FooOptions: OptionSet {
      let rawValue: Int

      static let bar = Self(rawValue: 0b01)
      static let baz = Self(rawValue: 0b10)
  }

Does the revised SE-0068 proposal allow this?

-- Ben


(Brent Royal-Gordon) #4

A proposal is imminent.

Great—thanks for the update.

···

--
Brent Royal-Gordon
Architechies


(Ben Rimmington) #5

<https://swift.org/documentation/api-design-guidelines/#type-conversion>

**In initializers that perform full-width type conversions, omit the
first argument label**, e.g. `Int64(someUInt32)`

OptionSet could add `init(_ rawValue: RawValue)` to reduce boilerplate:

  struct FooOptions: OptionSet {
      let rawValue: Int

      static let bar = Self(0b01)
      static let baz = Self(0b10)
  }

-- Ben


(Dave Abrahams) #6

Great idea; please submit a proposal!

···

on Fri Jun 17 2016, Ben Rimmington <swift-evolution@swift.org> wrote:

<https://swift.org/documentation/api-design-guidelines/#type-conversion>

**In initializers that perform full-width type conversions, omit the
first argument label**, e.g. `Int64(someUInt32)`

OptionSet could add `init(_ rawValue: RawValue)` to reduce boilerplate:

  struct FooOptions: OptionSet {
      let rawValue: Int

      static let bar = Self(0b01)
      static let baz = Self(0b10)
  }

--
-Dave


(Ben Rimmington) #7

On second thoughts, perhaps the current design is better. OptionSet changes the failable initializer (inherited from RawRepresentable) into a *nonfailable* initializer. But if we used `init(_ rawValue: RawValue)` in OptionSet, it would also still have the failable initializer (which could maybe have a default implementation).

The original FooOptions example is missing some required boilerplate: `init(rawValue: Int) { self.rawValue = rawValue }`. In the future, a *macro* could be used to hide the RawRepresentable requirements of option sets, making them as easy to read/write as enum cases.

-- Ben

···

On 18 Jun 2016, at 02:25, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:

on Fri Jun 17 2016, Ben Rimmington <swift-evolution@swift.org> wrote:

<https://swift.org/documentation/api-design-guidelines/#type-conversion>

**In initializers that perform full-width type conversions, omit the
first argument label**, e.g. `Int64(someUInt32)`

OptionSet could add `init(_ rawValue: RawValue)` to reduce boilerplate:

  struct FooOptions: OptionSet {
      let rawValue: Int

      static let bar = Self(0b01)
      static let baz = Self(0b10)
  }

Great idea; please submit a proposal!

--
-Dave