Strings and Text
NumFu treats text as first-class data with powerful string operations. Let's explore how to work with strings in NumFu.
String Literals
Basic Strings
Strings are enclosed in double quotes:
"Hello, NumFu!"
"Programming is fun"
"" // Empty string
Escape Sequences
Use backslash for special characters:
"Line 1\nLine 2" // Newline
"Tab\tSeparated" // Tab character
"Quote: \"Hello\"" // Escaped quotes
"Backslash: \\" // Escaped backslash
"Unicode: \u03B1" // Unicode (α)
String Operations
Strings are very similar to lists and share many operations with them. You can think of them as lists of characters.
Concatenation
Join strings with the +
operator:
"Hello" + " " + "World" // "Hello World"
"NumFu" + "!" // "NumFu!"
// Multi-line concatenation
"This is a very long string " +
"that spans multiple lines"
Repetition
Repeat strings with the *
operator:
3 * "Ho" // "HoHoHo"
"=" * 20 // "===================="
2* "NumFu " // "NumFu NumFu "
String Access and Properties
Character Indexing
Access individual characters with square brackets (just like elements in a list):
"Hello"[0] // "H" (first character)
"Hello"[4] // "o" (last character)
"NumFu"[2] // "m"
Negative Indexing
Count from the end with negative indices:
"Hello"[-1] // "o" (last character)
"Hello"[-2] // "l" (second to last)
"Programming"[-1] // "g"
String Properties & Functions
All of the functions shown below must be imported from the std
standard library module. When running the examples, remember to import it at the top of your file (or in the REPL):
import * from "std"
String Length
length("Hello") // 5
length("") // 0
length("NumFu rocks!") // 12
Case Conversion
toLowerCase("HELLO") // "hello"
toUpperCase("world") // "WORLD"
String Testing
contains("hello", "lo") // true (substring exists)
contains("hello", "xyz") // false
Count Substrings
count("The math is not mathing.", "math")
// 2 (two occurences of "math")
String Slicing
Extract substrings using slice(string, start, end)
:
slice("Hello World", 0, 4) // "Hello"
slice("Programming", 3, 6) // "gram"
slice("NumFu", 1, -1) // "umF" (from index 1 to end-1)
Splitting Strings
Split a string into a list of strings by the specified separator: split(string, separator)
let text = "NumFu Programming Language" in
let words = split(text, " ") in
words // ["NumFu", "Programming", "Language"]
Joining Lists
Join a list of strings with a separator: join(list, separator)
let words = ["NumFu", "Programming", "Language"] in
join(words, "-") // "NumFu-Programming-Language"
Template Strings & Formatting
The format()
function from std
allows you to create formatted strings by inserting values into placeholders. It takes a string and the same number of additional arguments as there are placeholders ({}
).
import format from "std"
format("Welcome to {}, {}!", "NumFu", "programmer")
// "Welcome to NumFu, programmer!"
format("Result: {} + {} = {}", 2, 3, 5)
// "Result: 2 + 3 = 5"
If you do not supply the correct number of arguments, an IndexError
will be raised.
format("{} likes {}", "John")
// IndexError: Incorrect number of placeholders
Escape placeholders
To escape placeholders and treat them as literal characters, enclose them in curly braces
format("Using placeholders {{}}, you can format {}", "strings")
// "Using placeholders {}, you can format strings"
Examples
When running the examples below, remember to import the std
standard library module at the top of your file (or in the REPL) because it provides essential functions for working with strings.
import * from "std"
Bordered Title
let border = "=" * 50 in
let title = "NumFu Tutorial" in
let padding = ((50 - length(title)) / 2) in
border + "\n" +
" " * padding + title + "\n" +
border
==================================================
NumFu Tutorial
==================================================
Building Messages
let name = "Alice" in
let age = 30 in
"Hello, " + name + "! You are " + String(age) + " years old."
// Hello, Alice! You are 30 years old.
String Validation
let isValidEmail = {email ->
if count(email, "@") != 1 then false else
let splitted = split(email, "@") in
count(splitted[1], ".") > 0
&& splitted[1][-1] != "."
&& splitted[0][0] != "."
}
isValidEmail("user@example.com") // true
isValidEmail("userexample.com") // false
isValidEmail("user@email@example.com") // false
isValidEmail("user@example.com.") // false
String Processing
Take a list of boolean options to determine whether to trim, lowercase, and replace spaces with underscores in the input text.
// Text processor factory
let makeTextProcessor = {options ->
let shouldTrim = options[0],
shouldLower = options[1],
shouldReplace = options[2] in
{text ->
let step1 = if shouldTrim then trim(text) else text in
let step2 = if shouldLower then toLowerCase(step1) else step1 in
let step3 = if shouldReplace then replace(step2, " ", "_") else step2 in
step3
}
}
let processor = makeTextProcessor([true, true, true]) in
processor(" Hello World ") // "hello_world"