Skip to content

Instantly share code, notes, and snippets.

@vassvik
Created September 25, 2017 00:41
Show Gist options
  • Save vassvik/b868fe130858f5408387a54389b048c6 to your computer and use it in GitHub Desktop.
Save vassvik/b868fe130858f5408387a54389b048c6 to your computer and use it in GitHub Desktop.
`using` in Odin
// Odin has a powerful keyword called `using`,
// which is similar to the `using` keyword in other languages like C++,
// but also a lot more versatile and powerful in Odin.
// The simplest case, that is similar to C++'s usage: it makes the names of an import name visible
// in function scope. Be careful, as this might call name collision.
fmt.println("This is a new line");
using fmt;
println("This is a new line, without fmt.");
fmt.println();
// A related, but slightly different use for `using` is while importing a file:
//
// import "core:fmt.odin"; // created an import name `fmt`
// using import "core:fmt.odin"; // creates an import name `fmt`, while also make the imported names visible at file scope.
//
// You can also use it to make names inside structs visible at function scope:
Foo :: struct {
an_int: int = -1,
a_string: string = "uninitialized",
};
using foo := Foo{42, "amazing"};
fmt.println(foo.an_int, foo.a_string);
an_int = 13;
a_string = "fabulous";
fmt.println(an_int, a_string);
fmt.println();
// A particularly practical use-case for this is to loop over containers by reference:
foos: [10]Foo;
for _, i in foos {
using t := &foos[i];
fmt.printf("i = %d: an_int = %v, a_string = '%v'\n", i, an_int, a_string);
an_int = i;
a_string = "initialized";
}
for _, i in foos {
using foo := &foos[i];
fmt.printf("i = %d: an_int = %v, a_string = '%v'\n", i, an_int, a_string);
}
// another useful case is to have implicit names in procedures, akin to methods in C++ where all the names in `this` is implicit
Weird_Struct :: struct {
a, b: int,
c, d: f64,
e: string,
};
Silly_Struct :: struct {
f: int,
g: f64,
h: string,
};
magic_proc :: proc(using w: ^Weird_Struct, using s: ^Silly_Struct) {
fmt.println(w^, s^);
w.b, s.f = s.f + 1, w.b - 2;
}
w: Weird_Struct;
s: Silly_Struct;
magic_proc(&w, &s);
magic_proc(&w, &s);
magic_proc(&w, &s);
magic_proc(&w, &s);
magic_proc(&w, &s);
magic_proc(&w, &s);
fmt.println();
// It can be used in defining variables in structs:
Vec2 :: struct {
using xy: struct {
x: f32 = 1.0,
y: f32 = 2.0,
}
};
v1: Vec2;
fmt.printf("xy = %v, x = %v, y = %v\n", v1.xy, v1.x, v1.y);
fmt.println();
// An even crazier example:
Vec4 :: struct #raw_union {
xyzw: struct {
x, y, z, w: f32
},
using x_yzw: struct #ordered {
x: f32,
yzw: struct {
y, z, w: f32
}
},
using xyz_w: struct #ordered {
xyz: struct {
x, y, z: f32
}
w: f32,
},
using xy_zw: struct #ordered {
xy: struct {
x, y: f32
}
zw: struct {
z, w: f32
}
},
using _yz_: struct #ordered {
pad1: f32,
using yz: struct {
y, z: f32
},
pad2: f32,
},
}
v: Vec4;
v.x, v.y, v.z, v.w = 1.0, 2.0, 3.0, 4.0;
fmt.printf("v = %v, size_of(v) = %v\n", v, size_of(v));
fmt.printf("v.x = %v, v.y = %v, v.z = %v, v.w = %v\n", v.x, v.y, v.z, v.w);
fmt.printf("v.xy = %v, v.yz = %v, v.zw = %v\n", v.xy, v.yz, v.zw);
fmt.printf("v.xyz = %v, v.yzw = %v\n", v.xyz, v.yzw);
fmt.printf("v.xyzw = %v\n", v.xyzw);
fmt.println();
// Finally, you can use `using` to make a struct array-like (indexable):
Array :: struct(T: type, N: int) {
using values: [N]T,
};
arr: Array(f64, 10);
arr[5] = 1.0;
fmt.printf("arr = %v\n", arr);
fmt.println();
// Note, this also works for vector types and slices
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment