Programming Without Structs
Krzysztof Kowalczyk writes in his blog post on the go programming language:
Go has shown that you can have a popular language without enums. I don’t think you could have a popular language without structs. There’s a line below which the language is just not useful enough.
What would it look like if we didn’t have structs? The core idea of struct is a covenient way to store and access data. We woud need to substitute our struct for another primitive type that can hold data. A map provides similar lookup capabilities by using a key, with less gaurantees that a field might even be present.
type User struct {
FirstName string
LastName string
EmployeeId string
}
func (u User) FullName() string {
return u.FirstName + " " + u.LastName
}
user := map[any]any{
"FirstName": "jane",
"LastName": "smith",
"EmployeeId": "1234",
"FullName": func(fn string, ln string) string { return fn + " " + ln},
}
Moving away from named fields, we can also just put everything in a list, hope the order is right, and access values by index.
user := []any{
"jane",
"smith",
"1234",
func(fn string, ln string) string { return fname + " " + lname },
}
There is also nothing stopping you from putting everything in a delimited string.
import "strings"
user := "jane,smith,1234"
fields := strings.Split(",")
lastName := fields[1]
Languages like python even allow you to evaluate a string as a function that can be called.
user = 'jane;smith;lambda x,y: x + " " + y'
fields = user.Split(';')
fn = eval(fields[2])
fullName = fn(fields[0], fields[1])
From a string, it’s not much farther to go to a byte array.
//allocate 30 bytes, 10 for each field
user := make([]byte, 30)
copy(user[0:10], []byte("jane"))
copy(user[10:20], []byte("smith"))
copy(user[20:30], []byte("1234"))
A theme arises from these examples, that lists make themselves quite useful for storing many types of data. A Tree is another example that be rewritten from a struct to a list.
type Node struct {
Value int
Left *Node
Right *Node
}
Applying the pattern we used for the user above, Value will be at index 0, Left at index 1, and Right at index 2. Since Left and Right are also Node types, they will also be lists. Even at a shallow depth, keeping track of brackets can get out of hand quickly.
// atomic example, no branches
node := []any{0, []any{}, []any{}}
// A tree with a left and a right branch
tree := []any{0, []any{1, []any{}, []any{}}, []any{2, []any{}, []any{}}}
// [0 [1 [] []] [2 [] []]]
It goes to show, Programming without structs can be done, but structs make things much more convenient.