I'm no expert, but I'll try to answer your questions.
buf
, as you say, is an array of 256 Int8's (signed bytes). You invoke the withUnsafeMutableBufferPointer
method on it, and pass a closure that takes as input, in this case, an "inout UnsafeMutableBufferPointer<Int8>
" (which is also in this case named buf
, but is not the same buf
that is defined earlier) and returns a String. (Probably the outer buf
should be renamed, maybe to bufferArray
or something...)
Basically (??), when the closure is invoked it is passed as an inout parameter the an "unsafe mutable buffer" that contains the address(baseAddress
) and size (count
) of the "backing storage" of the array. Since getcwd()
takes a pointer to a signed byte (array) and the size of the the array, those are the parameters you pass to it.
getcwd()
, assuming there is no error, populates the buffer with the value of the current working directory, along with a trailing "null" character. It returns the address of the buffer (the same value as buf.baseAddress
).
Since there is the possibility of this being a "null" address (binary zeroes), which would occur in the case of an error, you have to code for that possibility. That's where guard
comes in. The guard says that if the assignment (let) of the result of getcwd()
to the variable named cwdRef fails (because getcwd()
has returned a null pointer, which Swift treats as a nil
value) then the closure should return the nil value.
If the assignment succeeds (the guard "passes") then the result (cwdRef
) is passed to the call to String(cString:)
, which creates a Swift String based on the contents of the C String that cwdRef points to.
The outer return returns the results if the closure as the result of the call to cwd()
.
So to more specifically answer why there are three return
statements, the first one, as stated previously, returns the result of the closure. The two within the closure return from the closure itself, either with the value nil
or the created String.
As for the let _ =
in an earlier example, that simply says to ignore the result of the call to (in this case) getcwd()
. His example would have compiled if he had invoked String(cString:) with the parameter buf
instead of cwdRef
:
print(String(cString: buf))
Honestly, while I've described a lot here, once you get each item "under your thumb" individually it's "relatively simple" to understand.