Strings: building, slicing & formatting
One task in all eight languages: from name = "Ada Lovelace" and year = 1815, build a formatted line - "Hello, Ada Lovelace! That is 211 years since 1815." - by interpolating the bindings and an embedded 2026 - year expression, then slice out the first word and upper-case it to print "First name: ADA". Watch how each language formats: weaving values straight into the literal (Guji, Perl, Raku, Python f-strings), a positional printf-style template (Go, OCaml), or Rust's {} placeholder syntax. Notice too how each carves out a substring - splitting on a space versus indexing a range of bytes, chars, or code points.
“There's more than one way to do it.” - Larry Wall
sub main() {
$name = "Ada Lovelace"
$year = 1815
# build: interpolate bindings and an embedded expression
$age = 2026 - $year
print("Hello, $name! That is { $age } years since $year.")
# slice: take the first word, then upper-case it
$first = $name.split(" ")[0]
print("First name: { $first.upper() }")
}A double-quoted string interpolates a bare $name directly and evaluates an arbitrary expression inside { ... } (§12), so the format lives in the literal with no separate template. Guji has no character-index substring in the prelude; the idiomatic slice is split(" ")[0], where split/upper are data-first prelude functions (§15.3) chained with .. Indexing [0] panics on an empty list, but a name with a space always yields a first element.
package main
import (
"fmt"
"strings"
)
func main() {
name := "Ada Lovelace"
year := 1815
// build: a positional printf-style template
fmt.Printf("Hello, %s! That is %d years since %d.\n", name, 2026-year, year)
// slice: take the first word, then upper-case it
first := strings.Fields(name)[0]
fmt.Printf("First name: %s\n", strings.ToUpper(first))
}Go has no string interpolation, so formatting goes through fmt.Printf with positional verbs - %s for the string, %d for the ints - and the computed 2026-year is just another argument. Slicing splits on whitespace with strings.Fields (which handles any run of spaces) and indexes the result, and strings.ToUpper lives in the strings package rather than being a method on the value. A raw byte slice like name[:3] exists but would cut UTF-8 mid-rune, so word-splitting is the safe idiom here.
let () =
let name = "Ada Lovelace" in
let year = 1815 in
(* build: a positional printf-style template *)
Printf.printf "Hello, %s! That is %d years since %d.\n"
name (2026 - year) year;
(* slice: take the first word, then upper-case it *)
let first = List.hd (String.split_on_char ' ' name) in
Printf.printf "First name: %s\n" (String.uppercase_ascii first)OCaml formats with Printf.printf, whose format string is itself type-checked at compile time: %s demands a string and %d an int, so the argument types are verified statically. There is no interpolation, so the embedded 2026 - year is passed as an ordinary argument. The slice uses String.split_on_char ' ' then List.hd for the first word, and String.uppercase_ascii upper-cases it - the _ascii name flags that the standard library only case-folds ASCII, leaving anything Unicode to a library such as Uucp.
import Data.Char (toUpper)
import Text.Printf (printf)
main :: IO ()
main = do
let name = "Ada Lovelace"
year = 1815 :: Int
-- build: a type-checked printf template
printf "Hello, %s! That is %d years since %d.\n" name (2026 - year) year
-- slice: take the first word, then upper-case it
let first = head (words name)
printf "First name: %s\n" (map toUpper first)Haskell has no string interpolation, so the idiomatic format is Text.Printf.printf, whose format string is variadic and resolved against the argument types - %s for the String, %d for the Ints - with the computed 2026 - year passed as a plain argument. The slice uses words (split on any whitespace) and head for the first token, and map toUpper upper-cases it - a String is just [Char], so character-level work is ordinary list processing. toUpper is per-Char Unicode-simple case folding; for full locale-aware text the text package is preferred.
use strict;
use warnings;
my $name = "Ada Lovelace";
my $year = 1815;
# build: interpolate variables; compute the embedded value first
my $age = 2026 - $year;
print "Hello, $name! That is $age years since $year.\n";
# slice: take the first word, then upper-case it
my ($first) = split / /, $name;
print "First name: ", uc($first), "\n";A double-quoted Perl string interpolates scalar variables directly, but not arbitrary expressions, so the 2026 - $year arithmetic is computed into $age first and the variable is interpolated. The slice uses split / / in list context, where the parentheses around ($first) keep only the first field. uc upper-cases the string; like most Perl string operations it is a built-in function rather than a method call, so it reads inside-out as uc($first).
my $name = "Ada Lovelace";
my $year = 1815;
# build: interpolate variables and a { } expression block
say "Hello, $name! That is { 2026 - $year } years since $year.";
# slice: take the first word, then upper-case it
my $first = $name.split(' ')[0];
say "First name: { $first.uc }";Raku strings interpolate a bare $name and, like Guji, evaluate a full expression inside { ... }, so 2026 - $year is computed right in the literal. Splitting on a space with .split(' ') yields a list that [0] indexes for the first word. .uc is a method on the string (Unicode-aware, unlike Perl's ASCII-leaning history), and chaining stays method-style - the same data-first feel as Guji, since both descend from Perl's text orientation.
fn main() {
let name = "Ada Lovelace";
let year = 1815;
// build: {} placeholders, with one captured inline
let age = 2026 - year;
println!("Hello, {name}! That is {age} years since {year}.");
// slice: take the first word, then upper-case it
let first = name.split(' ').next().unwrap();
println!("First name: {}", first.to_uppercase());
}Rust's println! is a compile-time macro: {name} captures a variable in scope by name, and the format string is checked against its arguments at compile time. The slice splits on a space into a lazy iterator, so .next() pulls just the first word and .unwrap() asserts it exists. to_uppercase returns a fresh String and follows the Unicode case-mapping rules - name[..3] byte-slicing would also work here but panics if a boundary falls inside a multi-byte char, so splitting is safer.
name = "Ada Lovelace"
year = 1815
# build: f-string interpolation with an embedded expression
age = 2026 - year
print(f"Hello, {name}! That is {age} years since {year}.")
# slice: take the first word, then upper-case it
first = name.split(" ")[0]
print(f"First name: {first.upper()}")Python's f-strings interpolate any expression inside { ... }, so the format and the values live together in one literal (the embedded 2026 - year could even go straight in the braces). The slice uses str.split(" ")[0] for the first word, and str.upper() is a method on the string that returns a new, full-Unicode upper-cased copy. Python also supports index slicing like name[:3], which is safe because it indexes by code point rather than raw bytes.