DIVEX

Var return

When composing functions or classes for large programs, it is a good idea to extract some composition code into its own method. This makes composition code easier to deal with. It also allows us to reuse composition code.

[DivexCompose]
public static partial class Program
{
    public record Document(string Content, string Name);

    static void Main(string[] args)
    {
        DelFunc.DF1 getDocumentOwnerEmail = (Document document) =>
        {
            return document.Name + "@test.lab";
        };

        DelFunc.DF2 processDocument = (Document document,
            Func<Document,string> getDocumentOwnerEmail,
            Action<string /*to*/, string /*body*/> sendEmail) =>
        {
            Console.WriteLine(document.Content);

            var ownerEmail = getDocumentOwnerEmail(document);

            sendEmail(ownerEmail, "Your document has been processed");
        };

        var sendEmailAndLog = SendEmailAndLog();

        var process = processDocument
            .Inject(sendEmail: sendEmailAndLog)
            .Inject(getDocumentOwnerEmail: getDocumentOwnerEmail);

        process.Invoke(document: new Document("Hello", "Name"));
    }

    public static VarReturn.VR1 SendEmailAndLog()
    {
        DelFunc.DF3 log = (string message) =>
        {
            Console.WriteLine(message);
        };

        DelFunc.DF4 sendEmail = (string to, string body, Action<string /*message*/> log) =>
        {
            Console.WriteLine("Sending email to " + to);
            Console.WriteLine(body);

            log("Sending email");
        };

        var sendEmailAndLog = sendEmail.Inject(log: log);

        return sendEmailAndLog;
    }
}
DelFunc.DF1, DelFunc.DF2, DelFunc.DF3, and DelFunc.DF4 areĀ Delegate Functions. Delegate Functions is a way to support treating lambdas as functions.

In the above code example, the composition code that injects the log function into the sendEmail function is inside the SendEmailAndLog method. This method returns the sendEmailAndLog variable. The type of this variable is a generated type. This is why this variable is declared using var. Without var, using DIVEX will not be practical. This is because every time we use a DIVEX operator to manipulate a function, the generated type names might change. And thus without var, maintenance will be hard. Also, the generated type names are not very friendly and they will make the code verbose.

C# doesn’t support using var as a return type for methods. DIVEX has some support to something similar to var but for return types. The return type of the SendEmailAndLog method above is VarReturn.VR1. Because it starts with “VarReturn.”, DIVEX will generated the VarReturn.VR1 type upon save. And regarding of the return value of the SendEmailAndLog, things will work. When you view the code inside VIsual Studio with DIVEX installed, “var” will be displayed instead of VarReturn.VR1 to make the code look better:

Also, to make it easier to use this feature, if you start typing “varreturn” in the location of a method return type, IntelliSense (because DIVEX is installed) will provide a “varreturn” completion item that will put an appropriate VarReturn type like VarReturn.VR1 or VarReturn.VR2, etc.