• 0 Posts
  • 68 Comments
Joined 2 years ago
cake
Cake day: September 2nd, 2023

help-circle
  • The C example is the wonderful happy path scenario that only manifests in dreams.

    Most projects don’t have a dependency list you can just install in a single apt command. Some of those dependencies might not be even available on your distro. Or there is only a non-compatible version available. Or you have to cast some incantation to make that dependency available.

    Then you have to set some random environment variables. And do a bunch of things that the maintainers see as obvious since they do it every day, so it’s barely documented.

    And once you have it installed, you go to run it but discover that the fantastic CLI arguments you found online that would do what you installed this program to do, are not available in your version since it’s too new and the entire CLI was reworked. And they removed the functionality you need since it was “bad practice and a messy way to do things”.

    All of this assuming the installation process is documented at all and it’s not a “just compile it, duh, you should know how to do it”.


  • In my case, I don’t usually encounter cases where I can’t just ?. But when I do, just make an error enum (kinda like thiserror) that encapsulates the possible errors + possibly adds more.

    On the call site, just convert to string if I don’t care about specifics (anyhow-style).

    I don’t find this much painful.

    Concise: not much on the declaration side, since you have to create an entire enum for each function in worst-case scenario. But on code side, it’s just .map_err(MyError)?.

    Type-safe: can’t beat errors as enum values wrapped in Result.

    Composable: i don’t think you can beat rust enums in composability.

    I don’t use anyhow/thiserror, so I’m not sure. But I believe thiserror fixes the conciseness issue for this.



  • Rust allows you to choose whatever method you want.

    • Early return propagating the error
    • Early return ignoring the error (maybe by returning a default value)
    • Explicit handling by if-else (or match) to distinguish between error and not error cases.
    • Early return and turn the error into another type that is easier to handle by the caller.
    • Assume there is no error, and just panic if there is. (.unwrap)

    There are only 2 error handling methods that you cannot do:

    • Exceptions
    • Ignore the error and continue execution

    And that is because both of them are bad because they allow you to do the second one, when .unwrap is just there and better.

    If your concept of “not ugly” is “I just want to see the happy path” then you either write bad code that is “not ugly” or write good code that is “ugly”. Because there is no language that allows you to handle errors while not having error handling code near where the errors are produced.




  • You used macro_rules, which is not common at all. Most rust files don’t contain any macro definition.

    This code doesn’t even compile. There is a random function definition, and then there are loose statements not inside any code block.

    The loop is also annotated, which is not common at all, and when loops are annotated it’s a blessing for readability. Additionally, the loop (+annotation) is indented for some reason.

    And the loop doesn’t contain any codeblock. Just an opening bracket.

    Also, the function definition contains a lifetime annotation. While they are not uncommon, I wouldn’t say the average rust function contains them. Of course their frequency changes a lot depending on context, but in my experience most functions I write/read don’t have lifetime annotations at all.

    Yes, what you wrote somewhat resembles rust. But it is in no way average rust code.







  • My comment explicitly avoids the “standard” problem.

    A user could have many "theming system"s installed at once, while only having 1 DE. The user ideally would configure only one, and some program should try to translate that system into the other ones.

    Then each app will fetch the list of theming systems the user has installed, and choose whichever the app prefers. And if there’s no match, fall back to a default hard coded theme.



  • This can also be a side product for code blocks being expressions instead of statements.

    In rust for example they are, so it’s not rare to see functions like:

    fn add_one(x: i32) -> i32 {
        x+1
    }
    

    This lets you do amazing things like:

    let x = if y < 0.0 {
        0.0
    } else {
        y
    }
    

    which is the same as x = y < 0.0 ? 0.0 : y

    But is much better for more complex logic. So you can forget about chaining 3-4 ternary operations in a single line.


  • I’ve got all that. I just needed to convert a string of characters into a list of glyph IDs.

    For context, I’m doing a code editor.

    I don’t use harfbuzz for shaping or whatever, since I planned on rendering single lines of mono spaced text. I can do everything except string->glyphs conversion.

    Just trying to implement basic features such as ligatures is incredibly hard, since there’s almost no documentation. Therefore you can’t make assumptions that are necessary to take shortcuts and make optimizations. I don’t know if harfbuzz uses a source of documentation that I haven’t been able to find, or maybe they are just way smarter than me, or if fonts are made in a way that they work with harfbuzz instead of the other way around.

    As someone trying to have as little dependencies as possible, it is a struggle. But at the same time, harfbuzz saved me soo much time.

    EDIT: I don’t do my own glyph rasterization, but that’s because I haven’t gotten to it yet, so I do use a library. I don’t know if it’s going to be harder than string->glyphs, but I doubt so.


  • I cannot comprehend what the fuck harfbuzz does.

    I tried to implement my own because “I don’t need all the features, I’m gonna render self-to-right western text with very few font features”. But holly fuck, the font format documentation is barely non-existent. And when I tried my naive solution it was like 10000x (or more) slower than harfbuzz.


  • The problem with static mut is that it allows you to create multiple mutable references. And also mix mutable and immutable references. Additionally, it is accessible by any thread. So, as long as you don’t do any of that, it should be safe. Maybe I’m missing something.

    If this is the entire program, it’s not unsafe. But if it is just a fraction of the program, it may be unsafe. For example if 2 threads call the function at the same time. Since you would have 2 mutable references to BUF. Well, not actually unsafe since you don’t use the mutable reference, only create it.

    As to the other question, static variables are not in the stack. They have their own region of memory. If they were in the stack, they couldn’t be accessed across threads, since each thread has its own stack.

    EDIT: for completeness sake. For your last question. Yes, using a static buffer is probably more performant, since it doesn’t need to be set to 0 each time it’s called. However, that’s not what statics are for. If what you want is just to avoid that setting to 0, there are ways to get initialized arrays. For example MybeUninit. Which would be way better.



  • I don’t understand why any user would have to care or even know what GUI toolkit an app uses.

    I don’t know why the burden is put on the user/DE. You shouldn’t have to care about what GUI toolkit your DE uses either.

    DE and themes should be decoupled from eachother. So the user can install whatever “theming system” they want, and GUI toolkits should aim to support as many theming systems as practical.

    GUI toolkits are implementation details, the user doesn’t care about implementation, it cares about what it sees. And what it sees is the colors and icons.