Strings
Strings are sequences of UTF-8 encoded characters. Harneet provides comprehensive string support with both regular and multiline string literals, plus rich instance methods for common string operations.
Overview
Strings in Harneet are: - Immutable - string operations return new strings - UTF-8 encoded - full Unicode support - Method-rich - built-in .length(), .isEmpty(), .trim(), .ltrim(), .rtrim(), .toLower(), .toUpper(), .contains(), .startsWith(), .endsWith(), .indexOf(), .lastIndexOf(), .replace(), .replaceAll(), .repeat(), .padStart(), .padEnd() - Sliceable - use str[start:end] operator for substring extraction - Flexible - support regular strings with escape sequences and raw multiline strings
String Literals
Regular Strings
Regular strings use double quotes and interpret escape sequences:
| Regular Strings |
|---|
| package main
var greeting = "Hello, World!"
var multiline = "Line 1\nLine 2\tTabbed"
var unicode = "Unicode: 你好世界 🌍"
var escaped = "Quote: \"Hello\" and Path: C:\\Users\\file.txt"
|
Multiline Strings
Multiline strings use backticks and preserve formatting without interpreting escapes:
| Multiline Strings |
|---|
| package main
var raw = `Line 1
Line 2 Tabbed
Path: C:\Users\Name\file.txt
Quotes: "double" and 'single' work without escaping`
var sqlQuery = `
SELECT u.name, p.title
FROM users u
JOIN posts p ON u.id = p.author_id
WHERE u.active = TRUE
ORDER BY p.created_at DESC
`
|
String Instance Methods
All string methods return new strings without modifying the original. All methods enforce None-receiver safety.
Inspection Methods
length()
Returns the number of bytes in the string:
| length() |
|---|
| package main
var text = "hello"
var len = text.length() // 5
var empty = ""
var emptyLen = empty.length() // 0
|
isEmpty()
Returns true if the string has zero length:
| isEmpty() |
|---|
| package main
var empty = ""
var nonEmpty = "hello"
var e1 = empty.isEmpty() // true
var e2 = nonEmpty.isEmpty() // false
|
contains(substr)
Returns true if the string contains the substring:
| contains() |
|---|
| package main
var text = "Hello, World!"
var hasHello = text.contains("Hello") // true
var hasGoodbye = text.contains("Goodbye") // false
|
startsWith(prefix)
Returns true if the string starts with the prefix:
| startsWith() |
|---|
| package main
var text = "Hello, World!"
var startsHello = text.startsWith("Hello") // true
var startsGoodbye = text.startsWith("Goodbye") // false
|
endsWith(suffix)
Returns true if the string ends with the suffix:
| endsWith() |
|---|
| package main
var text = "Hello, World!"
var endsWorld = text.endsWith("World!") // true
var endsHello = text.endsWith("Hello") // false
|
Search Methods
indexOf(substr)
Returns the index of the first occurrence of substring, or -1 if not found:
| indexOf() |
|---|
| package main
var text = "Hello, World! Hello again!"
var idx = text.indexOf("Hello") // 0
var idx2 = text.indexOf("World") // 7
var missing = text.indexOf("Goodbye") // -1
|
lastIndexOf(substr)
Returns the index of the last occurrence of substring, or -1 if not found:
| lastIndexOf() |
|---|
| package main
var text = "Hello, World! Hello again!"
var idx = text.lastIndexOf("Hello") // 14
var missing = text.lastIndexOf("Goodbye") // -1
|
trim()
Removes leading and trailing whitespace:
| trim() |
|---|
| package main
var text = " hello world "
var trimmed = text.trim() // "hello world"
var tabs = "\t\nhello\t\n"
var trimmed2 = tabs.trim() // "hello"
|
ltrim()
Removes leading whitespace:
| ltrim() |
|---|
| package main
var text = " hello world "
var leftTrimmed = text.ltrim() // "hello world "
|
rtrim()
Removes trailing whitespace:
| rtrim() |
|---|
| package main
var text = " hello world "
var rightTrimmed = text.rtrim() // " hello world"
|
toLower()
Converts the string to lowercase:
| toLower() |
|---|
| package main
var text = "Hello, WORLD!"
var lower = text.toLower() // "hello, world!"
|
toUpper()
Converts the string to uppercase:
| toUpper() |
|---|
| package main
var text = "Hello, World!"
var upper = text.toUpper() // "HELLO, WORLD!"
|
Modification Methods
replace(old, new)
Replaces the first occurrence of old with new:
| replace() |
|---|
| package main
var text = "Hello, World! Hello again!"
var replaced = text.replace("Hello", "Hi") // "Hi, World! Hello again!"
|
replaceAll(old, new)
Replaces all occurrences of old with new:
| replaceAll() |
|---|
| package main
var text = "Hello, World! Hello again!"
var replaced = text.replaceAll("Hello", "Hi") // "Hi, World! Hi again!"
|
repeat(n)
Returns a new string with the original repeated n times:
| repeat() |
|---|
| package main
var text = "Ha"
var laughing = text.repeat(3) // "HaHaHa"
var dash = "-"
var line = dash.repeat(10) // "----------"
|
padStart(n, ch)
Pads the string on the left with ch until it reaches length n:
| padStart() |
|---|
| package main
var num = "42"
var padded = num.padStart(5, "0") // "00042"
var text = "hi"
var padded2 = text.padStart(5, " ") // " hi"
|
padEnd(n, ch)
Pads the string on the right with ch until it reaches length n:
| padEnd() |
|---|
| package main
var text = "hi"
var padded = text.padEnd(5, "!") // "hi!!!"
var label = "Name:"
var padded2 = label.padEnd(10, " ") // "Name: "
|
None-Receiver Safety
All string instance methods enforce None-receiver safety. Calling a method on None raises a runtime error:
| None-Receiver Safety |
|---|
| package main
var str string = None
// All of these will raise runtime errors:
// str.length() // ERROR: type null does not have method 'length'
// str.toUpper() // ERROR: type null does not have method 'toUpper'
// str.contains("x") // ERROR: type null does not have method 'contains'
|
String Concatenation
Use the + operator to concatenate strings:
| String Concatenation |
|---|
| package main
var first = "Hello"
var second = "World"
var greeting = first + ", " + second + "!" // "Hello, World!"
|
Unicode Support
Harneet strings are UTF-8 encoded and support full Unicode:
| Unicode Support |
|---|
| package main
var chinese = "你好世界"
var emoji = "Hello 🌍 🎉"
var mixed = "English + 日本語 + Español"
// String methods work correctly with Unicode
var len = emoji.length() // Byte length
var hasWorld = emoji.contains("🌍") // true
|
Complete Example
| Complete Example |
|---|
| package main
import fmt
var text = " Hello, World! "
// Inspection
fmt.Println("Length:", text.length()) // 17
fmt.Println("Is empty:", text.isEmpty()) // false
fmt.Println("Contains 'World':", text.contains("World")) // true
fmt.Println("Starts with ' H':", text.startsWith(" H")) // true
fmt.Println("Ends with '! ':", text.endsWith("! ")) // true
// Search
fmt.Println("Index of 'World':", text.indexOf("World")) // 9
fmt.Println("Index of 'Goodbye':", text.indexOf("Goodbye")) // -1
// Transformation
var trimmed = text.trim()
fmt.Println("Trimmed:", trimmed) // "Hello, World!"
fmt.Println("Lowercase:", trimmed.toLower()) // "hello, world!"
fmt.Println("Uppercase:", trimmed.toUpper()) // "HELLO, WORLD!"
// Modification
var replaced = trimmed.replace("World", "Harneet")
fmt.Println("Replaced:", replaced) // "Hello, Harneet!"
// Slice operator
var sliced = trimmed[0:5]
fmt.Println("Sliced:", sliced) // "Hello"
var repeated = "Ha".repeat(3)
fmt.Println("Repeated:", repeated) // "HaHaHa"
var padded = "42".padStart(5, "0")
fmt.Println("Padded:", padded) // "00042"
|
Best Practices
1. Use String Methods for Readability
| Use String Methods |
|---|
| // Preferred: Clear intent
var hasPrefix = text.startsWith("Hello")
// Less clear: Manual slicing with operator
var hasPrefix2 = text[0:5] == "Hello"
|
2. Chain Methods for Complex Operations
| Chain Methods |
|---|
| var result = text.trim().toLower().replace("world", "harneet")
|
3. Use Multiline Strings for Readability
| Multiline Strings |
|---|
| // Preferred: Readable
var query = `
SELECT * FROM users
WHERE active = TRUE
ORDER BY created_at DESC
`
// Less readable: Concatenation
var query2 = "SELECT * FROM users " +
"WHERE active = TRUE " +
"ORDER BY created_at DESC"
|
See Also