HackerTrans
TopNewTrendsCommentsPastAskShowJobs

ioanaci

12 karmajoined 8 ay önce

comments

ioanaci
·3 gün önce·discuss
Many people that use linux distros like postmarketos on ARM phones also have waydroid for running android apps.
ioanaci
·6 ay önce·discuss
> Fun fact: Bhutan is perhaps the only country in the world without traffic lights!

Afaict they have police officers regulating traffic instead. Not much difference in this particular discussion.
ioanaci
·7 ay önce·discuss
I also feel like map[T]struct{} communicates its purpose way better than map[T]bool. When I see a bool I expect it to represent a bit of information, I don't see why using it as a placeholder for "nothing" would be more readable than a type that can literally store nothing.
ioanaci
·8 ay önce·discuss
I commented this before but deleted it because I hadn't tested my code properly. Anyway, here is a version that works.

You're right Zig isn't quite as powerful, but you don't need type erasure if you have enough monomorphization. It's a bit annoying to use since you have to capture the comptime version of b inside the inline switch prongs, and get_value does need to take a comptime bool instead of a runtime one. It's functionally the same, except that instead of using the bool to prove the type of the type-erased value is correct and delaying the actual if (b) check to runtime, we're moving it to compile time and instead proving that b has the right value for each case, then generating specialized code.

This does NOT mean that it isn't dependent on user input, the call do_thing(get_user_input()) would absolutely work. do_thing has no compile-time parameters at all.

I don't have the natToString thing because it's a bit more annoying in Zig and would obscure the point.

    const std = @import("std");
    
    fn get_value(comptime b: bool) if (b) u32 else []const u8 {
        if (b) return 12
        else return "string";
    }
    
    fn do_thing(b: bool) void {
        switch (b) {
            inline true => |known_b| std.log.info("{d}", .{get_value(known_b)}),
            inline false => |known_b| std.log.info("{s}", .{get_value(known_b)}),
        }
    }
    
    pub fn main() void {
        do_thing(true);
        do_thing(false);
    }
You could define a function

    fn pick_type(comptime b: bool) type {
        if (b) return u32 else return []const u8;
    }
and change the signature

    fn get_value(comptime b: bool) pick_type(b)
if you wish.

Perhaps more convincingly, you can use inline for with a similar effect. It's obviously horrible code nobody would ever write but I think it might illustrate the point.

    fn do_thing(b: bool) void {
        inline for (0..2) |i| { // go through all bool variants
            const known_b = (i != 0);
            
            if (known_b == b) {
                // Essentially what we have now is a known_b which is proven
                // at compile-time to be equal to whatever runtime b we have.
                // So we're free to do any kind of dependent type things we'd like
                // with this value.
                
                const value = get_value(known_b);
                // Here we know the type of value but it still depends on the runtime b.
                
                if (known_b) std.log.info("{d}", .{value}) // treated as an int
                else std.log.info("{s}", .{value}); // treated as a string
                
                // We can also just decide based on the type of value at this point.
                if (@TypeOf(value) == u32) ... else ...;
                // Or, a switch
                switch (@TypeOf(value)) {
                    u32 => ...,
                    []const u8 => ...,
                }
            }
        }
    }