3

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?

  • 1
    You're essentially just using an extension as a namespace to tuck a global function into. You're not taking advantage of the main purpose, which is the access to `self`, as shown by Abhinav below – Alexander Sep 19 '22 at 18:16
  • OP might I know why has my answer not been accepted? It was added earlier and illustrates the same concept? – Abhinav Mathur Sep 20 '22 at 17:23
  • Rob's answer gives a clearer picture for this specific situation. His answer includes a code example that uses the function that was used in the question, providing a quicker visual help for the future visitors. The remark about OOP paradigm is a bit broad - the usage of `self` in the original question points to recognizing the fact that it's OOP. – Jordan Niedzielski Sep 20 '22 at 18:30

3 Answers3

3

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).

Abhinav Mathur
  • 7,791
  • 3
  • 10
  • 24
2

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]
        }
    }
}
Rob Napier
  • 286,113
  • 34
  • 456
  • 610
0

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)
    }
}
Soumya Mahunt
  • 2,148
  • 12
  • 30
  • The first example is wrong, since the `self.decomposed`does not accept parameters and calling it recursively with parameters would probably cause the code to not compile at all. For the second remark - please read the question again. The whole purpose of this extension is not having to rely on an auxiliary function. – Jordan Niedzielski Sep 21 '22 at 14:08
  • @JordanNiedzielski I have fixed the typo. – Soumya Mahunt Sep 21 '22 at 17:31