Concepts for function/procedure/widget-namespaces

Hi,

for my current TW5-development, clear namespaces (on function/procedure/widget level) would make things (most likely) much easier. I’m currently only aware of the possibility to put them into each other (by stating the name again after \end). But this is just “hiding information” because you cannot directly reach the inner func/proc/wid from outside.

I would like to have namespacing where i can trigger behavior (not directly talking about “inner state”, even if that would be nice too) in a classic OOP-way (like outer.inner).

Is there any (non JS) concept in TW5 that i oversee/misunderstand in the current state of TW5?
Is there anything planned in that direction for the near future?

Thanks,
Mirko

1 Like

As so many things in TW it will be a “convention”. Currently, we use a tf. prefix for global functions, which will be reserved for the TW core.

Using tf. t-f-dot over t-f-hyphen, has the advantage that functions can be used directly as tf.my-function[] in filter expressions, without the need to use the function[tf-my-function] operator.

The naming schema is similar to tc-, tm- for TW class and message prefixes …


So the f. prefix is free for users. So I personally will use f.functionName for my own functions, that are not part of wikilabs plugins.


For wikilabs plugins I will probably use wltf. or wlf. prefix for global functions as I use wltc- for class names.


Currently while refactoring core wikitext syntax, there was no need to create new prefixes for procedures or widgets.

If it has a $-prefix eg: $something it is a widget. So no need for special naming, except in libraries, where it depends on the usecase.

If it has no prefix, it is a procedure or a macro. Where macros are deprecated, and will be removed over time from the core, while keeping the name and parameter signatures compatible.


There is an other unofficial naming convention. Eg: _something. Variable names, that start with an underline, is meant to be used local only and should not be modified or relied on externally.

Locally used variables, even if they have a global scope, will be changed in incompatible ways, without warning.

Just my thoughts
Mario

1 Like

Hi Mario,

sorry for the confusion (your answer was interesting to me though), but i’m not talking about naming things but “creating encapsulated namespaces”. To give an example, the only TW-possibility to encapsulate something currently known to me is like this:

\function outer()
\function inner1()
...
\end inner1
\function inner2()
...
\end inner2
\end

where inner1 can only be directly used from within outer. Here i’m currently not able to call inner1 from outside because outer is basically just “hiding” it from the outside. I’m searching for a way to call inner1 or inner2 from outside directly, like f.e. outer.inner1 does for other object oriented programming languages. From my understanding that (or something similar) is not possible with TW5 on that function/procedure/widget-level right now, correct?
Anything planned here for the future?

Thanks,
Mirko

The nested functions and procedures have only be implemented, to create true local variables, that are protected from the outside. So from an OOP point of view they are private variables.

That’s by design


TW wikitext basically is a string based templating system. It is not compiled. Most of the time the stuff is a “big text substitution” engine, with some magic here and there. Eg: The parse-tree is cached for faster access.

If you have a look at the following screenshot, you can see the widget-tree. So you can see, only the outer function is parsed and converted to a variable. The inner part is “evaluated” once the outer function is used.

There is no way to “access” the inner function, because it is not really known upfront. Also the inner function will have no ideas about other variables, that are created inside “outer”, which may be used by the inner code.

The same is true for the cached parse-tree.

JavaScript is a functional programming language. It does not really know about OOP mechanics. The lately implemented Class system is syntactical sugar and not really object oriented programming.

Since TW wikitext needs to use the underlaying JS object structure, so it is kind of “functional” by design too.

Hi all,

Based on the documentation on tiddlywiki.com and also on my own tests, functions can only be nested inside procedures or macros, but not inside functions, which IMHO is a pity.
I’d very much like to be able to hide utility functions inside public functions without making inner functions available from the outside.

Fred

Very interesting idea, and I think completely doable. Perhaps multiline functions are an opportunity to learn other new techniques from other comparable query languages like SQL or XPath.

4 Likes

Elaborating on my previous message, here is some code to illustrate the concept:

Original, working code:

<!-- Utility functions, using datetimelocal inherited parent function parameter value -->
\function fn.iso2twdate()     [<datetimelocal>split[T]first[]split[-]join[]]
\function fn.iso2localhours() [<datetimelocal>split[T]last[]split[:]first[]trim:prefix[0]]
\function fn.iso2minutes()    [<datetimelocal>split[T]last[]split[:]last[]]
\function fn.iso2offset()     [<fn.iso2twdate>addsuffix[120000000]format:date[TZD]split[]nth[3]]
\function fn.iso2utctwhours() [<fn.iso2localhours>subtract<fn.iso2offset>pad[2]]
 
<!--
          Transforms an ISO local date, as returned by a "datetime-local" edit widget, to an UTC TW formated date
 
          WARNING! This function does NOT work for all input dates, assertions are:
           - French metropolitan timezone, with or without DST,
           - during working hours: will not work between 0:00 and 2:00 am
-->
\function fn.datetimelocal2utc(datetimelocal)
   [<fn.iso2twdate>addsuffix<fn.iso2utctwhours>addsuffix<fn.iso2minutes>addsuffix[00000]]
\end

Here is what I whish it would look like:

<!--
          WARNING! Below code does NOT work!
-->

\function fn.datetimelocal2utc(datetimelocal)

<!-- Local utility functions, using datetimelocal parent function parameter value -->
\function fn.iso2twdate()     [<datetimelocal>split[T]first[]split[-]join[]]
\function fn.iso2localhours() [<datetimelocal>split[T]last[]split[:]first[]trim:prefix[0]]
\function fn.iso2minutes()    [<datetimelocal>split[T]last[]split[:]last[]]
\function fn.iso2offset()     [<fn.iso2twdate>addsuffix[120000000]format:date[TZD]split[]nth[3]]
\function fn.iso2utctwhours() [<fn.iso2localhours>subtract<fn.iso2offset>pad[2]]

<!-- Main function code -->
   [<fn.iso2twdate>addsuffix<fn.iso2utctwhours>addsuffix<fn.iso2minutes>addsuffix[00000]]
\end fn.datetimelocal2utc

Fred

1 Like

While this is very different from what the OP was requesting, it’s exactly what I would like to have!

An alternative that would work well for me is to have some version of export in place of $:/tags/Global / $:/tags/Macro.

Then I would define module-local functions, procedures, macros, whatever, and export only the functions I want to make public. No nesting required.

1 Like