5

Created an extension in a command line app. When I tried calling the calc method, it won't work. Calling desc works.

What did I miss?

protocol Calculatable {
    var desc:String { get }
    mutating func calc()
}

class MyClass : Calculatable {
    var desc:String = "MyClass"
    func calc()  {
        desc += " is great"
    }
}

extension Int: Calculatable {
    var desc:String { return "hi" }
    mutating func calc() {
        self += 10
    }
}

7.desc  // works
7.calc() // Compiler error: could not find member calc
Boon
  • 40,656
  • 60
  • 209
  • 315

1 Answers1

5

That is because 7 is a constant. You can do it if you first store it in a variable:

var number = 10
number.calc()

Note: The error you are getting isn't a very good error. Swift definitely has some work to do on that side of things. The real error is that you are trying to call a mutating method on an immutable instance

What you can do is make it a regular method and return a new value instead of trying to mutate self:

extension Int: Calculatable {
    var desc: String { return "hi" }
    func calc() -> Int {
        return self + 10
    }
}

7.calc() // 17
drewag
  • 93,393
  • 28
  • 139
  • 128
  • It's a funny mix of great, insightful error messages and error messages that seem miles away from the real problem... Messages telling you that you've tried to mutate a constant are particularly opaque, IIRC. "Can't find an override for `+=`" when the real problem is I'm trying to `+=` a member of a struct assigned to a `let`. – matt Jun 23 '14 at 00:25
  • 1
    @matt ahah true. I try to submit bugs to Apple about error messages whenever I come across poor ones. Hopefully then they can improve those "miles away from the real problem" problems :) – drewag Jun 23 '14 at 00:26
  • Ah, was thinking of Ruby where such a thing is allowed. – Boon Jun 23 '14 at 00:41
  • 1
    @Boon, you can do similar things as long as you don't try to mutate the existing value. Instead have your calc function not be mutating and return a new value. I will update my answer with that example. – drewag Jun 23 '14 at 00:42
  • @Boon: `self += 10` is actually not allowed in Ruby. There is no real way in Ruby to make a Fixnum change its value. – Chuck Jun 23 '14 at 01:19
  • Thanks Chuck - you are right. I meant the syntax to write 9.x(). At first I thought it was not allowed, until @drewag pointed out the reason why. – Boon Jun 23 '14 at 01:31
  • 1
    To make it clearer, I'd add a new method that does not implement the mutating calc method and specifies that it returns an Int. Something like:func tenMore() -> Int { return self + 10 } – louielouie Jun 23 '14 at 01:45
  • I believe without specifying the -> Int the code won't compile. – Boon Jun 23 '14 at 02:56
  • @Boon which code? Technically my example code won't work with yours since I didn't implement your Calculatable protocol as you declared it. – drewag Jun 23 '14 at 03:28
  • @drewag I think you need to have -> Int above in order to return something. Otherwise compiler will complaint. – Boon Jun 23 '14 at 05:30