HN user

bluetomcat

3,504 karma
Posts38
Comments851
View on HN
bbuyukliev.blogspot.com 3mo ago

LLM coding is the wrong layer of abstraction

bluetomcat
3pts1
github.com 5mo ago

Show HN: Shell script and text database for vintage Lego Pirates collections

bluetomcat
3pts0
bbuyukliev.blogspot.com 7mo ago

The choice between Rust and C-derived languages is not only about memory safety

bluetomcat
45pts19
github.com 7mo ago

Show HN: Cdecl-dump - represent C declarations visually

bluetomcat
35pts13
codemia.io 8mo ago

From epoll to io_uring's Multishot Receives

bluetomcat
16pts1
bbu87.blogspot.com 2y ago

The Pitfalls of Pure Rationality

bluetomcat
1pts0
news.ycombinator.com 2y ago

Ask HN: Where do you find low-stress remote programming jobs?

bluetomcat
4pts5
bbu87.blogspot.com 2y ago

The Essence of Modern C++

bluetomcat
3pts1
bbu87.blogspot.com 2y ago

The trap of Unix

bluetomcat
1pts0
philosophynow.org 4y ago

Analytic versus Continental Philosophy (2009)

bluetomcat
33pts16
traversingtradition.com 5y ago

The Death of Community and the Rise of Individualism (2018)

bluetomcat
2pts0
areomagazine.com 6y ago

Postmodernism and Its Impact (2017)

bluetomcat
69pts91
www.bbc.com 9y ago

The next generation of jobs won't be made up of professions

bluetomcat
1pts0
voices.canonical.com 9y ago

Why GNU Autotools is not my favorite build system (2013)

bluetomcat
12pts0
stackoverflow.com 9y ago

The non-spiral rule about C declarations

bluetomcat
1pts0
github.com 10y ago

Show HN: Quaint – a statically typed language with seamless resumable functions

bluetomcat
4pts3
www.javaworld.com 10y ago

Why client-server must die

bluetomcat
3pts0
www.youtube.com 10y ago

Unix: Making Computers Easier to Use (1982) [video]

bluetomcat
3pts1
spin0r.wordpress.com 10y ago

K&R C (2014)

bluetomcat
136pts66
github.com 10y ago

Show HN: A toy interpreter for a minimalistic imperative language in 1.3k LoC

bluetomcat
17pts9
github.com 10y ago

Show HN: Userland slab allocator

bluetomcat
4pts0
jeffknupp.com 10y ago

How 'DevOps' Is Killing the Developer (2014)

bluetomcat
4pts4
op59.net 11y ago

Complacency in the computer industry – a rant (2006)

bluetomcat
1pts0
www.extremetech.com 11y ago

Russian firm debuts VLIW Elbrus 4 CPU with onboard x86 emulation

bluetomcat
2pts0
blog.nelhage.com 11y ago

A Brief Introduction to Termios (2009)

bluetomcat
15pts0
software.intel.com 11y ago

Processing Arrays of Bits with AVX-512 (2014)

bluetomcat
1pts0
www.akkadia.org 11y ago

How to Write Shared Libraries (2011) [pdf]

bluetomcat
13pts0
www.theguardian.com 11y ago

We need to talk about TED (2013)

bluetomcat
3pts0
dbp-consulting.com 11y ago

Linux x86 Program Start Up

bluetomcat
143pts30
www.lighterra.com 11y ago

Exception Handling Considered Harmful (2005)

bluetomcat
1pts0

No. Plausible code is syntactically-correct BS disguised as a solution, hiding a countless amount of weird semantic behaviours, invariants and edge cases. It doesn't reflect a natural and common-sense thought process that a human may follow. It's a jumble of badly-joined patterns with no integral sense of how they fit together in the larger conceptual picture.

It starts from the identifier. At every stage, it outputs a sub-expression which is the “mirrored use” and corresponds to the boxed representation below it. When it reaches the top of the expression, it prints the final type of the expression which is the lone specifier-qualifier list.

As per the screenshot, “arr” is an array of 4 elements. Consequently, “arr[0]” is an array of 8 elements. Then, “arr[0][0]” is a pointer. And so on, until we arrive at the specifier-qualifier list.

Because in C, every allocation incurs a responsibility to track its lifetime and to know who will eventually free it. Copying and moving buffers is also prone to overflows, off-by-one errors, etc. The generic memory allocator is a smart but unpredictable complex beast that lives in your address space and can mess your CPU cache, can introduce undesired memory fragmentation, etc.

In Java, you don't care because the GC cleans after you and you don't usually care about millisecond-grade performance.

Yes, you can do it with minimal allocations - provided that the source buffer is read-only or is mutable but is unused later directly by the caller. If the buffer is mutable, any un-escaping can be done in-place because the un-escaped string will always be shorter. All the substrings you want are already in the source buffer. You just need a growable array of pointer/length pairs to know where tokens start.

Good C code will try to avoid allocations as much as possible in the first place. You absolutely don’t need to copy strings around when handling a request. You can read data from the socket in a fixed-size buffer, do all the processing in-place, and then process the next chunk in-place too. You get predictable performance and the thing will work like precise clockwork. Reading the entire thing just to copy the body of the request in another location makes no sense. Most of the “nice” javaesque XXXParser, XXXBuilder, XXXManager abstractions seen in “easier” languages make little sense in C. They obfuscate what really needs to happen in memory to solve a problem efficiently.

These lies don’t just affect them but also the people reading it as they might never see what actually happens

This is what sustains this whole economic bubble built on debt and future promises. At all levels of society, you have these inflated unrealistic expectations and BS circulating in the media. Technically-incompetent but eloquent and charismatic CEOs predict that in 6 months, some major technological shift will happen. Managers preach about adjusting their organisations to these new realities. Workers have no choice but to play the game with all its dirty tricks, if they want to stay employed. Anyone who dares to say that the emperor has no clothes is isolated in a dark corner because they may suddenly deflate the value of the whole economy. This is corporate feudalism disguised as a competitive economy.

They were popular because there was no Unix culture in Eastern Europe at the time. Pretty much any computer geek was a DOS user. To me personally, it always seemed kind of lame because many of these people would not bother to properly learn the shell language.

Their English is sufficiently good. It's a cultural aspect regarding writing style. When Russians and most Eastern Europeans write about technical subjects, they tend to be concise, dense and straightforward. Americans, on the other hand, are over-expressive and tend to saturate their writing with pointless metaphors and rhetorical devices.

Pattern matching should make the language less verbose, not more.

In the most basic cases, yes. It can be used as a more polished switch statement.

It's the whole paradigm of "define an ad-hoc Enum here and there", encoding rigid semantic assumptions about a function's behaviour with ADTs, and pattern matching for control-flow. This feels like a very academic approach and modifying such code to alter its opinionated assumptions isn't funny.

Rust encourages a rather different "high-level" programming style that doesn't suit the domains where C excels. Pattern matching, traits, annotations, generics and functional idioms make the language verbose and semantically-complex. When you follow their best practices, the code ends up more complex than it really needs to be.

C is a different kind of animal that encourages terseness and economy of expression. When you know what you are doing with C pointers, the compiler just doesn't get in the way.

The W210s did indeed rust badly and the interiors weren't on par with previous generations, but in purely mechanical terms, they were still solid cars. The diesels (particularly E250 TD and E290 TD) could cover 700k+ kilometres without any interventions to the engine or the transmission. The W211 is an improvement to the W210 in almost every aspect, and they are still plentiful on the roads in Eastern Europe.

Big Tech drove us towards techno-feudalism. It's a wider social phenomenon and their hiring patterns for programmers are only one aspect of the problem. Small businesses are forced to do business on their platforms according to their rules, or else they go bust. Programmers are forced to learn their APIs, so that their "app" can live in their walled gardens. They soaked a huge amount of talent to optimise their ad and recommendation engines. This is a huge opportunity cost to society - that talent could be doing great creative stuff for small and medium-sized businesses instead.

Yes, that was my point. Regardless of the programming language, LLMs are glorified pattern matchers. A React/Node/MongoDB address book application exposes many such patterns and they are internalised by the LLM. Even complex code like a B-tree in C++ forms a pattern because it has been done many times. Ask it to generate some hybrid form of a B-tree with specific requirements, and it will quickly get lost.

It’s good at matching patterns. If you can frame your problem so that it fits an existing pattern, good for you. It can show you good idiomatic code in small snippets. The more unusual and involved your problem is, the less useful it is. It cannot reason about the abstract moving parts in a way the human brain can.

It’s a good direction to follow, but it can only get you so far. Some pieces of code do naturally evolve into a functional formalism, while others are inherently imperative. Usually, the top levels of your program (event loop) are imperative and deal with stateful “devices” like IO, the screen and storage subsystems. The “leaf” functions from the call graph can be functional, but you still can’t reason about the whole program when it is imperative at the top.

My thesis so far is something like "you should try to write little proofs in your head about your code." But there's actually a secret dual version of this post, which says "you should try to write your code in a form that's easy to write little proofs about."

Easier said than done. It is certainly feasible on greenfield projects where all the code is written by you (recently), and you have a complete mental model of the data layout and code dependencies. It's much harder to prove stuff this way when you call foo(), bar() and baz() across unit boundaries, when they modify global state and are written by different developers.

It’s not just skill atrophy. There’s the risk of homogenization of human knowledge in general. What was once knowledge rooted in an empirical subjective basis may become “conventional wisdom” reinforced by LLMs. Simple issues regarding one’s specific local environment will have generic solutions not rooted in any kind of sensory input.

Absolutely. LLMs offer you compressed documentation at your fingertips. Instead of scrolling through man pages and function references to find that specific flag or parameter you are interested in for the problem at hand, you can directly formulate such a question to the LLM, and it will give you a pretty good result.

I'm not sure if all this advice will become irrelevant or if those programmers trained in the 2020ies will not become those "best"..

It's how they use the AI. If they see it as a glorified StackOverflow where you paste a big chunk of code and ask "why does it not work", they'll be in trouble. If they are able to narrow-down their problems to a specific context, express them well and take the output of the AI with a grain of salt, they'll be 10x programmers compared to what we were in the 2000s, for example.

The idea of “traveling the world” when young is a very recent, very privileged and very Western perspective.

Growing up in post-communist Bulgaria during the 1990s and 2000s, I had never been abroad with my family as a child. At an age of 18 years, I started working from home as a PHP programmer for a guy from Switzerland I found online. When he invited me to his place in Basel for a 2-week visit, to me it felt like flying in space. I was valuing every second of my stay there like I am on another planet.

The perceived complexity from a semantic standpoint comes from the weakly-typed nature of the language. When the operands of an expression have different types, implicit promotions and conversions take place. This can be avoided by using the appropriate types in the first place. Modern compilers have warning flags that can spot such dodgy conversions.

The rest of the complexity stems from the language being a thin layer over a von Neumann abstract machine. You can mess up your memory freely, and the language doesn’t guarantee anything.

Interesting usage of "extern" and "auto". Quite different from contemporary C:

    tree() {
        extern symbol, block, csym[], ctyp, isn,
        peeksym, opdope[], build, error, cp[], cmst[],
        space, ospace, cval, ossiz, exit, errflush, cmsiz;

        auto op[], opst[20], pp[], prst[20], andflg, o, p, ps, os;
        ...
Looks like "extern" is used to bring global symbols into function scope. Everything looks to be "int" by default. Some array declarations are specifying a size, others are not. Are the "sizeless" arrays meant to be used as pointers only?

Political action is fuelled by beliefs and ideals for the future. As a subjective observer, no one can attain a complete image of reality, or "the thing in itself". All we observe are appearances (phenomena) from our subjective point of view. In the process of a wider societal dialogue, we can exchange these points of view and eventually come to a rough approximation of the objective state of things.

They treat an OOM situation as exceptional and immediately call abort() in case any allocation function returns NULL. The specification of these functions allows you to handle OOM situations gracefully.