A modern language with familiar syntax
Objo is a statically typed, object-oriented language that reads like English. Everything is an object, types are checked at compile time, and there is no boilerplate to wade through. If you have ever written any BASIC, you will feel right at home.
Clean, Readable Syntax
No semicolons, no curly braces. Objo reads naturally - declare variables, branch, loop and call methods with plain English keywords. Objo Studio handles class and method scaffolding for you, so all you write is the logic.
Var greeting As String = "Hello, " + player.Name
Var lives As Integer = 3
If lives > 0 Then
StatusLabel.Text = greeting
StartGame()
Else
StatusLabel.Text = "Game Over"
End If
For i As Integer = 1 To 10
SpawnEnemy(i * 50, 100)
Next i
Everything Is an Object
Integers, doubles, strings, booleans - every value in Objo is a full object. Call methods directly on literals, chain operations naturally, and never worry about the distinction between primitives and objects.
# Method calls on literals.
Var upper As String = "hello world".Uppercase()
Var hex As String = 255.ToHex()
Var abs As Integer = (-42).Abs()
# Chaining.
Var result As String = " hello ".Trim().Uppercase()
# result = "HELLO"
# Even numbers have useful methods.
Print(7.IsOdd()) # True
Print(100.Clamp(0, 50)) # 50
Print(2.Pow(10)) # 1024
Static Typing Without the Pain
Objo catches type errors at compile time, not at runtime. Value types like Integer and String can never be Nothing, eliminating an entire category of null-related bugs.
# Explicit types catch errors early.
Var name As String = "Alice"
Var age As Integer = 30
Var scores() As Double = [98.5, 87.3, 92.0]
# Value types are never Nothing.
Var count As Integer # Defaults to 0, not Nothing
Var label As String # Defaults to "", not Nothing
# Type checking at runtime.
If animal IsA Dog Then
Var dog As Dog = Dog(animal)
Print(dog.Breed)
End If
Powerful Collections
Arrays and dictionaries are first-class citizens with literal syntax. Create them inline, access elements by index or key, and iterate with For Each. Dictionaries support any hashable key type.
# Array literals.
Var names() As String = ["Alice", "Bob", "Charlie"]
names.Append("Diana")
names.Sort()
# Dictionary literals.
Var ages As Dictionary(Of String, Integer) = { _
"Alice": 30, "Bob": 25, "Charlie": 35}
# Iterate with For Each.
For Each name As String In names
If ages.HasKey(name) Then
Print(name + " is " + ages.Value(name).ToString())
End If
Next name
Functional Collections
Arrays ship with useful methods like Map(), Where() and Reduce(). Pass inline functions to transform and filter collections in a single expression. Closures capture their surrounding scope automatically.
Var numbers() As Integer = [1, 2, 3, 4, 5]
# Filter.
Var evens() As Integer = numbers.Where(Function(n) n Mod 2 = 0)
# evens = [2, 4]
# Transform.
Var doubled() As Integer = numbers.Map(Function(n) n * 2)
# doubled = [2, 4, 6, 8, 10]
# Accumulate.
Var sum As Integer = numbers.Reduce(0, Function(acc, n) acc + n)
# sum = 15
# Check conditions.
Print(numbers.All(Function(n) n > 0)) # True
Print(numbers.Any(Function(n) n > 4)) # True
Rich String Handling
Strings are immutable, Unicode-aware objects packed with useful methods. String interpolation lets you embed expressions directly.
Var name As String = "Garry"
Var age As Integer = 40
# String interpolation.
Var bio As String = $"My name is {name}, age {age}."
# Useful built-in methods.
Print("hello world".Capitalise()) # "Hello world"
Print("foo:bar:baz".Split(":").Count) # 3
Print(" padded ".Trim()) # "padded"
Print("abcdef".Substring(2, 3)) # "cde"
Print("banana".Replace("na", "🎉"))
# Case-insensitive by default.
Print("Hello" = "hello") # True
Structured Error Handling
Catch errors precisely with Try/Catch/Finally. Match on specific exception types or catch broadly - your choice. The Finally block always runs, making cleanup reliable.
Sub PrintFile(path As String)
Try
Var file As New FileSystemItem(path)
Print(file.ReadAllText())
Catch e As IOException
Print("File error: " + e.Message)
Catch e As Exception
Print("Unexpected error: " + e.Message)
Throw e # Re-throw if needed.
Finally
Print("Finished")
End Try
End Sub
Events Made Simple
Subscribe to events on any control or object with AddHandler. The IDE creates event stubs for you - just fill in the logic. Multiple handlers can respond to the same event, and you can add or remove them at any time.
# Wire up a button press.
AddHandler btn.Pressed, AddressOf HandlePress
AddHandler btn.Pressed, AddressOf LogPress
# Respond to value changes.
AddHandler slider.ValueChanged, AddressOf OnSliderChanged
# Remove a handler when done.
RemoveHandler btn.Pressed, AddressOf LogPress
# Raise custom events.
RaiseEvent DataLoaded(records.Count)
Async/Await
Write asynchronous code that reads like synchronous code. Await long-running operations and the language handles the rest. Errors propagate naturally through Await, so Try/Catch works exactly as expected.
Async Function FetchText(conn As URLConnection, url As String) As String
Var response As HTTPResponse = Await conn.SendAsync("GET", url)
Return response.Text()
End Function
Async Sub FetchAll(conn As URLConnection, urls() As String)
# Start all requests concurrently.
Var tasks() As Task(Of String)
For Each url As String In urls
tasks.Append(FetchText(conn, url))
Next url
Var results() As String = Await Task.WhenAll(tasks)
For Each result As String In results
Print(result)
Next result
End Sub
Expressive Control Flow
For/Next with Step, For Each over any collection, While/Wend, Do/Loop with Until or While, and Select Case with multi-value and range matching. Exit and Continue work in every loop type.
# Select Case with multiple matches.
Select Case httpStatus
Case 200
HandleSuccess(response)
Case 301, 302
FollowRedirect(response)
Case Is >= 400
ShowError(response)
End Select
# Loop with early exit.
For Each file As String In files
If file.EndsWith(".tmp") Then Continue
If file.IsBlank() Then Exit
ProcessFile(file)
Next file
Explore the full language reference
Everything you need to know about Objo — types, classes, generics, error handling, the standard library and more.
Read the full language reference