А нельзя ли как-нибудь малой кровью добавить возможность параметризовать генерики типом void, раз уж даже такие вещи можно делать:
mutable x : void = ();
x = WriteLine("Hi");
?
Когда это может понадобится:
//Выполнение кода в каком-то контексте
ExecInContext[T](f : SomeContext -> T) : T
{
using(def ctx = SomeContext())
f(ctx);
}
Так вот, передать в ExecInContext функцию SomeContext->void нельзя.
Придется явно делать перегрузку:
//Так, с копипастом
ExecInContext(f : SomeContext -> void) : void
{
using(def ctx = SomeContext())
f(ctx);
}
//Или как-нибудь так
ExecInContext(f : SomeContext -> void) : void
{
_ = ExecInContext(ctx => { f(ctx); null : object; });
}
Или, например, вместо void использовать везде FakeVoid из computation expressions.
Так вот, нельзя ли автоматизировать все это?
Например, добавить структуру
public struct VoidStruct
{
public static Value : VoidStruct = VoidStruct();
}
И научить компилятор делать замены в коде.
Т.е., например:
ExecInContext(_ => {/*...*/});//если тело лямбды имеет тип void
ExecInContext.[VoidStruct](_ => {/*...*/; VoidStruct.Value; });//заменять так
Для случая генериков с указанием "where T:class" использовать класс VoidClass:
public abstract class VoidClass
{
public static Value : VoidClass = null;
private this() {}
}
ExecInContext_Class[T](f : SomeContext -> T) : T
where T : class
{
using(def ctx = SomeContext())
f(ctx);
}
ExecInContext_Class(_ => {/*...*/});//если тело лямбды имеет тип void
ExecInContext_Class.[VoidClass](_ => {/*...*/; VoidClass.Value;});//заменять так
Есть проблема, если в качестве параметра f передается не лямбда, создаваемая по месту, а, например, некая уже существующая функция T->void:
module Test
{
F(ctx : SomeContext) : void { /*...*/ }
}
ExecInContext(F);
//придется заменять на
ExecInContext(ctx => {F(ctx); VoidStruct.Value; });
Или:
def f : SomeContext->void = ctx => {/*...*/};
//тут какой-то код, для которого требуется, чтобы f была с типом SomeContext->void
ExecInContext(f);//тоже придется оборачивать
В этом случае создается новый объект и передается в качестве параметра.
В случае делегатов это может привести, например, к невозможности отписки от событий.
Нет ли возможности как-то решить эту проблему?
PS На правах размышлений вслух.