Advertise here




Advertise here

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

How do you explain the inout keyword?

Hello,

I am trying to really understand the concept of the inout keyword, so I can explain to people clearly so I wrote a simple function:
func myInoutFunc(_ myInout: inout Int) -> Int {
    myNum = myInout * myInout
    return myNum
}

var myNum = 8
print(myNum) //before function myInoutFunc
print(myInoutFunc(&myNum)) //after function myInoutFunc


This function works Now if I were asked how it work
Can I say that when invoke a inout function, I am not modifing the variable myNum by its local value. I am actually modifying its value by reference(address) thus the '&' symbol. Kinda like pass by dress in C. Does this make sense? Please do share if you have a better to verbalize it. Thank.

Replies

  • BrianSlickBrianSlick Treadmill Desk Ninja Posts: 10,687 @ @ @ @ @ @ @ @
    Your example is not accurate. Notice that the item that you have tagged as inout - myInout - is never changed inside your function. Your function modifies myNum, which is not related to inout in this example. I'm pretty sure this is only "working" because of the oddball way that playgrounds solve everything in the file. I bet if you tried this in an ordinary code file in a sample project, it wouldn't work. Also notice that you did not have to "let" or "var" myNum INSIDE the function. That should have been a new variable, the first clue that something here isn't quite normal.

    Here is a version of your example that does modify the original value correctly:
    func myInoutFunc(_ myInout: inout Int) -> Void {
        myInout = myInout * myInout
    }
    
    var myNum = 8
    print(myNum) // 8
    myInoutFunc(&myNum)
    print(myNum) // 64
    

    I'm using a Void function on purpose. The return value of yours makes it a challenge to understand what is really happening here.

    As far as an explanation, can't go wrong starting with the source (In-Out Parameters section):
    https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Functions.html
    Professional iOS App Development. Available for hire.
    BriTer Ideas LLC - WWW | Facebook | Twitter | LinkedIn

    BTIKit | BTICoreDataKit | SlickShopper 2 | Leave a PayPal donation
  • dickthedevdickthedev Posts: 208 @ @
    Thank you very much for pointing out my mistake. I am still trying to digest Swift. So much to learn :)
  • dickthedevdickthedev Posts: 208 @ @
    edited May 5
    Hello, BrianSlick I had some time this morning to go through the code carefully.
    You said that my code wouldn't work because I never change myInout, is it because I shouldn't have to have a return value when I use inout? Is it because always needs to have a void return?
    aso you said "Also notice that you did not have to "let" or "var" myNum INSIDE the function." I am not very clear about this. In your code myInout = myInout * myInout
    there isn't a let or ver declared neither, doesn't Swift label a let by default if you don't use either of these keywords?
    Thanks.
  • BrianSlickBrianSlick Treadmill Desk Ninja Posts: 10,687 @ @ @ @ @ @ @ @
    Well, some of these things you can test for yourself. Try this in a playground:
    let a = 1
    let b = 2
    test = a + b
    

    Does it work? No. You must have a let or var declaration.

    So first let's take your example and just change some names. (and add let)
    func squareThisNumber(_ input: inout Int) -> Int {
        let calculation = input * input
        return calculation
    }
    
    var number = 8
    print(number) // 8
    print(squareThisNumber(&number)) // 64
    print(number) // 8
    

    Exactly the same as yours, just different names, and I had to add "let" inside the function. I've also added an extra log.

    You do get 64 at the second log. This is because your function takes a number, squares it, and returns a value. This does not modify the original number. Your log is showing the return value, which is 64 whether you modify the original number or not. So how can you tell if it is working? You ran it, saw 64, assumed it was working. Notice at the final log that "number" is still the original value. That means you didn't accomplish what you set out to accomplish.

    So why have inout in this case? Would this be any different if the function looked like this?
    func squareThisNumber(_ input: Int) -> Int {
    

    Nope. The function takes a number, performs a calculation, and returns another number. You certainly don't have to modify the original value in order to perform some math.

    Take your original code, remove "inout" and "&", and notice your logs. They are exactly the same. This means you didn't really need inout in your example, which, since you were specifically trying to demonstrate the use of inout, shows that the example is not so good.

    Now take a look at mine again, also with different names:
    func squareThisNumberToo(_ input: inout Int) -> Void {
        input = input * input
    }
    
    var anotherNumber = 8
    print(anotherNumber) // 8
    squareThisNumberToo(&anotherNumber)
    print(anotherNumber) // 64
    

    This one does not have a return value. The only way it affects the outside world is by modifying the original value, which is only possible when handled via inout. If you read the Apple link I posted earlier, it says that parameters are CONSTANTS. So normally, "input" would not be able to change. Thus, without the inout parameter, this could not work:
    input = input * input
    

    This would be a modification to a constant, which isn't allowed. So, we add the inout flag, and now we can change it.

    This is also the answer to why my code does not have a "let" or "var" on this line. I'm not declaring a new variable here. I'm messing with the input variable.

    As far as whether or not to have a return value, that depends on what the function is supposed to do. Just want to return a value? Then you may not need an inout parameter. Want to modify an original value? Then you may not need a return value. But it is certainly possible that you could want to return a value AND modify a variable like this, so you could do both.
    Professional iOS App Development. Available for hire.
    BriTer Ideas LLC - WWW | Facebook | Twitter | LinkedIn

    BTIKit | BTICoreDataKit | SlickShopper 2 | Leave a PayPal donation
Sign In or Register to comment.