Thread overview | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
August 08, 2011 Tuple [] operator | ||||
---|---|---|---|---|
| ||||
Hi, I'm receiving this error with dmd 2.054: "tmp.d(7): Error: no [] operator overload for type Tuple!(int,short)" for the following test case import std.typecons; void main() { auto x = 1; Tuple!(int,short) a; a[0] = 1; a[x] = 2; } If I use a value instead of a variable ie. a[1] = 2; it compiles fine. A search turned up http://d.puremagic.com/issues/show_bug.cgi?id=6273 and http://d.puremagic.com/issues/show_bug.cgi?id=6342 though they specifically mention the use of pure functions which I'm not using. Is this the same problem anyway? Chris |
August 08, 2011 Re: Tuple [] operator | ||||
---|---|---|---|---|
| ||||
Posted in reply to Christian Manning | Hi Chris,
> import std.typecons;
> void main() {
> auto x = 1;
> Tuple!(int,short) a;
> a[0] = 1;
> a[x] = 2;
> }
>
> If I use a value instead of a variable ie. a[1] = 2; it compiles fine.
The index need to be a compile-time constant, you cannot index a tuple
with a runtime value.
Try using
enum x = 1;
Philippe
|
August 08, 2011 Re: Tuple [] operator | ||||
---|---|---|---|---|
| ||||
Posted in reply to Christian Manning | On 08.08.2011 23:27, Christian Manning wrote: > Hi, > I'm receiving this error with dmd 2.054: > "tmp.d(7): Error: no [] operator overload for type Tuple!(int,short)" for > the following test case > > import std.typecons; > void main() { > auto x = 1; > Tuple!(int,short) a; > a[0] = 1; > a[x] = 2; > } > > If I use a value instead of a variable ie. a[1] = 2; it compiles fine. > > A search turned up http://d.puremagic.com/issues/show_bug.cgi?id=6273 and > http://d.puremagic.com/issues/show_bug.cgi?id=6342 though they specifically > mention the use of pure functions which I'm not using. Is this the same > problem anyway? > Your case seems simple, it means you can't index tuple with variable as index, only with something known at compile time. Replace auto with enum and you are fine, you can even call a function using CTFE to get an index. -- Dmitry Olshansky |
August 08, 2011 Re: Tuple [] operator | ||||
---|---|---|---|---|
| ||||
Posted in reply to Philippe Sigaud | Philippe Sigaud wrote:
> Hi Chris,
>
>> import std.typecons;
>> void main() {
>> auto x = 1;
>> Tuple!(int,short) a;
>> a[0] = 1;
>> a[x] = 2;
>> }
>>
>> If I use a value instead of a variable ie. a[1] = 2; it compiles fine.
>
> The index need to be a compile-time constant, you cannot index a tuple
> with a runtime value.
> Try using
>
> enum x = 1;
>
>
> Philippe
Ah I didn't know this, thanks. That makes a tuple pretty useless for what I was doing now as I was reading the "index" in from a file. Guess I'll find another way round it.
Thanks
Chris
|
August 08, 2011 Re: Tuple [] operator | ||||
---|---|---|---|---|
| ||||
Posted in reply to Christian Manning | On Mon, 08 Aug 2011 15:47:36 -0400, Christian Manning <cmanning999@gmail.com> wrote:
> Philippe Sigaud wrote:
>
>> Hi Chris,
>>
>>> import std.typecons;
>>> void main() {
>>> auto x = 1;
>>> Tuple!(int,short) a;
>>> a[0] = 1;
>>> a[x] = 2;
>>> }
>>>
>>> If I use a value instead of a variable ie. a[1] = 2; it compiles fine.
>>
>> The index need to be a compile-time constant, you cannot index a tuple
>> with a runtime value.
>> Try using
>>
>> enum x = 1;
>>
>>
>> Philippe
>
> Ah I didn't know this, thanks. That makes a tuple pretty useless for what I
> was doing now as I was reading the "index" in from a file. Guess I'll find
> another way round it.
You still can do it, but you have to do it by still using compile-time constants as indexes:
auto x = 1;
Tuple!(int, short) a;
a[0] = 1;
switch(x)
{
case 0:
a[0] = 2;
break;
case 1:
a[1] = 2;
break;
default:
assert(0, "does not compute!");
}
the point is, the compiler has no idea what the lvalue expression's type should be when you do:
a[x] = 1;
is it short or int?
so the compiler must *know* what type x is at compile time in order for this to be valid.
-Steve
|
August 08, 2011 Re: Tuple [] operator | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Mon, 08 Aug 2011 15:55:38 -0400, Steven Schveighoffer wrote: > On Mon, 08 Aug 2011 15:47:36 -0400, Christian Manning <cmanning999@gmail.com> wrote: [...] > auto x = 1; > Tuple!(int, short) a; > > a[0] = 1; > switch(x) > { > case 0: > a[0] = 2; > break; > case 1: > a[1] = 2; Those assignments are now bound at compile time. > break; > default: > assert(0, "does not compute!"); > } > > the point is, the compiler has no idea what the lvalue expression's type should be when you do: > > a[x] = 1; > > is it short or int? > > so the compiler must *know* what type x is at compile time in order for this to be valid. I think it's more import for the compiler to know what type a[x] is. The assignment operators of different types are different. On the other hand, I don't think a short vs int would make a difference when it comes to indexing (it shouldn't anyway). > > -Steve Ali |
August 08, 2011 Re: Tuple [] operator | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Mon, 08 Aug 2011 20:32:03 +0000, Ali Çehreli wrote:
>> the point is, the compiler has no idea what the lvalue expression's type should be when you do:
>>
>> a[x] = 1;
>>
>> is it short or int?
>>
>> so the compiler must *know* what type x is at compile time in order for this to be valid.
>
> I think it's more import for the compiler to know what type a[x] is. The assignment operators of different types are different. On the other hand, I don't think a short vs int would make a difference when it comes to indexing (it shouldn't anyway).
>
>
>> -Steve
>
> Ali
I correct myself before Steve does: I missed the "lvalue" above. Steve meant a[x] anyway.
Ali
|
August 08, 2011 Re: Tuple [] operator | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Mon, Aug 8, 2011 at 21:55, Steven Schveighoffer <schveiguy@yahoo.com> wrote:
> You still can do it, but you have to do it by still using compile-time constants as indexes:
>
> auto x = 1;
> Tuple!(int, short) a;
>
> a[0] = 1;
> switch(x)
> {
> case 0:
> a[0] = 2;
> break;
> case 1:
> a[1] = 2;
> break;
> default:
> assert(0, "does not compute!");
> }
Christian, I think Steven even suggested in an article some months ago
that this big switch could be generated at compile time.
Steven, do you have a link somewhere?
I mean, the tuple length is known as C-T. It's easy to loop on it and build a string of cases. If you wrap it in a function, it becomes a runtime switcher.
Proof of concept:
import std.typecons;
string generateSwitches(T...)()
{
string result = "switch(x) {\n";
foreach(i,Type; T)
{
result ~= "case " ~ to!string(i) ~ ":\n"
~ "fun(tup[" ~ to!string(i) ~ "]);\n"
~ "break;\n";
}
return result ~ "default:\n"
~ "assert(0, q{Bad index: } ~ to!string(x));\n}";
}
void actOnTuple(alias fun, T...)(int x, ref Tuple!T tup)
{
mixin(generateSwitches!(T));
}
void foo(T)(ref T t) { writeln(t); t = T.init;}
void main()
{
auto tup = tuple(1, 3.14, "abc");
auto x = 1;
actOnTuple!foo(x, tup);
writeln(tup);
}
Philippe
|
August 08, 2011 Re: Tuple [] operator | ||||
---|---|---|---|---|
| ||||
Posted in reply to Philippe Sigaud | Philippe Sigaud wrote:
> On Mon, Aug 8, 2011 at 21:55, Steven Schveighoffer <schveiguy@yahoo.com> wrote:
>
>> You still can do it, but you have to do it by still using compile-time constants as indexes:
>>
>> auto x = 1;
>> Tuple!(int, short) a;
>>
>> a[0] = 1;
>> switch(x)
>> {
>> case 0:
>> a[0] = 2;
>> break;
>> case 1:
>> a[1] = 2;
>> break;
>> default:
>> assert(0, "does not compute!");
>> }
>
> Christian, I think Steven even suggested in an article some months ago
> that this big switch could be generated at compile time.
> Steven, do you have a link somewhere?
>
> I mean, the tuple length is known as C-T. It's easy to loop on it and build a string of cases. If you wrap it in a function, it becomes a runtime switcher.
>
> Proof of concept:
>
> import std.typecons;
>
> string generateSwitches(T...)()
> {
> string result = "switch(x) {\n";
> foreach(i,Type; T)
> {
> result ~= "case " ~ to!string(i) ~ ":\n"
> ~ "fun(tup[" ~ to!string(i) ~ "]);\n"
> ~ "break;\n";
> }
> return result ~ "default:\n"
> ~ "assert(0, q{Bad index: } ~ to!string(x));\n}";
> }
>
> void actOnTuple(alias fun, T...)(int x, ref Tuple!T tup)
> {
> mixin(generateSwitches!(T));
> }
>
> void foo(T)(ref T t) { writeln(t); t = T.init;}
>
> void main()
> {
> auto tup = tuple(1, 3.14, "abc");
> auto x = 1;
> actOnTuple!foo(x, tup);
> writeln(tup);
> }
>
>
> Philippe
I haven't used string mixins before so I suppose this is a good time to
learn!
Thanks for the help, Steven and Philippe.
Chris
|
August 08, 2011 Re: Tuple [] operator | ||||
---|---|---|---|---|
| ||||
Posted in reply to Philippe Sigaud | On Mon, 08 Aug 2011 16:50:48 -0400, Philippe Sigaud <philippe.sigaud@gmail.com> wrote: > On Mon, Aug 8, 2011 at 21:55, Steven Schveighoffer <schveiguy@yahoo.com> wrote: > >> You still can do it, but you have to do it by still using compile-time >> constants as indexes: >> >> auto x = 1; >> Tuple!(int, short) a; >> >> a[0] = 1; >> switch(x) >> { >> case 0: >> a[0] = 2; >> break; >> case 1: >> a[1] = 2; >> break; >> default: >> assert(0, "does not compute!"); >> } > > Christian, I think Steven even suggested in an article some months ago > that this big switch could be generated at compile time. > Steven, do you have a link somewhere? Sorry, wasn't me... > > I mean, the tuple length is known as C-T. It's easy to loop on it and > build a string of cases. If you wrap it in a function, it becomes a > runtime switcher. > > Proof of concept: > > import std.typecons; > > string generateSwitches(T...)() > { > string result = "switch(x) {\n"; > foreach(i,Type; T) > { > result ~= "case " ~ to!string(i) ~ ":\n" > ~ "fun(tup[" ~ to!string(i) ~ "]);\n" > ~ "break;\n"; > } > return result ~ "default:\n" > ~ "assert(0, q{Bad index: } ~ to!string(x));\n}"; > } > > void actOnTuple(alias fun, T...)(int x, ref Tuple!T tup) > { > mixin(generateSwitches!(T)); > } > > void foo(T)(ref T t) { writeln(t); t = T.init;} > > void main() > { > auto tup = tuple(1, 3.14, "abc"); > auto x = 1; > actOnTuple!foo(x, tup); > writeln(tup); > } > I like this idea. I think it belongs in phobos somewhere, if not already. -Steve |
Copyright © 1999-2021 by the D Language Foundation