Hacker News new | past | comments | ask | show | jobs | submit login

articles about rust don't have to include a link to "what is Rust" like this one does.



They did when Rust was as mature as Zig is now. Language popularity is a reasonable deciding factor when one is starting a project that has a hiring component; personal projects not so much.


For one thing I do not think you can implement allocator in Rust. This alone would disqualify it as a "low level"/"systems" language in my opinion.


You can implement an allocator in Rust; it's unclear why you think this is not possible.

One example:

- https://github.com/fitzgen/bumpalo


Worth noting that support for custom allocators in standard collections is not finalized yet: https://github.com/rust-lang/rust/issues/32838

The (awesome) bumpalo crate that you link to gets around this by providing ported implementations of Vec and String, but if you need e.g. a custom-allocated HashMap, you need to implement it yourself.


Thanks for the additional points! What you state is true, but somewhat orthogonal to the point that the grandparent post was making (and I sought to refute).

Creating an allocator is inherently possible. Using that allocator with the rest of the ecosystem is currently not stable, as you point out.

As a sometimes Rust embedded developer, I look forward to both parameterized allocators and fallible allocation.


Also worth noting that this is one thing Zig seems to have gotten quite right already: every standard library function which might need to allocate memory requires the user of that function to pass in an allocator of one's choosing, whether provided with the standard library or provided from scratch.

For example, I've been (slowly, given limited free time) working on a SQLite binding for Zig. SQLite has its own allocator, which I've wrapped like so:

    const std = @import("std");
    const Allocator = std.mem.Allocator;
    const ArrayList = std.ArrayList;
    
    // This is all ripped from Zig's C allocator, with adaptations to point to
    // SQLite's allocator instead.
    pub const allocator = &allocator_state;
    var allocator_state = Allocator{
        .reallocFn = realloc,
        .shrinkFn = shrink,
    };
    
    fn realloc(self: *Allocator,
               old_mem: []u8,
               old_align: u29,
               new_size: usize,
               new_align: u29) ![]u8 {
        std.debug.assert(new_align <= @alignOf(c_longdouble));
        const old_ptr =
            if (old_mem.len == 0) null else @ptrCast(*c_void, old_mem.ptr);
        const buf = sqlite3_realloc64(old_ptr, @intCast(u64, new_size))
            orelse return error.OutOfMemory;
        return @ptrCast([*]u8, buf)[0..new_size];
    }
    
    fn shrink(self: *Allocator,
              old_mem: []u8,
              old_align: u29,
              new_size: usize,
              new_align: u29) []u8 {
        const old_ptr = @ptrCast(*c_void, old_mem.ptr);
        const buf = sqlite3_realloc64(old_ptr, @intCast(u64, new_size))
            orelse return old_mem[0..new_size];
        return @ptrCast([*]u8, buf)[0..new_size];
    }
And later, to actually open a database (where we need an allocator to add a null byte to a Zig string to satisfy SQLite's expectations for a database name, so we might as well use SQLite's)¹:

    pub fn open(name: []const u8) !Database {
        // "allocator" here being the const-defined one above
        var cstrName = try std.cstr.addNullByte(allocator, name);
        defer allocator.free(cstrName);
        var db: Database = undefined;
        var rc = sqlite3_open(cstrName.ptr, &db);
    
        if (rc == SQLITE_OK) {
            return db;
        } else {
            _ = sqlite3_close(db);
            return errorCode(rc);
        }
    }
Of course, it'd be even better if such a wrapper actually used SQLite's own support for custom allocators to follow the Zig stdlib convention of allowing the user to supply one's own allocator. Going the other way seemed like a reasonable short-term choice, though, and it was a good enough excuse for me to learn the ropes on custom allocators (even if most of the code ultimately came from Zig's own C allocator).

----

¹: It turns out that this specific example will apparently be entirely unnecessary in future versions of Zig; the master branch documentation seems to do away with "Zig strings" v. "C strings", instead just making strings null-terminated by default (using what looks to be new support for "sentinel-terminated" pointers/arrays/slices). Looks like I've got some work to do :)


I said "I do not think". I do not really know Rust. Obviously I was wrong.


You also cannot fully implement libc in ISO C, without using either language extensions or an external Assembler.

So I guess it is not a "low level"/"systems".


True. You beat me. But C with extensions does qualify ;)


So does any other language with extensions, even stuff like CircuitPython.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: