Thread overview
Is using function() in templates possible at all?
Apr 11
Alex
Apr 12
Alex
April 11
I am trying to do a binary insert into my sorted array.
To sort classes and structs I would like to give a delegate `(t) => t.myValue` to sort on that value whitout having to implement an interface or specifically declare opCmp for every class I want to have sorted.
After all, I might want one group of objects of a given class sorted in one way and another group of objects sorted on another way depending on the usecase.
In C# this is done by passing on a lambda in for instance a LinQ expression to sort such list after insertion, and is also usefull in other circumstances.

But is it possible in D to do something simular but then pass on this Function() during compile time?

something like
`
void main() { SortedList!(Vector3, (v) => v.y) list; }

struct Vector3 { float x, y, z; }

class SortedList(T, int function(T) comparer)
{
	T[] array;
	
	int foo(T t)
	{
		for(int i = 0; i < array.lenght; i++)
		{
			if(comparer(this.otherT) <=  comparer(t))
			{
				//do stuff
				array[i] = t;
			}
		}
	}
}
`

April 11
On Wednesday, 11 April 2018 at 21:07:03 UTC, Sjoerd Nijboer wrote:

> class SortedList(T, int function(T) comparer)

I would say, alias template parameter is your friend.
https://dlang.org/spec/template.html#TemplateAliasParameter

´´´
import std.stdio;
import std.range;

void main()
{
	auto list = new SortedList!(Vector3, v => v.y)();

	assert(list.array.empty);
	list.foo(Vector3.init);
}

struct Vector3 { float x, y, z; }

class SortedList(T, alias comparer)
{
	T[] array;
	
	auto foo(T t)
	{
		for(int i = 0; i < array.length; i++)
		{
			if(comparer(this.array[i]) <=  comparer(t))
			{
				//do stuff
				array[i] = t;
			}
		}
	}
}
´´´
April 11
On Wednesday, 11 April 2018 at 21:29:27 UTC, Alex wrote:
> I would say, alias template parameter is your friend.
> https://dlang.org/spec/template.html#TemplateAliasParameter
>
> class SortedList(T, alias comparer)

It works, thank you!
But just to be shure, there's no way to have this more strongly typed in D so I can enforce that `comparer`is a funciton or delegate with a specific defenition?
Right now i'm relying on the template to error on some different place which might not give such a readable error message to the user.
April 12
On Wednesday, 11 April 2018 at 22:13:33 UTC, Sjoerd Nijboer wrote:
> On Wednesday, 11 April 2018 at 21:29:27 UTC, Alex wrote:
>> I would say, alias template parameter is your friend.
>> https://dlang.org/spec/template.html#TemplateAliasParameter
>>
>> class SortedList(T, alias comparer)
>
> It works, thank you!
> But just to be shure, there's no way to have this more strongly typed in D so I can enforce that `comparer`is a funciton or delegate with a specific definition?


There is, with template constraints:

class SortedList(T, alias comparer) if(is(typeof(comparer(T.init) : int))
{
    //...
}
April 12
On Thursday, 12 April 2018 at 00:05:26 UTC, Nicholas Wilson wrote:
> There is, with template constraints:
>
> class SortedList(T, alias comparer)
>     if(is(typeof(comparer(T.init) : int))
> {
>     //...
> }

If the function is declared with explicit parameter types:
```
auto list = new SortedList!(Vector3, (Vector3 v) => v.y)();
```

Then the template guard can even have a full type definition:
```
class SortedList(T, alias comparer)
    if (is(typeof(comparer) :  int function(T)))
{
    //...
}
```
April 12
On Thursday, 12 April 2018 at 11:17:01 UTC, Laurent Tréguier wrote:
> If the function is declared with explicit parameter types:

There are cool things possible, if the param type is explicitly typed :)

´´´
import std.traits;

void main()
{
	auto list = new SortedList!((Vector3 v) => v.y)();
	list.foo(Vector3.init);
}

struct Vector3 { float x, y, z; }

class SortedList(alias comparer) if(is(ReturnType!comparer : float))
{
	alias T = Parameters!comparer[0];

	T[] array;
	
	auto foo(T t)
	{
		// do stuff
	}
}
´´´
April 12
On Thursday, 12 April 2018 at 11:53:21 UTC, Alex wrote:
> On Thursday, 12 April 2018 at 11:17:01 UTC, Laurent Tréguier wrote:
>> If the function is declared with explicit parameter types:
>
> There are cool things possible, if the param type is explicitly typed :)
>
> ´´´
> import std.traits;
>
> void main()
> {
> 	auto list = new SortedList!((Vector3 v) => v.y)();
> 	list.foo(Vector3.init);
> }
>
> struct Vector3 { float x, y, z; }
>
> class SortedList(alias comparer) if(is(ReturnType!comparer : float))
> {
> 	alias T = Parameters!comparer[0];
>
> 	T[] array;
> 	
> 	auto foo(T t)
> 	{
> 		// do stuff
> 	}
> }
> ´´´

Getting rid of redundancy. Now that's nice !