"function" filter op

I am in tw 5.3.1 node version. Reading the official doc, I see the new “function” filter op.

There is not a single example though. And not much explanation about it.

I understood that for the filter [[one two three]function[grab],[2]] it would call the regular “grab” function with arguments “one two three” and “2” and returns the output of the grab function.

OK, complete example below:

\define grab(input, rank)
<$let res = {{{ [enlist[$input$]nth[$rank]] }}}><<res>></$let>
\end


<$let a = "one two three"
b = {{{ [enlist<a>function[grab],[2]] }}}
>
<<b>> IS <<grab "un deux trois" 2>>
</$let>

The output is “one IS deux” instead of “two IS deux”.

What is going wrong? I am pretty sure that “grab” is not called within the filter. “one” is just the value for b = {{{ [enlist[one two three]] }}}

Also, I have not understood what [[enlist[one two three]function[grab],[2]] should do.

I think we need to grow into these new features, the trick is finding when and how best to make use of this. Some quick tips;

  • Functions can only be created as follows
    • \function functionname(input, rank) [enlist<input>nth<rank>]
  • They contain only filters
  • The parameters are only available as variables <varname>
  • Once defined <<functionname>> only returns the first value
    • Although there are ways around this to store a list
  • They can be used as a function as you did above
  • Define with a dot in the title, and you can use it as a custom operator
    • \function function.name(input, rank) [enlist<input>nth<rank>]
    • thus use in a filter [function.name[]] or [function.name[input],[rank]]
    • Of course usage is dependant on how you design the function

But your actual problem may not need a function, try this nth operator;

<$let a = "one two three"
b = {{{ [enlist<a>nth[2]] }}}
>
2nd IS '<<b>>'
</$let>
  • just an example vary as needed.
  • Eg you could use [enlist<a>nth<varname>] or [enlist<list-var>nth{!!fieldname}]

Functions are in fact wonderful and I plan to publish from my extensive set of notes and example I have collected offline. I do not think it exaggeration they are revolutionary in their uses.

It is worth the time to learn about them in detail.

Hi @jypre first of all, functions are defined with \function, not \define, which is used to define old-style macros.

All functions and filter operators take explicit arguments (given after the function/operator), and the input list which acts as an implicit argument. In other words, your grab function doesn’t need to explicitly take an input parameter. Instead you should be able to use something like:

\function grab(rank)
[nth<rank>]
\end

<$text text={{{ [enlist[one two three]function[grab],[2]] }}}/>

The “enlist” operator parses its parameter as a title list and returns the result.

According to the Function documentation.

If a function name contains a dot eg: fn.grab it can be activated using its name only. Which make it more abstract. To compensate the increased abstraction I did use a fn. prefix for the function name, which should make it more verbose again.

\function fn.grab(rank) [nth<rank>]

<$text text={{{ [enlist[one two three]fn.grab[2]] }}}/>

@jeremyruston Thank you for this information. Now all is clear.
@pmario Thank you for this trick too.
@TW_Tones Thank you for both things. But your function definition has explicit “input” parameter while @jeremyruston and @pmario do not ?

As for my very real problem, it was a bit more complex. I was just wanting a simple function for my question.

And I too think that function will simplify a lot of my code. And in fact, my current code is broken, seemingly because a field is not written when I read it, although I had used the $action-confirm widget. Using only filter make this field unnecessary and overall code much simpler. With functions, a filter can always be made, perhaps with an ad-hoc filter operator coded in javascript. I think that’s a good trade-off.

1 Like

I keep having problems with function. With the input of the filter. the doc for “function operator” really REQUIRES a functionning example. The doc for “functions” too.

OK, here is tiddler where the intended result is correct. but… the input within the filter is not used.

\function .grab(input, rank) [enlist<input>dump[list for],<rank>nth<rank>dump[got]]

<$let a = "one two three for"
b = {{{ [[nothing].grab<a>,[2],[71]dump[res]] }}}
>
<<b>> IS <<.grab "un deux trois" 2>>
</$let>

We get “two IS deux”. But the “input” variable of the function is fed as the first parameter of the filter op .grab and if that’s correct then surely the “input” name in the doc is the culprit for my error.

I’m sure this is the cause of my still being puzzled. But that would mean that functions ere not filter operators. Be or be not, let that also be expressly written in the doc because it’s an important thing to know.

Oh, and for my original problem, I finally wrote a custom filter operator in javascript. It was so easy. But I will speak of it in an other topic because it gave me an idea for improvement.

I was just illustrating according to your example, and showing if you have the input you need to use it as a variable <input>, rather than $input$.

  • My fully worked solution was the one using the nth operator.
  • One word of warning currently the functions are not necessarily updated in the editor, if unsure save and reopen the tiddler.
  • When using functions, triple curly braces and the new backtick forms $( and ${ they only return the first result (although there are tricks for lists)
  • This is three parameters but you define only two input, rank
  • I am not sure what dump is
  • As they say a man with a hammer see’s everything as a nail.

I hope the above notes help you, but I don’t understand enough of your issues to help much more, but will if you ask.

  • I am, confident I have a 95%+ understanding of functions, so I am available if needed.

@TW_Tones Than you. Yes you finished enlightening me.Things are clear about functions for me now.

As for dump, it’s a debugging custom filter that display the input in the filter on the javascript console. Very handy. I could propose the code for submission. I use it for a very long time now.

As for my third parameter: this was just an attempt to really persuade me that no filter input were used. And it showed that you can put more parameters than in the function parameter without any problem (above that it is in itself a source of later bugs).