Simplify additional assignment

Sorry about the terrible topic name...

Is there any "Swifty sugar" that could simplify the following?

let x: Int
let sign: FloatingPointSign
if let p = signedPositiveValues.index(of: c) {
    x = p
    sign = .plus
}
else if let n = signedNegativeValues.index(of: c) {
    x = n
    sign = .minus
}
else {
    return nil
}

Something with the coalesce operator maybe?

guard let (x, sign) =
    signedPositiveValues.index(of: c).map({ ($0, FloatingPointSign.plus) }) ??
    signedNegativeValues.index(of: c).map({ ($0, FloatingPointSign.minus) }) else {
  return nil
}

But I'm not sure that's actually clearer than what you have. It might be enough to write a helper function:

func lookUp(_ c: Whatever) -> (Int, FloatingPointSign)? {
  if let p = signedPositiveValues.index(of: c) {
    return (p, .plus)
  } else if let n = signedNegativeValues.index(of: c) {
    return (n, .minus)
  } else {
    return nil
  }
}

guard let (x, sign) = lookUp(c) else {
  return nil
}
1 Like

I will ponder both. Thanks! Trying to be as "Swifty" as I can.

Any thoughts on the "Swiftyness" of this full example?

import Foundation

extension Collection {
    public var finalIndex: Self.Index {
        return self.index(self.endIndex, offsetBy: -1)
    }
}

extension Decimal {
    public enum SignPosition {
        case none, leading, trailing
    }

    // scale:  Scale is the number of digits to the right of the decimal point in a number.
    public init?(digitString digits: String, signPosition: SignPosition = .none, scale: Int = 0) {
        // make sure digit string is not an empty string
        guard let firstDigit = digits.first, let lastDigit = digits.last else { return nil }

        var digitsWithSign: (String, FloatingPointSign)? {
            let digit: Character
            let digitPos: String.Index
            switch signPosition {
            case .none:
                return (digits, .plus)
            case .leading:
                (digit, digitPos) = (firstDigit, digits.startIndex)
            case .trailing:
                (digit, digitPos) = (lastDigit, digits.finalIndex)
            }

            let signedPositiveDigits = [Character]("{ABCDEFGHI")
            let signedNegativeDigits = [Character]("}JKLMNOPQR")
            let sign: FloatingPointSign
            let digitValue: Int
            if let p = signedPositiveDigits.index(of: digit) {
                digitValue = p
                sign = .plus
            }
            else if let n = signedNegativeDigits.index(of: digit) {
                digitValue = n
                sign = .minus
            }
            else {
                return nil    // sign position does not have a valid "sign digit"
            }

            var unsignedString = digits
            unsignedString.replaceSubrange(digitPos ... digitPos, with: String(digitValue))
            return (unsignedString, sign)
        }

        guard let (digits, sign) = digitsWithSign else { return nil }
        guard let significand = Decimal(string: digits) else { return nil }
        self = Decimal(sign: sign, exponent: 0 - scale, significand: significand)
    }
}

if let d = Decimal(digitString: "201", scale: 2) {
    print(d)  // 2.01
}

if let d = Decimal(digitString: "R87", signPosition: .leading, scale: 2) {
    print(d)  // -9.87
}

if let d = Decimal(digitString: "21{", signPosition: .trailing, scale: 2) {
    print(d)  // 2.1
}

Thanks.