People still believe this? Google pays their ISP. I pay my ISP. Google does not pay my ISP. Why is my ISP's response to the amount of traffic I use demanding to bill someone other than me?
To be clear, Google was doing this out of self-interest. Paying user ISPs for access to those users is not a cost they want to pay. But it's the same as any other protection racket. A local shopkeeper has personal reasons to not want to pay off the mob, but that doesn't mean their position is wrong.
It's not difficult to communicate the difference between losing all future rights and settling a dispute over an incident that has already happened. I don't know why you'd act like it's a huge challenge to understand the difference.
It's nothing at all how like C runs on top of assembly. C has semantics. Code means something without ever being run. You can check in your source code and (assuming it actually follows the C standard and your compiler's documented extensions, which almost no real C code does - C was a horrible example) it will work just as well in a year as it does today.
Try checking in only your prompts and nothing else. Just the parts you actually typed. See how well it works to regenerate the same application next week, let alone next year. Prompts are fundamentally a different sort of thing from code. Do not mix them up.
> (assuming it actually follows the C standard and your compiler's documented extensions, which almost no real C code does - C was a horrible example) it will work just as well in a year as it does today.
> See how well it works to regenerate the same application next week, let alone next year. Prompts are fundamentally a different sort of thing from code
I mean... yes, but also no. C is actually a great example. So much of the code we wrote is about manipulating the specifics of that specific computer system we happen to be using at that exact moment. Everything from cpu specific instructions to how the ram behaves or how much of it there is all the way up to how library functions operate at any given point in time.
And in relatively short amounts of time, it can all change out from underneath you.
No. C is a language with a specification independent of implementation. If you write correct C code (according to the specification, which no one does), it does not depend on any of those factors. C is almost uniquely bad in terms of accepting broken programs and just compiling them differently. But that doesn't change the fact that the language has semantics, even if most code that violates the documented preconditions those semantics depend on.
Eh. A quick scan of steam reviews shows a clear pattern - the game has been in decline ever since Yegge took over, well before LLMs were a product. It seems he started upsetting people with a capitalist-brain insistence on extracting value, and nothing has changed since. As long as he doesn't understand that his goals are contrary to building a game people enjoy, quality of the code is completely irrelevant. I don't think this one works as a test case on the value of programming like this, as the intended audience just isn't interested.
> his goals are contrary to building a game people enjoy, quality of the code is completely irrelevant
i think this happens a lot inside and outside of games when people get obsessed with the tech or process behind it; they completely miss the goal of the job
Yes, you're describing cosmology. We can't create separate test universes, so all we can do is argue over which model is the best way to explain our observations. The difference from ad-hoc reasoning is the exact same as any other science. You make predictions based on models and then try to find places where those predictions hold - or are broken. In either case, you're testing the validity of a model. And when something isn't good enough, you either adjust the model or find a new one that works better.
This isn't some slapdash random patching. Everyone involved knows that assuming that the λ in λCDM is a constant is shaky. It could be a function of time, or even location in some way. But it's simplest if it's a constant. So you start by modeling the universe as if it is. Then you determine what sorts of observations would support or contradict that, and you start making them. When you get results, you start examining what version of the model best explains those observations. And someone somewhere goes off to try find a better model than any version of λCDM. If they succeed, their model will eventually supplant it. This is how science progresses, even if the experiments are less under the control of the experimentors than they'd like. The important part that you make revisions in response to observations.
(FWIW, particle physicists are constantly frustrated that they can't find counterexamples to the Standard Model. They know it has to be incomplete, but the lack of contradictory observation leaves them no direction to try to improve it.)
What makes this a desirable feature? From the perspective where local reasoning is the most desirable property a language can have, how does homoiconicity support that?
I honestly am curious. I've seen a few examples presented for it, but they always seem like bad software engineering to me. Where's an example that does something in a cleaner way than alternatives present in other languages while remaining compatible with local reasoning?
Easy is an understatement. Macros and dynamic programming (often done using runtime reflection in other languages) are so trivially easy in Lisps that one can stumble into it without realizing they're even doing it. Anyone who has done these things in more "modern" languages knows these features are not something one can accidentally start doing. They take a lot of deliberate effort relative to standard, static programming.
> Easy is an understatement. Macros and dynamic programming (often done using runtime reflection in other languages) are so trivially easy in Lisps that one can stumble into it without realizing they're even doing it.
Well, getting the interaction between modules and syntax transformations (macros) right is not an easy task.
Is Prolog bicameral? Because it has a `read` predicate? Is bicameral then just a matter of implementing a `read` function which returns a tree of tokens, which you could implement for C or Python? Which makes bicamerality a property of a library rather than a property of the language?
> From the perspective where local reasoning is the most desirable property a language can have
That's a perspective. If you're looking for a low-level language, then Scheme isn't it. (Forget iconicity - Scheme is garbage-collected. And supports continuations!)
If you don't program in machine code - which would maximize local reasoning - then you must know the language with the Correct balance of local reasoning and higher-level constructs. Knowing which language that is would add specificity to this discussion...
Pre-Scheme is a statically typed dialect of the Scheme programming language, combining the flexibility of Scheme with the efficiency and low-level machine access of C. The compiler uses type inference, partial evaluation, and other correctness-preserving transformations to compile a subset of Scheme into C with no additional runtime overhead. This makes Pre-Scheme a viable alternative to C for programming virtual machines, operating systems, and embedded systems where the runtime overhead of a complete Scheme implementation is not desirable.
Microscheme, or (ms) for short, is a functional programming language for the Arduino, and for Atmel 8-bit AVR microcontrollers in general. Microscheme is a subset of Scheme, in the sense that every valid (ms) program is also a valid Scheme program (with the exception of Arduino hardware-specific primitives). The (ms) compiler performs function inlining, and features an aggressive tree-shaker, eliminating unused top-level definitions. Microscheme has a robust FFI (Foreign Function Interface) meaning that C code may be invoked directly from (ms) programs. Therefore, the power of the existing wealth of Arduino libraries is available within Microscheme.
CRUNCH is an embedded compiler for a statically typed subset of R7RS Scheme, generating C code. The compiler uses type inference to decorate the code with type information without requiring declarations. CRUNCH can be used to translate embedded Scheme code sections, whole programs or multiple source modules into standalone executables or compiled code that can be invoked from Scheme.
The generated C code uses a small runtime-system contained completely in a single C header file. Reference counting is used for managing aggregate data like strings which removes the need for full tracing garbage collection or manual memory management while still having a relatively small overhead.
Since more or less a direct translation of Scheme to C is done, the generated code should run at roughly the same performance as C. No type-checking takes place as the types of all values have been inferred at compile time, and values are not tagged. With the exception of reference counted objects there is no additional runtime overhead and Scheme and C can directly interchange data. This makes CRUNCH very appropriate for writing programs that need a maximum of speed or that are target for constrained environments like deeply embedded systems. The code is portable to all systems that at least have a C compiler.
UNICODE strings are supported and can optionally be disabled for improving performance and reducing code size.
CRUNCH is heavily inspired by PreScheme, the low-level compiler that is originally part of the Scheme48 project. In fact, CRUNCH can be considered a modern reimplementation of PreScheme written in and for use with CHICKEN.
See also:
Crunch – a Scheme compiler with a minimal runtime (more-magic.net)
190 points by sjamaan on Dec 17, 2024 | hide | past | favorite | 72 comments
That's not at all what local reasoning means. Local reasoning is the property that a piece of code contains (when including the call graph) everything that can affect what it does. All mutation of a value is kept within some scope of ownership of that value. If you want to understand a piece of code, you can do it by understanding that piece of code, not the program as a whole.
Assembly makes non-local reasoning mandatory, as any code can update any location in memory without restriction. All memory accesses are global. References need not even be by name - they can be via computed addresses. There are no restrictions in place allowing the structure of the program to provide boundaries on what pieces of code may be understood as units.
Homoiconicity is orthogonal to local reasoning. It just means the syntax is represented by the native data format, nested lists. This does make code generation very straightforward with list processing primitives.
Mutation in scheme is possible, via set!, and set-car! and set-cdr!, but it's not recommended. Functional program design side-steps the issue.
Yes, I know they're orthogonal. But every example of using macros I see in lisp is either some horrendous non-local logic, or something that can be done better using simpler tools. Where's the killer use case that clearly is good software engineering and not papering over the lack of another feature?
Coalton is an efficient, statically typed functional programming language that supercharges Common Lisp by taking great ideas from Haskell, Scheme, and OCaml.
it allows you to create a language that compiles to your original language.
You can abstract everything away. Not like Haskell where laziness accounts for some and typeclasses for some (and often an exponential growth in compile times). No, it property let's you change the language.
This doesn't strike me as better than the alternatives. In Haskell, it's just a few different functions to handle the different use cases. That strikes me as far better than one "function" that magically does different things depending on how it's called. It is local, I'll give you that. But it still seems bad because you have overloaded the semantics along multiple axes simultaneously. I prefer building blocks with only a single set of semantics each. I believe it's better to write precise code than DWIM code.
everybody agrees, which is why most sane people very rarely reach for macros. At the same time, it would be great if some of the libraries that rely on typeclass machinery for code generation could use lisp-like macros, because turning a 3 second recompile to a 35 second recompile (and I have experienced worse. Much worse.) is what kills exploratory programming. I heard optics mostly solves much of the problems of generic lens, but god forbid you use something like servant or polysemy.
Chez compiles a project of about 35000 lines (with heavy macro usage) in less than 0.5s on -O2.
The ideal would be to go into swap without becoming unresponsive, so that the user can quit a program of their choice to free memory. If you really want to make an issue out of it, do something like pre-X macOS, where it would provide a warning when you are getting close to running out of memory, so that a user might have the chance to do something before the current process starts getting swapped out.
> The ideal would be to go into swap without becoming unresponsive, so that the user can quit a program of their choice to free memory.
Linux already does this. The issue is when your swap is full too, or you’ve exhausted your RAM at such a rapid pace that the disk IO cannot keep up with the read and writes to swap.
I’ve seen Windows choke under the same conditions too.
> do something like pre-X macOS, where it would provide a warning when you are getting close to running out of memory, so that a user might have the chance to do something before the current process starts getting swapped out.
This is where the desktop and the kernel being entirely separate organisations (not even projects, but literal organisations) makes things a touch harder. And those DEs aren’t even Linux specific either. So any tooling would have to portable (which, in fairness, should be possible with POSIX in this particular scenario).
I think KDE does provide tools here for gracefully handling memory constraints. But that’s just one desktop environment of many.
>> do something like pre-X macOS, where it would provide a warning when you are getting close to running out of memory
And I've run out of memory while compiling packages (I'm looking at you, composable-kernel) on Gentoo. It's not like it can notify me and I close things in the milliseconds it takes for a few more GCC processes to spawn and allocate and fault all the remaining memory.
> [...] or you’ve exhausted your RAM at such a rapid pace that the disk IO cannot keep up with the read and writes to swap.
I don't know what that means. When your system is in such extreme memory pressure, it comes to a crawl, exactly because your memory use can't outpace your IO. There's no 'cannot keep up' state.
(1) While there's plenty of headroom, you might still want to swap out 'cold' memory, so you can keep more files cached in RAM.
(2) When you are (nearly) out of memory, you need to evict to swap so that you don't run out-of-memory.
Swap mostly helps you, when you have plenty of cold memory that are pretty much never accessed again. Or when you have applications that you switch, but that you don't use concurrently.
When your active working set is bigger than your RAM, then, yes, swap is slow.
Following this argument to its natural conclusion, we should tell LLMs to generate the binary directly. It's still an abstraction, but it's the lowest level we can go to on current consumer hardware.
I don't think raw machine code (not even assembly) is the best form to reason about program logic. It just takes too many steps to execute sophisticated processes to keep them all in your head at once - or keep them all in an LLM context at once.
Good lord, the damage LLM use has done to deep thinking is amazing for such a short time. Maybe if it stayed hard to find your phone, you would have put some time into considering the root cause of the problem: you put an employer MDM on your phone. Except, well. Now it's their phone. You just pay for it.
The expressed (not implied) alternative in the post is for those people to stop pretending they care, and start actually caring. Stop trying to save the world. The world doesn't need an invention to save it. Just put that energy into caring about others.
People do care, but there are so many problems in the world, and only so much caring to go around.
It's extremely cynical to view it as "people pretend to care", rather than looking around and realizing there's a ton of important problems out there that the caring is distributed over. People care about disabilities, but they also care about war, about public schooling, about the environment, about feminism, about animal rights, about transparency in government, about road safety, about child well-being, about unemployment, and so on. All of these are important things, and of course there are dozens more that I haven't listed.
And inventions are sometimes actually useful. Sure, most of those prototypes will go nowhere, but every once in a while something that really helps is invented. And you can't predict in advance only the ones that will actually go on to help.
Some people actually care, but they can't always win the battle at their own companies when there are other priorities, much less go fix all the other websites, pour concrete at other businesses, etc. Is the solution for everyone to care? If, so how do you accomplish that? ("Americans with Disability Act" v2?)
The world doesn't need an invention to save it. Just put that energy into caring about others.
This is an excellent summary of the sort of anti-tech thinking that I strongly disagree with. Caring about people with Alzheimer's is well and good, but what we actually want are vaccines and cures.
The dream of a vaccine or cure is all well and good, but when my grandfather has Alzheimer's today and there's no properly functioning social supports, processes, etc to get him into a home and it takes months and months of phone calls and panicked searches when he wanders off to improve the situation at all, I think maybe there really is a dearth of "caring about the problem and not just the solution"
To be clear, Google was doing this out of self-interest. Paying user ISPs for access to those users is not a cost they want to pay. But it's the same as any other protection racket. A local shopkeeper has personal reasons to not want to pay off the mob, but that doesn't mean their position is wrong.
reply