Python still surprises

After the better part of 20 years working with Python, it still managed to surprise me today.

I’m so used to languages treating x += y et al. as pure sugar for x = x + y that it skipped my mind that some don’t.

I’m not surprised that you can override them separately in some languages (e.g. I simply assume this to be the case in C++, and on checking it turns out to be true — but that seems fair enough given the scope of the language), but I really am so accustomed to them being only sugar in Ruby that I assumed the same would hold, at least in effect, in Python.

Thus my surprise on some_list += x modifying some_list in place (unlike some_list = some_list + x), but once observed, I realised there’d be a separately-overridden operator function — namely __iadd__ — and so I figured it “had” to be that way.

Or did it? I then found myself assuming it’s because these operators can’t actually reassign the receiver, but in fact they can and do: the return value is what’s assigned to the LHS. So it’s just a matter of convention.

sint, kell 08:03:

my new theory is that satan Crept into this world through signed integers


I’ve been getting back into using CXXRTL and Zig together, so I’ve extracted and rendered somewhat reusable the bindings I made to use them together!

zxxrtl uses CXXRTL’s C API to provide a somewhat idiomatic way to access, manipulate, and respond to events happening in the design. Its README covers the setup — it’s a bit involved as it’s necessarily something of a build system, but once you’re done it’s good to go and flexible enough to be instrumented from a higher build system.

I’m going to paste the example usage here; this doesn’t use the Sample API for edge detection, and just drives the simulation while optionally recording VCD:

const Cxxrtl = @import("zxxrtl");

// Initialise the design.
const cxxrtl = Cxxrtl.init();

// Optionally start recording VCD. Assume `vcd_out` is `?[]const u8` representing an
// optional output filename.
var vcd: ?Cxxrtl.Vcd = null;
if (vcd_out != null) vcd = Cxxrtl.Vcd.init(cxxrtl);

defer {
    if (vcd) |*vcdh| vcdh.deinit();

// Get handles to the clock and reset lines.
const clk = cxxrtl.get(bool, "clk");
const rst = cxxrtl.get(bool, "rst");  // These are of type `Cxxrtl.Object(bool)`.

// Reset for a tick.;;
if (vcd) |*vcdh| vcdh.sample();;
if (vcd) |*vcdh| vcdh.sample();;

// Play out 10 cycles.
for (0..10) |_| {;
    if (vcd) |*vcdh| vcdh.sample();;
    if (vcd) |*vcdh| vcdh.sample();

if (vcd) |*vcdh| {
    // Assume `alloc` exists.
    const buffer = try;

    var file = try std.fs.cwd().createFile(vcd_out.?, .{});
    defer file.close();

    try file.writeAll(buffer);

Hopefully this is useful to someone else!