# How bad is $~?

**URL:** <https://forum.crystal-lang.org/t/how-bad-is/2742>\
**Category:** Help & Support\
**Created:** [December 7, 2020, 10:39pm UTC](https://forum.crystal-lang.org/t/how-bad-is/2742 "2020-12-07T22:39:27Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![BrucePerens](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/bruceperens/32/852_2.png) [@BrucePerens](https://forum.crystal-lang.org/u/BrucePerens)\
**Post date:** [December 7, 2020, 10:39pm UTC](https://forum.crystal-lang.org/t/how-bad-is/2742/1 "2020-12-07T22:39:27Z")

</div>

In my new internationalization system, I am using `$~`, `$1`, `$2`, etc. The idea is that your original string may contain `"#{a} arbitrary text #{b}"`, and your translated string is `"#{$1} translated arbitrary text #{$2}"` and gets the original interpolated expressions in whatever order you specify. You can also rewrite the expressions if you have to.

`$~`, `$1`, `$2` is a weird thing we inherited via Perl and Ruby and inspired by Bourne shell. It is singular in the language in that it leaks one scope level out of a function, and _only_ one scope level, and thus can be used to return multiple values, although tuples are cleaner. You can’t take its value if it’s not set. It was intended to hold the return value of regular expession matches, although it’s better to take the value of `Regex#match`.

The way I use it, it does not leak into the scope of the caller of my internationalization functions.

What I want to know is how bad $~ is considered, especially by the language developers. In particular:

- Does it do bad things to code generation and optimization?

- Does it cause block captures where they would otherwise be expanded inline?

- Is it another of the language features @asterite wants to delete, and what are his reasons?

---

<div class="post-metadata">

**Author:** ![straight-shoota](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/straight-shoota/32/36_2.png) [@straight-shoota](https://forum.crystal-lang.org/u/straight-shoota)\
**Post date:** [December 7, 2020, 11:46pm UTC](https://forum.crystal-lang.org/t/how-bad-is/2742/2 "2020-12-07T23:46:42Z")

</div>

This issue should have the basic answers covered: [https://github.com/crystal-lang/crystal/issues/6969](https://github.com/crystal-lang/crystal/issues/6969)

I don’t understand what you’re trying to do or how dollar sign variables would help anything with you i18n use case. Why can’t you use `a` and `b` in your translated string?  
In any case, I’d advise not to use dollar sign variables for anything but the intended use case of convenient access to regex matchdata.

---

<div class="post-metadata">

**Author:** ![BrucePerens](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/bruceperens/32/852_2.png) [@BrucePerens](https://forum.crystal-lang.org/u/BrucePerens)\
**Post date:** [December 8, 2020, 1:13am UTC](https://forum.crystal-lang.org/t/how-bad-is/2742/3 "2020-12-08T01:13:37Z")

</div>

I don’t want to use a and b in my translated strings because the translators are not programmers, and since the translated strings are in different files from the native language strings, I want to avoid changing code in the translated strings.

---

<div class="post-metadata">

**Author:** ![jhass](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jhass/32/1779_2.png) [@jhass](https://forum.crystal-lang.org/u/jhass)\
**Post date:** [December 8, 2020, 10:11am UTC](https://forum.crystal-lang.org/t/how-bad-is/2742/4 "2020-12-08T10:11:02Z")

</div>

I love translation APIs where you can have named placeholders. “%person likes this post” just gives the translator so much more context vs “$1 likes this post”.

---

<div class="post-metadata">

**Author:** ![straight-shoota](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/straight-shoota/32/36_2.png) [@straight-shoota](https://forum.crystal-lang.org/u/straight-shoota)\
**Post date:** [December 8, 2020, 12:16pm UTC](https://forum.crystal-lang.org/t/how-bad-is/2742/5 "2020-12-08T12:16:48Z")

</div>

Exactly. And translators need to understand the source translation in order to translate it, so what’s the point in having different formats?

On a different, note - still not sure what exactly this is about - localization in my understanding mostly happens at runtime, but in order to use Crystal expressions like string interpolation, that would need to happen at compile time.

---

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [December 8, 2020, 12:18pm UTC](https://forum.crystal-lang.org/t/how-bad-is/2742/6 "2020-12-08T12:18:51Z")

</div>

The magic variables `$~`, `$1`, etc. are fine. I was a bit reluctant at first (even though I implemented them! :-P) but they are usually used next to a match, and they are very convenient.

That said, I also don’t understand why they need to be part of a translation API.

---

<div class="post-metadata">

**Author:** ![BrucePerens](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/bruceperens/32/852_2.png) [@BrucePerens](https://forum.crystal-lang.org/u/BrucePerens)\
**Post date:** [December 8, 2020, 7:30pm UTC](https://forum.crystal-lang.org/t/how-bad-is/2742/7 "2020-12-08T19:30:04Z")

</div>

@jhass I am all for giving the translator instructions. But I am starting with crystal’s existing string syntax and not inventing a new string format. So, I can do something like this:

t(“String #{1+1} #{2+2} String”, exp=[“person”, “place”])

---

<div class="post-metadata">

**Author:** ![BrucePerens](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/bruceperens/32/852_2.png) [@BrucePerens](https://forum.crystal-lang.org/u/BrucePerens)\
**Post date:** [December 9, 2020, 1:11am UTC](https://forum.crystal-lang.org/t/how-bad-is/2742/8 "2020-12-09T01:11:45Z")

</div>

@asterite The reason I wanted them for the translation API was that I wanted to use interpolated strings as the translated strings, and I wanted to have a set of local variables that would never collide with my caller, even if I was in a block in the caller’s context. But I was probably getting a bit too clever for my own good.

---

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [December 9, 2020, 1:45am UTC](https://forum.crystal-lang.org/t/how-bad-is/2742/9 "2020-12-09T01:45:53Z")

</div>

Maybe this can help you? [https://crystal-lang.org/reference/syntax\_and\_semantics/macros/fresh\_variables.html](https://crystal-lang.org/reference/syntax_and_semantics/macros/fresh_variables.html)

---

<div class="post-metadata">

**Author:** ![BrucePerens](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/bruceperens/32/852_2.png) [@BrucePerens](https://forum.crystal-lang.org/u/BrucePerens)\
**Post date:** [December 9, 2020, 1:50am UTC](https://forum.crystal-lang.org/t/how-bad-is/2742/10 "2020-12-09T01:50:47Z")

</div>

@asterite My problem with fresh variables is that they work by letter rather than number, and the alphabet is wildly different across national languages. So, I can’t expect the translator to think that %b is the second argument, etc.
