Using C functions in Swift that take functions as arguments - c

I'm writing a wrapper around a C mathematical library. Every function takes one or two functions as arguments. However, the arguments for those child functions (as well as the parent functions) are not Swifty -hence the wrapper.
I've cleaned up the example code to just show the three main pieces: the c-library function, the desired Swift function that would be passed to the wrapper (body not shown, but wrapping around the c-library function), and the required C function form.
//C library function, that calls the passed function dozens, hundreds or thousands of times, each time it changes the data provided in p, and uses the output from x
//The Swift arrays are passed as pointers, and the length of the and x array are m and n respectively
returnValue = cLibraryFunc(passedFunc, &p, &x, Int32(m), Int32(n), Int32(itmax), &opts, &info, &work, &covar, &adata)
//I would like to create a Swift function that would look like this (internals could be any myriad of things that takes inputs p and adata and returns data in x:
func desiredSwifty(p: inout [Double], x: inout [Double], m: Int, n: Int, adata: inout [Double]) {
//very simple example
//this example knows the length of p (so m as well)
//and assumes that adata length is the same as the x length (n)
//obviously, it could ifer m and n from p.count and x.count
for i in 0..<n {
x[i] = p[0] + p[1]*adata[i] + p[2]*pow(adata[i], 2)
}
}
//And the wrapper would "convert" it -internally- into the form that the C library function requires:
func requiredC(p: UnsafeMutablePointer<Double>?, x: UnsafeMutablePointer<Double>?, m: Int32, n: Int32, adata: UnsafeMutablePointer<Void>?) {
//same thing, but using pointers, and uglier
//first, have to bitcast the void back to a double
let adataDouble : UnsafeMutablePointer<Double> = unsafeBitCast(adata, to: UnsafeMutablePointer<Double>.self)
for i in 0..<Int(n) {
x![i] = p![0] + p![1]*adataDouble[i] + p![2]*pow(adataDouble[i], 2)
}
}
addition
I should add that I have access to the c source code, so I could possibly add some dummy parameters (possibly to find a way to pass context in). But given that the docs seem to indicate that one can't grab context with a c function pointer, this may be of no use.

(Note: the following example uses Swift 3 on Xcode 8 beta 2.)
Your question is about C functions taking another C function as an argument, so let us reduce the question to that problem. Here is a simple C function which takes a single argument which is
again a C function which takes a pointer to an array of doubles
and an integer count:
// cfunction.h:
void cFunc(void (*func)(double *values, int count));
// cfunction.c:
void cFunc(void (*func)(double *values, int count)) {
double x[] = { 1.2, 3.4, 5,6 };
func(x, 3);
}
This function is imported to Swift as
func cFunc(_ func: (#convention(c) (UnsafeMutablePointer<Double>?, Int32) -> Swift.Void)!)
Here #convention(c) declares the block to have C-style calling
conventions. In particular, from Swift you can pass only a global function or a closure which does not capture any context.
A simple example for a Swift wrapper is
func swiftyFunc(passedFunc: (#convention(c) (UnsafeMutablePointer<Double>?, Int32) -> Void)) {
cFunc(passedFunc)
}
which you can use like this:
func functionToPass(values: UnsafeMutablePointer<Double>?, count: Int32) {
let bufPtr = UnsafeBufferPointer(start: values, count: Int(count))
for elem in bufPtr { print(elem) }
}
swiftyFunc(passedFunc: functionToPass)
or with a closure argument:
swiftyFunc { (values, count) in
let bufPtr = UnsafeBufferPointer(start: values, count: Int(count))
for elem in bufPtr { print(elem) }
}

Do you know that you can get a mutable pointer to a var just by using the & operator? It does the "right thing" on arrays too.
func foo(_ x: UnsafeMutablePointer<Int>) {
print(x)
}
func bar(_ x: UnsafeMutablePointer<Int>) {
print(x)
}
var array = [0]
foo(&array)
var int = 0
bar(&int)
(Tested on Swift 2, but most likely still valid on Swift 3.)
I suspect that this could drastically reduce your need for wrappers.

Related

Swift 5 Create 3D Array of Doubles And Pass To C Function

I need to call a legacy C function (from swift) that expects a 3D array of Doubles as an argument. I am fairly new to Swift and have begun converting a large ObjC and C code base written for iOS and Mac over to Swift. The C code does a lot of complex astronomical math and for which Swift is just too cumbersome. I will not convert those, but I need to use them from Swift
The C function is declared like this and the .H file is visible to swift:
void readSWEDayData(double dData[DATA_ROWS_PER_DAY][NUM_PLANET_ELEMENTS][NUM_ELEMENTS_PER_PLANET]);
The Constants used in the declaration are defined to be:
DATA_ROWS_PER_DAY = 1
NUM_PLANET_ELEMENTS = 35
NUM_ELEMENTS_PER_PLANET = 4
I am struggling with declaring the array of doubles in a way that Swift will allow to be passed to the C function. I've tried several approaches.
First Approach:
I declare the array and call it like so:
var data = Array(repeating: Double(EPHEMERIS_NA), count:Int(DATA_ROWS_PER_DAY * NUM_PLANET_ELEMENTS * NUM_ELEMENTS_PER_PLANET))
readSWEDayData(&data)
I get this error: Cannot convert value of type 'UnsafeMutablePointer' to expected argument type 'UnsafeMutablePointer<((Double, Double, Double, Double),...
Second Approach:
If I declare the array this way:
var data = [(Double, Double, Double, Double)](repeating: (EPHEMERIS_NA, EPHEMERIS_NA, EPHEMERIS_NA, EPHEMERIS_NA), count: Int(NUM_PLANET_ELEMENTS))
readSWEDayData(&data)
I get this error: Cannot convert value of type 'UnsafeMutablePointer<(Double, Double, Double, Double)>' to expected argument type 'UnsafeMutablePointer<((Double, Double, Double, Double),
So, how the heck does one declare a 3D Array in Swift of a specific size so that it can be passed to a C Function?
The function needs an UnsafeMutablePointer to a 35-tuple of things, where each of those things are 4-tuples of Doubles. Yes, C arrays translate to tuples in Swift, because Swift doesn't have fixed size arrays. You could do:
var giantTuple = (
(EPHEMERIS_NA, EPHEMERIS_NA, EPHEMERIS_NA, EPHEMERIS_NA),
(EPHEMERIS_NA, EPHEMERIS_NA, EPHEMERIS_NA, EPHEMERIS_NA),
(EPHEMERIS_NA, EPHEMERIS_NA, EPHEMERIS_NA, EPHEMERIS_NA),
// 32 more times...
)
readSWEDayData(&giantTuple)
But I don't think you'd like that. You can create an array, and use some pointer magic to convert that to a tuple, as discussed in this Swift Forums post. In fact, that post is highly relevant to your situation.
To save some typing, we can write some type aliases first:
typealias Tuple35<T> = (T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T)
typealias Double4x35 = Tuple35<(Double, Double, Double, Double)>
Then we can do:
var giantTuple = Array(repeating: (EPHEMERIS_NA, EPHEMERIS_NA, EPHEMERIS_NA, EPHEMERIS_NA), count: NUM_PLANET_ELEMENTS).withUnsafeBytes { p in
p.bindMemory(to: Double4x35.self)[0]
}
readSWEDayData(&giantTuple)
This works because tuples and arrays have essentially the same "layout" in memory.
Note that I "cheated" a little bit here, since DATA_ROWS_PER_DAY is 1, you can just create one such giantTuple, and get a pointer to it. However, if it is greater than 1, you'd have to do something like:
var giantTuples = Array(repeating:
Array(repeating: (EPHEMERIS_NA, EPHEMERIS_NA, EPHEMERIS_NA, EPHEMERIS_NA), count: NUM_PLANET_ELEMENTS).withUnsafeBytes { p in
p.bindMemory(to: Double4x35.self)[0]
},
count: DATA_ROWS_PER_DAY)
readSWEDayData(&giantTuples)
To convert from the giant tuple back to an array, you can do something like this:
// converting the first giantTuples in "giantTuples" as an example
let arrayOf4Tuples = asCollection(giantTuples[0], Array.init)
let finalArray = arrayOf4Tuples.map { asCollection($0, Array.init) }
// these are adapted from the Swift forum thread
// you'll need two of these, because you have 2 types of tuples
// yes, working with C arrays is hard :(
func asCollection<T, E>(_ tuple: Tuple35<E>, _ perform: (UnsafeBufferPointer<E>)->T) -> T {
return withUnsafeBytes(of: tuple) { ptr in
let buffer = ptr.bindMemory(to: (E.self))
return perform(buffer)
}
}
func asCollection<T, E>(_ tuple: (E, E, E, E), _ perform: (UnsafeBufferPointer<E>)->T) -> T {
return withUnsafeBytes(of: tuple) { ptr in
let buffer = ptr.bindMemory(to: (E.self))
return perform(buffer)
}
}
Because Swift 5 lacks support for interoperability with C language multi-dimensional Arrays of fixed size except via tuples of explicitly declared structure (See Sweeper's answer above) and which is something I wish to avoid to keep my code flexible for future changes to the C Library being used, I opted to write a wrapper for the C function and make it appear to Swift as a 1 dimensional array.
This was necessary because the Constants used in the C Code change when readSWEDayData increases the array sizes to support additional elements and tuple declarations like this:
let Double4x35 = Tuple35<(Double, Double, Double, Double)>
will DEFINITELY break in a way that will be hard to find:
So my C wrapper function looks like so:
void readSWEDayDataForSwift(double *dData) {
readSWEDayData((double (*)[NUM_PLANET_ELEMENTS][NUM_ELEMENTS_PER_PLANET])dData);
}
Making it easy to call it from Swift like so:
var data = Array(repeating: Double(EPHEMERIS_NA), count:Int(DATA_ROWS_PER_DAY * NUM_PLANET_ELEMENTS * NUM_ELEMENTS_PER_PLANET))
I was surprised that this far into Swift's evolution there is no better way to do this!
My two cents for others..Hoping will help.
I got a similar problem, but hope can save time for other.
I had to pass down:
path (from String to char *)
title (from String to char *)
columns ([String] to array of char *)
a counter
to sum up I had to call "C" function:
bool OpenXLSXManager_saveIn(const char * cFullPath,
const char * sheetName,
char *const columnTitles[],
double *const values[],
int columnCount);
I started from excellent:
// https://oleb.net/blog/2016/10/swift-array-of-c-strings/
expanded a bit:
public func withArrayOfCStringsAndValues<R>(
_ args: [String],
_ values: [[Double]],
_ body: ([UnsafeMutablePointer<CChar>?] , [UnsafeMutablePointer<Double>?] ) -> R ) -> R {
var cStrings = args.map { strdup($0) }
cStrings.append(nil)
let cValuesArrr = values.map { (numbers: [Double]) -> UnsafeMutablePointer<Double> in
let pointer = UnsafeMutablePointer<Double>.allocate(capacity: numbers.count)
for (index, value) in numbers.enumerated() {
pointer.advanced(by: index).pointee = value
}
return pointer
}
defer {
cStrings.forEach { free($0) }
for pointer in cValuesArrr{
pointer.deallocate()
}
}
return body(cStrings, cValuesArrr)
}
so I can call:
func passDown(
filePath: String,
sheetName:
String,
colNames: [String],
values: [[Double]]
) -> Bool
{
let columnCount = Int32(colNames.count)
return withArrayOfCStringsAndValues(colNames, values) {
columnTitles, values in
let retval = OpenXLSXManager_saveIn(filePath, sheetName, columnTitles, values, columnCount)
return retval
}
}
(SORRY for formatting, S.O. formatter has BIG issues ..)

Swift Array: Cannot invoke 'append' with an argument list of type '(Int)'

I'm trying to implement a padding function for Array:
extension Array {
func dataWithPadding(offset: Int, length: Int, paddingLength: Int) -> NSData {
var arr = Array(self[offset..<(offset + length)])
arr = arr.reverse()
for (var i = 0; i < paddingLength; i++) {
arr.append(0)
}
let d = NSData(bytesNoCopy: &arr, length: length)
return d
}
}
This errors at arr.append with:
Cannot invoke 'append' with an argument list of type '(Int)'
I try to change the declaration into:
var arr[UInt8] = Array(self[offset..<(offset + length)])
However, this also errors:
Cannot assign to immutable expression of type '[UInt8].Type' (aka 'Array.Type')
The weird part: I try to run the original code with arr.append commented out, and use lldb to directly run arr.append(0), it actually works.
I'm using Xcode 7.2.
Since your Array extension puts no constraint on which types of arrays (element types) that can be used with it, .append(0) cannot be invoked; not all types can be converted into from integer literals. Hence, it's not weird that you cannot use .append(0) in the "generic" array extension, whereas you naturally can use it directly on an array that Swift can infer to have integer literal convertible elements, e.g. [Int]. Consider the following example:
var arr : [UInt8] = []
arr.append(0)
var arr2 : [String] = []
arr2.append(0) // error
In the example above, both arrays would have access to your extension dataWithPadding, but both can naturally not make use of arr.append(0) in the extension, hence the error message
Cannot invoke 'append' with an argument list of type '(Int)'
Now, a simple fix is to add a type constraint for the array elements to IntegerLiteralConvertible, after which you extension is valid, and accessible for all arrays that have elements which conform to IntegerLiteralConvertible.
extension Array where Element: IntegerLiteralConvertible {
func dataWithPadding(offset: Int, length: Int, paddingLength: Int) -> NSData {
var arr = Array(self[offset..<(offset + length)])
arr = arr.reverse()
for (var i = 0; i < paddingLength; i++) {
arr.append(0)
}
let d = NSData(bytesNoCopy: &arr, length: length)
return d
}
}
Alternatively, make use of the less general SignedNumberType, UnSignedIntegerType or IntegerType as type constraint for Element; these conform also to e.g. Comparable and Equatable, in case you'd like to compare and perform operations on your generic elements in the extension.
Finally note that you can naturally use your own custom protocol as type constraint for Element in your extension, allowing you to include additional blueprints (below, foo() method) accessible for your Element:s in the extension
protocol MyIntegerLiteralInitializableTypes: IntegerLiteralConvertible {
func foo()
}
extension MyIntegerLiteralInitializableTypes {
func foo() {
print("I am of type \(self.dynamicType)!")
}
}
/* For the Array<Type>:s you want to have access to .dataWithPadding,
extend those 'Type':s to MyIntegerLiteralInitializableTypes */
extension Int8 : MyIntegerLiteralInitializableTypes { }
extension UInt8 : MyIntegerLiteralInitializableTypes { }
extension Array where Element: MyIntegerLiteralInitializableTypes {
func dataWithPadding(offset: Int, length: Int, paddingLength: Int) -> NSData {
self.first?.foo() /* I am of type ...! */
var arr = Array(self[offset..<(offset + length)])
arr = arr.reverse()
for (var i = 0; i < paddingLength; i++) {
arr.append(0)
}
let d = NSData(bytesNoCopy: &arr, length: length)
return d
}
}
It's also probably a good idea to add #warn_unused_result to your dataWithPadding(...) function signature, as a call to it without assigning the return will yield a runtime exception ("... malloc: ...: pointer being freed was not allocated").

Swift + C functions

I have the following C function
struct answer* create(struct callbacks *callbacks);
I need to create a struct of function pointers and call this function from Swift
What I have so far is:
func aa(state: CInt, user_data: UnsafeMutablePointer<Void>) {}
func bb(state: CInt, user_data: UnsafeMutablePointer<Void>) {}
struct CallbacksStruct {
let on_aa = aa
let on_bb = bb
}
and I try to call the function like this:
var callbackStruct = CallbacksStruct()
let ans = create(&callbackStruct)
but, without any success
Is it even possible in Swift ?
Yes, it should be possible. In Swift 2, one can send a Swift closure as a parameter to C, when C expects a function pointer. In your case, you have wrapped it in a struct, so an addition of '#convention(c)' to explicitly state that it's C, might help.
see examples here
new-conventionc-in-swift-2-how-can-i-use-it

Using generic iterators instead of specific list types

I'm very new to Rust, coming from C# / Java / similar.
In C# we have IEnumerable<T> that can be used to iterate almost any kind of array or list. C# also has a yield keyword that you can use to return a lazy list. Here's an example...
// Lazily returns the even numbers out of an enumerable
IEnumerable<int> Evens(IEnumerable<int> input)
{
foreach (var x in input)
{
if (x % 2 == 0)
{
yield return x;
}
}
}
This is a silly example of course. I know I could do this with Rust's map function, but I would like to know how to create my own methods that accept and return generic iterators.
From what I can gather, Rust has generic iterators that can be use similarly, but they are above my understanding. I see Iter, IntoIterator, Iterator types, and probably more in documentation, but no good way to understand them.
Can anyone provide clear examples of how to create something like above? Thank you!
P.S. The lazy aspect is optional. I am more concerned with abstraction away from specific list and array types.
First, forget about IntoIterator and other traits or types. The core iteration trait in Rust is Iterator. Its trimmed down definition is as follows:
trait Iterator {
type Item; // type of elements returned by the iterator
fn next(&mut self) -> Option<Self::Item>;
}
As you probably know, you can think of an iterator as a cursor inside of some structure. next() method advances this cursor forward, returning an element it pointed at previously. Naturally, if the collection is exhausted, there is nothing to return, and so next() returns Option<Self::Item>, not just Self::Item.
Iterator is a trait, and so it can be implemented by specific types. Note that Iterator itself is not a proper type which you can use as a return value or a function argument - you have to use concrete types which implement this trait.
The above statement may sound too restrictive - how to use arbitrary iterator types then? - but because of generics this is not so. If you want a function to accept arbitrary iterators, just make it generic in the corresponding argument, adding an Iterator bound over the corresponding type parameter:
fn iterate_bytes<I>(iter: I) where I: Iterator<Item=u8> { ... }
Returning iterators from functions may be difficult, but see below.
For example, there is a method on &[T], called iter(), which returns an iterator which yields references into the slice. This iterator is an instance of this structure. You can see on that page how Iterator is implemented for Iter:
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<&'a T> { ... }
...
}
This structure holds a reference to the original slice and some iteration state inside it. Its next() method updates this state and returns the next value, if there is any.
Any value whose type implements Iterator can be used in a for loop (for loop in fact works with IntoIterator, but see below):
let s: &[u8] = b"hello";
for b in s.iter() {
println!("{}", b); // prints numerical value of each byte
}
Now, Iterator trait is actually more complex than the above one. It also defines a lot of transformation methods which consume the iterator they are called on and return a new iterator which somehow transforms or filters values from the original iterator. For example, enumerate() method returns an iterator which yields values from the original iterator together with the positional number of the element:
let s: &[u8] = b"hello";
for (i, b) in s.iter().enumerate() {
println!("{} at {}", b, i); // prints "x at 0", "y at 1", etc.
}
enumerate() is defined like this:
trait Iterator {
type Item;
...
fn enumerate(self) -> Enumerate<Self> {
Enumerate {
iter: self,
count: 0
}
}
...
}
Enumerate is just a struct which contains an iterator and a counter inside it and which implements Iterator<Item=(usize, I::Item)>:
struct Enumerate<I> {
iter: I,
count: usize
}
impl<I> Iterator for Enumerate<I> where I: Iterator {
type Item = (usize, I::Item);
#[inline]
fn next(&mut self) -> Option<(usize, I::Item)> {
self.iter.next().map(|a| {
let ret = (self.count, a);
self.count += 1;
ret
})
}
}
And this is how most iterator transformations are implemented: each transformation is a wrapping struct which wraps the original iterator and implements Iterator trait by delegating to the original iterator and transforming the resulting value somehow. For example, s.iter().enumerate() from the example above returns a value of type Enumerate<Iter<'static, u8>>.
Note that while enumerate() is defined in Iterator trait directly, it can be a standalone function as well:
fn enumerate<I>(iter: I) -> Enumerate<I> where I: Iterator {
Enumerate {
iter: iter,
count: 0
}
}
The method works very similarly - it just uses implicit Self type parameter instead of an explicitly named one.
You may wonder what IntoIterator trait is. Well, it is just a convenience conversion trait which can be implemented by any type which can be converted to an iterator:
pub trait IntoIterator where Self::IntoIter::Item == Self::Item {
type Item;
type IntoIter: Iterator;
fn into_iter(self) -> Self::IntoIter;
}
For example, &'a [T] can be converted into Iter<'a, T>, and so it has the following implementation:
impl<'a, T> IntoIterator for &'a [T] {
type Item = &'a T;
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Iter<'a, T> {
self.iter() // just delegate to the existing method
}
}
This trait is implemented for most container types and references to these types. It is in fact used by for loops - a value of any type which implements IntoIterator can be used in in clause:
let s: &[u8] = b"hello";
for b in s { ... }
This is very nice from learning and reading perspective because it has less noise (in form of iter()-like methods). It even allows things like these:
let v: Vec<u8> = ...;
for i in &v { /* i is &u8 here, v is borrowed immutably */ }
for i in &mut v { /* i is &mut u8 here, v is borrowed mutably */ }
for i in v { /* i is just u8 here, v is consumed */ }
This is possible because IntoIterator is implemented differently for &Vec<T>, &mut Vec<T> and just Vec<T>.
Every Iterator implements IntoIterator which performs an identity conversion (into_iter() just returns the iterator it is called on), so you can use Iterator instances in for loops as well.
Consequently, it makes sense to use IntoIterator in generic functions because it will make the API more convenient for the user. For example, enumerate() function from above could be rewritten as such:
fn enumerate<I>(source: I) -> Enumerate<I::IntoIter> where I: IntoIterator {
Enumerate {
iter: source.into_iter(),
count: 0
}
}
Now you can see how generics can be used to implement transformations with static typing easily. Rust does not have anything like C#/Python yield (but it is one of the most desired features, so one day it may appear in the language!), thus you need to wrap source iterators explicitly. For example, you can write something analogous to the above Enumerate structure which does the task you want.
However, the most idiomatic way would be to use existing combinators to do the work for you. For example, your code may be written as follows:
let iter = ...; // iter implements Iterator<Item=i32>
let r = iter.filter(|&x| x % 2 == 0); // r implements Iterator<Item=i32>
for i in r {
println!("{}", i); // prints only even items from the iterator
}
However, using combinators may turn ugly when you want to write custom combinator functions because a lot of existing combinator functions accept closures (e.g. the filter() one above), but closures in Rust are implemented as values of anonymous types, so there is just no way to write the signature of the function returning the iterator out:
fn filter_even<I>(source: I) -> ??? where I: IntoIter<Item=i32> {
source.into_iter().filter(|&x| x % 2 == 0)
}
There are several ways around this, one of them is using trait objects:
fn filter_even<'a, I>(source: I) -> Box<Iterator<Item=i32>+'a>
where I: IntoIterator<Item=i32>, I::IntoIter: 'a
{
Box::new(source.into_iter().filter(|&x| x % 2 == 0))
}
Here we hide the actual iterator type returned by filter() behind a trait object. Note that in order to make the function fully generic I had to add a lifetime parameter and a corresponding bound to Box trait object and I::IntoIter associated type. This is necessary because I::IntoIter may contain arbitrary lifetimes inside it (just like Iter<'a, T> type above), and we have to specify them in the trait object type (otherwise the lifetime information would be lost).
Trait objects created from Iterator trait implement Iterator themselves, so you can continue using these iterators as usual:
let source = vec![1_i32, 2, 3, 4];
for i in filter_even(source) {
println!("{}", i); // prints 2 and 4
}
Here is the full version of Map, and here is the function that builds it.
A minimal implementation would look something like
fn map<I, E, B, F>(i: I, f: F) -> Map<I, F> where
F: FnMut(E) -> B,
I: Iterator<Item=E>
{
Map {iter: i, f: f}
}
pub struct Map<I, F> {
iter: I,
f: F,
}
impl<B, I: Iterator, F> Iterator for Map<I, F> where F: FnMut(I::Item) -> B {
type Item = B;
fn next(&mut self) -> Option<B> {
self.iter.next().map(|a| (self.f)(a))
}
}
Playpen link. Note that the map used inside the iterator is the method on Option; this isn't recursively defined!
It's not too convenient to write, but boy is it fast!
Now, to write this for an arbitrary "enumerable" type one would change map to
fn map<I, E, B, F>(i: I, f: F) -> Map<I::IntoIter, F> where
F: FnMut(E) -> B,
I: IntoIterator<Item=E>
{
Map {iter: i.into_iter(), f: f}
}
IntoIterator is basically IEnumerable, only instead of GetEnumerator there's into_iter.
Implement the Iterator trait for the struct that should serve as iterator. You only need to implement the next method. The other methods have default implementations.
It is not possible to create an iterator that works with any container. The type system machinery needed for this doesn't exist yet.
I am too learning Rust coming from a C# background. Here is how I would implement it:
fn evens<'a>(input: impl Iterator<Item = &'a i32>) -> impl Iterator<Item = &'a i32> {
input.filter(|x| (*x % 2) == 0)
}
and here is the test
#[test]
fn test_evens() {
let input = vec![1, 2, 3];
let mut iter = evens(input.iter());
assert_eq!(iter.next(), Some(&2));
assert_eq!(iter.next(), None);
}

Why does the same method fail when inside an Array extension in Swift?

I'm getting strange behavior when trying to call sort() from within an Array extension, e.g this method:
func test() {
let a = [1,2,3]
sort(a) { x, y in x < y }
}
Works on its own, but fails when its inside an Array extension:
extension Array {
func test() {
let a = [1,2,3]
sort(a) { x, y in x < y }
}
}
It's a build error, failing with:
Extra argument in call
Curiously the same method works as a String extension:
extension String {
func test() {
let a = [1,2,3]
sort(a) { x, y in x < y }
}
}
Why can't I call sort() from within an Array extension?
Because Array has a method called sort of its own, which is of the form sort(isOrderedBefore: (T, T) -> Bool)
So, when you call sort inside the scope of Array, you are actually referring to that version instead of the global sort function.
Thanks to this answer in a question of mine, I found that you can make sure you're calling the sort version in the global scope by using Swift's default namespace, Swift. So, the global version is accessible via Swift.sort.

Resources