Jacob Vlijm
Jacob Vlijm

Reputation: 3159

Can I make a function handle multiple data type arguments in Vala?

On the snippet below, I have two functions doing exactly the same (read_array and read_array2), look up an item in an array. The only difference is the data type of the arguments (string[], string and int[] int). Creating two similar functions seems quite unelegant.

Is there a way to handle both in a generic way in one function?

void main () {
    /* get index of string in array */
    string[] arr = {"one", "two", "three"};
    int index = read_array(arr, "two");
    print(@"$index\n");
    secundary ();
}

void secundary () {
    /* get index of int in array */
    int[] arr = {1, 2, 3};
    int index = read_array2(arr, 2);
    print(@"$index\n");
}


public int read_array (string[] arr, string needle) {
    for (int i=0; i < arr.length; i++) {
        if(needle == arr[i]) return i;
    } return -1;
}

// write a separate function because other data type? ughh...
public int read_array2 (int[] arr, int needle) {
    for (int i=0; i < arr.length; i++) {
        if(needle == arr[i]) return i;
    } return -1;
}

Upvotes: 2

Views: 166

Answers (1)

Jens M&#252;hlenhoff
Jens M&#252;hlenhoff

Reputation: 14873

You can use Generics, but you have to be careful with some things.

First of all you can't pass an array of value type (i .e. int[]) to a generic function, see this question for reference:

Vala: Passing a generic array corrupts values

Second you need to pass some sort of equality test function that you have to write once for every type.

Here is a working example:

public delegate bool EqualFunc<T> (T l, T r);

bool str_equals (string l, string r) {
    return l == r;
}

bool int_equals (int? l, int? r) {
    return l == r; 
}

public int read_array<T> (T[] arr, T needle, EqualFunc<T> equal_func) {
    for (int i = 0; i < arr.length; i++) {
        if (equal_func (needle, arr[i])) {
            return i;
        }
    }
    return -1;
}

void main () {
    // get index of string in array
    string[] arr = {"one", "two", "three"};
    int index = read_array (arr, "two", str_equals);
    print(@"$index\n");
    secondary ();
}

void secondary () {
    // get index of int in array
    int?[] arr = {1, 2, 3};
    int index = read_array (arr, 2, int_equals);
    print(@"$index\n");
}

Boxing a value into a nullable value like this is quite ugly, but I don't know a better way to fix the mentioned compiler problem ...

If you're willing to use libgee you can use a Gee.ArrayList which will also work.

Upvotes: 2

Related Questions