www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Mixin templates accessing mixed out scope

reply "Prudence" <Pursuit Happyness.All> writes:
The following code simply does not work, it might be buggy now 
after fiddling with it but basically remove and the 
SingleStore.New are not working(Says the creating new SingleStore 
is not an expression, which makes no sense to me).


Essentially I'm creating a mixin template so I can have different 
"object stores", which is just an associative array of arrays. 
The SingleStore wraps the key, value pair added to the store so 
that I can keep track of and remove the added object easily 
without having to explicitly remember everything(e.g., what if 
TValue is a delegate? Then it get's messy).

Why remove can't disambiguate is beyond me... Why I can't create 
a SingleStore!(int, double)() is beyond me! It would be nice if 
D's errors were a little more helpful!


Error		Error: type SingleStore!(int, double) is not an 
expression		Test.d	56

auto o = new SingleStore!(TKey, TValue)(k, v);	

huh??? Have I just lost it or is this how one is suppose to 
create such an object?

(I do realize that I do not have to parameterize SingleStore. It 
is irrelevant here though)

import std.stdio;
import std.concurrency;



extern (C) int getch();
import std.string;
import std.concurrency;
import core.time;
import core.thread;
import std.container.array;
import std.typecons;








// Creates a static Associative Array that stores multiple values 
per key. The object returned by New can then be used to remove 
the object without having to remember the object specifically.
public mixin template ObjectStore(TKey, TValue)
{
	// The object store. It is static. Mixin the template into it's 
different types to create different types of stores. All objects 
of that type are then in the same store.
	public static TValue[][TKey] store;

	public static auto New(TKey k, TValue v)
	{
		(store[k]) ~= v;
		auto o = SingleStore!(TKey, TValue).New(k, v);
		return o;
	}

	public static auto Remove(SingleStore!(TKey, TValue) o)
	{
		import std.algorithm;
		//remove!(c => (this.Value == c))(store[o.Key], 
SwapStrategy.unstable);
	}


	public class SingleStore(TKey, TValue)
	{
		public TValue Value;
		public TKey Key;

		public auto Remove()
		{
			import std.algorithm;
			//remove!("c => (this.Value == c)")(store[this.Key], 
SwapStrategy.unstable);
			//super.Remove(this);
		}

		public static auto New(TKey k, TValue v)
		{
			auto o = new SingleStore!(TKey, TValue)(k, v);	
			return o;
		}

		private this(TKey k, TValue v)
		{
			Key = k;
			Value = v;
		}
	}

}


class MyStore
{
	mixin ObjectStore!(int, double);
}

void main()
{
	auto s = new MyStore();


	getch();
Sep 12 2015
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 09/12/2015 06:37 AM, Prudence wrote:
 Says the creating new SingleStore is not an expression
Reduced: mixin template ObjectStore(TKey) { class SingleStore { static void New() // Removing 'static' compiles { new SingleStore(); } } } class MyStore { mixin ObjectStore!(int); } void main() { auto s = new MyStore(); } Error: type SingleStore is not an expression Ali
Sep 12 2015
next sibling parent "Prudence" <Pursuit Happyness.All> writes:
On Saturday, 12 September 2015 at 14:30:16 UTC, Ali Çehreli wrote:
 On 09/12/2015 06:37 AM, Prudence wrote:
 Says the creating new SingleStore is not an expression
Reduced: mixin template ObjectStore(TKey) { class SingleStore { static void New() // Removing 'static' compiles { new SingleStore(); } } } class MyStore { mixin ObjectStore!(int); } void main() { auto s = new MyStore(); } Error: type SingleStore is not an expression Ali
Are you saying this is a bug or something else? The only alternative I can think of is to use string mixins but this method should work?
Sep 12 2015
prev sibling parent reply anonymous <anonymous example.com> writes:
On Saturday 12 September 2015 16:30, Ali Çehreli wrote:

 Reduced:
[...]
 Error: type SingleStore is not an expression
Reduced further: ---- class MyStore { class SingleStore { static void New() // Removing 'static' compiles { new SingleStore(); } } } ---- And now the problem can be spotted: SingleStore is a nested class. That means, instances of it are bound to MyStore instances. But New is static, so it doesn't have a MyStore to which it could attach the `new SingleStore`. That error message is pretty awful. I filed an issue: https://issues.dlang.org/show_bug.cgi?id=15049 As for a fix: I guess SingleStore isn't supposed to be a nested class. Mark it static then.
Sep 12 2015
parent reply "Prudence" <Pursuit Happyness.All> writes:
On Saturday, 12 September 2015 at 17:11:04 UTC, anonymous wrote:
 On Saturday 12 September 2015 16:30, Ali Çehreli wrote:

 Reduced:
[...]
 Error: type SingleStore is not an expression
Reduced further: ---- class MyStore { class SingleStore { static void New() // Removing 'static' compiles { new SingleStore(); } } } ---- And now the problem can be spotted: SingleStore is a nested class. That means, instances of it are bound to MyStore instances. But New is static, so it doesn't have a MyStore to which it could attach the `new SingleStore`. That error message is pretty awful. I filed an issue: https://issues.dlang.org/show_bug.cgi?id=15049
like most D errors ;/ it's the #1 problem I'm struggling with in D. Remember there's another error with remove, that isn't releated to SingleStore.
 As for a fix: I guess SingleStore isn't supposed to be a nested 
 class. Mark it static then.
NO! That is the whole point! SingleStore is a momento that wraps the key value pair, e.g., auto t = DeleteStore.New("mycooldelegate", (int x) { return true; }); t is suppose to be a single store. then t.Remove(); removes the delegate from the store. Note I don't have to know the actual key or delegate!! Which is the whole point! Else it would lool like this: store[][string] mydelegatestore; auto dg = (int x) { return true; }; mydelegatestore["mycooldelegate"] ~= dg; then mydelegatestore["mycooldelegate"].remove(d => dg == d); which requires remembering both the key and the delegate, which makes using inline lambdas infeasible(because you'll never be able to remove them). I see no reason why SingleStore has to be static. The mixin template should insert all that stuff into the class, which, by the way, works... I've also used that New pattern all that time and it works, maybe not for nested classes. Moving SingleStore outside the template works. I've fixed the issue with that, it's not as pretty but works. Still have the remove error: import std.stdio; import std.concurrency; extern (C) int getch(); import std.string; import std.concurrency; import core.time; import core.thread; import std.container.array; import std.typecons; public class SingleStore(TKey, TValue) { public TValue Value; public TKey Key; public TValue[][TKey] Store; public auto Remove() { import std.algorithm; remove!(c => Value == c")(Store[this.Key], SwapStrategy.unstable); // Not working, can't disambiguate } public static auto New(TKey k, TValue v, ref TValue[][TKey] s) { auto o = new SingleStore!(TKey, TValue)(k, v); o.Store = s; return o; } private this(TKey k, TValue v) { Key = k; Value = v; } } public mixin template ObjectStore(TKey, TValue) { public static TValue[][TKey] store; public static auto New(TKey k, TValue v) { (store[k]) ~= v; auto o = SingleStore!(TKey, TValue).New(k, v, store); o.store = store; return o; } } class MyStore { mixin ObjectStore!(string, bool delegate(int)); } void main() { auto s = MyStore.New("x", (int x) { return true; }); // works, stores delegate in MyStore s.Remove(); // Doesn't work because std.algorithm's remove isn't working getch(); } (The whole point of nesting was so I wouldn't have to explicitly create a pointer to the store in SingleStore. Should have worked, probably another one of D's bugs)
Sep 12 2015
parent anonymous <anonymous example.com> writes:
On Saturday 12 September 2015 19:36, Prudence wrote:

 On Saturday, 12 September 2015 at 17:11:04 UTC, anonymous wrote:
[...]
 class MyStore
 {
     class SingleStore
     {
         static void New() // Removing 'static' compiles
         {
             new SingleStore();
         }
     }
 }
[...]
 As for a fix: I guess SingleStore isn't supposed to be a nested 
 class. Mark it static then.
NO! That is the whole point!
So New is supposed to create a SingleStore that's associated with a MyStore? That static can't work like that then. It doesn't escape just the first level (SingleStore), but all levels (SingleStore and MyStore). That is, a static method isn't bound to any object. But you need a MyStore to construct a (nested) SingleStore. You have to pass a MyStore somehow. It can come via `this.outer`: ---- class MyStore { class SingleStore { SingleStore New() { return new SingleStore; } } } void main() { auto ms = new MyStore; auto ss1 = ms.new SingleStore; auto ss2 = ss1.New(); } ---- But here you need a SingleStore object to call New on. Not what you want, I think. Or the MyStore can come via parameter: ---- class MyStore { class SingleStore { static SingleStore New(MyStore ms) { return ms.new SingleStore; } } } void main() { auto ms = new MyStore; auto ss = MyStore.SingleStore.New(ms); } ---- Or you can move New a level up, into MyStore, and then plain `this` is the needed MyStore: ---- class MyStore { class SingleStore { } SingleStore NewSingleStore() { return new SingleStore; } } void main() { auto ms = new MyStore; auto ss = ms.NewSingleStore(); } ----
Sep 12 2015