There exist C APIs which have functions that take pointers as arguments, where a null pointer indicates that the argument has no value. Here is an example from an API I am working with:
C header
/*
* XPLMFindNavAid
*
* This routine provides a number of searching capabilities for the nav
* database. XPLMFindNavAid will search through every navaid whose type is
* within inType (multiple types may be added together) and return any navaids
* found based on the following rules:
*
* * If inLat and inLon are not NULL, the navaid nearest to that lat/lon will
* be returned, otherwise the last navaid found will be returned.
*
* * If inFrequency is not NULL, then any navaids considered must match this
* frequency. Note that this will screen out radio beacons that do not have
* frequency data published (like inner markers) but not fixes and airports.
*
* * If inNameFragment is not NULL, only navaids that contain the fragment in
* their name will be returned.
*
* * If inIDFragment is not NULL, only navaids that contain the fragment in
* their IDs will be returned.
*
* This routine provides a simple way to do a number of useful searches:
* * Find the nearest navaid on this frequency.
* * Find the nearest airport.
* * Find the VOR whose ID is "KBOS".
* * Find the nearest airport whose name contains "Chicago".
*
*/
XPLM_API XPLMNavRef XPLMFindNavAid(
const char * inNameFragment, /* Can be NULL */
const char * inIDFragment, /* Can be NULL */
float * inLat, /* Can be NULL */
float * inLon, /* Can be NULL */
int * inFrequency, /* Can be NULL */
XPLMNavType inType);
In these cases, my translation into a more idiomatic API in Swift takes an optional keyword argument, defaulting to nil. I would like to be able to use the normal syntactic sugar of &it, so that when, for example with lat, if it's nil, then the C API gets NULL, but if it's not nil, then the C API gets a pointer to it.
Currently, this is considered an error -- T? cannot be coerced to a UnsafeMutablePointer<T>?. This results in some very clumsy code:
Clumsy Swift code
// In one file
internal func withModulatedOptional<T, Res>(
mut it: inout T?,
_ clz: (UnsafeMutablePointer<T>?) -> Res
) -> Res {
if var it {
return clz(&it)
} else {
return clz(nil)
}
}
// In the static function to find a navaid:
let ref = withModulatedOptional(mut: &lat) { (lat) in
withModulatedOptional(mut: &lon) { (lon) in
withModulatedOptional(mut: &frequency) { (frequency) in
XPLMFindNavAid(
nameFragment,
identFragment,
lat,
lon,
frequency,
type.xplm
)
}
}
}
This really isn't ideal. I don't think it's too major a change to do this, and it would get rid of those nested closures and the weird wrapper function.