Cool use cases for inferred literals in Umka
Inferred literals have been recently added to Umka. They allow you to omit the type in the struct/array literals. For example, from my game’s codebase:
[]Window{
Window{
name: "Test window",
rect: rect.Rect{ 20, 20, 64, 48 },
aspect: th.Vf2{ 4, 3 },
f: fn(this: ^Window) { },
ctx: null,
gui: ui.mk(rect.Rect{}, res.getUiStyle()) } }
This can now be converted to the following code:
{ {
name: "Test window",
rect: { 20, 20, 64, 48 },
aspect: { 4, 3 },
f: { },
ctx: null,
gui: ui.mk({}, res.getUiStyle()) } }
This allows Umka code to be much cleaner and compact, although the programmer must make sure the code stays readable.
This new feature also allows you to create functions with keyword arguments. See this greeting function as an example:
type greetKWArgs = struct {
firstName: str
lastName: str
greeting: str
}
fn greet(a: greetKWArgs) {
if len(a.greeting) == 0 {
a.greeting = "Hello"
}
printf("%s, %s %s\n", a.greeting, a.firstName, a.lastName)
}
greet({ firstName: "Umka" }) // outputs: Hello, Umka
They also allow you to create great struct constructors.
type UserCfg* = struct {
name: str
username: str
}
type User* = struct {
name: str
email: str
username: str
id: int
}
fn mkUser*(email: str, cfg: UserCfg = {}): User {
if cfg.name == "" {
cfg.name = sprintf("Guest %d", std.rand() % 1000)
}
if cfg.username == "" {
cfg.username = usernameFromName(cfg.name)
}
return {
name: cfg.name,
username: cfg.username,
email: email,
id: fetchIdByEmail(email) }
}
As you can notice, providing email
is required, however the name and the
username can be generated by the constructor. For that reason they are
specified using the UserCfg
struct. id
on the other hand, is always
generated by the function.
Other articles
4MB game jam 2023
via Marek Maskarinec's website October 24, 2023Announcement: MMRE
via Marek Maskarinec's website October 24, 2023My smartwatch experience
via Marek Maskarinec's website October 24, 2023Generated by openring