# Making a DSL for building a UI component tree?

**URL:** <https://discourse.julialang.org/t/making-a-dsl-for-building-a-ui-component-tree/72914>\
**Category:** New to Julia\
**Created:** [December 10, 2021, 9:55pm UTC](https://discourse.julialang.org/t/making-a-dsl-for-building-a-ui-component-tree/72914 "2021-12-10T21:55:49Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![RobertN](https://avatars.discourse-cdn.com/v4/letter/r/f0a364/32.png) [@RobertN](https://discourse.julialang.org/u/RobertN)\
**Post date:** [December 10, 2021, 9:55pm UTC](https://discourse.julialang.org/t/making-a-dsl-for-building-a-ui-component-tree/72914/1 "2021-12-10T21:55:49Z")

</div>

I’m new to Julia. I’m experimenting with using it for a native macOS app (wrapping the native AppKit classes). Lately I’ve used both Apple’s SwiftUI and Android’s Jetpack Compose. They have DSLs for UIs that are very similar, and they do a nice job defining the tree structure of a UI in a clean and declarative way. Here’s some sample pseudocode to give a sense of what it looks like:

```julia
MyPanel {
    Button("Foo") { print("clicked") }
    List(data: items) { item -> 
        HStack {
            Text(item.name, font: .large)
            Image(item.thumbnail)
        }
    }
}

```

Most of those elements would map to objects (`NSView` subclasses on macOS) that form the nodes of a tree.

The languages (Swift, or Kotlin) have different ways to translate this syntax, but the overall look is similar. How could I do something similar in Julia?

I see Julia has macros (Lisp style, real macros), so I could do that. In that case, would the curly braces above end up as `begin` … `end`. That seems a bit verbose. Is there way to create something that looks like the above – minimal keywords and boilerplate, and clearly showing the nested tree structure?

I know this is partly a subjective issue. I just like the look of the SwiftUI/Compose style. I’ve been using curly brace languages most of my life 🙂 (C, C++, Java, Swift, etc.)

---

<div class="post-metadata">

**Author:** ![Jeff\_Emanuel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff_emanuel/32/15440_2.png) [@Jeff\_Emanuel](https://discourse.julialang.org/u/Jeff_Emanuel)\
**Post date:** [December 10, 2021, 10:32pm UTC](https://discourse.julialang.org/t/making-a-dsl-for-building-a-ui-component-tree/72914/2 "2021-12-10T22:32:36Z")

</div>

The input to a macro needs to be acceptable to the Julia parser. The parser will accept curly braces at least as deprecated vector syntax or for specifying type parameters. This seems to be acceptable:

```julia
julia> macro dummy(args...)
         println(typeof(args)); println(args)
         return :()
         end

julia> @dummy Panel {
         Button("Foo")
         }
Tuple{Symbol, Expr}
(:Panel, :({Button("Foo")}))
()

```

Your example text failed for me at `.large`:

```julia
julia> @dummy MyPanel {
         Button("Foo") { print("clicked") }
         List(data: items) { item ->
           HStack {
             Text(item.name, font: .large)
ERROR: syntax: invalid identifier name "."
Stacktrace:
 [1] top-level scope
   @ none:1

```

---

<div class="post-metadata">

**Author:** ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)\
**Post date:** [December 10, 2021, 10:36pm UTC](https://discourse.julialang.org/t/making-a-dsl-for-building-a-ui-component-tree/72914/3 "2021-12-10T22:36:35Z")

</div>

With macros you can make the DSL look any way you want.

```julia
@mydsl MyPanel(
    Button("Foo")( print("clicked"))
    List(items)( item -> 
        HStack(
            Text(item.name, font = :large)
            Image(item.thumbnail)
        )
    )
)

```

```julia
@MyPanel(
    @Button("Foo") print("clicked") 
    @List(items)( item -> 
        @HStack(
            @Text(item.name, font = :large)
            @Image(item.thumbnail)
        )
    )
)

```

The only thing that’s actually making use of macros there is the `print("clicked")`, since that would evaluate eagerly.

If you want it to be plain non-macro julia, a few options come to mind off hand using a declarative style.

```julia
# curried parameters
MyPanel(
    Button("Foo")(Print("clicked"))
    List(data=items)( item -> 
        HStack(
            Text(item.name, font = :large)
            Image(item.thumbnail)
        )
    )
)

```

```julia
# uncurried parameters
MyPanel(
    Button("Foo", Print("clicked")),
    List(items, item -> 
        HStack(
            Text(item.name, font = :large),
            Image(item.thumbnail),
        )
    )
)

```

```julia
# swapped parameters
MyPanel() do 
  Button("Foo") do print("clicked") end
  List(items) do item
    HStack() do
        [Text(item.name, font=:large)
         Image(item.thumbnail)]
    end    
  end      
end

```

---

<div class="post-metadata">

**Author:** ![RobertN](https://avatars.discourse-cdn.com/v4/letter/r/f0a364/32.png) [@RobertN](https://discourse.julialang.org/u/RobertN)\
**Post date:** [December 10, 2021, 11:22pm UTC](https://discourse.julialang.org/t/making-a-dsl-for-building-a-ui-component-tree/72914/4 "2021-12-10T23:22:26Z")

</div>

Thanks, that gives me a lot to experiment with.

---

<div class="post-metadata">

**Author:** ![sairus7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sairus7/32/10816_2.png) [@sairus7](https://discourse.julialang.org/u/sairus7)\
**Post date:** [December 10, 2021, 11:48pm UTC](https://discourse.julialang.org/t/making-a-dsl-for-building-a-ui-component-tree/72914/5 "2021-12-10T23:48:38Z")

</div>

Take a look at CImGui.jl: [https://github.com/Gnimuc/CImGui.jl/discussions/39](https://github.com/Gnimuc/CImGui.jl/discussions/39)
