How Would You Compare Metaprogramming in Julia and Tcl?

Hi folks! :wave:

I had a very interesting discussion today with an actual Tcl programmer (never met one before!). He and I were discussing a domain specific language (DSL) he had created in Tcl that had syntax that looked something like this:

I wish this was $blue

Which would produce a little png that prints the exact same Tcl code and changes the color of the text to blue. He had found that writing DSLs in Tcl was very easy given that everything was treated as a string. Additionally, with his DSL, he was trying to keep the semantics and syntax very close to the English language which he found Tcl well-suited to do.

When he found out that I was a Julia programmer, he was very curious – he said that if Julia was better at creating DSLs he’d probably give Julia a serious look. In my mind, I see replicating this sort of syntax as somewhat a challenge but could be done with Julia’s metaprogramming support and tools within the ecosystem. Now, as I am not a Tcl programmer, I was wondering if folks could help me with thinking through the following questions I had:

  1. How is metaprogramming within Julia and Tcl similar?
  2. How is metaprogramming within Julia and Tcl different?
  3. Would you say that metaprogramming within Julia is easier than Tcl?
  4. How does metaprogramming within Julia compare to Tcl?

I tried googling around to answer these questions but the intersection of Tcl programmers and Julians is very small. I found a few perspectives like this: Julia Programming Language where Tcl-ers seemed positive on Julia but other than that, it’s very sparse.

Could anyone help me with understanding this space better?

Thanks,

~ tcp :deciduous_tree:

P.S. I found some Tcl-ers in the Julia Discourse so I am CC’ing them in case they want to comment (sorry if this is rude to ping you!): @lmiq @jessymilare @goncharovdk @lkadgrjh

I know nothing of TLC and I am not even a programmer, but if it is true that in TLC “everything was treated as a string”, then it is a very different approach to Julia metaprogramming where “everything is an expression”…

1 Like

This reminds me of non-standard string literals, which is really just an abbreviated macro taking in a standard string literal. Metaprogramming usually goes from Julia expression to expression, which is flexible but still constrained by the AST; for example, the expression :(1 + * 1) does not have a valid AST structure, so an attempt throws an error. You can get around that if you start with strings and take the responsibility of parsing and evaluation. This is standard practice for embedding other languages’ source code in Julia files, though in the case of interpreted languages like Python and R, not much happens to the string, it’s just evaluated in a running interpreter.

Point is, it can get as flexible as you like, but whether it is as easy as TCL I have no idea, I tried looking up some demonstrations of DSLs in TCL but I couldn’t find a straight answer on how flexible the metaprogramming is or whether it’s more like text-substitution or syntactic macros (roughly, working with strings vs structured expressions).

1 Like

As of 1.9 Julia’s non-standard string literals aren’t as flexible as they could be, because of their current behavior around nested quoting and escaping. That is, " is the same character for both opening and closing a string, so nesting is awkward. The solution proposed in this issue is a paired delimiter syntax like

htl⟪
  <table><caption><h3>Selected Books</h3></caption>
  <thead><tr><th>Book<th>Authors<tbody>$(htl⟪
    <tr><td>$(book.name)<td>$(join(book.authors, " & "))
    âź« for b in books)</tbody></table>âź«

Personally not sold on that proposal because

  1. another delimiter would have its own character nesting and escaping problems.
  2. it doesn’t seem accurate to lump all non-standard string literals together because the macros themselves do parse the input strings differently. raw_str actually does nothing to an input string, so the standard string does other things on top of that, like $-interpolation.
  3. preserving the nested text of non-standard strings seems inconsistent with how I expect macros to work. It can be useful, especially for other language’s nonstandard strings, but that could be implemented as part of the particular macro’s parsing (maybe it makes $ or some other special characters exclude text from special parsing) and isn’t always what I’d want. If I do remove_all_b""" printbln(b"hellob, bworld") """, I expect all the b’s to be removed """ println("hello, world") """, no matter what delimiters replace the quotes. This isn’t particular to non-standard strings, standard strings do things to nested text:
julia> x = "whoops"
"whoops"

julia> "$x", raw""" "$x" """ # nested standardness not preserved
("whoops", " \"\$x\" ")

julia> raw"$x", """ raw"$x" """ # nested rawness not preserved
("\$x", " raw\"whoops\" ")

julia> y = raw"$x"; "$x $y" # but standard literals can interpolate
"whoops \$x"

But this is quite a tangent from the Tcl thread, should be its own thread or conversation.

1 Like

As for me, I never used meta programming neither in TCL or Julia, so I cannot contribute.

TCL for what I used it, is a scripting language which integrates well with external programs (awk, sed, etc), but I never saw it as a programming language for more than that.

1 Like

This is old, but a good quick overview. Also this which has roots in MIT, before the Software Engineering for Internet Applications book and course. First came into contact with Tcl while learning OpenACS, the Millennium Falcon of web frameworks.

3 Likes

You can do something similar in Julia:

julia> macro _(args...)
           (args..., )
       end
@_ (macro with 1 method)

julia> @_ I wish this was $blue
(:I, :wish, :this, :was, :($(Expr(:$, :blue))))
2 Likes