# Non-standard string literals create global-like objects!?

**URL:** <https://discourse.julialang.org/t/non-standard-string-literals-create-global-like-objects/97283>\
**Category:** Internals & Design\
**Tags:** macros, strings\
**Created:** [April 9, 2023, 4:51pm UTC](https://discourse.julialang.org/t/non-standard-string-literals-create-global-like-objects/97283 "2023-04-09T16:51:05Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Krastanov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/krastanov/32/6817_2.png) [@Krastanov](https://discourse.julialang.org/u/Krastanov)\
**Post date:** [April 9, 2023, 4:51pm UTC](https://discourse.julialang.org/t/non-standard-string-literals-create-global-like-objects/97283/1 "2023-04-09T16:51:05Z")

</div>

I am very confused by the way non-standard string literals work when called inside of other functions. See this example with regex (but it happens with any non-standard string literal):

```julia
r"a" === r"a" # false
Regex("a") === Regex("a") # false
r"a" == Regex("a") # true, because it is ==, not ===

f() = r"a" 
g() = Regex("a")

f() === f() # true !?
g() === g() # false

```

Why does it matter whether I type `r"a"` or `Regex("a")` ? What explains why `r"a" === r"a"` is false while `f() === f()` is true? I would have expected `===` to return false for all these examples.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [April 9, 2023, 5:06pm UTC](https://discourse.julialang.org/t/non-standard-string-literals-create-global-like-objects/97283/2 "2023-04-09T17:06:03Z")

</div>

> [@Krastanov](#):
>
> Why does it matter whether I type `r"a"` or `Regex("a")` ?

In the former case (string macro), the regex compilation is done once at compile time and cached, whereas in the latter case it is repeated at runtime on every call.

---

<div class="post-metadata">

**Author:** ![Krastanov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/krastanov/32/6817_2.png) [@Krastanov](https://discourse.julialang.org/u/Krastanov)\
**Post date:** [April 9, 2023, 5:43pm UTC](https://discourse.julialang.org/t/non-standard-string-literals-create-global-like-objects/97283/3 "2023-04-09T17:43:08Z")

</div>

I was using the regex just as a convenient built-in example. I see how this behavior is valuable for regex and similar situations, but that is causing problems for my use case. **Can one make a non-standard string literal that does not perform such caching?** After all, these are just macros and I expected them to behave more like:

```julia
macro H() :(Regex("a")) end
h() = @H
h() === h() # false

```

I imagine, plenty of people think of non-standard string literals as a convenient way to make a small DSL, a way to convert something represented as a string into a more convenient datastructure, and not as a tool for caching. Is that simply a wrong way to view them? Even looking at the documentation seems to describe something more along the lines of my usecase, not caching-focused: [Strings · The Julia Language](https://docs.julialang.org/en/v1/manual/strings/#non-standard-string-literals)

> There are situations when you want to construct a string or use string semantics, but the behavior of the standard string construct is not quite what is needed. For these kinds of situations, Julia provides non-standard string literals.

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [April 9, 2023, 5:53pm UTC](https://discourse.julialang.org/t/non-standard-string-literals-create-global-like-objects/97283/4 "2023-04-09T17:53:37Z")

</div>

Don’t think this is specific to string literals.

```julia
macro m1()
    :(Regex("abc"))
end

# creates new regex every time
f1() = @m1()

macro m2()
    Regex("abc")
end

# creates regex only once
f2() = @m2()

```

---

<div class="post-metadata">

**Author:** ![Krastanov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/krastanov/32/6817_2.png) [@Krastanov](https://discourse.julialang.org/u/Krastanov)\
**Post date:** [April 9, 2023, 5:58pm UTC](https://discourse.julialang.org/t/non-standard-string-literals-create-global-like-objects/97283/5 "2023-04-09T17:58:30Z")

</div>

Thank you! This explains my confusion perfectly. At the root of it was not recognizing that a macro’s return value is treated differently depending on whether it is an Expr or anything else (I was not really appreciating that a macro might be written to return a non-Expr).

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [April 9, 2023, 6:26pm UTC](https://discourse.julialang.org/t/non-standard-string-literals-create-global-like-objects/97283/6 "2023-04-09T18:26:22Z")

</div>

And it’s not just the return value — an object such as `Regex("abc")` can be put anywhere in the expression. `:( occursin($(Regex("abc")), $expr) )` would create the regex once, and put it into the expression.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [April 9, 2023, 6:26pm UTC](https://discourse.julialang.org/t/non-standard-string-literals-create-global-like-objects/97283/7 "2023-04-09T18:26:31Z")

</div>

This isn’t unique to non-expression returns. It just depends on if you defer the evaluation or do it inside the macro. E.g you could write

```julia
macro m3()
    s = "abc"
    quote
        r1 = $(Regex(s))
        r2 = Regex($s)
    end
end

```

`r1` is constructed during macroexpansion whereas `r2` is constructed at runtime
