www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to create a template class using foreach delegate to filter objects in a member function call?

reply =?iso-8859-1?Q?Robert_M._M=FCnch?= <robert.muench saphirion.com> writes:
I have myClass and I want to add a way where I can provide a delegate 
to iterate over myClass.objects when a member function put(...) of 
myClass is called. The idea is that a user of myClass can provide 
something like an "iterator filter" so that the function is only called 
on a subset of myClass.objects.


myClass(E){
	myOtherClass!E objects;

	void put(E obj) {
		.put(objects, obj);
	}

	void put(T)(E obj, T filter) {
		foreach(o ; filter!E(objects)){
			.put(o, obj);
		}
	}
}

struct myFilter {
	myOtherClass!E object;

	opApply(int delegate(E) foreach_body) const {
		if(mytestfunc(object))
			return(foreach_body(object));
	}
}

But I'm struggeling how to write all this down with tempaltes, because 
E is not known in myFilter. But the filter code needs to be aware of 
the template type if myClass. I hope the idea want to do is 
understandable.

-- 
Robert M. Mnch
http://www.saphirion.com
smarter | better | faster
May 30 2019
parent reply Alex <sascha.orlov gmail.com> writes:
On Thursday, 30 May 2019 at 18:34:31 UTC, Robert M. Münch wrote:
 I have myClass and I want to add a way where I can provide a 
 delegate to iterate over myClass.objects when a member function 
 put(...) of myClass is called. The idea is that a user of 
 myClass can provide something like an "iterator filter" so that 
 the function is only called on a subset of myClass.objects.


 myClass(E){
 	myOtherClass!E objects;

 	void put(E obj) {
 		.put(objects, obj);
 	}

 	void put(T)(E obj, T filter) {
 		foreach(o ; filter!E(objects)){
 			.put(o, obj);
 		}
 	}
 }

 struct myFilter {
 	myOtherClass!E object;

 	opApply(int delegate(E) foreach_body) const {
 		if(mytestfunc(object))
 			return(foreach_body(object));
 	}
 }

 But I'm struggeling how to write all this down with tempaltes, 
 because E is not known in myFilter. But the filter code needs 
 to be aware of the template type if myClass. I hope the idea 
 want to do is understandable.
Not sure, if I understood your problem correctly. It is meant that the class myClass defines an array of myOtherClass objects? The code does not compile and it does not provide an example, how you would apply the pattern, even in a non-compileable way... However, commonly, a filter is a higher order function, which expects a predicate acting on each element of a set. Even if it's higher order, it is still a function, not a delegate. Therefore, it is unexpected, that you want to store something inside the filter. Said this, I for myself had a similar problem. I solved this by reversing the hierarchy: I templated my objects I wanted to use the filter on with the filter function and removed the need of the template parameter inside the filter. You could still write a general filter function in this case, if you want. For example, you could use mixins for this... As I said... not sure if this is of any help for you...
May 31 2019
parent reply =?iso-8859-1?Q?Robert_M._M=FCnch?= <robert.muench saphirion.com> writes:
On 2019-05-31 11:07:00 +0000, Alex said:

 Not sure, if I understood your problem correctly.
I can imagine... I try my best :-)
 It is meant that the class myClass defines an array of myOtherClass objects?
Yes. So there is one class having an array of other stuff.
 The code does not compile and it does not provide an example, how you 
 would apply the pattern, even in a non-compileable way...
The code is just to show the problem and not meant to compile. I couldn't get anything to compile...
 However, commonly, a filter is a higher order function, which expects a 
 predicate acting on each element of a set. Even if it's higher order, 
 it is still a function, not a delegate. Therefore, it is unexpected, 
 that you want to store something inside the filter.
I choose filter to give a hint what the idea is, not meant to be that I want to use a filter.
 Said this, I for myself had a similar problem. I solved this by 
 reversing the hierarchy: I templated my objects I wanted to use the 
 filter on with the filter function and removed the need of the template 
 parameter inside the filter.
The thing is, myClass is not under my control. It's coming from a library I don't maintain and I don't want to mess around with the code or if, as minimalistic as possible. That's why I was thinking about providing a put(T)... function. My first idea was to sub-class myClass, but objects is private, so no chance to get access to it.
 You could still write a general filter function in this case, if you 
 want. For example, you could use mixins for this...
Then myClass needs to somehow get the mixin in. So, to summurize the problem: Given a class that manages an array of things as an OutputRange how can I provide a put() function with something like a filter-predicate? I only want to put() to some of the things, not all. -- Robert M. Mnch http://www.saphirion.com smarter | better | faster
May 31 2019
parent reply Alex <sascha.orlov gmail.com> writes:
On Friday, 31 May 2019 at 16:24:28 UTC, Robert M. Münch wrote:
 The code is just to show the problem and not meant to compile. 
 I couldn't get anything to compile...
That's ok, but could you provide an example anyway? Is it like this? ´´´ void main(){ auto target = new myClass!int(); target.objects.length = 4; auto val = 42; put(target, val, testfunction); // does the test function enters here? put(target, val); auto f = myFilter!int; // where do you want to use this entity? } ´´´
 Said this, I for myself had a similar problem. I solved this 
 by reversing the hierarchy: I templated my objects I wanted to 
 use the filter on with the filter function and removed the 
 need of the template parameter inside the filter.
The thing is, myClass is not under my control. It's coming from a library I don't maintain and I don't want to mess around with the code or if, as minimalistic as possible. That's why I was thinking about providing a put(T)... function.
*
 My first idea was to sub-class myClass, but objects is private, 
 so no chance to get access to it.

 You could still write a general filter function in this case, 
 if you want. For example, you could use mixins for this...
Then myClass needs to somehow get the mixin in. So, to summarize the problem: Given a class that manages an array of things as an OutputRange how can I provide a put() function with something like a filter-predicate? I only want to put() to some of the things, not all.
Do you have control about the contained classes? If so, it is a hint to implement the testing inside them. Like: /* probably inside a templated mixin */ bool testfunction(inputs){...} class myOtherClass(/*probably templated*/){... mixin testfunction ... & provide a put function} * So, you are not totally against the idea of modifying the foreign library, but you want to keep modifications small? With the approach now, you could, for example, handle compile time blocks inside the put function in the myClass and dynamical ones inside the myOtherClasses. class myClass(E){/* inserted put function */ void put(...){static if put action is at all possible --> put. }}
May 31 2019
parent reply =?iso-8859-1?Q?Robert_M._M=FCnch?= <robert.muench saphirion.com> writes:
On 2019-06-01 04:43:13 +0000, Alex said:

 That's ok, but could you provide an example anyway? Is it like this?
 
 
 void main(){
      auto target = new myClass!int();
      target.objects.length = 4;
      auto val = 42;
      put(target, val, testfunction); // does the test function enters here?
      put(target, val);
      auto f = myFilter!int; // where do you want to use this entity?
 }
 
myClass shouldn't be subclassed, only just used. The myFilter struct is the implementation which myClass.put() should use to iterate over all objects. All things being only examples. So, the idea is, that I can provide a delegate which foreach(...; myFilter(objects)) uses. Like a run-time plug-in.
 Do you have control about the contained classes? If so, it is a hint to 
 implement the testing inside them. Like:
 
 /* probably inside a templated mixin */
 bool testfunction(inputs){...}
 
 class myOtherClass(/*probably templated*/){... mixin testfunction ... & 
 provide a put function}
I thought about a mixin too. But this requires an understanding of how myClass works. Which I what I want to avoid.
 * So, you are not totally against the idea of modifying the foreign 
 library, but you want to keep modifications small?
Yes, because myClass is some external lib, which can be changed to support this approach here. But not more.
 With the approach now, you could, for example, handle compile time 
 blocks inside the put function in the myClass and dynamical ones inside 
 the myOtherClasses. class myClass(E){/* inserted put function */ void 
 put(...){static if put action is at all possible --> put. }}
As said, KISS and really just want to provide a plug-in which is used to iterate of a sequence I provide from the outside. -- Robert M. Mnch http://www.saphirion.com smarter | better | faster
Jun 01 2019
parent Alex <sascha.orlov gmail.com> writes:
On Saturday, 1 June 2019 at 14:24:11 UTC, Robert M. Münch wrote:
 The myFilter struct is the implementation which myClass.put() 
 should use to iterate over all objects.
Which ones? The E-objects, or the objects contained in myClass, which you don't want to know about?
 All things being only examples.
Sure. So, please, provide a minimal example, as I'm only guessing what use case you want to solve. Even if it is not compilable.
 So, the idea is, that I can provide a delegate which 
 foreach(...; myFilter(objects)) uses. Like a run-time plug-in.
Maybe you can. But "put" has to remain a function, not a template.
 Do you have control about the contained classes? If so, it is 
 a hint to implement the testing inside them. Like:
 
 /* probably inside a templated mixin */
 bool testfunction(inputs){...}
 
 class myOtherClass(/*probably templated*/){... mixin 
 testfunction ... & provide a put function}
I thought about a mixin too. But this requires an understanding of how myClass works. Which I what I want to avoid.
Over which objects your filter will be iterating then?
 * So, you are not totally against the idea of modifying the 
 foreign library, but you want to keep modifications small?
Yes, because myClass is some external lib, which can be changed to support this approach here. But not more.
Jun 01 2019