Auto return type inference issue?
Here's the gist of what I'm trying to do. https://gist.github.com/pontifechs/11169069 I'm getting an error I don't understand: tinker.d(42): Error: mismatched function return type inference of tinker.B and tinker.A tinker.d(55): Error: template instance tinker.DynamicTuple!(A, B).DynamicTuple.notopDispatch!one error instantiating Failed: 'dmd' '-v' '-o-' 'tinker.d' '-I.' Also, as an aside, why can't tuples be indexed dynamically? Most of my problems with this have been because you apparently can't.
Re: Auto return type inference issue?
Matthew Dudley: Also, as an aside, why can't tuples be indexed dynamically? Most of my problems with this have been because you apparently can't. Think about how D tuples are implemented, they are essentially structs. Every tuple element can have a different type and to be represented in memory with a different number of bytes. D is statically typed so when you read an element of a tuple, you need to know at compile-time the type (and size) of what you are reading. To have tuples indexable at run-time their items need to be all of the same type (so they are essentially arrays), or they need to be some kind of variants (but later you need to manage their type more manually). Bye, bearophile
Throw exception on segmentation fault in GNU/Linux
What should I add in the D program in GNU/Linux to throw exception if I have segmentation fault error? I read somewhere that it's possible, but I don't know how to do it.
Re: Function to print a diamond shape
Wow, joiner is much slower than join. Such a small choice can make this big of a difference. Not at all expected, since the lazy calls, I thought, were considered to be more efficient. This is with ldc2 -O2. jay@jay-ubuntu:~/ec_ddt/workspace/diamond/source$ ./main 1/dev/null brad: time: 21958[ms] sergei: time: 24629[ms] jay2: time: 259[ms] diamondShape: time: 6701[ms] printDiamond: time: 194[ms] printDiamonde2a: time: 95[ms] printDiamonde2b: time: 92[ms] printDiamond3: time: 144[ms] printDiamonde2monarch: time: 67[ms] printDiamonde2cJoin: time: 96[ms] printDiamonde2cJoiner: time: 16115[ms] void printDiamonde2cJoin(in uint N) { int n,l; size_t N2 = N/2; size_t NM1 = N-1; char p[] = uninitializedArray!(char[])(N2+N); p[0..N2] = ' '; p[N2..$] = '*'; char nl[] = uninitializedArray!(char[])(1); nl[] = '\n'; char wc[][] = minimallyInitializedArray!(char[][])(N); for(n=0,l=0; nN2; n++,l+=2){ wc[n] = wc[NM1-n] = p[n .. N2+l+1]; } wc[N2] = p[N2..$]; auto wj = join(wc,nl); write(wj); write('\n'); } void printDiamonde2cJoiner(in uint N) { int n,l; size_t N2 = N/2; size_t NM1 = N-1; char p[] = uninitializedArray!(char[])(N2+N); p[0..N2] = ' '; p[N2..$] = '*'; char wc[][] = minimallyInitializedArray!(char[][])(N); for(n=0,l=0; nN2; n++,l+=2){ wc[n] = wc[NM1-n] = p[n .. N2+l+1]; } wc[N2] = p[N2..$]; write(joiner(wc,\n)); write('\n'); }
Re: Best way to check for an element in an array?
On Mon, 21 Apr 2014 23:25:39 -0400, Taylor Hillegeist taylorh...@gmail.com wrote: So I find myself Doing this kind of thing very frequently. I have a Array of Somethings and i want to see if something specific is inside the array. I wrote a template for it. but is this the best way to do this kind of thing. I feel like it doesn't help with readability. Is there a better way? Maybe i missed something in the std library. import std.stdio; Change this: template FNDR(T){ To this: template isIn(T) { bool isIn(T Element, T[] Array){ bool rtn=false; foreach(T ArrayElement; Array){ if(Element==ArrayElement){ rtn=true; } } return rtn; } } void main(string[] args) { int[3] stuff=[0,1,2]; if (FNDR!int.isIn(2,stuff)) now: if(isIn(2, stuff)) see implicit function template instantiation (IFTI) in docs. Also, using UFCS (Unified Function Call Syntax (I think)), we can do: if(2.isIn(stuff)) Or if you swap the parameters, and perhaps rename your template/function: if(stuff.contains(2)) { writeln(Hello World!); } } -Steve
Named template constraints
Hi there, I recently read the 'More Templates' chapter of Ali's book (-- thanks for that ;) ). At the section 'Named constraints', there were a definition like this: template isUsable(T) { enum isUsable = is ( typeof( { T obj; obj.call(); obj.otherCall(1); obj.ye tAnotherCall(); }() ) ); } But at Phobos I always see definitions like this (std.range : isInputRange): template isInputRange(R) { enum bool isInputRange = is(typeof( (inout int = 0) { R r = R.init; // can define a range object if (r.empty) {} // can test for empty r.popFront(); // can invoke popFront() auto h = r.front; // can get the front of the range })); } What does (inout int = 0) mean/affect here? I created the same template for myself just without the (inout int = 0) and it worked (at least with a dummy struct).. - Tim
Re: Throw exception on segmentation fault in GNU/Linux
You should write and register a signal handler. Implementation for x86-32 was posted here.
Re: Throw exception on segmentation fault in GNU/Linux
On Tuesday, 22 April 2014 at 09:58:45 UTC, ilya-stromberg wrote: What should I add in the D program in GNU/Linux to throw exception if I have segmentation fault error? I read somewhere that it's possible, but I don't know how to do it. etc.linux.memoryerror Just remember that it is more of hack than reliable production-ready solution ;)
Re: Named template constraints
On 4/22/14, Tim Holzschuh via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: What does (inout int = 0) mean/affect here? This was asked recently, see my reponse here: http://forum.dlang.org/post/mailman.102.1396007039.25518.digitalmars-d-le...@puremagic.com
Re: Named template constraints
On Tue, 22 Apr 2014 10:58:41 -0400, Andrej Mitrovic via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: On 4/22/14, Tim Holzschuh via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: What does (inout int = 0) mean/affect here? This was asked recently, see my reponse here: http://forum.dlang.org/post/mailman.102.1396007039.25518.digitalmars-d-le...@puremagic.com I think this can be fixed a different way: template isInputRange(R) { enum bool isInputRange = is(typeof( (R r) { R r2 = R.init; // can define a range object if (r.empty) {} // can test for empty r.popFront(); // can invoke popFront() auto h = r.front; // can get the front of the range })); } Note, is the r2 = R.init needed? Not sure. -Steve
Re: Named template constraints
Not sure what InputRange is defined as atm, but I don't think anything should have to define init to be a valid inputrange.
Array of interface only with cast()?
Hi, I just stumbled about this issue with array of interface. I want to pass several objects (C and D) which shares the same interface A. It seems somehow cumbersome that it only works if there is a cast on the first element of the array. interface A{} class B: A{} class C: B{}; class D: B{}; void main() { //A[] arr = [new C(), new D()]; // Does not work A[] arr = [cast(A) new C(), new D()]; // Does work } Is the cast really needed? Kind regards André
Re: Named template constraints
On Tuesday, 22 April 2014 at 15:06:34 UTC, Steven Schveighoffer wrote: Note, is the r2 = R.init needed? Not sure. Yes: It R2 has no default init, or is an immutable, then that line will fail to compile.
Re: Array of interface only with cast()?
On Tuesday, 22 April 2014 at 15:19:55 UTC, Andre wrote: Is the cast really needed? It's a known issue and a filed bug report. I don't have the Issue number at hand though, someone else will likely provide it.
Re: Function to print a diamond shape
On Tuesday, 22 April 2014 at 05:05:30 UTC, Jay Norwood wrote: On Monday, 21 April 2014 at 08:26:49 UTC, monarch_dodra wrote: The two key points here, first, is to avoid using appender. Second, instead of having two buffer: and **\n, and two do two slice copies, to only have 1 buffer *, and to do 1 slice copy, and a single '\n' write. At this point, I'm not sure how we could be going any faster, short of using alloca... How does this hold up on your environment? Yes your solution is the fastest yet. Also, its times are similar for all three compilers. The range of execution times varied for different solutions from over 108 seconds down to 64 msec. I see that RefAppender's data() returns the managed array. Can write() handle that? It seems that would be more efficient than duplicating the character buffer ... I'm not sure what you mean? data returns the managed array, but no duplication ever actually happens. It's allocated on the GC. the only thing that is copied is the slice itself. or perhaps writing directly to an OutBuffer, and then sending that to write() would avoid the duplication? appender *is* the outbuffer :)
Re: Array of interface only with cast()?
Am 22.04.2014 17:23, schrieb Andrej Mitrovic: On Tuesday, 22 April 2014 at 15:19:55 UTC, Andre wrote: Is the cast really needed? It's a known issue and a filed bug report. I don't have the Issue number at hand though, someone else will likely provide it. Nice to hear that it is not by design but will be fixed. Thanks a lot. Kind regards André
Re: Function to print a diamond shape
On Tuesday, 22 April 2014 at 11:41:41 UTC, Jay Norwood wrote: Wow, joiner is much slower than join. Such a small choice can make this big of a difference. Not at all expected, since the lazy calls, I thought, were considered to be more efficient. This is with ldc2 -O2. Yeah, that's because join actually works on RoR, R, rather than R, E. This means if you feed it a string[], string, then it will actually iterate over individual *characters*. Not only that, but since you are using char[], it will decode them too. join is faster for 2 reasons: 1) It detects you want to joins arrays, so it doesn't have to iterate over them: It just glues them slice at once 2) No UTF decoding. I kind of wish we had a faster joiner, but I think it would have made the call ambiguous.
Re: Named template constraints
On Tue, 22 Apr 2014 11:15:14 -0400, monarch_dodra monarchdo...@gmail.com wrote: On Tuesday, 22 April 2014 at 15:06:34 UTC, Steven Schveighoffer wrote: Note, is the r2 = R.init needed? Not sure. Yes: It R2 has no default init, or is an immutable, then that line will fail to compile. I don't believe it's possible to have no 'init'. I think the reason it says '= R.init' is for ranges that have @disable this(). Also, an immutable can be initialized that way: immutable int[] = int[].init; Of course, it wouldn't pass the rest of isInputRange. -Steve
Re: Array of interface only with cast()?
On Tue, 22 Apr 2014 11:19:57 -0400, Andre an...@s-e-a-p.de wrote: Hi, I just stumbled about this issue with array of interface. I want to pass several objects (C and D) which shares the same interface A. It seems somehow cumbersome that it only works if there is a cast on the first element of the array. interface A{} class B: A{} class C: B{}; class D: B{}; void main() { //A[] arr = [new C(), new D()]; // Does not work A[] arr = [cast(A) new C(), new D()]; // Does work } Is the cast really needed? At this point, yes. This is because the expression [new C(), new D()] does not take into account what you are assigning to (IMO it should). The compiler will use the most derived type possible that all the elements implicitly cast to. In this case, it will be a B[]. -Steve
Re: Named template constraints
On 4/22/14, Steven Schveighoffer via Digitalmars-d-learn digitalmars-d-learn@puremagic.com I think this can be fixed a different way. Feel free to file a bug / make a pull. :
Re: Named template constraints
On Tuesday, 22 April 2014 at 15:30:36 UTC, Steven Schveighoffer wrote: On Tue, 22 Apr 2014 11:15:14 -0400, monarch_dodra monarchdo...@gmail.com wrote: On Tuesday, 22 April 2014 at 15:06:34 UTC, Steven Schveighoffer wrote: Note, is the r2 = R.init needed? Not sure. Yes: It R2 has no default init, or is an immutable, then that line will fail to compile. I don't believe it's possible to have no 'init'. I think the reason it says '= R.init' is for ranges that have @disable this(). Yes, that's what I meant by no default init. Guess I got my terms wrong. Sorry. Also, an immutable can be initialized that way: immutable int[] = int[].init; Isn't that exactly R.init ? Of course, it wouldn't pass the rest of isInputRange. -Steve In this particular case, probably not (except for, maybe repeat?) In any case, it's become the generic way of initializing a generic type.
Re: Array of interface only with cast()?
Andre: Nice to hear that it is not by design but will be fixed. See: https://issues.dlang.org/show_bug.cgi?id=3543 Bye, bearophile
Re: Throw exception on segmentation fault in GNU/Linux
On Tuesday, 22 April 2014 at 14:49:58 UTC, Dicebot wrote: On Tuesday, 22 April 2014 at 09:58:45 UTC, ilya-stromberg wrote: What should I add in the D program in GNU/Linux to throw exception if I have segmentation fault error? I read somewhere that it's possible, but I don't know how to do it. etc.linux.memoryerror Just remember that it is more of hack than reliable production-ready solution ;) Thanks. How shall I use the module? Should I just import it or call any init function?
Re: Throw exception on segmentation fault in GNU/Linux
On Tuesday, 22 April 2014 at 15:47:37 UTC, ilya-stromberg wrote: On Tuesday, 22 April 2014 at 14:49:58 UTC, Dicebot wrote: On Tuesday, 22 April 2014 at 09:58:45 UTC, ilya-stromberg wrote: What should I add in the D program in GNU/Linux to throw exception if I have segmentation fault error? I read somewhere that it's possible, but I don't know how to do it. etc.linux.memoryerror Just remember that it is more of hack than reliable production-ready solution ;) Thanks. How shall I use the module? Should I just import it or call any init function? AFAIR it is just matter of calling registerMemoryErrorHandler() and deregisterMemoryErrorHandler() - this module doesn't even have any other public functions / methods.
The lifetime of reduce's internal seed
I opened the following bug before reading reduce's documentation carefully: https://issues.dlang.org/show_bug.cgi?id=12610 import std.stdio; import std.algorithm; void main() { int[] arr = [ 0 ]; int[1] seed; int[] result = reduce!((sum, _) = sum[])(seed, arr); writefln(%s, result); } The output is garbage like [373728176]. Note that the original seed is a value type, which is later sliced by the lambda. Now I think that it can be considered a user error. Do you agree whit that? If so, this is something else we should be careful about similar to the internal buffer of byLine. Ali
Re: The lifetime of reduce's internal seed
On Tuesday, 22 April 2014 at 17:31:22 UTC, Ali Çehreli wrote: I opened the following bug before reading reduce's documentation carefully: https://issues.dlang.org/show_bug.cgi?id=12610 import std.stdio; import std.algorithm; void main() { int[] arr = [ 0 ]; int[1] seed; int[] result = reduce!((sum, _) = sum[])(seed, arr); writefln(%s, result); } The output is garbage like [373728176]. Note that the original seed is a value type, which is later sliced by the lambda. Now I think that it can be considered a user error. Do you agree whit that? If so, this is something else we should be careful about similar to the internal buffer of byLine. Ali I see one user bug, and one language bug, but no library issues. The user bug is the lambda, that returns a reference to a local (sum[]). That said, I do believe the compiler should be able to catch think. The int[] reduce..., however, I think is a outright language issue. Implicilty calling opSlice on a static array is one thing, but doing it on an rvalue is an outright aberration. The code should be rejected no questions asked.
Re: Named template constraints
On 04/22/2014 07:07 AM, Tim Holzschuh via Digitalmars-d-learn wrote: read the 'More Templates' chapter of Ali's book (-- thanks for that ;) ). Yay! :) At the section 'Named constraints', there were a definition like this: template isUsable(T) { enum isUsable = is ( typeof( { T obj; obj.call(); obj.otherCall(1); obj.ye tAnotherCall(); }() ) ); } That is how Phobos used to be. But at Phobos I always see definitions like this (std.range : isInputRange): template isInputRange(R) { enum bool isInputRange = is(typeof( (inout int = 0) I had noticed that as well and am curious myself. My guess is that it is a syntax issue where that default parameter list makes it a stronger delegate syntax. :p { R r = R.init; // can define a range object if (r.empty) {} // can test for empty r.popFront(); // can invoke popFront() auto h = r.front; // can get the front of the range })); } What does (inout int = 0) mean/affect here? I created the same template for myself just without the (inout int = 0) and it worked (at least with a dummy struct).. - Tim Same here: I cannot find an example where the first version does not work. (?) Ali
Re: Named template constraints
Am 22.04.2014 16:58, schrieb Andrej Mitrovic via Digitalmars-d-learn: On 4/22/14, Tim Holzschuh via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: What does (inout int = 0) mean/affect here? This was asked recently, see my reponse here: http://forum.dlang.org/post/mailman.102.1396007039.25518.digitalmars-d-le...@puremagic.com Aargh, I'm sorry. Didn't see that one. - Tim
Re: The lifetime of reduce's internal seed
On 04/22/2014 11:03 AM, monarch_dodra wrote: On Tuesday, 22 April 2014 at 17:31:22 UTC, Ali Çehreli wrote: I opened the following bug before reading reduce's documentation carefully: https://issues.dlang.org/show_bug.cgi?id=12610 import std.stdio; import std.algorithm; void main() { int[] arr = [ 0 ]; int[1] seed; int[] result = reduce!((sum, _) = sum[])(seed, arr); writefln(%s, result); } The output is garbage like [373728176]. Note that the original seed is a value type, which is later sliced by the lambda. Now I think that it can be considered a user error. Do you agree whit that? If so, this is something else we should be careful about similar to the internal buffer of byLine. Ali I see one user bug, Let this thread be a lesson to me (and other mortals) then. and one language bug, but no library issues. The user bug is the lambda, that returns a reference to a local (sum[]). That said, I do believe the compiler should be able to catch think. The int[] reduce..., however, I think is a outright language issue. Implicilty calling opSlice on a static array is one thing, but doing it on an rvalue is an outright aberration. The code should be rejected no questions asked. I don't think there is slicing an rvalue though. (?) reduce() is taking a copy of the seed and then returning a slice to it because the user slices it in their lambda. It effectively does the following, which unfortunately compiles: int[] foo() { int[1] sum; return sum[];// -- no warning } void main() { int[] result = foo(); } The code would be safe if the user gave a slice to reduce(). This brings up another concern though: Template authors must watch out for cases like the above. There would be cases where we shouldn't simply take a copy of a T object and return it. Ali
Re: The lifetime of reduce's internal seed
On Tue, 22 Apr 2014 14:17:57 -0400, Ali Çehreli acehr...@yahoo.com wrote: I don't think there is slicing an rvalue though. (?) reduce() is taking a copy of the seed and then returning a slice to it because the user slices it in their lambda. It effectively does the following, which unfortunately compiles: int[] foo() { int[1] sum; return sum[];// -- no warning } It's not slicing an rvalue, but the above is trivially no different than: int[] foo() { int[1] sum; return sum; } which does NOT compile. The issue is that D's escape analysis is very very simplistic. It would be nice if it were better. Ironically, because of return type inference in lambdas, you circumvented the check! -Steve
Re: Named template constraints
On Tue, 22 Apr 2014 11:36:07 -0400, monarch_dodra monarchdo...@gmail.com wrote: On Tuesday, 22 April 2014 at 15:30:36 UTC, Steven Schveighoffer wrote: Also, an immutable can be initialized that way: immutable int[] = int[].init; Isn't that exactly R.init ? Yes, you said if it's an immutable it would fail to compile. I think this is not true. -Steve
Re: The lifetime of reduce's internal seed
On Tue, 22 Apr 2014 14:47:19 -0400, monarch_dodra monarchdo...@gmail.com wrote: In this case no, but; // int[1] foo(); int[] a = foo(); // *is* slicing an rvalue, and it *does* compile. I don't think there needs to be escape analysis to catch this. Oh yeah, that's bad. -Steve
Re: The lifetime of reduce's internal seed
On Tuesday, 22 April 2014 at 18:34:47 UTC, Steven Schveighoffer wrote: On Tue, 22 Apr 2014 14:17:57 -0400, Ali Çehreli acehr...@yahoo.com wrote: I don't think there is slicing an rvalue though. (?) reduce() is taking a copy of the seed and then returning a slice to it because the user slices it in their lambda. It effectively does the following, which unfortunately compiles: int[] foo() { int[1] sum; return sum[];// -- no warning } It's not slicing an rvalue, but the above is trivially no different than: In this case no, but; // int[1] foo(); int[] a = foo(); // *is* slicing an rvalue, and it *does* compile. I don't think there needs to be escape analysis to catch this.
Re: Named template constraints
On Tue, 22 Apr 2014 14:50:44 -0400, monarch_dodra monarchdo...@gmail.com wrote: On Tuesday, 22 April 2014 at 18:35:58 UTC, Steven Schveighoffer wrote: On Tue, 22 Apr 2014 11:36:07 -0400, monarch_dodra monarchdo...@gmail.com wrote: On Tuesday, 22 April 2014 at 15:30:36 UTC, Steven Schveighoffer wrote: Also, an immutable can be initialized that way: immutable int[] = int[].init; Isn't that exactly R.init ? Yes, you said if it's an immutable it would fail to compile. I think this is not true. -Steve Ah... you said: Note, is the r2 = R.init needed? Not sure. To whitch I replied: Yes: It R2 has no default init, or is an immutable, then that line will fail to compile. I meant that if you *don't* add the R.init, then the code will *not* compile. EG = R.init is necessary. Sorry for the mixup :/ OH!!! I meant is the whole *line* necessary, not the R.init part :) Note that in my updated version, r is passed in as a parameter to the mock function. This means if R is inout(something), it will be part of the parameters, and you don't need a dummy inout parameter to shut the compiler up. So the r2 = R.init; was just to keep things the same, but I'm not sure it's necessary to have. It has a comment saying can define a range object, whereas it could just be I need a range object to compile the rest of this code :) -Steve
Variable Naming Issue (Conflicts?)
Hello, I'm working on some code where I'm trying to generate structs that map to JSON documents via a mixin. That part works except when specific variable gets created. Below is the error that I'm getting: source/objects.d-mixin-70(75): Error: no identifier for declarator string source/objects.d-mixin-70(75): Error: found '=' when expecting '(' source/objects.d-mixin-70(75): Error: basic type expected, not source/objects.d-mixin-70(75): Error: found '' when expecting ')' If I prefix all of the generated variables with an underscore, it works fine. It looks like the variable delete is the issue. To me, it looks like it's expecting some sort of delete method. Now, I'm planning on leveraging vibe.d's JSON serialization to convert an object to/from JSON, so the variable names have to match the names they have in the JSON document. My question is, is there a way I can prevent this conflict from occurring without affecting what the struct will look like?
Re: Variable Naming Issue (Conflicts?)
Casey: My question is, is there a way I can prevent this conflict from occurring without affecting what the struct will look like? The usual strategy is to append an underscore. (I think C# uses a @ prefix). Bye, bearophile
Re: Variable Naming Issue (Conflicts?)
On Tue, 22 Apr 2014 15:35:33 -0400, Casey sybra...@gmail.com wrote: If I prefix all of the generated variables with an underscore, it works fine. It looks like the variable delete is the issue. To me, it looks like it's expecting some sort of delete method. delete is a keyword, it cannot be a symbol. -Steve
Re: Variable Naming Issue (Conflicts?)
On Tuesday, 22 April 2014 at 19:38:09 UTC, bearophile wrote: Casey: My question is, is there a way I can prevent this conflict from occurring without affecting what the struct will look like? The usual strategy is to append an underscore. (I think C# uses a @ prefix). Bye, bearophile I've done that, but then it changes the name which, from what I've read in the documentation, means the JSON - object conversion won't work since it won't see a variable named delete.
Re: Variable Naming Issue (Conflicts?)
Casey: I've done that, but then it changes the name which, from what I've read in the documentation, means the JSON - object conversion won't work since it won't see a variable named delete. Perhaps we need a built-in syntax solution as in C#, like a $delete. Bye, bearophile
Re: Variable Naming Issue (Conflicts?)
Perhaps we need a built-in syntax solution as in C#, like a $delete. So, two things: 1. I guess my current approach is screwed. I figured as much. 2. Seeing $delete makes me miss Perl/PHP variable naming. It is one extra character, but it did make them stand out more. Anyway, thanks. Casey
Re: Auto return type inference issue?
On Tuesday, 22 April 2014 at 07:54:34 UTC, Matthew Dudley wrote: Here's the gist of what I'm trying to do. https://gist.github.com/pontifechs/11169069 I'm getting an error I don't understand: tinker.d(42): Error: mismatched function return type inference of tinker.B and tinker.A tinker.d(55): Error: template instance tinker.DynamicTuple!(A, B).DynamicTuple.notopDispatch!one error instantiating Failed: 'dmd' '-v' '-o-' 'tinker.d' '-I.' Also, as an aside, why can't tuples be indexed dynamically? Most of my problems with this have been because you apparently can't. Might have this a little bit wrong, just a quick hand translation of: foreach (i, elem; tuple) if (names[i] == s) { return elem; } This becomes something like: if (names[0] == one) return A; if (names[1] == one) return B; As said I could have this mixed up, but /elem/ is a type. But even if they were an object, you are saying that this method may return an A or a B, it is not legal for a function to return different types. I'd suggest a static if, but since /names/ is dynamic, that won't work.