View mode: basic / threaded / horizontal-split · Log in · Help
February 22, 2007
Template question
I'm not yet familiar enough with the template system to do this.

I wrote the following function:

----------------------------------------
Set!(T[0]) set(T ...)(T elements) {
   auto result = new Set!(T[0]);

   foreach (element; elements) {
       result.add(element);
   }

   return result;
}
----------------------------------------

This gives a nice set literal syntax with implicit type deduction.

auto x = set(4, 5, 6, 99);

But the user of the function should also have the option to use it like
this:

auto x = set!(int);

To create the empty set (that can hold int). How can I implement this?

Thanks!

PS: I would have liked to skip the type altogether for the empty set,
but the problem appears when you want to put something inside that set.
I've considered using a dummy type and to somehow construct the correct
set-type after the first insert, but it wouldn't be consistent with
normal sets and altogether too much trouble.

-- 
Michiel
February 22, 2007
Re: Template question
Reply to Michiel,

> I'm not yet familiar enough with the template system to do this.
> 
> I wrote the following function:
> 
> ----------------------------------------
> Set!(T[0]) set(T ...)(T elements) {
> auto result = new Set!(T[0]);
> foreach (element; elements) {
> result.add(element);
> }
> return result;
> }
> ----------------------------------------
> This gives a nice set literal syntax with implicit type deduction.
> 
> auto x = set(4, 5, 6, 99);
> 
> But the user of the function should also have the option to use it
> like this:
> 
> auto x = set!(int);

would this work?

auto x = Set!(int);

it's not quite as clean but...


If you don't like that 

you could try having set used as above take 2 things plus a tuple, then have 
a version of the template that takes one type and has function that take 
one or zero arguments

Set!(T) set(T, U, V...)(T e1, U e2, V elements) {...}

template set(T)
{
Set!(T) set(T e1) {...}
Set!(T) set() {...}
}

again, not as clean but, it could work.

I haven't tried this so it may not work.
February 22, 2007
Re: Template question
BCS wrote:

> would this work?
> 
> auto x = Set!(int);
> 
> it's not quite as clean but...

It would have to be:

auto x = new Set!(int);

> If you don't like that
> you could try having set used as above take 2 things plus a tuple, then
> have a version of the template that takes one type and has function that
> take one or zero arguments
> 
> Set!(T) set(T, U, V...)(T e1, U e2, V elements) {...}
> 
> template set(T)
> {
> Set!(T) set(T e1) {...}
> Set!(T) set() {...}
> }
> 
> again, not as clean but, it could work.
> 
> I haven't tried this so it may not work.

I don't really care if the function implementation isn't very clean, as
long as it's clean where set literals are used. That's what you want
from a library.

I'll try it out and get back to you.

-- 
Michiel
February 22, 2007
Re: Template question
Michiel wrote:
> But the user of the function should also have the option to use it like
> this:
> 
> auto x = set!(int);
> 
> To create the empty set (that can hold int). How can I implement this?

What's wrong with "auto x = new Set!(int);"? It's how every other class 
type is instantiated.

An alternative would be to make your set type a struct instead of a 
class, then you could just have "Set!(int) x;" declare an empty set.
You'd have to be careful about the copying behavior though, structs are 
copied by value, not reference. But if the struct contained a 
reference/pointer to the actual data, it could work.

> PS: I would have liked to skip the type altogether for the empty set,
> but the problem appears when you want to put something inside that set.
> I've considered using a dummy type and to somehow construct the correct
> set-type after the first insert, but it wouldn't be consistent with
> normal sets and altogether too much trouble.

This would probably be a bad idea in a statically typed language. It 
could be made to work, but that would require you to specify the type 
whenever you wanted to extract an element from the set...
February 22, 2007
Re: Template question
Frits van Bommel wrote:

>> But the user of the function should also have the option to use it like
>> this:
>>
>> auto x = set!(int);
>>
>> To create the empty set (that can hold int). How can I implement this?
> 
> What's wrong with "auto x = new Set!(int);"? It's how every other class
> type is instantiated.

In this case I'm trying to create set literals. They're very pretty if
you have at least one parameter. I just wanted the empty set to not be
an exception to the syntax.

> An alternative would be to make your set type a struct instead of a
> class, then you could just have "Set!(int) x;" declare an empty set.
> You'd have to be careful about the copying behavior though, structs are
> copied by value, not reference. But if the struct contained a
> reference/pointer to the actual data, it could work.

Hm.. I'd rather use 'new' as an exception for the empty set than go
through that, I think.

>> PS: I would have liked to skip the type altogether for the empty set,
>> but the problem appears when you want to put something inside that set.
>> I've considered using a dummy type and to somehow construct the correct
>> set-type after the first insert, but it wouldn't be consistent with
>> normal sets and altogether too much trouble.
> 
> This would probably be a bad idea in a statically typed language. It
> could be made to work, but that would require you to specify the type
> whenever you wanted to extract an element from the set...

That way it would become like Java data structures before generics. :) I
knew it wouldn't be a good idea the minute I thought of it.

-- 
Michiel
February 22, 2007
Re: Template question
Michiel wrote:
> BCS wrote:
> 
>> would this work?
>>
>> auto x = Set!(int);
>>
>> it's not quite as clean but...
> 
> It would have to be:
> 
> auto x = new Set!(int);
> 
>> If you don't like that
>> you could try having set used as above take 2 things plus a tuple, then
>> have a version of the template that takes one type and has function that
>> take one or zero arguments
>>
>> Set!(T) set(T, U, V...)(T e1, U e2, V elements) {...}
>>
>> template set(T)
>> {
>> Set!(T) set(T e1) {...}
>> Set!(T) set() {...}
>> }
>>
>> again, not as clean but, it could work.
>>
>> I haven't tried this so it may not work.
> 
> I don't really care if the function implementation isn't very clean, as
> long as it's clean where set literals are used. That's what you want
> from a library.
> 
> I'll try it out and get back to you.

Hm. No go. I implemented it like this:

-----------------------------------------------
Set!(T) set(T, U, V ...)(T e1, U e2, V rest) { // line 287
	auto result = new Set!(T);
	
	result.add(e1);
	result.add(e2);
	foreach (element; rest) {
		result.add(element);
	}
	
	return result;
}

template set(T) {
	Set!(T) set() {
		return new Set!(T);
	}
	
	Set!(T) set(T e1) {
		auto result = new Set!(T);
		
		result.add(e1);
		
		return result;
	}
}

-----------------------------------------------

But got this error:

set.d(287): template tools.Set.set(T,U,V...) is not a function template

It's because of the existence of the second template. I removed it and
the first would work. I also tried to rewrite the last two functions
like this:

-----------------------------------------------
Set!(T) set(T)() {
	return new Set!(T);
}

Set!(T) set(T)(T e1) { // line 303
	auto result = new Set!(T);
	
	result.add(e1);
	
	return result;
}
-----------------------------------------------

But got this error:

set.d(303): template tools.Set.set(T) conflicts with
tools.Set.set(T,U,V...) at set.d(287)

Which is strange, because it shouldn't conflict at all. A bug in dmd,
perhaps?

Thanks for the suggestion, anyway! I hadn't thought of it.

-- 
Michiel
February 22, 2007
Re: Template question
Michiel wrote:
> I'm not yet familiar enough with the template system to do this.
> 
> I wrote the following function:
> 
> ----------------------------------------
> Set!(T[0]) set(T ...)(T elements) {
>     auto result = new Set!(T[0]);
> 
>     foreach (element; elements) {
>         result.add(element);
>     }
> 
>     return result;
> }
> ----------------------------------------
> 
> This gives a nice set literal syntax with implicit type deduction.
> 
> auto x = set(4, 5, 6, 99);
> 
> But the user of the function should also have the option to use it like
> this:
> 
> auto x = set!(int);
> 
> To create the empty set (that can hold int). How can I implement this?
> 
> Thanks!

SetOf!(T) set(T...)(T elements)
{
   auto result = new SetOf!(T);

   foreach( element ; elements )
       result.add(element);

   return result;
}

template SetOf(T...)
{
   static if( is( typeof(T[0]) ) )
       alias Set!(typeof(T[0])) SetOf;
   else
       alias Set!(T[0]) SetOf;
}

Obviously, this only works if Set!(T) expects "T" to be an actual type.

Note that I haven't tried the above.  This should *theoretically* work
since taking the type of a type makes no sense (hence, the is expression
should fail), whilst taking the type of a value does.

If it doesn't work, blame it on just having woken up :P

> PS: I would have liked to skip the type altogether for the empty set,
> but the problem appears when you want to put something inside that set.
> I've considered using a dummy type and to somehow construct the correct
> set-type after the first insert, but it wouldn't be consistent with
> normal sets and altogether too much trouble.

Bad idea; the more you can get fixed at compile-time, the better.  For
instance, std.boxer.Box can store any type you want.  Putting things
into a box is easy enough,

 auto x = box(42);

But taking them back out is a bit ugly.

 auto y = unbox!(int)(x);

The reason for this is that the compiler needs to know what the result
type of "unbox" is at compile-time, so you need to tell it.

	-- Daniel

-- 
Unlike Knuth, I have neither proven or tried the above; it may not even
make sense.

v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D
i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP  http://hackerkey.com/
February 22, 2007
Re: Template question
Reply to Michiel,

> Michiel wrote:
> 
[...]
> 
> Thanks for the suggestion, anyway! I hadn't thought of it.
> 

How about this, it might work.

template set(T, U...)
{
static if(U.length == 0)
{
 Set!(T) set() {
 return new Set!(T);
 }
  Set!(T) set(T e1) {
  auto result = new Set!(T);
  result.add(e1);
  return result;
 }
}
else
{
  Set!(T) set(T e1, U rest) { // line 287
  auto result = new Set!(T);
  result.add(e1);
  foreach (element; rest)
  {
   result.add(element);
  }
  return result;
 }
}
}
February 22, 2007
Re: Template question
BCS wrote:

> How about this, it might work.

No, afraid not.

set.d(312): template tools.Set.set(T,U...) is not a function template

I don't think the compiler can recognize it as a function template if
you put a static if in between the function and the template. I've tried
this one before.

-- 
Michiel
February 22, 2007
Re: Template question
Daniel Keep wrote:
> SetOf!(T) set(T...)(T elements)
> {
>     auto result = new SetOf!(T);
> 
>     foreach( element ; elements )
>         result.add(element);
> 
>     return result;
> }
> 
> template SetOf(T...)
> {
>     static if( is( typeof(T[0]) ) )
>         alias Set!(typeof(T[0])) SetOf;
>     else
>         alias Set!(T[0]) SetOf;
> }
> 
> Obviously, this only works if Set!(T) expects "T" to be an actual type.

(Note: I haven't actually tried that code)

First I'd like to suggest also skip adding the first element if it was a 
type.

Second, if your SetOf doesn't work you might also try removing the 
typeof from the condition and switching the two clauses. IIRC is(x) is 
also false for any x that isn't a type.

> Note that I haven't tried the above.  This should *theoretically* work
> since taking the type of a type makes no sense (hence, the is expression
> should fail), whilst taking the type of a value does.

I seem to remember typeof(myType) being the type aliased to myType. I 
don't know why, but I do seem to recall that being the case...

> If it doesn't work, blame it on just having woken up :P

Ditto, except in my case blame it on it being after midnight here :P.
Top | Discussion index | About this forum | D home