A beginners question about nested macros

115 views
Skip to first unread message

Joe Armstrong

unread,
Jan 19, 2019, 2:59:55 PM1/19/19
to TiddlyWiki

I have two macros 

\define text()
A line of text
\end

\define foo(x)
fooStart $x$ fooStop
\end

So

<<text>> is replaced by  "A line of text"

and 

<<foo "abc">> is replaced by "Start abc fooStop"

But <<foo <<text>> >>

is replaced by "fooStart <<text fooStop >>"

And NOT "fooStart A line of text fooStop" as I had expected.

After a lot of head scratching I realised that this means that the argument (x) to foo is the
string "<<text" ie the first occurrence of ">>" to the left
of the start "<<" of the macro and not the second occurrence. 

ie. "<<" and ">>" do not properly nest as I had expected.

This seems like a pretty big pothole for a beginner to fall into ...

So what is the accepted idiom for using a macro result
as the input argument to another macro - how does one chain macro calls together?

Cheers

/Joe

Mohammad

unread,
Jan 19, 2019, 3:53:08 PM1/19/19
to tiddl...@googlegroups.com
Use it as below.

<$macrocall $name=foo x=<<text>> />


But this is not nested macro! By nesting it means a macro inside another macro as internal macro.
Seems this is not possible in Tiddlywiki.


Not directly related but useful

TonyM

unread,
Jan 19, 2019, 7:01:12 PM1/19/19
to TiddlyWiki
Joe,

Using Mohamads suggestion of using macrocall is one way to pass a value to a macro when that value comes from another macro or variable. It is however possible to reference the value in <<text>> without putting it in the parameters as $(text)$ (inside the macro)

\define foo()
fooStart $(text)$ fooStop
\end

As long as you have set <<text>> this will work.

There are ways to test if text is set and provide a default value if it is not as well.

Regards
Tony

Jeremy Ruston

unread,
Jan 20, 2019, 10:31:41 AM1/20/19
to tiddl...@googlegroups.com
Hi Joe

As you've discovered macro calls don't nest. It's intentional: for the shorthand syntax we prefer conciseness over flexibility.

<<macroname param-one:"alpha" param-two:"beta">>

is actually sugar for

<$macrocall $name="macroname" param-one="alpha" param-two="beta"/>

With the full widget syntax you can then do things like this:

<$macrocall $name="macroname" param-one=<<my-other-macro "something">> param-two="beta"/>

If you want to pass the wikified output of one macro to another then you'd need to use the wikify widget.

Best wishes

Jeremy


--
You received this message because you are subscribed to the Google Groups "TiddlyWiki" group.
To unsubscribe from this group and stop receiving emails from it, send an email to tiddlywiki+...@googlegroups.com.
To post to this group, send email to tiddl...@googlegroups.com.
Visit this group at https://groups.google.com/group/tiddlywiki.
To view this discussion on the web visit https://groups.google.com/d/msgid/tiddlywiki/2f55a6b2-cf48-4550-94f6-4b0955bc5d5c%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Joe Armstrong

unread,
Jan 20, 2019, 11:58:09 AM1/20/19
to tiddl...@googlegroups.com
On Sun, Jan 20, 2019 at 4:31 PM Jeremy Ruston <jeremy...@gmail.com> wrote:
Hi Joe

As you've discovered macro calls don't nest. It's intentional: for the shorthand syntax we prefer conciseness over flexibility.

<<macroname param-one:"alpha" param-two:"beta">>

is actually sugar for

<$macrocall $name="macroname" param-one="alpha" param-two="beta"/>

Now you tell me :-) 

With the full widget syntax you can then do things like this:

<$macrocall $name="macroname" param-one=<<my-other-macro "something">> param-two="beta"/>

If you want to pass the wikified output of one macro to another then you'd need to use the wikify widget.


I'd wondered why.

I think this point needs emphasising - coming from virtually
any programming langage one expects that function calls
to be nestable the BIG surprise was that "<<" ">>" didn't have to be properly balanced and that the scope of the macro was not what I thought it was.
 
I guess this is not changable now - since it would break
all old macros.

Actually to make macros composable it would be
very nice to pipe the output of the first macro into a second.

This is done in the language 'elixir' using the notatation '|>'
to represent a pipe operator.

In TW you could think of writing:

    <<macro1 .. args>> |> <<macro2 arg1 arg2>>

which means take the output of <<macro1 ... args>>
stick it into a temporary variable (say t1) then evaluate
<<macro2 t1 arg1 arg2>>

The pipe operator injects the result of the first macro into the
first argument of the second macro.

This is actually very nice - since it eliminates nested function calls.

So things like:

f(g(h(i(X))) become pipes like this:

i(X) |> h |> g |> f

And I guess it would not break old code - since old code would
never have used a |> symbol :-)

I'm not sure if this is possble - but a pipe notation often beats
nested function calls for simplicity :-)

And pipes are nice as abstractions for different reasons.

Cheers

/Joe


     
 
    
      


 
You received this message because you are subscribed to a topic in the Google Groups "TiddlyWiki" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/tiddlywiki/MHRIdRaJqDs/unsubscribe.
To unsubscribe from this group and all its topics, send an email to tiddlywiki+...@googlegroups.com.

To post to this group, send email to tiddl...@googlegroups.com.
Visit this group at https://groups.google.com/group/tiddlywiki.
Reply all
Reply to author
Forward
0 new messages