News for hackers. Stuff that matters.
Re:Sayonara, C++, and Hello to Rust by kitd on Tuesday December 07, 2021 @04:04AM (#29470413)
I deeply miss C++ templates in most other languages, excepting fully dynamic languages, and D.

Have you tried Zig? Comptime templating it one of its selling points.

https://ziglang.org/documentation/0.8.1/#comptime

Re:Sayonara, C++, and Hello to Rust by moth-fuzz on Tuesday December 07, 2021 @04:19AM (#29470513)
I loooove Zig - my only gripe with Zig is that it feels somewhat arcane at times, and the documentation was borderline absent last I checked. I follow Andrew Kelley on twitter and am fascinated by his exploits. Crystal has a similar macro system that I enjoy, from what I've used of it. Rust macros are similarly satisfying in what you can accomplish with them, but the implementation is so immeasurably difficult, it's almost never worth it to bother, from a general design standpoint.

As far as C replacements go, Zig has my vote for the most approachable but also the most well thought-out. I couldn't sing its praises enough.

Re:Sayonara, C++, and Hello to Rust by lenkite on Tuesday December 07, 2021 @08:43AM (#29472341)
Would love Zig if it had RAII.
Re:Sayonara, C++, and Hello to Rust by AndyKelley on Friday December 10, 2021 @12:45AM (#29506814)
RAII works fine in Zig
Re:Sayonara, C++, and Hello to Rust by lenkite on Friday December 10, 2021 @04:11AM (#29507959)
Re:Sayonara, C++, and Hello to Rust by AndyKelley on Friday December 10, 2021 @04:17AM (#29507992)
show me a raii code example in C++ and I'll show you the zig equivalent
Re:Sayonara, C++, and Hello to Rust by lenkite on Friday December 10, 2021 @10:41AM (#29511169)
Note that in `good` below, one can have many such lock guards: lk1, lk2, etc without any explicit lock release expression in the body of the function.

    std::mutex m;
    void good()
    {
    std::lock_guard<std::mutex> lk(m); // RAII class: mutex acquisition is initialization
    f();                               // if f() throws an exception, the mutex is released
    if(!everything_ok()) return;       // early return, the mutex is released
    }                                      // if good() returns normally, the mutex is released
Re:Sayonara, C++, and Hello to Rust by AndyKelley on Friday December 10, 2021 @06:16PM (#29516648)

    var m: std.Thread.Mutex = .{};

    fn good() !void {
        m.lock();
        defer m.unlock();

        try f();
        if (!everything_ok()) return;
    }
It's still the RAII pattern. The explicit call to deinitialization does not disqualify it. I can overcomplicate it with a LockGuard class too:

    const LockGuard = struct {
        mutex: *std.Thread.Mutex,

        fn init(mutex: *std.Thread.Mutex) !LockGuard {
            mutex.lock();
            return .{
                .mutex = mutex,
            };
        }

        fn deinit(lg: *LockGuard) void {
            lg.mutex.unlock();
        }
    };

    fn good() !void {
        var lk = try LockGuard.init(&m);
        defer lk.deinit();

        try f();
        if (!everything_ok()) return;
    }
In this case it demonstrates an improvement over C++, which is what happens if an error happens during a constructor. In C++ throwing an exception in a constructor is essentially UB; in zig it's a regular function call just like anything else.
Re:Sayonara, C++, and Hello to Rust by lenkite on Sunday December 12, 2021 @01:42PM (#29532305)
Thanks for the informative snippet, but explicit expressions involving defer is not what RAII means. In RAII resource is automatically tied to object lifetime.

https://en.wikipedia.org/wiki/Resource_acquisition_is_initia...

Regarding errors in a C++ constructor: https://isocpp.org/wiki/faq/exceptions#ctors-can-throw