Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Here's an excerpt from std.ArrayList[1]:

    pub fn ArrayList(comptime T: type) type {
        return struct {
            const Self = @This();

            raw_items: []T,
            len: usize,
            allocator: *Allocator,

            // ...

            pub fn append(self: *Self, item: T) !void {
                const new_item_ptr = try self.addOne();
                new_item_ptr.* = item;
            }
            
            pub fn addOne(self: *Self) !*T {
                const new_length = self.len + 1;
                try self.ensureCapacity(new_length);
                return self.addOneAssumeCapacity();
            }
            
            // ...
        };
    }


    test "std.ArrayList.basic" {
        var bytes: [1024]u8 = undefined;
        const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator;

        var list = ArrayList(i32).init(allocator);

        try list.append(1);
        try list.append(2);
        try list.append(3);

        assert(list.len == 3);
    }

In summary, functions that can fail have an inferred error set, or an explicit one[2]. At the callsite of functions that can fail will either be `if`, `while`, `catch`, or `try`, in order to deal with the error case.

[1]: https://github.com/ziglang/zig/blob/e3d8cae35a5d194386eacd9a...

[2]: https://ziglang.org/documentation/master/#Error-Set-Type



Neat! So yeah, reducing Result to ! and inferring errors makes this way less boiler-plate-y. One of Rust's core design decisions is that we should never do type inference for function definitions, so we can't do this.

And yeah, if you hold a pointer to the allocator instead of parameterizing by it, that helps too. With that in mind,

  fn append(&mut self, item: i32) -> Result<(), Box<Error>> {
      v.push_back(item)?;
  }
In today's Rust, which is sort of what already happens; a given instance can't change the allocator, but refers to the global one. I don't have a great handle on the tradeoffs from keeping a pointer vs parameterization.

Anyway, yeah, if we allowed for inferring the error type, that would make this almost the same as Zig here. Stealing your syntax:

  fn append(&mut self, item: i32) -> !() {
      v.push_back(item)?;
  }
A four character diff from current Rust. Very cool! Thanks for the elaboration. That's quite nice.




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

Search: