Skip to content

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
1
2
3
4
5
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()
1
2
3
4
5
6
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()
1
2
3
4
5
6
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()
1
2
3
4
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()
1
2
3
4
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()
1
2
3
4
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()
1
2
3
4
5
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()
1
2
3
4
package main
var text = "Hello, World! Hello again!"
var idx = text.lastIndexOf("Hello")  // 14
var missing = text.lastIndexOf("Goodbye")  // -1

Transformation Methods

trim()

Removes leading and trailing whitespace:

trim()
1
2
3
4
5
6
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()
1
2
3
package main
var text = "  hello world  "
var leftTrimmed = text.ltrim()  // "hello world  "

rtrim()

Removes trailing whitespace:

rtrim()
1
2
3
package main
var text = "  hello world  "
var rightTrimmed = text.rtrim()  // "  hello world"

toLower()

Converts the string to lowercase:

toLower()
1
2
3
package main
var text = "Hello, WORLD!"
var lower = text.toLower()  // "hello, world!"

toUpper()

Converts the string to uppercase:

toUpper()
1
2
3
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()
1
2
3
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()
1
2
3
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()
1
2
3
4
5
6
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()
1
2
3
4
5
6
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()
1
2
3
4
5
6
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
1
2
3
4
5
6
7
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
1
2
3
4
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
1
2
3
4
5
6
7
8
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
1
2
3
4
5
// 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