9000's recent activity

  1. Comment on Progress update on Git's migration from SHA-1 to SHA-256 in ~comp

    9000
    Link Parent
    They address a real world example where this could have happened: Essentially, the attacker could have poisoned the server's copy of floppy.c, and since HEAD's hash would still match, no one would...

    They address a real world example where this could have happened:

    The compromise of kernel.org in 2011 created a fair amount of concern about the security of the kernel source repository. If an attacker were able to put a backdoor into the kernel code, the result could be the eventual compromise of vast numbers of deployed systems.

    Essentially, the attacker could have poisoned the server's copy of floppy.c, and since HEAD's hash would still match, no one would suspect anything. Then, any clones from kernel.org would result in the poisoned file being returned, which would slowly start to poison many people's kernel repositories. Depending on where in the code base the backdoor was inserted, it could be a long time before people find the vulnerability and trace its source.

    If this were to happen on the scale of GitHub, there would be madness (though, Linux is infrastructure-critical too). They could selectively poison individual projects, or even individual developer's repositories, without any major red flags.

    3 votes
  2. Comment on At ten thousand page views a month, Tildes emits the same amount of carbon as one tree absorbs in one year. in ~enviro

    9000
    Link
    According to this site, Tildes uses as much carbon in a year as a tree (whatever that metric means) absorbs in a year. Should we start a yearly tradition of planting a tree to offset our carbon?...

    According to this site, Tildes uses as much carbon in a year as a tree (whatever that metric means) absorbs in a year. Should we start a yearly tradition of planting a tree to offset our carbon? It sounds cheap enough to be doable, and like a fun tradition!

    32 votes
  3. Comment on What are your recommendations for self hosting? in ~comp

    9000
    Link Parent
    I did mean running it as a desktop client, yes. That way, the only requests Riot has to make to your server are for chats, otherwise, it will also have to request all of the HTML, JavaScript, etc,...

    I did mean running it as a desktop client, yes. That way, the only requests Riot has to make to your server are for chats, otherwise, it will also have to request all of the HTML, JavaScript, etc, and potentially make many more calls, which will likely choke more on the 1 mb/s up connection.

    1 vote
  4. Comment on What are your recommendations for self hosting? in ~comp

    9000
    Link
    So, a Pi-Hole is a great choice, and very easy to implement! It has a lot of great documentation, and I highly recommend it. On the Matrix front, I would hesitate a little. First, the main server...

    So, a Pi-Hole is a great choice, and very easy to implement! It has a lot of great documentation, and I highly recommend it.

    On the Matrix front, I would hesitate a little. First, the main server implementation for Matrix is Synapse, which is known to have performance issues. There are several alternative implementations (notably, Dendrite), but as far as I know, no alternative server implementation is ready to be run full time. Synapse is the only one that is standards compliant, and until that changes, you will have a hard time running a Matrix homeserver on a Raspberry Pi. However, if you have a server with some more power, you could get it running. There are lots of guides online, however, it's still going to be more effort to manage, and manage securely. If you're looking for a fun project to learn a lot, then great! But if you want to have a very secure system for your messaging, you may find Synapse's configuration and upkeep a little complicated to keep very secure, especially as a first time project.

    To answer your other questions, the DSL connection is slow, which isn't great, but it should still run. If I were you, I'd install Riot locally instead of hosting it as a website, then your only bandwidth limitation is the Synapse server. Alternatively, you can get a pretty cheap VPS, but then you no longer own the hardware. I dunno how you feel about that.

    Yes, voice and video should work, but they will require a little configuration (this is not related to your connection speed). And, my understanding is that Matrix calls are peer-to-peer, and only use the server to establish a connection, so your server connection being slow should not hurt you too much here.

    And yes! Your self-hosted account will be able to talk to others! This is what people mean by 'federation'. It's one of the major features of Matrix.

    One final note, if you do self-host Synapse at home, even if the bandwidth is okay for your server, you may find it slowing down the rest of your connection, or your server's performance being very variable depending on what you're doing on your other machines (watching videos, etc.).

    4 votes
  5. Comment on What programming/technical projects have you been working on? in ~comp

    9000
    Link
    I mean, it's not really a cohesive project, but this past week or two, I've been making a conscious effort to document and attempt to fix many of the minor bugs that have been bothering me in the...

    I mean, it's not really a cohesive project, but this past week or two, I've been making a conscious effort to document and attempt to fix many of the minor bugs that have been bothering me in the FLOSS software I use regularly. There were a couple GitHub issues that sat silent for a few months that I decided to finally investigate and get to the bottom of, and a few other things I hadn't even filed issues for, that I also attempted to fix. Some of these efforts were more successful than others, but it was productive on the whole.

    In addition to being personally beneficial, I think this was a great learning exercise, since I had no experience with these code bases, and oftentimes no experience with the language.

    15 votes
  6. Comment on Fact-check: Five claims about thorium made by Andrew Yang in ~enviro

    9000
    Link Parent
    I read through the thread you linked (or, what was still available of it), and I see what you're getting at. However, I feel like the sentiment quoted right here goes much too far. I have a few...

    I just kinda accept that this is a fuzzy concept that I won't ever know enough to have an opinion on, and avoid it like the plague.

    I read through the thread you linked (or, what was still available of it), and I see what you're getting at. However, I feel like the sentiment quoted right here goes much too far.

    I have a few reasons for this belief. First, sometimes partial or vague knowledge is still useful or important, as long as it is accurate (even if it is not sufficiently precise). There are a lot of topics that are deeply complicated, but which have general rules that help people navigate the day-to-day. Algebra can get complicated and unintuitive, but my high school understanding of it has been deeply enriching to my life, even if I could not sufficiently explain it at a PhD level. However, you seem to be talking about stuff at the bleeding edge of research, yet, even there it can be useful to have a vague grasp. For instance, the reproducibility crisis affecting psychology and the other social sciences. Do I have a Ph.D. in social science or experimental design? No. But, understanding that a large amount of relatively new research is overturning a lot of my conventionally held wisdom tips me off that I should remain skeptical of a lot of that conventional advice until the expert community comes to a new consensus. Following that new research leaves me more informed, even if I am not in an intellectual position to create novel research in the field myself.

    Second, living in a democracy, it is our duty to make decisions on a plethora of topics, some deeply complicated. Science can answer questions like, "What is the probability distribution of deaths in the event of a reactor meltdown?", but it cannot answer questions like, "Is that an appropriate risk given the economic benefits? Will the people be okay with this trade off?". That second set of questions can only be answered in a political process that also cites deep and complicated research from an entirely different field (economics), but must gain approval from the masses for political legitimacy. Those questions should not only be answered by the very few people who have PhDs in both nuclear physics and nuclear economics. Sure, it is very important for experts to give us the facts and to contextualize those facts as neutrally as possible, but we shouldn't avoid having an opinion like the plague! Foreign policy is complicated, U.S. involvement in Syria is complicated, much less the rest of the Middle East. Experts must be consulted. But change can only occur if there is political will for it, and that means entrusting the lay people to have opinions.

    Third, if we don't trust anyone but experts to engage with the experts, we leave them entirely to self-regulation. While in some places this can make sense, it can also lead to deeply troubling political outcomes. For instance, the methodology you espouse is essentially the same reasoning that leads to regulatory capture. ISPs understand the intricacies of being an ISP much better than anyone else, so an ex-Verizon executive should run the FCC. Only someone deeply engrossed in the fossil fuel industry is qualified to understand its supply chains and motivations, so someone from that industry should be put in charge of regulating it. Barbers know who the best barbers are, so people should be required to be licensed before they can cut hair for money (!!). The list goes on, but my point is that when left unchecked by the rest of society, a small group (even of highly educated people) is liable to swerve from common sense towards corruption. I am not saying that modern science is currently this way, but if we are sufficiently convinced that we shouldn't even try to understand why they believe certain things without formal degrees, it is an inevitable outcome.

    Finally, in the conversation you cite, you argue that what we should do is evaluate the credibility of our sources, and then choose whether to believe them or not1. By asking Amarok to provide sources, we can engage in exactly that evaluation. Is Amarok getting his information primarily from Berkeley, as in that first link, or some sketchy site? Are they representing one side of an issue that is legitimately controversial in its field, or are they repeating fringe theories? These questions can be evaluated by examining their citations, even if we don't try and interpret the primary sources ourselves. Ideally, Amarok is acting as a tertiary or even a quaternary source, and so citing quality secondary and tertiary sources can make their claims more credible.

    Ultimately what I'm saying is this: yes, these topics are complicated, and yes, as lay people, we should not presume to have knowledge equivalent to experts. But, the solution is not to run in the opposite direction and plug our ears to big issues, but to continue to struggle with these issues and temper our confidence to be in line with our learning.


    1. An aside: this too seems like a skill that requires ever more specialization to master. In fact, it is not uncommon to hear arguments that journalists are themselves these experts, but that leaves a remaining question: which journalists do you trust to find which scientists to trust to find which research to trust?
    7 votes
  7. Comment on How do you organize your digital files? in ~tech

    9000
    Link
    I self-host Nextcloud on a server at home, which backs up to a pi with an external HDD off-site. I manage these backups with Borg. For all of the things not in Nextcloud (config files, etc.), I...

    Do you do backups? If so, how? (Cloud storage, offline backups, etc.)

    I self-host Nextcloud on a server at home, which backs up to a pi with an external HDD off-site. I manage these backups with Borg. For all of the things not in Nextcloud (config files, etc.), I also use Borg to backup to the same Pi. I just recently had to rebuild my entire stack, so I am confident that these backups work, although I have not sufficiently automated restoring from them.

    Do you use your OS's default user folders (Documents, Pictures, Downloads, Desktop, etc.) or do you opt for a more custom scheme?

    I have used my system defaults with a few extras for a while, but am just now experimenting with something more custom. At the very least, I renamed all files to be lowercase to make command line navigation easier. I also removed some directories I don't use, and added a few top level that I felt were helpful (I will cover these in answers below).

    Do you use your browser's default download directory, or do you do something more custom?

    I have ~/download set to be my default, but I have my browser ask me where to download every time. It's annoying 30% of the time, and useful 70% of the time.

    Do you navigate through your files using a file browser, the command line, or both?

    Both, really. It depends on the file and what I need to do with it.

    Do you have any naming conventions for files and folders? (Dash/underscore/space delimiting? Lower/uppercase?)

    Mostly camel case, but the files are really not as standardized as they should be.

    Where do you store code repositories (if that's something you do), and do you make a distinction between code repositories and documents?

    I have ~/code/ in my home folder for code repositories. Since they are almost all git repositories that are backed up elsewhere, they are not usually included in my backup regime.

    How do you deal with programs that automatically create directories in your workspaces without your permission? (I'm looking at you, IDEs with "Projects" folders.)

    I don't have a good answer to this yet. One I have heard, but not tried, is setting your home directory to be read-only, but I don't know how much that may or may not break things.

    How do you handle media storage? Do you use any library managers for ebook/pdf files, image files, music files, video files, etc.?

    I use Calibre for e-books, Airsonic (soon to be moved to Funkwhale) on my server for music, and Jellyfin on my server for videos. All images and documents are in Nextcloud, and I manage those mostly by hand.

    How do you handle document/note storage? Do you use files in the Documents folder, or do you use an alternative method like cloud-based office tools, or some sort of wiki-ish program like Indigrid or Trillium?

    Mostly I use a file hierarchy in Nextcloud, although not all of it is well organized. My school folder is well organized since the input data is nice and hierarchical and I use it regularly. The hierarchy goes: School name >> Semester >> Class >> Project. My photos are partially organized. The old ones from before my organization are a mess, but any recent ones are synced into a folder based on the device they come from, and they retain timestamps. My documents are a mess, I have some folders to help, but nothing cohesive.

    If you use a Linux-based OS, where do you put sandboxed/portable applications (e.g. snap, flatpak, appimage)?

    I also have a ~/programs/ directory in my home folder where I mostly keep these. Really, this folder is for code I do not intend to hack on, just to use, so there are some compiled git repositories in there as well. ~/code/ is exclusively for source code I want to look at or manipulate, and is mostly git repos and some extracted tar files.

    6 votes
  8. Comment on Day 4: Secure Container in ~comp

    9000
    Link
    Language: Rust As everyone else is saying, this one was much easier. I felt that there was probably a pure math way to solve this, but I couldn't quite work it out and I don't think it would work...

    Language: Rust

    As everyone else is saying, this one was much easier. I felt that there was probably a pure math way to solve this, but I couldn't quite work it out and I don't think it would work for arbitrary ranges. Anyway, the solution:

    Solution
    fn main() {
        let mut num_1: usize = 0;
        let mut num_2: usize = 0;
        for n in 382345..843167{
            let mut increasing = true;
            let mut double_1 = false;
            let mut double_2 = false;
            let mut prev_digit = n % 10;
            let mut run_length = 1;
            for digit in 1..6 {
                let next_digit = (n / 10_u32.pow(digit)) % 10;
                if prev_digit < next_digit {
                    increasing = false;
                    break;
                } else if prev_digit == next_digit {
                    double_1 = true;
                    run_length += 1;
                } else {
                    if run_length == 2 {
                        double_2 = true;
                    }
                    run_length = 1;
                }
                prev_digit = next_digit;
            }
            if increasing && double_1 {
                num_1 += 1;
            }
            if increasing && (double_2 || run_length == 2) {
                num_2 += 1;
            }
        }
    
        println!("Number of passwords (Part 1): {}", num_1);
        println!("Number of passwords (Part 2): {}", num_2);
    }
    
    2 votes
  9. Comment on Day 3: Crossed Wires in ~comp

    9000
    Link
    Language: Rust This problem was much more intricate, so the code is much more complicated. I really wish it was cleaner and easier to follow. I had to refactor several times to get part 2 to work...

    Language: Rust

    This problem was much more intricate, so the code is much more complicated. I really wish it was cleaner and easier to follow. I had to refactor several times to get part 2 to work at all. If people have readability suggestions, I'm willing to listen (though, please don't be too pedantic).

    When I first started working on this problem, I tried to be clever and account for the case where two horizontal or two vertical wires crossed, and then choose the correct point. It's possible, but super complicated and not necessary for the problem, so I gave up (hence the _ case in the cross_*() functions).

    Part 1 and 2
    use std::fs;
    use std::vec::Vec;
    
    struct Line {
        horizontal: bool,
        x: isize,
        y: isize,
        length: isize,
    }
    
    impl Line {
        fn new (line: &str, x: &mut isize, y: &mut isize) -> Line {
            let (dir, length) = line.split_at(1);
            let length = length.parse().unwrap();
    
            let ret;
            match dir {
                "R" => {
                    ret = Line {horizontal : true, x : *x, y : *y, length : length};
                    *x += length;
                }
                "D" => {
                    ret = Line {horizontal : false, x : *x, y : *y, length : -1 * length};
                    *y -= length;
                }
                "L" => {
                    ret = Line {horizontal : true, x : *x, y : *y, length : -1 * length};
                    *x -= length;
                }
                "U" => {
                    ret = Line {horizontal : false, x : *x, y : *y, length : length};
                    *y += length;
                }
                _ => {panic!("Cannot parse line: {}", line);}
            }
    
            ret
        }
    
        /* Returns the point at which the lines cross (if they do cross)
         * Only used for part 1
         */
        fn cross_point(&self, other: &Line) -> Option<(isize, isize)> {
            match (self.horizontal, other.horizontal) {
                (true, false) => {
                    let (self_lower, self_upper) = order(self.x, self.x + self.length);
                    let (other_lower, other_upper) = order(other.y, other.y + other.length);
                    if self_lower < other.x
                        && self_upper > other.x
                        && other_lower < self.y
                        && other_upper > self.y {
                            return Some((other.x, self.y))
                        }
                }
                (false, true) => {
                    let (self_lower, self_upper) = order(self.y, self.y + self.length);
                    let (other_lower, other_upper) = order(other.x, other.x + other.length);
                    if self_lower < other.y
                        && self_upper > other.y
                        && other_lower < self.x
                        && other_upper > self.x {
                            return Some((self.x, other.y))
                        }
                }
                _ => {}
            }
    
            None
        }
    
        /* Returns the length of wire, until the lines cross, for each line (if they do cross)
         * Only used for part 2
         */
        fn cross_length(&self, other: &Line) -> Option<(isize, isize)> {
            match (self.horizontal, other.horizontal) {
                (true, false) => {
                    let (self_lower, self_upper) = order(self.x, self.x + self.length);
                    let (other_lower, other_upper) = order(other.y, other.y + other.length);
                    if self_lower < other.x
                        && self_upper > other.x
                        && other_lower < self.y
                        && other_upper > self.y {
                            return Some(((other.x - self.x).abs(), (self.y - other.y).abs()))
                        }
                }
                (false, true) => {
                    let (self_lower, self_upper) = order(self.y, self.y + self.length);
                    let (other_lower, other_upper) = order(other.x, other.x + other.length);
                    if self_lower < other.y
                        && self_upper > other.y
                        && other_lower < self.x
                        && other_upper > self.x {
                            return Some(((self.x - other.x).abs(), (other.y - self.y).abs()))
                        }
                }
                _ => {}
            }
    
            None
        }
    
    }
    
    fn main() {
        let paths = fs::read_to_string("input").unwrap();
        let paths: Vec<&str> = paths.split('\n').collect();
        let mut x = 0;
        let mut y = 0;
        let path_1: Vec<Line> = paths[0].split(',').map(|line| {Line::new(line.trim(), &mut x, &mut y)}).collect();
        x = 0;
        y = 0;
        let path_2: Vec<Line> = paths[1].split(',').map(|line| {Line::new(line.trim(), &mut x, &mut y)}).collect();
    
        println!("The closest point by Manhattan distance (Part 1): {}", manhattan_distance_of_closest_point(&path_1, &path_2));
        println!("The closest point by wire distance (Part 2): {}", wire_distance_of_closest_point(&path_1, &path_2));
    }
    
    /* Finds the closest point by Manhattan distance, and returns that distance.
     * Only used for part 1
     */
    fn manhattan_distance_of_closest_point(path_1: &Vec<Line>, path_2: &Vec<Line>) -> isize {
        let mut closest_point: isize = isize::max_value();
        for line_1 in path_1 {
            for line_2 in path_2 {
                match line_1.cross_point(line_2) {
                    Some((x, y)) => {
                        if x.abs() + y.abs() < closest_point {
                            closest_point = x.abs() + y.abs();
                        }
                    }
                    None => {}
                }
            }
        }
    
        closest_point
    }
    
    /* Finds the closest point by cumulative wire length, and returns that distance.
     * Only used for part 2
     */
    fn wire_distance_of_closest_point(path_1: &Vec<Line>, path_2: &Vec<Line>) -> isize {
        let mut closest_point: isize = isize::max_value();
        let mut line_1_length = 0;
        for line_1 in path_1 {
            let mut line_2_length = 0;
            for line_2 in path_2 {
                match line_1.cross_length(line_2) {
                    Some((line_1_cross_dist, line_2_cross_dist)) => {
                        if line_1_length + line_1_cross_dist + line_2_length + line_2_cross_dist < closest_point {
                            closest_point = line_1_length + line_1_cross_dist + line_2_length + line_2_cross_dist;
                        }
                    }
                    None => {}
                }
                line_2_length += line_2.length.abs();
            }
            line_1_length += line_1.length.abs();
        }
    
        closest_point
    }
    
    #[inline]
    fn order(n: isize, m: isize) -> (isize, isize) {
        if n < m {
            return (n, m);
        }
        (m, n)
    }
    
    2 votes
  10. Comment on Day 1: The Tyranny of the Rocket Equation in ~comp

    9000
    Link
    Language: Rust I initially thought that we had to run the rocket equation on the total mass of fuel instead of each module's fuel, so my initial answer was high. But, that was just me misreading...

    Language: Rust

    I initially thought that we had to run the rocket equation on the total mass of fuel instead of each module's fuel, so my initial answer was high. But, that was just me misreading the instructions.

    Part 1 I got a little carried away with argument parsing in my main function... It's way too complicated. I should have just assumed there would be one file. Oh well.
    /* day_1
     *
     * USAGE
     *     cargo run [input files]
     * 
     * Input files must be a newline-separated list of positive integers greater 
     * than 5. For each input file listed, day_1 will return the answer for both
     * part one and part two.
     *
     */
    
    use std::env;
    use std::fs;
    use std::vec::Vec;
    
    fn main() {
        let args: Vec<String> = env::args().collect();
        if args.len() <= 1 {
            eprintln!("File name(s) required!");
            return;
        }
    
        for index in 1..args.len() {
            println!("{}", args[index]);
            println!("----------");
            let mut module_masses: Vec<u32> = Vec::new();
            for line in fs::read_to_string(&args[index]).unwrap().lines() {
                module_masses.push(line.parse().unwrap());
            }
            println!("Fuel required for modules (part 1): {}", calculate_fuel_required_for_part_one(&module_masses));
            println!("Fuel required for modules (part 2): {}", calculate_fuel_required_for_part_two(&module_masses));
            if index != args.len() - 1 {
                println!();
            }
        }
    }
    
    fn calculate_fuel_required_for_part_one(module_masses: &Vec<u32>) -> u32 {
        let mut total_fuel = 0;
        for module_mass in module_masses {
            total_fuel += (module_mass / 3) - 2;
        }
    
        total_fuel
    }
    
    fn calculate_fuel_required_for_part_two(module_masses: &Vec<u32>) -> u32 {
        let mut total_fuel = 0;
        for module_mass in module_masses {
            total_fuel += calculate_fuel_required_for_a_module(module_mass);
        }
    
        total_fuel
    }
    
    fn calculate_fuel_required_for_a_module(mass: &u32) -> u32 {
        let mut total_fuel = 0;
        let mut fuel_delta = (mass / 3) - 2;
    
        while fuel_delta > 6 {
            total_fuel += fuel_delta;
            fuel_delta = (fuel_delta / 3) - 2;
        }
    
        total_fuel + fuel_delta
    }
    
    3 votes
  11. Comment on Day 2: 1202 Program Alarm in ~comp

    9000
    (edited )
    Link
    Language: Rust I just refactored and extended my initial solution to give me the answer to both parts, so i don't have a Part 1/2 distinction. I used this as an opportunity to get a little more...

    Language: Rust

    I just refactored and extended my initial solution to give me the answer to both parts, so i don't have a Part 1/2 distinction.

    I used this as an opportunity to get a little more used to streams! I haven't really used them at all before, but structured file parsing is a good use case where streams prevent me from allocating unnecessary Vecs.

    Solution
    /* day_2
     *
     * USAGE
     *     day_2 [filename]
     * 
     * Runs the Intcode program at `filename`.
     */
    use std::env;
    use std::fs;
    use std::vec::Vec;
    
    const GOAL: usize = 19690720;
    
    fn main() {
        // Get filename
        let args: Vec<String> = env::args().collect();
        let filename = "input".to_string();
        let filename = args.get(1).unwrap_or(&filename);
    
        // Parse instructions
        let instructions = fs::read_to_string(filename).unwrap();
        let instructions: Vec<usize> = instructions.split(',')
            .map(|x| x.trim().parse().unwrap())
            .collect();
    
        // Constants given in problem for part 1
        println!("Part 1: {}", run_intcode(&instructions, 12, 2));
    
        for noun in 0..100 {
            for verb in 0..100 {
                if run_intcode(&instructions, noun, verb) == GOAL {
                    println!("Part 2: noun = {}, verb = {}, answer = {}", noun, verb, 100 * noun + verb);
                    return;
                }
            }
        }
    }
    
    fn run_intcode(instructions: &Vec<usize>, noun: usize, verb: usize) -> usize {
        let mut instructions = instructions.clone();
        instructions[1] = noun;
        instructions[2] = verb; 
    
        let mut index = 0;
        while index < instructions.len() {
            match instructions[index] {
                1 => { // Add
                    let num_1 = instructions[instructions[index + 1]];
                    let num_2 = instructions[instructions[index + 2]];
                    let dest = instructions[index + 3];
                    instructions[dest] = num_1 + num_2;
                }
                2 => { // Multiply
                    let num_1 = instructions[instructions[index + 1]];
                    let num_2 = instructions[instructions[index + 2]];
                    let dest = instructions[index + 3];
                    instructions[dest] = num_1 * num_2;
                }
                99 => { // End
                    return instructions[0];
                }
                _ => { // Error
                    eprintln!("ERROR: Received instruction {} at position {}", instructions[index], index);
                }
            }
            index += 4;
        }
    
        eprintln!("WARNING: End of memory! Did not end at opcode 99.");
        instructions[0]
    }
    
    2 votes
  12. Comment on A Comment Is An Invitation For Refactoring in ~comp

    9000
    Link Parent
    I think it also depends on the kind of churn you expect your project to have. Because, like you said, domain experts don't need comments. So, if you're working with the same code day in and day...

    I think it also depends on the kind of churn you expect your project to have. Because, like you said, domain experts don't need comments. So, if you're working with the same code day in and day out such that you become a domain expert, you might find all comments to be unnecessary. But, even another competent programmer (or, your future self) might not have the context that makes it clear. Sure, you can have variable and function names that are a sentence long (especially if you use an IDE), but sometimes it's just more clear and ergonomic to use shorter names and have a comment that explains their relationship. Or, keep more lines of code in the same function and leave an inline comment to group them without as much boilerplate as a new function (and thus, without forcing the reader to CTRL-f back and forth to understand what's going on).

    For instance, I don't like the first example. I'd rather just leave the context in the function. Otherwise, if I wanted to change something, I have to search through a deep callstack to understand what's going on. Why create a function if you're not planning on reusing the code? If it's just to name what's going on, that seems wasteful of line space and mental real estate.

    I've seen codebases where there were three login*() functions in a class, one calling the next, before the logic was implemented in a different class! To discover that, I found the first login call, and had to keep searching through it's callstack, understanding a new context each time, until I found the implemented logic. Self-documenting code is nice, but it's a tool, not a Platonic form.

    6 votes
  13. Comment on Tildes Pen Pals in ~talk

    9000
    Link
    Age group: early twenties Topics of interest: (no particular order) philosophy (esp. ethics, philosophy of mind, political philosophy, and some epistemology. But I'll discuss anything!) world...

    Age group: early twenties

    Topics of interest: (no particular order)

    • philosophy (esp. ethics, philosophy of mind, political philosophy, and some epistemology. But I'll discuss anything!)
    • world politics
    • spirituality (esp. Buddhism)
    • free culture
    • wildlife
    • travel
    • distributed systems (DAT, ipfs, etc.)
    • computer security/cryptography

    Country: USA

    Happy to mail anywhere in the world or email.

    5 votes
  14. Comment on Exploring the feasibility of brute-force guessing a 64-bit number through different techniques in ~comp

    9000
    Link Parent
    That's an interesting point! You could open an issue or pull request, since they say help is welcome?

    That's an interesting point! You could open an issue or pull request, since they say help is welcome?

    2 votes
  15. Comment on Exploring the feasibility of brute-force guessing a 64-bit number through different techniques in ~comp

  16. Comment on Peertube 2.0 is out in ~tech

    9000
    Link Parent
    What you say is true, but not quite what @WendigoTulpa seems to be asking about. They seem to be asking about whether users' machines will be involved in serving videos to other users, and the...

    What you say is true, but not quite what @WendigoTulpa seems to be asking about. They seem to be asking about whether users' machines will be involved in serving videos to other users, and the answer there is "yes". Not only does the server serve the video content to you, but other users will as well (à la bittorrent or LimeWire). For instance, if you click on the video in the OP article, it will list some number of peers that you are connected and sharing data with.

    This is an important property of PeerTube. Video hosting is expensive. Like, really expensive. So, to be able to compete with YouTube, not only would you want decentralization with ActivityPub, but you also want to distribute the load across your clients. This means that if a video becomes super popular, the server sees a lot less load than they would otherwise. For the long tail of videos, the server will still be doing about as much work as YouTube, but those are also the videos that are significantly less likely to be seen.

    3 votes
  17. Comment on The Mandalorian | S01E01+E02 in ~tv

    9000
    Link Parent
    You're right! I thought he was a Mandalorian, but according to the fan wikis, he is not. My bad!

    I don't think Boba Fett is related to the Mandalorians, aside from the armor he wears.

    You're right! I thought he was a Mandalorian, but according to the fan wikis, he is not. My bad!

    3 votes
  18. Comment on The Mandalorian | S01E01+E02 in ~tv

    9000
    (edited )
    Link
    So far I've been really enjoying it! The aesthetics are very high quality and really help to set the tone. I also really like how they reference but also expand on things we already know about the...

    So far I've been really enjoying it! The aesthetics are very high quality and really help to set the tone. I also really like how they reference but also expand on things we already know about the Star Wars universe. The Force Awakens felt so copycat and The Last Jedi, like The Phantom Menace, seemed to break some of the pre-established lore. But I really like the direction The Mandalorian is going, because it expands on existing lore, bringing in new concepts, but without overwriting anything. At least, so far.

    There are a few things I am either confused about, or didn't like. On the confusion side, I'd be interested in the backstory to the female Mandalorian. Because, my understanding was that Boba Fett and the clones in the Prequels were all clones of Jengo Fett. But, I'm opticimistic that there will be an interesting backstory here, since it seems like the Mandalorians have developed a sort of group identity and "religion". Honestly, I was confused that there was anyone more than just Boba Fett!

    In terms of dislike, I don't like how easily the baby Yoda could use the Force. They make a big fuss in all the movies about how important and difficult it is to train, and that prior to training the Force shows itself in subtler, harder to control ways. Like, I get that Yoda was a super masterful jedi, but I always assumed that was through centuries of training and self-discipline. But, I digress.

    All in all, I am very excited to see where this goes!


    EDIT: Jengo and Boba Fett were not Mandalorians, they just wore Mandalorian armor [1]

    4 votes
  19. Comment on What are some good news outlets you would recommend? in ~talk

    9000
    Link Parent
    I'm sorry, but my initial investigation was not thorough enough. Please see my edit. It appears that NewsHour is now owned by an independent public broadcasting company based out of Washington...

    I'm sorry, but my initial investigation was not thorough enough. Please see my edit. It appears that NewsHour is now owned by an independent public broadcasting company based out of Washington D.C.

    Apologies for the initial misrepresentation.

    3 votes
  20. Comment on What are some good news outlets you would recommend? in ~talk

    9000
    (edited )
    Link Parent
    I cannot find any evidence that the Koch brothers are on the board of NewsHour. I found that they have donated (though my cursory search has not turned up a number), but I can't find evidence they...

    I cannot find any evidence that the Koch brothers are on the board of NewsHour. I found that they have donated (though my cursory search has not turned up a number), but I can't find evidence they are on the board.

    According to the Wikipedia page, Liberty Media bought a controlling stake in NewsHour in 1994, and John C. Malone has a controlling stake in Liberty Media [SEE EDIT]. There is no mention of the Kochs, though.

    I recommend reading the Criticism and Scholarly Analysis sections of the NewsHour Wikipedia page for a discussion of bias, because I don't feel comfortable summarizing in any fewer words.


    EDIT: Apparently Liberty Media no longer owns NewsHour. In 2013, they sold their stake to WETA-TV, a PBS member station. It mentions this in the NewsHour history section, and NewsHour is listed as a former asset on Liberty Media's page.

    WETA-TV itself is owned by Greater Washington Educational Telecommunications Association, which also owns the WETA NPR station. So, WETA-TV seems to almost exclusively be an independent public media company.

    8 votes