Today I was looking at the Record.AddField() M function and saw it had a mysterious – and badly documented – optional fourth argument called delayed. Of course I had to work out what it did, and having done so I thought I’d blog about it in case someone found it useful (and however obscure the topic, there’s always someone out there who finds this stuff useful).
Imagine you have an M function called ReturnANumber that has no arguments at all and returns the number 999:
[sourcecode language=”text” padlinenumbers=”true”]
() as number => 999
[/sourcecode]
Now imagine that you want to return this function in a record (which is exactly what #shared does). The following expression:
[sourcecode language=”text”]
[MyFunction = ReturnANumber]
[/sourcecode]
…returns a record with one field whose value is of type function:
But what if you wanted the field to contain the number that the function returns, not a reference to the function itself? The delayed option of Record.AddField() allows you to do this: if you set it to true, you get the value the function returns.
[sourcecode language=”text”]
Record.AddField([], "MyFunction", ReturnANumber, true)
[/sourcecode]
Setting delayed to false does the same as the first example above:
[sourcecode language=”text”]
Record.AddField([], "MyFunction", ReturnANumber, false)
[/sourcecode]
Another way to get the same result as setting delayed to true is to use Function.Invoke():
[sourcecode language=”text”]
[MyFunction = Function.Invoke(ReturnANumber,{})]
[/sourcecode]
Now I need to think of a real-world use for this…
Ben Gribaudo explains that Delayed=true is useful to add something like this:
() => ExpensiveToCompute(“some”, “arguments”)
The expensive computation will only happen when that field is accessed.
See https://bengribaudo.com/blog/2021/08/09/5941/dynamic-lazy-records