Ramblings about things

For humans, by humans (optional)

Don't you just love it when the source code you're reading looks like it was made to be read, as opposed to write-only code?

When you're in the middle of working on something and you're not quite sure how to hold the thing in your hands (lest it breaks), one (hopefully) consults the manual.

But if said manual isn't up to date (if it even exists), sometimes you just wish you could read the standard library to see what the authors had in mind when creating it.

Well let me tell you, that is a perfectly reasonable wish!

Unless you're a C++ programmer, which you've probably surmised what a Sisyphean task that really is early in your career.

I mean, just look at this1:

#if __cplusplus > 201402L
	reference
#else
	void
#endif
	emplace_back(_Args&&... __args)
	{
	  if (std::__is_constant_evaluated())
	    return _Base::emplace_back(std::forward<_Args>(__args)...);

	  bool __realloc = this->_M_requires_reallocation(this->size() + 1);
	  _Base::emplace_back(std::forward<_Args>(__args)...);
	  if (__realloc)
	    this->_M_invalidate_all();
	  this->_M_update_guaranteed_capacity();
#if __cplusplus > 201402L
	  return back();
#endif

      // 23.2.4.3 modifiers:
      _GLIBCXX20_CONSTEXPR
      void
      push_back(const _Tp& __x)
      {
	if (std::__is_constant_evaluated())
	  return _Base::push_back(__x);

	bool __realloc = this->_M_requires_reallocation(this->size() + 1);
	_Base::push_back(__x);
	if (__realloc)
	  this->_M_invalidate_all();
	this->_M_update_guaranteed_capacity();
      }

These are std::vector::emplace_back and std::vector::push_back2 in case blood is obstructing your vision.

Who in their right mind would take a look at this and think "Ah yes, I obviously wanted emplace_back here instead of push_back"?

Whereas on the other hand if you wish to read how would you append something to an ArrayList in zig:

/// Extend the list by 1 element. Allocates more memory as necessary.
/// Invalidates element pointers if additional memory is needed.
pub fn append(self: *Self, gpa: Allocator, item: T) Allocator.Error!void {
    const new_item_ptr = try self.addOne(gpa);
    new_item_ptr.* = item;
}

/// Increase length by 1, returning pointer to the new item.
/// The returned element pointer becomes invalid when the list is resized.
pub fn addOne(self: *Self, gpa: Allocator) Allocator.Error!*T {
    // This can never overflow because `self.items` can never occupy the whole address space
    const newlen = self.items.len + 1;
    try self.ensureTotalCapacity(gpa, newlen);
    return self.addOneAssumeCapacity();
}

/// Increase length by 1, returning pointer to the new item.
/// Never invalidates element pointers.
/// The returned element pointer becomes invalid when the list is resized.
/// Asserts that the list can hold one additional item.
pub fn addOneAssumeCapacity(self: *Self) *T {
    assert(self.items.len < self.capacity);
    self.items.len += 1;
    return &self.items[self.items.len - 1];
}

But the reason I actually wanted to praise zig and what got me started on this is the fact that I can look at the tests for the standard library, without wondering where did my life go wrong.

I wanted to make a HTTP server and saw that there are both std.net.Server and std.http.Server available. The documentation being what it is3 left me wanting so I turned to the source code4, and it was a godsend!

One of the tests creates a server that echoes back the content you send in, which is pretty darn useful when you have no idea how to use the things the standard library offers! And of course it uses the Reader/Writer interfaces which was quite a big change so you get two for one!

Don't take my word for it, judge for yourself if this is readable or not:

test "echo content server" {
    const test_server = try createTestServer(struct {
        fn run(test_server: *TestServer) anyerror!void {
            const net_server = &test_server.net_server;
            var recv_buffer: [1024]u8 = undefined;
            var send_buffer: [100]u8 = undefined;

            accept: while (!test_server.shutting_down) {
                const connection = try net_server.accept();
                defer connection.stream.close();

                var connection_br = connection.stream.reader(&recv_buffer);
                var connection_bw = connection.stream.writer(&send_buffer);
                var http_server = http.Server.init(connection_br.interface(), &connection_bw.interface);

                while (http_server.reader.state == .ready) {
                    var request = http_server.receiveHead() catch |err| switch (err) {
                        error.HttpConnectionClosing => continue :accept,
                        else => |e| return e,
                    };
                    if (mem.eql(u8, request.head.target, "/end")) {
                        return request.respond("", .{ .keep_alive = false });
                    }
                    if (request.head.expect) |expect_header_value| {
                        if (mem.eql(u8, expect_header_value, "garbage")) {
                            try expectError(error.HttpExpectationFailed, request.readerExpectContinue(&.{}));
                            request.head.expect = null;
                            try request.respond("", .{
                                .keep_alive = false,
                                .status = .expectation_failed,
                            });
                            continue;
                        }
                    }
                    ...
                }
            }
        }
        ...
    });
}

There are still some questions to be had, but at least it's unmistakably zig code, and not some monstrosity.

The point

So in short - readability is an important UX quality that I think zig is doing quite a good job of. That's in line with Andrew's view on things - it's accessible.

At least more accessible than some system languages5.


  1. I didn't format it, copied it straight from the source on my machine.

  2. I'm not even sure these are the right implementation what with overloading and all, which is a remark in and of itself.

  3. Given that zig is a relatively new kid on the block it's not that surprising.

  4. Highly recommended in general, not just for zig!

  5. Yes, I'm looking at both of you, Rust and C++.

#zig