Is there something special about the functionality provided by the builtins that cannot be expressed in the standard library? Do other languages have builtins?
I guess they are kind of like operators, you cant exactly express them without building them into the compiler.
Certain ones could be expressed as raw zig (memcpy), but others are somewhat more basal than that. I’m thinking of like @intFromPtr
. A lot of them map to direct instructions.
I see three broad categories: metaprogramming / reflection, compiler directives, and primitive instructions. A few oddballs which don’t fit that typology, many of those are C interop, but it covers most of the set.
With a few exceptions these are things which are either impossible or impractical/pointless to implement in Zig. Something like @bitCast
doesn’t really do anything, it tells the compiler “this number is now a struct”, @intCast
says “this large number is fitting into this smaller number and I guaranteed that it will”, and so on. Same with the metaprogramming, @typeInfo
needs to come from the compiler, because it’s the only thing which knows what a type is.
The ones like @sin
, if there was a Zig function implementing sine (absolutely possible) the optimizer would just have to recognize that function and turn it into FSIN or the like on chips which have it. Better to do it the other way around and emit a sine function directly in the case where it isn’t a single instruction.
I couldn’t honestly tell you why @min
and @max
aren’t in std.math
though. As in, unlike @sin
which also has std.math.sin
(which simply calls the former), there is no std.math.max
. I found this surprising when I was still picking up the language.
My sense is that the builtins are “things which should be provided by the compiler”, which of course includes everything which must be, and a few which simply happen to be. I don’t know of an exact equivalent in another language, and it struck me as somewhat unprincipled at first.
What I came around to is this: if you were stuck on a desert island with just the builtins, you could reimplement the standard library using just them. After that, it made sense.
I think it’s also worth pointing out that the standard library will be audited at some point in the future so all of this is subject to change.
There are also circumstances where you may not want to use std lib at all (e.g. embedded).
But this isn’t the case in zig right?
Zig has perhaps the laziest compiler ever, so only the stuff you use in the standard library will be compiled, and we have the allocator interface.
Is there a reason to avoid standard library use in zig?
There was std.math.max
back in 0.10.0. The decision to change it to a builtin probably has something to do with vector support.
I think you’re right about this. The only reason you’d want to avoid a function from std is if it’s implementation isn’t embedded friendly. You won’t include all of std when you import it. Just the parts you use.