Parameterised Transclusion [TW 5.3.0]: Why is Function Called Function?

No problem. I think there is no difference from recursion point of view! But let one of developers perhaps @jeremyruston reply this specific question.

Side note: Like @Scott_Sauyet I believe @Mark_S just jocking with “You know why function is called function? Because it’s recursive! :wink:

Man, I wish somebody had replied that to me right away. Because this was turning into a real “cognitive overload” nightmare for me. Better late than never.

I think the OT and the resulting banter is a result of the ambiguity in the terms adopted in 5.3.0 which I tried to influence during its design, the following terms are all quite similar in English and quite specific in TiddlyWiki and carry with them baggage inherited from other languages.

  • function
  • procedure
  • macro
  • widget
  • Parameters

For those involved with the development of parametrised transclusions it may all appear self evident, but for most users it will not. The “horse has bolted” on this naming, but now we need to provide informed overviews and definitions to assist in adoption and understanding.

I understand the question “Why is Function Called Function?” but would suggest the safest answer is “because it was chosen”. Similarly with other new terms. For example “Why is Procedure Called Procedure: perhaps because it not a called macro?”

Now we need to construct an understanding of what these terms meaning within TiddlyWiki and how we use them.

Here is my attempt

  • function - A function is a named snippet of text containing a Filter Expression, which can also be used as a filter operator when named with a leading period “.filteroperator
  • procedure - A newer version of the macro with different parameter handling, and can now be transcluded
  • macro - the existing method using \define macros.
  • widget - allows you to define new or overriding versions of existing widgets. It is but a procedure by another name but with a particular syntax, as in core widgets.
  • parameter - additional parameter handling in procedures and widget definitions

Ways to remember these may be;

  • Function - Starts with F so think of filters and filter operators (using period ‘.’)
  • Procedure - Starts a with P so think of parameters, different parameter handling to the legacy define/macro.
  • Parameters - Starts a with P so think of using in Procedures and Widgets (a type of procedure?)
  • Macros - Starts with M, so comes before P(roceedure) the way we used to “\define”.

Finally, with the exception of widgets, all of the above exist as variables so we typically use the form <<variable>> or <<macroname>>,

  • but when we wanted more advanced parameter handling in the past, we would make use of the <$macrocall $name=macroname widget.
  • Since Procedures now have different “Parameter Handling” the macrocall widget has being deprecated and we now use the <$transclude $variable="proceedurename" widget
  • Perhaps we need a synonym for this, the <$proceedurecall or $call widget.

What do you think?

4 Likes

Perhaps these names show their heritage from programming languages in general, but they are not specific to particular languages. While not universal, they are extremely common programming terms. I’m still not well-versed enough in the parameterized transclusion to know exactly how well these constructs match the common names, but for perspective, here’s a programmer’s view of what the terms mean. (Caveat: I’m a working programmer, not a programming language experts; their views may be slightly different.)

  • A function is a callable snippet of code that accepts parameters and returns one or more values.

  • A procedure is a callable snippet of code that accepts parameters and performs some actions.

  • A macro is a reusable snippet of code that will be substituted in place of its name before the code is run. It may also accept parameters, whose values may also become part of the expanded source code.

  • A widget is an encapsulated bit of data and behavior, generally associated with a graphical user interface. Parameters might be used in their creation, but are less central to them.

  • A parameter is the association of a name used in a callable snippet of code with the value passed when that snippet is invoked.

Functions and procedures are ephemeral. Although they can be called over and over, they don’t hold any state. (This is not technically true – see closures – but is close enough for these purposes.) The difference between them is that procedures are about taking actions, and functions about returning values; but many languages (including JS) conflate these two notions. Macros are a bit different, as at runtime, after the substitution has occurred, their expansions become part of the source code. And widgets are different still, as they hold run-time state and have observable UI behaviors.

Again, it’s not clear enough to me how closely the new TW terms associate with these notions, but I think macro and widget are already close matches; I would expect function and procedure to do so too, but haven’t learned enough to confirm that.

2 Likes

Although I find these new tricks in TiddlyWiki very confusing, I see how the great majority (or everybody except me) will appreciate functions because it helps with conciseness.

To illustrate the difference (between function in the OP and the snippet below), showing why most should appreciate functions over macros (I much prefer this approach because of the verbosity; it is clearer to me what is going on):

\define eff(date) [!is[system]]:filter[get[created]split[]first[4]join[]compare:number:gt[$date$]]

<$macrocall $name="list-links" filter=<<eff 2022>>/>

So far, from what I’m seeing, I’m not sure functions and procedures in TW ought to be defined that way.

Each of them (function, procedure, macro) seems to be a reusable snippet of text that will be substituted in place of its macro/function/procedure reference before a tiddler is rendered. A macro/function/procedure reference may also include parameters, whose values will become part of (or play a part in) the resulting substitution .

(Which doesn’t surprise me because TiddlyWiki is a transclusion heavy-weight champ.)

The only difference I’m seeing is in the ways they are constructed and where/how they are applied.

There’s probably nothing inherently horrible about framing an understanding of functions and procedures in TW as one would with an imperative programming language, but that might make troubleshooting problems awkward/challenging. When doing something extraordinarily complex, whatever behavioural expectations one may have (from an imperative programming language perspective) could be confounded a bit if one isn’t thinking with a (pristine?) “transclusions-grounded” mindset.

But all of these thoughts of mine could be complete bunk if I’m completely misunderstanding functions and procedures. For all of the ranting/raving and fawning over them, I really don’t get it.

No need to use $macrocall, you can use subfilter like below

<<list-links "[subfilter<eff 2022>]">>

If this date is given through a variable or transcluded from a tiddler field how your macro will work?

Assume the date is stored in mydate field in current tiddler. The function will handle this easily like below

<<list-links "[.f{!!mydate}]">>

I never use the list-links macro. Whenever I need something like that, I build the thing that does what I need and works how I need it to work. (and displays all of the pieces I need to see to understand what I’m looking at; it it has all of the puzzle pieces that are in my head, I recognise it; if it is missing pieces, then it does not match what is in my head, and I get into paralysis by analysis trying to figure out what is missing.)

Multiple cognitive problems over here, so how I process and organise things will never make sense to anybody else. When I don’t see all of the pieces in a way that I can process (that matches the intertwingled mess in my head), I do not understand what I’m looking at.

For the giggles though, just because it is a fun exercise…

Assuming the tiddler containing the following TWscript is the one with the “mydate” field with a value of 2020:

\define effList(date)
<$macrocall $name="list-links" filter="[tag[HelloThere]]:filter[get[created]split[]first[4]join[]compare:number:gt[$date$]]"/>
\end


!! One

<$macrocall $name="effList" date={{!!mydate}}/>

!! Two

<<effList 2020>>

<<effList 2020>> is much easier on my head (easier to remember syntax) than <<list-links "[.f[2022]]">>

<$macrocall $name="effList" date={{!!mydate}}/> is verbose, but the syntax is still much easier for me to remember than <<list-links "[.f[2022]]">>

I am not trying to discourage folk from getting all hyped-up on these new TW features. The features just do not offer anything of benefit to me. They are just gumming up the works in respect to how I process and recognise things.

If anything, I’m largely frustrated because I want to get excited, but it is all a semantically overloaded cognitive gong-show for my abilities.

I hope that in time, once we digest the meaning and values we may have some methods that can help. There are features within the current version such as subfilters, which are only improving from 5.3.x, that stand to make thinking about filters simpler.

  • Watch this space

Anything is possible at any time.

However, mine are dysfunction-avoiding necessities. I only make a switch/upgrade when it hurts too much not to switch/upgrade.

  • If anybody takes a deep-into-the-weeds look at anything I’ve done, I use only a particular subset of TW features in 5.2.3 and earlier, because I much prefer master a small subset of features that let me do all I need, rather than be distracted by too many choices and be master of none.

  • Travel light (use only what’s necessary, and ignore the rest) and use the “simplest” features (to me: the core “rudiments”, they are the fundamental blocks from which all other things can be built.)

I like to learn and embrace new things, but my too-long-for-one-lifetime list has way more wildly interesting and useful stuff in it.

@Charlie_Veniot and all

I understand, I will only encourage you to look at something new if I think it may help you. As I have said before these issues tend to be on a spectrum, one of which I may also be on, perhaps just at the other end :nerd_face:

et al

In this particular case I am interested in what we may call “named filters”, or “named filter operators”. That is, design a simple filter or operator and give it a name. Then later reuse it and if necessary combine with others, such that they remain simple.

  • Thus it should be simple to define some atomic filters
  • and relatively simple to combine some atomic filters to get a result,
    • while keeping them looking simple, even look like “plain language”.

Oh for sure, if and when it helps me do something that hurts too much to do otherwise, then I’ll be on the latest TW like white on instant rice.

1 Like

I’m not a fan of subfilter, and will only use it if I really don’t have any choice.

The sample TWscript I presented, I see the parts clearly. "[subfilter<eff 2022>]" is too messy for me (the syntax is too busy.)

I need to use $macrocall. It makes sense to me. The parts of it are clear (well delineated, non-distracting.)

I do not process things like anybody I know of. I’ve carefully curated the TiddlyWiki features to the ones that work well for me and I have banished those that don’t fit the way I operate (they are sticks in my wheels and mud for my wheels to get stuck in).

A wonderful example by @xcazin has been given in GitHub which is quite interesting.

See

\function .frame(begin:"[[",end:"]]")
[addprefix<begin>addsuffix<end>]
\end

<$list filter="""[[Hello].frame[]]
[[Hello].frame[<<],[>>]]
[[Hello].frame[{{],[}}]]
[[Hello].frame[`],[`]]
[[Hello].frame['],[']]
[[Hello].frame["],["]]
""">
<$text text=<<currentTiddler>>/><br>
</$list>

Produces

[[Hello]]
<<Hello>>
{{Hello}}
`Hello`
'Hello'
"Hello"

The .frame custom filter operator created by function, wraps your input into given chars.

To give a try

Give your example, if you made a different example

3 Likes

This will be nice worked into an editor toolbar button.

A minor change turns a function into an operator by having a period “.” anywhere in the name, not just a leading period. As a result I threw this togather on the prerelease.

\function .has.changed() [all[shadows+tiddlers]haschanged[]]

`{{{ [.has.changed[]] }}}`

{{{ [.has.changed[]] }}}
<hr>

* `{{{ [<.has.changed>] }}}` {{{ [<.has.changed>] }}}
* `<<.has.changed>>` <<.has.changed>>
* `<$text text=<<.has.changed>>/>` <$text text=<<.has.changed>>/>

This illustrates how even a function can be referenced as a variable, like a macro.

Notes

  • See how only the first result is returned at the bottom below the line examples?
  • see how <<.has.changed>> returns the plain text result and it is no different from using the text widget.
    • At least when you want the first entry as text only this is nicer than
      • <$text text={{{ [<.has.changed>] }}} />

Wether or not you concider the new function a function in a programing sence it must be emphasised it is as far as TiddlyWiki filters are concerned. It is not a generic function, but it is one that unleashes filters as functions not to mention making custom filter operators with parameters.

  • Filters are a core feature and strength of tiddlywiki despite there somewhat bespoke nature.
  • Filters are in many ways a 4th Generation Programing language feature, which can simplify the use of lists/sets/tiddlers/reports/queries and text manipulation.
  • the new function liberates filters even further.
1 Like