Guillermo Alvarez
Guillermo Alvarez

Reputation: 1775

Change in recent Swift update regarding mutating structs?

I am following along in the Stanford iOS course and I have a question that I believe is related to a recent update. Here is the section of code:

func evaluate(ops: [Op]) -> (result: Double?,remainingOps: [Op]) {
    let op = ops.removeLast() //*I thought ops was immutable?         
}

On the video, the instructor gets an error that says you cannot do this because ops is immutable. This makes complete sense but when I try typing this in I do not get an error. What does this mean? Is this a change in a recent Swift update that structs passed into methods are mutable? Any ideas? In the video, the instructor solves the problem by creating an instance variable which is a copy of ops but I no longer get the error and would like to understand why this is.

EDIT When typing this into a playground I still get the error but I do not in my Swift File. For reference here is the entire file so far. Any ideas? I just want to understand what is going on here:

import Foundation

class CalculatorBrain {

    private enum Op {
        case Operand(Double)
        case UnaryOperation(String,Double -> Double)
        case BinaryOperation(String, (Double,Double) -> Double)
    }

    private var opStack = [Op]()

    private var knownOps = [String:Op]()

    init() {
        knownOps["×"] = Op.BinaryOperation("×",*)
        knownOps["÷"] = Op.BinaryOperation("÷") { $1 / $0 }
        knownOps["+"] = Op.BinaryOperation("+",+)
        knownOps["−"] = Op.BinaryOperation("−") { $1 - $0 }
        knownOps["^"] = Op.BinaryOperation("^") { pow($1,$0) }
        knownOps["√"] = Op.UnaryOperation("√",sqrt)
        knownOps["sin"] = Op.UnaryOperation("sin") { sin($0) }
        knownOps["cos"] = Op.UnaryOperation("cos") { cos($0) }
        knownOps["tan"] = Op.UnaryOperation("tan") { tan($0) }

    }

    func evaluate(ops: [Op]) -> (result: Double?,remainingOps: [Op]) {
        if !ops.isEmpty {
            let op = ops.removeLast()//*Error should appear here but does not

        }
        return (nil,ops)
    }

    func evaluate() -> Double? {

    }

    func pushOperand(operand: Double) {
        opStack.append(Op.Operand(operand))
    }

    func performOperation(symbol: String) {
        if let operation = knownOps[symbol] {
            opStack.append(operation)
        }
    }
}

Upvotes: 0

Views: 177

Answers (2)

ubersnack
ubersnack

Reputation: 510

I've just tried this now with the following Playground code which throws up an error (Xcode 6.3.1):

//: Playground - noun: a place where people can play

import UIKit
import XCPlayground

//: Developing iOS 8 Apps with Swift 3. Applying MVC 40 minutes in

enum Op {
    case Operand(Double)
    case UnaryOperation(String, Double -> Double)
    case BinaryOperation(String, (Double, Double) -> Double)
}

var knownOps = [String:Op]()

knownOps["x"] = Op.BinaryOperation("x", *)

// by putting let for the parameter we are declaring ops as immutable
// the default is for each parameter is let
func evaluate(ops: [Op]) -> (result: Double?, remainingOps: [Op]) {
    if !ops.isEmpty {
        let op = ops.removeLast() // Immutable value of type '[Op]' only has mutating members named 'removeLast'
    }
    return (nil, ops)
}

if I change evaluate(ops: [Op]) to evaluate(var ops: [Op]), the same as in the video it removes the error. I'm thinking that there is something wrong with the Xcode project you are using - maybe try restarting Xcode (the old off 'n on)?

Upvotes: 0

Salihcyilmaz
Salihcyilmaz

Reputation: 326

I have just checked to see if it implicitly makes copy of array. No it does not. Your xCode is in bug i think. Please restart xCode and try again. Go to utilities bar, move your cursor on ops array in the code. What do you observe as a type? "error type" or something else? You can also check this by pressing opt and click to the variable.

Upvotes: 1

Related Questions