• 2 Posts
  • 646 Comments
Joined 1 year ago
cake
Cake day: September 2nd, 2023

help-circle








  • If you need to use bash a lot just to learn 2 “keywords”, then it’s not a good language.

    I have looked at bash scripts in the past, and even written some (small amount). I had to look up -z and -n every time. I’ve written a lot more python than bash, that’s for sure. But even if I don’t write python for a year, when needed I can just write an entire python script without minimal doc lookups. I just need to search if the function I want is part of syd, os or path.

    The first time I want to do an else if my IDE will mark it red and I’ll write eliffrom then on, same thing if I try to use { }.

    If a bash script requires at least one array and one if statement, I can write the entire thing in python faster than I can search how to do those 2 things in bash.


  • Well, to get a boolean out of a bit array you have to do some operations. So at first it doesn’t make it more performant. Compilers probably don’t automatically make them bitarrays because of that.

    However, the memory savings means less cache used. And a cache miss is way more expensive than those bit operations. So they should be more performant. I’m sure someone out there has done the actual research and there’s a good reason why compilers don’t make all booleans bitarrays.



  • I hate both of them. The first one is very clunky with all the ". The second one is not self-docummenting at all, and it makes some enums impossible.

    For example, you can’t represent:

    enum A {
        B(u32)
        C(u32)
        D
    }
    

    It would be

    A {
        | u32
        | u32
        | ()
    }
    

    Also, the pipe is very awkward to type, specially depending on keyboard layout. Since it’s a rare character. If you need to separate between enums and struts and really don’t want to use the enum and struct keywords, you can use different delimiters, like:

    A [
     u32,
     u32
    ]
    
    B {
     u32,
     u32
    }
    



  • In my experience, nobody really knows what OOP is, everyone has a different definition.

    Most of the “OOP” features are implemented in languages that are not OOP. The only one that is to me an OOP-exclusive feature is class-inheritance. So IMO OOP=class inheritance.

    There is plenty of criticism about inheritance, specially among rust lovers. Since rust implements other features associated with classes, except class inheritance. Such as: methods (and self keyword), interfaces (traits), default interface method implementation.

    Anti-OOPs usually argue that encapsulation and interface is a much better alternative to class inheritance.

    Some things class inheritance is criticized for:

    Diamond inheritance problem: If there is class A. B and C inherit from A and override its methods. D inherits B and C without overriding them. What implementation should D inherit? B or C? Same happens if only B or C overrides.

    Encourages having multiple layers of abstraction: it’s not uncommon to see huge inheritance chains. MyCustomList -> OrderedVector -> OrderedList and Vector -> List -> Collection -> Iterator. Just by looking at MyCustomList, you don’t know the entire chain, you just see “OrderedVector”. You have to follow many nested links until you can know it all, and then you have to retain that knowledge along with tens of other inheritance chains.

    Not ideal for performance: Inheritance encourages designs where the compiler will need to add a v-table to classes. These tables make implementation of OOP patterns much easier, but they require additional overhead when calling methods. Note that v-tables are not OOP specific, rust needs them also for trait objects. However, rust encourages designs with small amount of trait objects.

    Not as intuitive as claimed: People are taught OOP with simple examples involving real-world objects like: car -> vehicle -> object. However, these situations are rare except in some specific cases like UIs, video games, simulations. In most other cases, you are dealing with concepts rather than objects. And even when you’re dealing with objects, it’s not a clear cut. Sometimes it might happen that bicycle -> car. Even though not intuitive, in some situations this may be a useful inheritance. But when bicycle inherits car, it no longer resembles the inheritance-chain of the real world, so that’s extra work for the brain.






  • C:

    int increment(int i) {
        return (int) (1[(void*) i])
    

    However, if you wanna go blazingly fast you gotta implement O(n) algorithms in rust. Additionally you want safety in case of integer overflows.

    use std::error::Error;
    
    #[derive(Debug, Error)]
    struct IntegerOverflowError;
    
    struct Incrementor {
        lookup_table: HashMap<i32, i33>
    }
    
    impl Incrementor {
        fn new() -> Self {
            let mut lut = HashMap::new();
            for i in 0..i32::MAX {
                lut.insert(i, i+1)
            }
            Incrementor { lookup_table: lut }
        }
    
        fn increment(&self, i: i32) -> Result<i32, IntegerOverflowError> {
            self.lookup_table.get(i)
                .map(|i| *i)
                .ok_or(IntegerOverflowError)
    }
    

    On mobile so I don’t even know if they compile though.