HackerLangs
TopNewTrendsCommentsPastAskShowJobs

norir

1,104 karmajoined 4 tahun yang lalu
For those who haven't been trained by it, no discipline feels better at the time, but painful.

comments

norir
·4 hari yang lalu·discuss
This infrastructure is also slow and leads to poor compilation times for any language that uses llvm as a backend. In an era of automatic code generation, this will become more and more of a problem as llvm compilation times will become a huge bottleneck. I am very bearish on llvm as a technology and while I will acknowledge its influence, I expect that it is at or near its peak and market share will decline dramatically over the next five to ten years.
norir
·20 hari yang lalu·discuss
Perhaps then it would be better to not use tools of this level of complexity.
norir
·22 hari yang lalu·discuss
I am actively opposed to this design for a first compiler. There is no need for a lexer with a recursive descent parser. Register allocation is also an unnecessary distraction. It is better for a first compiler to compile to a higher level language in which neither register assignment nor memory management are necessary.

Optimizing compilers are suboptimal in that they waste enormous amount of time optimizing code that can't or needn't be optimized and even where the optimizations are helpful, they are opaque and at risk of unexpectedly regressing both due to small changes at the source code level or changes in the compiler optimizer, both of which are quite insidious.

If instead of optimizing compilers, we had languages that allowed for seamless interop between low level and high level functions, then perhaps an llm becomes the optimizer (or you can invoke the compiler to optimize a specific function by source level rewrite). The benefit of this compared to a traditional optimizing compiler is that the optimization is done once per function and never repeated (until prompted) and the implementation is human readable and not buried in a binary. Moreover, and perhaps even more importantly, by not doing optimizations in the compiler, compilation times can be much faster, easily 100-1000x than state of the art optimizing compiler, while generating equivalent or even better runtime performance. As it has been said: premature optimization is the root of all evil.
norir
·bulan lalu·discuss
Terry Tao is a next level vibe coder: he inspires people to do his vibe coding for him. As someone with a background in advanced math, though never even close to Tao's level, I find myself skeptical about this type of mathematics. I don't personally find it beautiful and it feels like the line between the profound and the trivial (as in of minimal importance not difficulty) is blurry. One could argue for pure mathematics that is of no practical utility but is aesthetically beautiful, but I struggle to see the beauty in a gargantuan lean proof constructed by 100 different people. Perhaps this work will lead to deeper insight about the universe and the human condition, but I catch a whiff of problem solving for the sake of problem solving untethered from a deeper sense of purpose and meaning.
norir
·bulan lalu·discuss
I think the people with extreme positions are often the most useful because they get closer to the source of the argument. Extreme boosters of ai often want to either bypass developing skills to advance their careers or want to exploit what they perceive to be overpaid labor. Extreme pessimists tend to value skill and autonomy and distrust the people with power above them in the hierarchy. They also may identify with their skills and feel existentially threatened by a society that is rapidly devaluing them.

Framing this disagreement as a fundamental misunderstanding of the technical capacity and appropriate use cases, for me, completely misses the plot. Both sides have compelling reasons for their beliefs and the cold rational analysis of the tech is as likely to further entrench the extremes as it is to enlighten.

I will also note that in your comment, you lament the dismissal of entire groups of engineers while doing exactly this when you dismiss the loudest voices (as well as those who think highly of their own ability) and imply that it is the loudest voices who are inherently extreme and therefore inferior to the pragmatic engineer who understands tradeoffs and cost benefit analysis.
norir
·bulan lalu·discuss
> We could start off with how are you worse off because of people wealthier than you?

You are smart enough to come up with some answers of your own. It's rude to demand others to do your own thinking for you.
norir
·bulan lalu·discuss
It is hard for me to fully trust a compiler backend that isn't self hosted. There is a discipline that self hosting imposes that would both improve the quality of their ir as well as the backend itself. A self hosted backend can always be updated to have performance meeting or exceeding the best that llvm or any other backend can offer.
norir
·2 bulan yang lalu·discuss
When using null terminated strings, parsing can be branchless because you don't need bounds checks and can use a jump table indexed by the byte.
norir
·2 bulan yang lalu·discuss
This is not a hard thing to do without using a library. The code below is easily adapted to the unsigned case and/or arbitrary base rather than 10.

    #include <stdio.h>
    int main(int argc, char **argv) {
        if (argc != 2) {
            fprintf(stderr, "usage: require one numeric argument");
        }
        char *nump = argv[1];
        unsigned neg = 0;
        unsigned long long ures = 0;
        if (*nump == '-') {
            neg = 1;
            nump = nump + 1;
        }
        if (!*nump) {
            fprintf(stderr, "require non empty string\n");
            return 1;
        }
        char b;
        while (b = *nump++) {
            if (b >= '0' && b <= '9') {
                unsigned long long nres = (ures * 10) + (b - '0'); 
                if (nres < ures) {
                    fprintf(stderr, "overflow in '%s'\n", argv[1]);
                    return 1;
                }   
                ures = nres;
            } else {
                if (b >= ' ') {
                    fprintf(stderr, "invalid char '%c' in '%s'\n", b, argv[1]); 
                } else {
                    fprintf(stderr, "invalid byte '%d' in '%s'\n", b, argv[1]);
                }
                return 1;  
            }
        }
        long long res = (long long) ures;
        if (neg) {
            if (ures <= 0x8000000000000000ULL) {
                res = -res;
            } else {
                fprintf(stderr, "underflow in '%s'\n", argv[1]);
                return 1;
            }
        } else if (ures > 0x7FFFFFFFFFFFFFFFULL) {
            fprintf(stderr, "overflow in '%s'\n", argv[1]);
            return 1;
        }
        fprintf(stdout, "result: %lld\n", res);
        return 0;
    }
norir
·2 bulan yang lalu·discuss
The product and the process are not orthogonal.
norir
·2 bulan yang lalu·discuss
This is true, which means that a language has to be designed from the ground up to deal with these problems or there will always be inscrutable bugs due to misuse of arithmetic results. A simple example in a c-like language would be that the following function would not compile:

    unsigned foo(unsigned a, unsigned b) { return a - b; }
but this would:

    unsigned foo(unsigned a, unsigned b) {
      auto c = a - b;
      return c >= 0 ? c : 0;
    }
Assuming 32 bit unsigned and int, the type of c should be computed as the range [-0xffffffff, 0xffffffff], which is different from int [-0x100000000, 0x7fffffff]. Subtle things like this are why I think it is generally a mistake to type annotate the result of a numerical calculation when the compiler can compute it precisely for you.
norir
·2 bulan yang lalu·discuss
In my reading, what Stroustroup is saying is that given other problems in c/c++, that singed sizes are less bad than unsigned but both have clear and significant deficiencies. A new language doesn't have to inherit all of these deficiencies.
norir
·3 bulan yang lalu·discuss
I also expect that most side projects that are made with ai end up abandoned within 3 months and contribute next to nothing to the user's personal development and that the use of ai prevented them from the kind of deliberate practice that could have led to durable skill growth which ultimately will lead to much better work (side or main projects).
norir
·3 bulan yang lalu·discuss
This highly depends on the language and your skill as a compiler writer. You can write a single pass assembler that generates great code but you have to of course write the low level code yourself (including manual register assignment). To do decent automatic register assignment, I agree you need at least two passes, but not 10 or more.
norir
·3 bulan yang lalu·discuss
You don't need a repl for this workflow and it can be easily implemented in any language. `ls *.MY_LANG | entr -c run.sh` You get feedback whenever you save the file.

Personally, I find waiting more than 200ms unacceptable and really < 50ms is ideal. When the feedback is very small, it becomes practical to save the file on every keystroke and get nearly instantaneous results with every input char.
norir
·3 bulan yang lalu·discuss
It is easily possible to parse at > 1MM lines per second with a well designed grammar and handwritten parser. If I'm editing a file with 100k+ lines, I likely have much bigger problems than the need for incremental parsing.
norir
·4 bulan yang lalu·discuss
> I recognize that it is reminiscent of a few decades ago when old timers complained about the proliferation of high level programming languages and insisted they would lead to a generation of programmers lacking a proper understanding of how the system behaves beneath all that syntactic sugar and automatic garbage collection. They won’t have the foundational skills necessary to design and build quality software. And, for the most part, they turned out to be wrong.

What if the old timers were actually right? I tend to think they were.
norir
·4 bulan yang lalu·discuss
> In the meantime, there's nothing stopping you from using the agent to write the code that is every bit as high quality as if you sat down and typed it in yourself.

You can only speak for yourself.
norir
·4 bulan yang lalu·discuss
If you have well defined boundaries, you can move the stack to an arbitrarily large chunk of memory before the recursive call and restore it to the system stack upon completion.
norir
·5 bulan yang lalu·discuss
I have a personal aversion to defer as a language feature. Some of this is aesthetic. I prefer code to be linear, which is to say that instructions appear in the order that they are evaluated. Further, the presence of defer almost always implies that there are resources that can leak silently.

I also dislike RAII because it often makes it difficult to reason about when destructors are run and also admits accidental leaks just like defer does. Instead what I would want is essentially a linear type system in the compiler that allows one to annotate data structures that require cleanup and errors if any possible branches fail to execute the cleanup. This has the benefit of making cleanup explicit while also guaranteeing that it happens.