String interpolation v1

Multiline raw strings can have placeholders with the common language expressions:

using sys{ log }
using string;

fn greet(name ?str, age int) {
    log("{}\
       Hello {name : "traveler"},
       You look great for your {age} year{age != 1 ? "s"}!
    ")
}
greet("Mark", 49);
greet(?str, 1);

It prints:

Hello Mark,
You look great for your 49 years!
Hello traveler,
You look great for your 1 year!

As described here, the format expression of a multiline string defines extra indent, tab handling, line endings and extra linefeeds/indentaions.

There is more. It can contain one of three placeholder formats: "() {} []". If, for example, "{}" is presented, the string can contain generic Argentum expressions in curly braces, as in the above example. And the same for "[]" and "()" they just select the form of the placeholder syntax. If none is presented, the string contains no placeholders and act as a basic raw string.

String with placeholders is not a string literal. It is internally converted to more or like this code:

sys_StrBuilder
   .putStr("Hello")
   .putStr(name : "traveler")               // see PS section
   .putStr("{LF}You look great for your ")
   .putInt(age)
   .putStr(" year")
   .putOptStr(age != 1 ? "s")               // see PPS section
   .putStr("{LF}")
   .toStr();

In order for this code to work, class StrBuilder from module sys should have methods "put*" of types of the expressions in curly brackets.

Supported types and StringBuilder method names:

TypeMethod name
intputInt
doubleputDouble
boolputOptVoid
function, lambda, delegatenot supported
weak pointersnot supported, dereference it in {weak?_}
all other pointersputObj
all pointers to stringsputStr
optional typesputOpt* where * is name of the wrapped type.
Since all classes in Argentum are open for methods addition, you can always add support of exotic combinations like OptOptDouble etc.

Full multiline string format with placeholders is:

format =: prefix* tabs_handling placeholders? line_ends* extra_whitespaces*

prefix            =: "."      // emits space
                   | "t"      // emits tab
tabs_handling     =: [0-9]*   // number of spaces to convert to a tab
placeholders      =: "{}" | "()" | "[]"
line_ends         =: "n"      // adds "\n" to the end of line
                   | "r"      // adds "\r"
extra_whitespaces =: "\"  // adds `line_end` after the last line
                   | "\+" // adds `line_end` and a `prefix`

Example:

fn formatListItem(r Record) String { "t{}/
    <li id={r.id}>
      {escapeHtml(r.txt)}
    </li>
"}

Placeholder expressions can span to multiple lines:

forRange(0, 3, (i){
   log("{}\
      Number {i} is {
         i % 1 == 0
            ? "even"
            : "odd"
      }!
   ")
});

This prints:

Number 0 is even!
Number 1 is odd!
Number 2 is even!

Conclusion: Argentum string formatting is now in par with or even above the industry leading languages.

PS: Expression:

name : "traveller" 

Reads as: use the value of the optional variable name but if it's empty, use string "traveller".

Binary operator ":" plays the role of "else-operator" in other languages. Also in unwraps optional values.

PPS: Expression:

age != 1 ? "s"

Reads as: if age is not 1, return string "s" (otherwise return empty).

Binary operator "?" plays the role of "if" operator in other languages. Also it creates optional values.
BTW StrBuilder.putOptStr simply skips empty values.

3 Comments

  1. Does Argentum have a short syntax for single-line strings with placeholders [f-strings]?
    I think it is useful, because single-line f-strings are needed much more often than multi-line f-strings.

Comments are closed.