1

I am using LeMP v2.8.1 from the Extended CSharp and have the following shortcut for defining and initializing the fields in a class:

compileTimeAndRuntime 
{
    public partial class DI : IResolver
    {
        replace (T => ConcurrentDictionary<Type, Expression<Func<IResolver, object>>>) { public T Registrations = new T(); }
        replace (T => ConcurrentDictionary<Type, Func<IResolver, object>>) { public T DelegateCache = new T(); }
    }
}

The replace pattern is very similar except the public and internal modifiers. But let's skip them for a moment.

My question is there a way to factor this replace pattern into a single define macro, so that I don't need to repeat the pattern.

I tried something like define New($T, $F) { $T $F = new $T(); } but it spits the error when using it with Type argument like this New(ConcurrentDictionary<Type, Expression<Func<IResolver, object>>>, Registrations).

dadhi
  • 4,807
  • 19
  • 25

1 Answers1

1

It works for me:

compileTimeAndRuntime 
{
    define New($T, $F) { $T $F = new $T(); }
    
    public partial class DI : IResolver
    {
        public New(ConcurrentDictionary<Type, Expression<Func<IResolver, object>>>, Registrations);
        internal New(ConcurrentDictionary<Type, Func<IResolver, object>>, DelegateCache);
    }
}

// Generated from Untitled.ecs by LeMP 2.8.2.0.
public partial class DI : IResolver
{
    public ConcurrentDictionary<Type, Expression<Func<IResolver, object>>> Registrations = new ConcurrentDictionary<Type, Expression<Func<IResolver, object>>>();
    internal ConcurrentDictionary<Type, Func<IResolver, object>> DelegateCache = new ConcurrentDictionary<Type, Func<IResolver, object>>();
}

Here's a more interesting version:

// Matches variable declarations and replaces __var with the type name.
// Useful to avoid repeating the type twice when declaring fields in classes.
[Passive] // avoids warning on variable declarations that don't match
define #var(__var, $name = new $T($(..args)) { $(..initializers) }) {
    $T $name = new $T($args) { $initializers };
}

public partial class DI : IResolver
{
    public __var Registrations = new ConcurrentDictionary<Type, Expression<Func<IResolver, object>>>();
    internal __var DelegateCache = new ConcurrentDictionary<Type, Func<IResolver, object>>();
    private __var _array = new int[4] { 0, 10, 20, 30 };
}

// Generated from Untitled.ecs by LeMP 2.8.2.0.
public partial class DI : IResolver
{
    public ConcurrentDictionary<Type, Expression<Func<IResolver, object>>> Registrations = new ConcurrentDictionary<Type, Expression<Func<IResolver, object>>>();
    internal ConcurrentDictionary<Type, Func<IResolver, object>> DelegateCache = new ConcurrentDictionary<Type, Func<IResolver, object>>();
    private int[] _array = new int[4] { 
        0, 10, 20, 30
    };
}

This is based on my knowledge that T x = y has a Loyc tree of the form #var(T, x = y), but the replace macro allows you to do the same thing without this knowledge:

replace (
    { __var $name = new $Type($(..args)) { $(..initializers) }; } =>
    { $Type $name = new $Type($(..args)) { $(..initializers) }; });

Apologies for taking so long to answer.

Qwertie
  • 16,354
  • 20
  • 105
  • 148
  • Thanks for the answer, I am impressed! The last example with `replace` though I am sure I get it - is it works automatically when put into the class scope.. or is it supposed to be called somehow? – dadhi Jul 29 '20 at 08:13
  • Correct it me if I am wrong, that in the example with `__var` (btw, I like it the most) we are adding "overload" for the "system" `#var` macros using the `__var` instead of original `T` ? – dadhi Jul 29 '20 at 08:17
  • When `replace` is used without a braced block, it performs a find and replace operation to the rest of the statements in scope. In this case, it's appropriate to use it at class, namespace or file scope. – Qwertie Jul 29 '20 at 14:35
  • Omg, cool... Btw, I've ended up with `define #var(#var, $name = new $T($(..args)) { $(..initializers) }) => {...}` so that declaration is looks more like macros involved `public #var F = new Foo()` – dadhi Jul 30 '20 at 06:40