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
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
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
Honestly, while I've described a lot here, once you get each item "under your thumb" individually it's "relatively simple" to understand.