Use Freemarker macro call within string parameter of another macro - macros

I have a macro A that formats some text
<#macro A text>...${text}...</#macro>
and another macro that has a parameter accepting text
<#macro B x>Another ${x} text</#macro>
I'd like to call B with the x paramter to be some text formatted by A, s.th. like
<#B x="<#A text='abc'/>" /> returns Another <#A text='abc'/>
Is this possible somehow?
I tried the ?interpret as suggested here by ddekany -
<#B x="<#A text='abc'/>"?interpret /> but this fails with the error:
Expecting a string, date or number here, Expression .... is
instead a freemarker.core.Interpret$TemplateProcessorModel
It seems that a macro call in FreeMarker is something different than a function call in other languages.

Macro calls aren't expressions, and hence can't be used inside expression (like a parameter value). Macros are called for their side effects, which is typically printing to the output, and have no return value. Functions (see #function) are called for their return values, and so function calls are expressions. So maybe you need functions, not a macros in this case.
But if you absolutely have to use the output of a macro call in an expression (or of any arbitrary template fragment), then you have to capture the output via <#assign someVar>...</#assign> or <#local someVar>...</#local>. (Beware with #escape. If you re-print the captured output with ${...}, it will be escaped again, so you will need #noescape.)

I found a workaround using assign:
<#assign a><#A text="abc"/></#assign>
<#B text=a/>
Anyway, it would be interesting to know if this is possible somehow.

Related

Call a kdb function passing another function as argument using sendSync method of qpython(kdb)

In the KDB server, we have two functions defined as
q)t:{0N!x[`min]; 0N!x[`max];}
q).up.map:{[keyList; valueList] keyList!valueList}
The KDB server, does not allow to pass dict()!() as an argument directly to a function, rather one has to use .up.map.
Calling t function from kdb would be like
q)t[.up.map[`min`max;10 20]]
I want to call the t function from qpython sendSync() method passing another function .up.map[`min`max;10 20] as an argument to t.
Unfortunately, I cannot find a solution in the qptyhon doc - https://qpython.readthedocs.io/en/latest/qpython.html#qpython.qconnection.QConnection.sendSync
Error -
When I tried sendSync() method, below error is raised -
qpython.qtype.QException: b'['
The KDB server, does not allow to pass dict()!() as an argument directly to a function, rather one has to use .up.map.
May I know why this is so? It's not a bad idea to challenge the original design before looking for workarounds. If dictionary were allowed as its parameter, it could have been as simple as
params = QDictionary(qlist(numpy.array(["min", "max"], dtype=numpy.string_), qtype=QSYMBOL_LIST),
qlist(numpy.array([10, 20], dtype=numpy.int64), qtype=QLONG_LIST))
with qconnection.QConnection(host='localhost', port=5000) as q:
q.sendSync("t", params)
If you want to do what you can do in q console via qpython, it's actually also simple: you pass the same string over. Effectively it's the same mechanism as a q client passing a string via IPC to the server, where the string is parsed and evaluated. Here you need to convert the input to the given string format in your Python code, thus not as clean as the above (although it looks more verbose).
with qconnection.QConnection(host='localhost', port=5000) as q:
q.sendSync("t[.up.map[`min`max;10 20]]")
Maybe you can use a lambda for this. That way it's just the arguments that need be serialized:
q.sendSync("{t[.up.map[x;y]]}", qlist(["min", "max"], qtype=QSYMBOL_LIST), [10, 20])
If that's not permitted, you could create it as a named wrapper function on the kdb side, which could be.
Alternatively, you could format your call with arguments as a string. A bit hacky; but workable for simple input.
q.sendSync(f"t[.up.map[`{'`'.join(['min', 'max'])};{' '.join(['10', '20'])}]]")

Spread syntax in function call in Reason

In Javascript you can use the spread syntax in a function call like this:
console.log(...[1,2,3]);
Is there an equivalent in Reason? I tried the following:
let bound = (number, lower, upper) => {
max(lower, min(upper, number));
};
let parameters = (1,0,20);
bound(...parameters) |> Js.log;
But this gives an unknown syntax error:
Try reason snippet
There's not. Reason is a statically typed language, and lists are dynamically-sized and homogenous. It would be of very limited use, and not at all obvious how it would deal with too few or too many arguments. If you want to pass a list, you should just accept a list and deal with it appropriately, as a separate function if desired.
You could of course use a tuple instead, which is fixed-size and heterogenous, but I don't see a use-case for that either, since you might as well just call the function directly then.
For JavaScript FFI there is however the bs.splice attribute, which will allow you to apply a variable number of arguments to a js function using an array. But it needs to be called with an array literal, not just any array.

Passing parameters to freemarker macro dynamically

I have a macro in freemarker say
<#macro printHelloWorld var1 var2>
${var1}
${var2}
</#macro>
When I call this macro as
<#macro printHelloWorld var1="hello" var2="world" />
It prints it in the expected manner
hello
world.
However, my problem is that I want to pass this variable names dynamically. I receive the macro arguments dynamically from a source,
and I want to be able to pass them on. Something along the lines of
$paramater1 = "var1"
$parameter2 = "var2"
$valueForParameter1 = "hello"
$valueForParameter2 = "world"
<#macro printHelloWorld paramater1=valueForParameter1 parameter2=valueForParameter2 />
which I want to be equivalent to the call
<#macro printHelloWorld var1="hello" var2="world" />
I have unable to find any solutions to it. Any tips ?
To describe the use-case more,
We actually have a freemarker macro, exposed via Java Tag which takes in dynamic attributes. I want to be able to call this macro, and provide the parameters to it dynamically.
There's no language feature that does quite that. There are two possibilities that do something similar:
One is simply passing an FTL hash (like a Map) to the macro, like <#myMacro params={'a': 1, 'b': 2}/>. In this case the parameter value expression can also be a Map dynamically created in Java.
The other is defining a macro like <#macro myMacro p1 p2 otherParams...>, in which case <#myMacro p1=11 p2=22 a=1 b=1/> will pass in {'a': 1, 'b': 2} as otherParams. In this case, however, you can't pass in an externally constructed hash as otherParams.

What is the difference between ByRef and Output method argument modifiers?

All is in the subject, really.
I fail to see what the difference in behavior is between those two methods for x:
// first version
Method m(ByRef x As whatever)
{
// play with x
}
// second version
Method m(Output x As whatever)
{
// play with x
}
There must be some reason why both those modifiers exist, however my "mastery" (uhm) of the language is not enough to understand the difference. I have tried and read the documentation, search it etc, to no avail so far.
So, what is the difference between those two argument modifiers?
Well those are just "prettifiers", they don't do much in terms of actual language behaviour, and only used to provide documentation. Idea is that arguments documented as ByRef provide both input and output, for example you can pass an array to be sorted, and Output arguments only provide output, for example list of errors. Output modifier was introduced later, and a lot of system code still use ByRef for both use cases.
If argument is actually passed by reference is only determined by method caller, and keyword doesn't really matter. You will call your method as ..m(.parameter) to pass variable by reference, and ..m(parameter) to pass variable by value.

What is the definition of a 'helper' in CodeMirror registerHelper method

I am looking at CodeMirror help and registerHelper is described as
CodeMirror.registerHelper(type: string, name: string, value: helper)
Registers a helper value with the given name in the given namespace
(type). This is used to define functionality that may be looked up by
mode. ...
http://codemirror.net/doc/manual.html#registerHelper
This does not explain what the value is, when is it called (it seems to be a function), or why getHelpers accepts a position.
Is helper similar to a mode, but providing non-visual annotations (for code lookups)?
It's just a value -- any value. How it will be used depends on the type of helper. For "hint", it'll be a function providing completions at a given point in a document, for "hintWords", it'll be an array of strings that form possible completions, for "wordChars", it is a regular expression describing the characters that count as word characters for a mode, and so on.