Thread overview
Type deduction using switch case
Feb 19, 2012
Xinok
Feb 19, 2012
Robert Jacques
Feb 19, 2012
Xinok
Feb 19, 2012
Robert Jacques
Feb 19, 2012
Xinok
Feb 19, 2012
Nick Sabalausky
Feb 19, 2012
David
February 19, 2012
While reading "The Right Approach to Exceptions", it gave me this idea. The user would declare a list of variables of different types as case statements, and the variable with matches the type of the switch expression is used.

I don't know how the syntax should look, this is merely an example:

void foo(T)(T arg){
	switch(arg){
		case int i:
			writeln("Type is int ", i); break;
		case float f:
			writeln("Type is float ", f); break;
		case string s:
			writeln("Type is string ", s); break;
		default:
			writeln("Type is unknown"); break;
	}
}

While static if would be more practical for templates, my idea could be extended to dynamic upcasting of classes as well, which could be applied to exception handling:

try{ ... }
catch(Throwable err) switch(err){
	case IOError a:
		break;
	case OutOfMemoryError b:
		break;
	default:
		throw err;
}
February 19, 2012
On Sat, 18 Feb 2012 18:33:01 -0600, Xinok <xinok@live.com> wrote:

> While reading "The Right Approach to Exceptions", it gave me this
> idea. The user would declare a list of variables of different
> types as case statements, and the variable with matches the type
> of the switch expression is used.
>
> I don't know how the syntax should look, this is merely an
> example:
>
> void foo(T)(T arg){
> 	switch(arg){
> 		case int i:
> 			writeln("Type is int ", i); break;
> 		case float f:
> 			writeln("Type is float ", f); break;
> 		case string s:
> 			writeln("Type is string ", s); break;
> 		default:
> 			writeln("Type is unknown"); break;
> 	}
> }

The above should be switch (T) not switch(arg) for the example to be correct.

> While static if would be more practical for templates, my idea
> could be extended to dynamic upcasting of classes as well, which
> could be applied to exception handling:
>
> try{ ... }
> catch(Throwable err) switch(err){
> 	case IOError a:
> 		break;
> 	case OutOfMemoryError b:
> 		break;
> 	default:
> 		throw err;
> }

You can do this today using a string switch:
switch(err.classinfo.name) { ... }
February 19, 2012
"Xinok" <xinok@live.com> wrote in message news:yeuigezlevjbhgufwrti@forum.dlang.org...
> While reading "The Right Approach to Exceptions", it gave me this idea. The user would declare a list of variables of different types as case statements, and the variable with matches the type of the switch expression is used.
>
> I don't know how the syntax should look, this is merely an example:
>
> void foo(T)(T arg){
> switch(arg){
> case int i:
> writeln("Type is int ", i); break;
> case float f:
> writeln("Type is float ", f); break;
> case string s:
> writeln("Type is string ", s); break;
> default:
> writeln("Type is unknown"); break;    }
> }
>
> While static if would be more practical for templates, my idea could be extended to dynamic upcasting of classes as well, which could be applied to exception handling:
>
> try{ ... }
> catch(Throwable err) switch(err){
> case IOError a:
> break;
> case OutOfMemoryError b:
> break;
> default:
> throw err;
> }

Yea, pattern matching, basically. Great as D is, pattern matching is one thing where Nemerle blows D out of the water: http://nemerle.org/Grok_Variants_and_matching

With exceptions in particular, I've often felt that we need some sort of templated catch:

try {...}
catch(TypeTuple!(ExceptionA, ExceptionB) e)
{
    // Common implementation, but NO need
    // for that re-throwing abomination you'd
    // inevitably need if you just caught
    // a common base type.
}


February 19, 2012
On Sunday, 19 February 2012 at 00:49:56 UTC, Robert Jacques wrote:
> On Sat, 18 Feb 2012 18:33:01 -0600, Xinok <xinok@live.com> wrote:
>
>> While reading "The Right Approach to Exceptions", it gave me this
>> idea. The user would declare a list of variables of different
>> types as case statements, and the variable with matches the type
>> of the switch expression is used.
>>
>> I don't know how the syntax should look, this is merely an
>> example:
>>
>> void foo(T)(T arg){
>> 	switch(arg){
>> 		case int i:
>> 			writeln("Type is int ", i); break;
>> 		case float f:
>> 			writeln("Type is float ", f); break;
>> 		case string s:
>> 			writeln("Type is string ", s); break;
>> 		default:
>> 			writeln("Type is unknown"); break;
>> 	}
>> }
>
> The above should be switch (T) not switch(arg) for the example to be correct.

Notice how it's "int i" and not just "int". Also notice how each writeln statement also prints the variable. Each case statement declares a variable, so it matches the type of the expression against the type of the variable, and stores the switch expression in that variable.
February 19, 2012
On Sat, 18 Feb 2012 20:03:51 -0600, Xinok <xinok@live.com> wrote:

> On Sunday, 19 February 2012 at 00:49:56 UTC, Robert Jacques wrote:
>> On Sat, 18 Feb 2012 18:33:01 -0600, Xinok <xinok@live.com>
>> wrote:
>>
>>> While reading "The Right Approach to Exceptions", it gave me
>>> this
>>> idea. The user would declare a list of variables of different
>>> types as case statements, and the variable with matches the
>>> type
>>> of the switch expression is used.
>>>
>>> I don't know how the syntax should look, this is merely an
>>> example:
>>>
>>> void foo(T)(T arg){
>>> 	switch(arg){
>>> 		case int i:
>>> 			writeln("Type is int ", i); break;
>>> 		case float f:
>>> 			writeln("Type is float ", f); break;
>>> 		case string s:
>>> 			writeln("Type is string ", s); break;
>>> 		default:
>>> 			writeln("Type is unknown"); break;
>>> 	}
>>> }
>>
>> The above should be switch (T) not switch(arg) for the example
>> to be correct.
>
> Notice how it's "int i" and not just "int". Also notice how each
> writeln statement also prints the variable. Each case statement
> declares a variable, so it matches the type of the expression
> against the type of the variable, and stores the switch
> expression in that variable.
>

And why not simply do:

 void foo(T)(T arg){
     switch(T){
 		case int:
 			writeln("Type is int ", arg); break;
 		case float:
 			writeln("Type is float ", arg); break;
 		case string:
 			writeln("Type is string ", arg); break;
 		default:
 			writeln("Type is unknown"); break;
 	}
 }
February 19, 2012
Am 19.02.2012 02:47, schrieb Nick Sabalausky:
> With exceptions in particular, I've often felt that we need some sort of
> templated catch:
>
> try {...}
> catch(TypeTuple!(ExceptionA, ExceptionB) e)
> {
>      // Common implementation, but NO need
>      // for that re-throwing abomination you'd
>      // inevitably need if you just caught
>      // a common base type.
> }
>

+1 best would be with built-in Tuples, but I guess built-in tuples are just a dream …


February 19, 2012
On Sunday, 19 February 2012 at 06:28:37 UTC, Robert Jacques wrote:
> On Sat, 18 Feb 2012 20:03:51 -0600, Xinok <xinok@live.com> wrote:
>> Notice how it's "int i" and not just "int". Also notice how each
>> writeln statement also prints the variable. Each case statement
>> declares a variable, so it matches the type of the expression
>> against the type of the variable, and stores the switch
>> expression in that variable.
>>
>
> And why not simply do:
>
>  void foo(T)(T arg){
>      switch(T){
>  		case int:
>  			writeln("Type is int ", arg); break;
>  		case float:
>  			writeln("Type is float ", arg); break;
>  		case string:
>  			writeln("Type is string ", arg); break;
>  		default:
>  			writeln("Type is unknown"); break;
>  	}
>  }
Because all of the code gets compiled in, so if one statement uses the type incorrectly, it won't compile. It also doesn't allow for dynamic upcasting of classes as in my second example.