Thread overview
Using a tuple as a function parameter
Nov 22
Andrew
Nov 22
monkyyy
Nov 22
user1234
Nov 22
monkyyy
Nov 23
IchorDev
November 22

I'm getting started using D for some small personal projects and one thing I wanted to do was use a helper function for a tuple. I declared the function like this:

string getOrZeroth(Tuple!(string, string, string) tup, int i) pure {
    return tup[i] == "" ? tup[0] : tup[i];
}

and would like to use it like this:

auto foo = tuple("a", "", "c");
writeln(foo.getOrZeroth(1)); // prints a

but when I try it, I'm getting the below error:

>

Error: variable `i` cannot be read at compile time

It would probably make more sense to create a class and make that a member function, but at this point I'm mostly just curious about how to use a tuple as a function parameter. I tried using a couple different options like tuple and TypeTuple as well as trying to convert the function into a template, but didn't have any better luck with those. I feel like I'm probably missing something silly, and any help would be appreciated.

November 22

On Friday, 22 November 2024 at 16:36:43 UTC, Andrew wrote:

>

I'm getting started using D for some small personal projects and one thing I wanted to do was use a helper function for a tuple. I declared the function like this:

string getOrZeroth(Tuple!(string, string, string) tup, int i) pure {
    return tup[i] == "" ? tup[0] : tup[i];
}

and would like to use it like this:

auto foo = tuple("a", "", "c");
writeln(foo.getOrZeroth(1)); // prints a

but when I try it, I'm getting the below error:

>

Error: variable `i` cannot be read at compile time

It would probably make more sense to create a class and make that a member function, but at this point I'm mostly just curious about how to use a tuple as a function parameter. I tried using a couple different options like tuple and TypeTuple as well as trying to convert the function into a template, but didn't have any better luck with those. I feel like I'm probably missing something silly, and any help would be appreciated.

Thats being successfully passed, what the compiler hates is that tuples could be mixed types

auto foo(tuple!(int,bool,float) t,int i)=>t[i]; should and does fail

You happen to be passing in all strings but thats not what the api is for, you could probaly make it compile with an ugly cast, verbose switch, but if you know its all the same type you should use an array(foo(T,N)(T[N] arr...) btw)

November 22

On Friday, 22 November 2024 at 16:36:43 UTC, Andrew wrote:

>

I'm getting started using D for some small personal projects and one thing I wanted to do was use a helper function for a tuple. I declared the function like this:

string getOrZeroth(Tuple!(string, string, string) tup, int i) pure {
    return tup[i] == "" ? tup[0] : tup[i];
}

and would like to use it like this:

auto foo = tuple("a", "", "c");
writeln(foo.getOrZeroth(1)); // prints a

but when I try it, I'm getting the below error:

>

Error: variable `i` cannot be read at compile time

It would probably make more sense to create a class and make that a member function, but at this point I'm mostly just curious about how to use a tuple as a function parameter. I tried using a couple different options like tuple and TypeTuple as well as trying to convert the function into a template, but didn't have any better luck with those. I feel like I'm probably missing something silly, and any help would be appreciated.

tuples elements must be retrieved with indexes that are known at compile time (integer literals or enum members). You pass one but this becomes a value that's not known inside the body

so you can use a template value parameter instead:

string getOrZeroth(int i)(Tuple!(string, string, string) tup)
{
    return tup[i] == "" ? tup[0] : tup[i];
}

and use it like that:

writeln(foo.getOrZeroth!(1)); // prints a
November 22

On Friday, 22 November 2024 at 16:36:43 UTC, Andrew wrote:

> >

Error: variable `i` cannot be read at compile time

Tuple access seems to be internally coded as a template (with unusual syntax) for the reasons already said. i has to be known at compile time for this to work, so a template parameter.

string getOrZerothT(Tuple!(string, string, string) tup, int i)() pure {
	//AliasSeq!(a,b,c) = tup.expand;
    return tup[i] == "" ? tup[0] : tup[i];
}

string getOrZerothT2(int i)(Tuple!(string, string, string) tup) pure {
    return tup[i] == "" ? tup[0] : tup[i];
}

>

you could probaly make it compile with an ugly cast, verbose switch, but if you know its all the same type you should use an array(foo(T,N)(T[N] arr...) btw)

Here is something that compiles

string getOrZeroth(Tuple!(string, string, string) tup, int i) pure {
	string[tup.length] s = [tup.expand];
	return s[i] == "" ? s[0] : s[i];
}
November 22

On Friday, 22 November 2024 at 17:24:08 UTC, Inkrementator wrote:

>

Tuple access seems to be internally coded as a template (with unusual syntax)

Its been a while since Ive tolerated std.tuple, is there any unusual syntax?

November 22

On Friday, 22 November 2024 at 16:36:43 UTC, Andrew wrote:

>

I'm getting started using D for some small personal projects and one thing I wanted to do was use a helper function for a tuple. I declared the function like this:

string getOrZeroth(Tuple!(string, string, string) tup, int i) pure {
    return tup[i] == "" ? tup[0] : tup[i];
}

and would like to use it like this:

auto foo = tuple("a", "", "c");
writeln(foo.getOrZeroth(1)); // prints a

I'm guessing you have some Python in your background, where "tuple" means "read-only list (e.g., array)". Your "tuple" here actually wants to be an immutable array of string, and then life is good. Tuples are a way to have an array of dissimilar types--but then run-time generated values used to index the tuple will add--in the general case--all sorts of imponderables to the compiler's type treatment.

You could claim it can do it for the special case of a tuple holding only one type, but why bother? We already have arrays.

You might want to study what it takes to walk the fields of a type (Type.tupleof). The foreach is actually unrolled at compile time for each field. From one of my own exercises, a mini-CSV module:

https://sources.vsta.org:7100/dlang/file?name=tiny/csv.d&ci=tip

November 22

On Friday, 22 November 2024 at 16:36:43 UTC, Andrew wrote:

>

I'm getting started using D for some small personal projects and one thing I wanted to do was use a helper function for a tuple. I declared the function like this:

string getOrZeroth(Tuple!(string, string, string) tup, int i) pure {
    return tup[i] == "" ? tup[0] : tup[i];
}

and would like to use it like this:

auto foo = tuple("a", "", "c");
writeln(foo.getOrZeroth(1)); // prints a

but when I try it, I'm getting the below error:

>

Error: variable `i` cannot be read at compile time

You can do this with a switch statement:

string getOrZeroth(Tuple!(string, string, string) tup, int i)
{
    switch (i)
    {
        static foreach (j; 0 .. tup.length)
        {
            case j:
                return tup[j] == "" ? tup[0] : tup[j];
        }
        default:
            assert(0, "Tuple index out of bounds");
    }
}
November 23

On Friday, 22 November 2024 at 16:36:43 UTC, Andrew wrote:

>

I'm getting started using D for some small personal projects and one thing I wanted to do was use a helper function for a tuple. I declared the function like this:

string getOrZeroth(Tuple!(string, string, string) tup, int i) pure {
    return tup[i] == "" ? tup[0] : tup[i];
}

and would like to use it like this:

auto foo = tuple("a", "", "c");
writeln(foo.getOrZeroth(1)); // prints a

but when I try it, I'm getting the below error:

>

Error: variable `i` cannot be read at compile time

It would probably make more sense to create a class and make that a member function, but at this point I'm mostly just curious about how to use a tuple as a function parameter. I tried using a couple different options like tuple and TypeTuple as well as trying to convert the function into a template, but didn't have any better luck with those. I feel like I'm probably missing something silly, and any help would be appreciated.

Why not this?

     string getOrZeroth(string[3] tup, int i) pure {
         return tup[i] == "" ? tup[0] : tup[i];
     }

     auto foo = ["a", "", "c"];
     writeln(foo.getOrZeroth(1)); // prints a

No need for a class unless you want a reference type. Tuples are basically just ad-hoc structs. If you want to pass around several types of data that are also used as compile-time sequences then Tuples are for you, otherwise just make a struct for anything using multiple data types.