Jordan Niedzielski
Jordan Niedzielski

Reputation: 123

Providing default instance arguments for (recursive) extension in Swift

I was having fun while practicing a Kata.
I wanted to implement one of the functions in my solution as an extension of Int, because I liked the idea of having pretty syntax. The function, in itself, looks like this:

func decomposed(_ n: Int) -> [Int] {
    if n > 10 {
      return n.decomposed(n / 10) + [n % 10] 
    } else {
      return [n]
    }
  }

Now, I've tried to implement it as an extension. Due to the fact that I would like to use it like 420.decomposed(), I figured that I would need the instance as the default argument. I proceeded with:

extension Int {
  func decomposed(_ n: Int = self) -> [Int] {
    if n > 10 {
      return n.decomposed(n / 10) + [n % 10] 
    } else {
      return [n]
    }
  }
}

This is the part, however, in which it gets trickier. I'm being told by the compiler that error: cannot find 'self' in scope.

Having read about the methods in the docs, I've resorted to using Int? default argument. Now, the extension is implemented as:

extension Int {
  func decomposed(_ n: Int? = nil) -> [Int] {
    var _n = n ?? self
    if _n > 10 {
      return _n.decomposed(_n / 10) + [_n % 10] 
    } else {
      return [_n]
    }
  }
}

I don't like the look of the _n, though.
I would love to use self as the default argument. Is that possible? Or are we stuck with hackity hacks until the judgement day?

Upvotes: 3

Views: 62

Answers (3)

Soumya Mahunt
Soumya Mahunt

Reputation: 2792

In your function decomposed, you aren't using self and n anywhere together you can either make your decomposed method accept no parameter and use self from the function:

extension Int {
    func decomposed() -> [Int] {
        if self > 10 {
            return (self / 10).decomposed() + [self % 10]
        } else {
            return [self]
        }
    }
}

or if you plan to pass any parameter then you can just define a top level function instead of using extension:

func intDecomposed(_ n: Int) -> [Int] {
    if n > 10 {
        return n.decomposed(n / 10) + [n % 10]
    } else {
        return [n]
    }
}

You can use the above method inside the decomposed extension method providing self as parameter:

extension Int {
    func decomposed() -> [Int] {
        return intDecomposed(self)
    }
}

Upvotes: 0

Rob Napier
Rob Napier

Reputation: 299565

You need to remove n as a parameter, replace every use of n in the function with self (since that's what's being operated on), and convert the function syntax to the method syntax in the recursion:

extension Int {
    func decomposed() -> [Int] {
        if self > 10 {
            return (self / 10).decomposed() + [self % 10]
        } else {
            return [self]
        }
    }
}

Upvotes: 2

Abhinav Mathur
Abhinav Mathur

Reputation: 8186

Wrote a quick implementation to highlight the usage of extensions:

import Foundation

func main() {
  print(2.test()) // prints 2
  print(12.test()) // prints 3
  print(42.test()) // prints 6
}

extension Int {
  func test() -> Int {
    if self <= 10 {
      return self
    }
    return (self % 10) + (self/10).test();
  }
}

main()

You don't need to pass self as an argument, since that will not work. By default, self will be available for use inside the extension methods (since that follows the object oriented paradigm).

Upvotes: 3

Related Questions