HN user

ceronman

2,861 karma

Programmer

Posts33
Comments260
View on HN
www.theguardian.com 1y ago

Is doom scrolling rotting our brains?

ceronman
7pts2
goodereader.com 1y ago

New Kindle e-readers no longer appear on computers

ceronman
4pts1
www.theguardian.com 2y ago

It's not them, it's us: the real reason teens are 'addicted' to video games

ceronman
8pts1
www.theguardian.com 2y ago

France's lower house votes to limit 'excesses' of fast fashion

ceronman
1pts0
bsless.github.io 4y ago

Idiomatic Clojure without sacrificing performance

ceronman
150pts79
medium.com 5y ago

Why nullable types?

ceronman
126pts115
medium.com 6y ago

GraalVM 20.1

ceronman
3pts0
www.reddit.com 6y ago

Dart can now produce self-contained, native executables

ceronman
18pts2
code.visualstudio.com 7y ago

Remote Python Development in Visual Studio Code

ceronman
2pts0
neopythonic.blogspot.com 7y ago

Why Operators Are Useful

ceronman
2pts0
news.ycombinator.com 7y ago

Ask HN: Do you use terminal based GUI applications?

ceronman
1pts2
pythoncapi.readthedocs.io 7y ago

Design a new better C API for Python

ceronman
1pts0
relm.ml 9y ago

Relm, a GUI library, based on GTK+ and futures, written in Rust

ceronman
4pts0
arstechnica.com 9y ago

Hackers unlock NES Classic, upload new games via USB cable

ceronman
3pts0
medium.com 9y ago

Why I moved from JavaScript to Dart

ceronman
3pts0
medium.com 10y ago

Events are not cesspools of harassment

ceronman
2pts0
stupidpythonideas.blogspot.com 10y ago

Python: Why can’t we write list.len()?

ceronman
4pts2
blog.booking.com 10y ago

Using multivariant tests to determine performance impact

ceronman
2pts0
www.youtube.com 10y ago

The Clean Architecture in Python

ceronman
1pts0
archive.org 10y ago

The Internet Archive just added 2,300 MS-DOS games to their library

ceronman
3pts0
github.com 10y ago

Pyjion – A JIT for Python Based Upon CoreCLR

ceronman
1pts0
blog.jetbrains.com 10y ago

Python 3.5 type hinting in PyCharm 5

ceronman
173pts117
windows.uservoice.com 10y ago

Petition to ship Python with Windows by default

ceronman
1pts0
glyph.twistedmatrix.com 10y ago

Software You Can Use

ceronman
3pts0
pythonjobs.github.io 11y ago

GitHub-Hosted Python Jobs Board

ceronman
4pts2
stupidpythonideas.blogspot.com 11y ago

Understanding Python's augmented assignment (a += b)

ceronman
72pts15
blog.carbonfive.com 11y ago

WebRTC Made Simple

ceronman
2pts0
www.tvdw.eu 11y ago

Implementing a Tor relay from scratch in Go

ceronman
9pts0
www.kickstarter.com 11y ago

Lumera: Add smartphone features to a regular DSLR camera

ceronman
2pts1
www.newyorker.com 11y ago

Gamergate: A Scandal Erupts in the Video-Game Community

ceronman
5pts0

1. Credit cards are not that common. People usually have debit cards. Those can sometimes be used online but they're not widely accepted. My debit card is Maestro, which is not accepted in many places.

2. Even with my Mastercard credit card, the process is still inconvenient. For small purchases, it's fine. But for larger ones, there is an annoying second factor authentication, I have to enter a special password, and the wait to receive an SMS.

3. Visa and Mastercard fees. Most of the time these are paid by the merchant. But sometimes the customer has to pay more if the payment method is credit card. Some places don't accept these at all.

In general iDEAL is simple, secure and convenient. Not only to pay online, but also for example for splitting a bill with friends. I'm very happy to see this being adopted more widely in Europe.

A switch or pattern matching approach is useful, but not practical for some cases. For example, there are cases where you are interested in only a single kind of node in the three, for those cases the Visitor pattern is very helpful, while doing pattern matching is cumbersome because you have to match and check almost every node kind. That's why, for example, the Rust compiler still uses the visitor pattern for certain things, and pattern matching for others.

The parsers in crafting interpreters do not use the visitor pattern. The visitor pattern is used when you already have a tree structure or similar. The parser is what gives you such tree structure, the AST. When you have this structure, you typically use the visitor pattern to process it for semantic analysis, code generation, etc.

The visitor pattern is very common in programming language implementations. I've seen it in the Rust compiler, in the Java Compiler, in the Go compiler and in the Roslyn C# compiler. Also used extensively in JetBrains' IDEs.

What do you have against this pattern? Or what is a better alternative?

The elderly, the kids, the teenagers, the adults. Screen addiction is a pandemic. The biggest one humanity has ever seen.

The richest, most powerful organizations are spending billions every month to make it more addictive, to reach more people.

I used to agree with this, but then I realized that you can use trace points (aka non-suspending break points) in a debugger. These cover all the use cases of print statements with a few extra advantages:

- You can add new traces, or modify/disable existing ones at runtime without having to recompile and rerun your program.

- Once you've fixed the bug, you don't have to cleanup all the prints that you left around the codebase.

I know that there is a good reason for debugging with prints: The debugging experience of many languages suck. In that case I always use prints. But if I'm lucky to use a language with good debugging tooling (e.g Java/Kotlin + IntelliJ IDEA), there is zero chance to ever print for debugging.

I don't know why you're getting down voted. But you are right. Rust type system solves this in a very nice way. Maybe to clarify we can show how to do the exact same example shown with Clojure multi-methods, but in Rust:

    struct Constant { value: i32 }
    struct BinaryPlus { lhs: i32, rhs: i32 }
    
    trait Evaluate {
        fn evaluate(&self) -> i32;
    }
    
    impl Evaluate for Constant {
        fn evaluate(&self) -> i32 { self.value }
    }
    
    impl Evaluate for BinaryPlus {
        fn evaluate(&self) -> i32 { self.lhs + self.rhs }
    }
    
    // Adding a new operation is easy. Let's add stringify:
    
    trait Stringify {
        fn stringify(&self) -> String;
    }
    
    impl Stringify for Constant {
        fn stringify(&self) -> String { format!("{}", self.value) }
    }
    
    impl Stringify for BinaryPlus {
        fn stringify(&self) -> String { format!("{} + {}", self.lhs, self.rhs) }
    }
    
    // How about adding new types? Suppose we want to add FunctionCall
    
    struct FunctionCall { name: String, arguments: Vec<i32> }
    
    impl Evaluate for FunctionCall {
        fn evaluate(&self) -> i32 { todo!() }
    }
    
    impl Stringify for FunctionCall {
        fn stringify(&self) -> String { todo!() }
    }

That's not the expression problem.

To me it looks like this is exactly the expression problem. The expression problem is not about adding methods to a trait, it's about adding an operation to a set of types. In this case every operation is defined by a single trait.

The idea behind the expression problem is to be able to define either a new operation or a new type in such a way that the code is nicely together. Rust trait system accomplish this beautifully.

That's not unique to Rust, you can add new interfaces in any language...

Many languages have interfaces, but most of them don't allow you to implement them for an arbitrary type that you have not defined. For example, in Java, if you create an interface called `PrettyPrintable`, but you can't implement it for the `ArrayList` type from the standard library. In Rust you can do this kind of things.

Why would the the orphan rule be a problem here?

The orphan rule only disallow impls if both the trait and the type are defined outside the crate.

But in this example if you are adding a new type (struct) or a new operation (trait), well this new item should be in your crate, so all the impls that follow are allowed.

Very cool. I think Wasm is a nice instruction set, but I agree that its structured control flow is a bit weird and also the lack of instructions to handle the memory stack. But it's much more cleaner than something like x86_64.

If you are interesting in learning in more detail how to write a C compiler, I highly recommend the book "Writing a C Compiler" by Nora Sandler [0]. This is a super detailed, incremental guide on how to write a C compiler. This also uses the traditional architecture of using multiple passes. It uses its own IR called Tacky and it even includes some optimization passes such as constant folding, copy propagation, dead code elimination, register allocation, etc. The book also implements much more features, including arrays, pointers, structs/unions, static variables, floating point, strings, linking to stdlib via System V ABI, and much more.

[0] https://norasandler.com/book/

This looks really cool. I especially like the "Keep your progress, whatever happens" feature.

The product looks polished and I definitely see myself using it. My only concern is: Are they taking VC money? Is this going to be enshittified to death trying to pursue a 1000x investment return?

I bet that if you take those 278k lines of code and rewrite them in simple Rust, without using generics, or macros, and using a single crate, without dependencies, you could achieve very similar compile times. The Rust compiler can be very fast if the code is simple. It's when you have dependencies and heavy abstractions (macros, generics, traits, deep dependency trees) that things become slow.

It was. But he had 9 minutes vs more than an hour for Gukesh. The entire match has been Ding defending miraculously, I thought it was a matter of time before he eventually failed. The fact that it happened on the last moves of the last game, it's definitely hard for Ding, but fair for Gukesh IMO.

YouTube Premium was already quite expensive. They increased my family plan from €17.99 to €25.99. This is almost a 45% hike! Compare to Netflix which is €13.99.

I only pay this to skip ads, but a lot of content creators still have their own ads on the videos. There doesn't seem to be enough value to justify such price hike. I am likely to cancel my subscription.

It's possible to write some pretty unreadable code with Clojure, just like it's possible in any programming language.

I can tell you that this code is very easy to read if you are familiar with Clojure. In fact, this example is lovely! Seeing this code really makes me wanting to try this library! Clojure has this terse, yet readable aesthetic that I like a lot.

But I completely understand you because at some point Clojure code also looked alien to me. You are not broken for having familiarity with some style of code. Familiarity is something you can acquire at any time, and then this code will be easy to read.

True hard-to-read code is one that is hard to understand even if you master the language it is written in.

Nice article. A couple of years ago I also implemented Lox in Rust. And I faced the exact same issues that the author describes here, and I also ended up with a very similar implementation.

I also wrote a post about it: https://ceronman.com/2021/07/22/my-experience-crafting-an-in...

I ended up having two implementations: One in purely safe Rust and another one with unsafe.

Note that if you're interesting in the "object manager" approach mentioned, I did that in my safe implementation, you can take a look at https://github.com/ceronman/loxido

I was talking about a monoculture specifically in the systems programming area. Java, Perl, PhP, Python, Ruby, JavaScript, C#, Go, these got popular but they use garbage collection and have limitations for systems programming. C and C++ were the only options for a long while.

The author seems very anxious because Rust is getting traction and they don't like Rust. They're afraid that one day Rust will become a "monoculture" and everything will be written in it.

I like Rust, but I consider this very, very unlikely.

Rust has actually brought more choice to the programming language scenario. If we're talking about monoculture, let's talk about C/C++. For decades this was the only viable option for systems programming. All new languages were focusing on a higher lever. Languages for lower level stuff were rare. There was D, but it never got enough traction.

Then Rust appeared and there is finally an alternative. And not only that, I because of that, other language designers decided to create new systems languages, and now we have Zig, and Odin, and Vale, etc.

So if anything, Rust is helping in breaking the monoculture, not creating it. C and C++ are not going away, but now we have alternatives.

And I think it's important to acknowledge that even if you don't like a language, if you see a bunch of software being written in such language, it's because the language is useful. I don't like C++ but I admit it's damn useful! People are writing interesting software in Rust because they find it useful.

The result is a ~300 KiB statically linked executable, that requires no libraries, and uses a constant ~1 MiB of resident heap memory (allocated at the start, to hold the assets). That’s roughly a thousand times smaller in size than Microsoft’s. And it only is a few hundred lines of code.

And even with this impressive reduction in resource usage, it's actually huge for 1987! A PC of that age probably had 1 or 2 MB of RAM. The Super NES from 1990 only had 128Kb of RAM. Super Mario Word is only 512KB.

A PlayStation from 1994 had only 2MB of system RAM. And you had games like Metal Gear Solid or Silent Hill.

Very interesting! They say they went from a stack-based IR, which provided faster translation but slow execution time to a register-based one, which has slightly slower translations, but faster execution time. This in contrast with other runtimes which provide much slower translation times but very fast execution time via JIT.

I assume that for very short-lived programs, a stack based interpreter could be faster. And for long-lived programs, a JIT would be better.

This new IR seems to be targeting a sweet spot of short, but not super short lived programs. Also, it's a great alternative for environments where JIT is not possible.

I'm happy to see all these alternatives in the Wasm world! It's really cool. And thanks for sharing!

In no way I intended to be dismissive of you work or the RISC-V architecture. I apologize if my words could be interpreted in that way. I actually think that RISCV is a really cool architecture, mostly because it is open. I would love to see it getting more traction in the hardware world. I also think that your work on libriscv is impressive!

My criticism was at the idea of using a RISC-V emulator as a scripting platform. And I'm not saying that it doesn't work, only that I personally think that Web assembly seems a better option for that particular use case.

If I understand correctly, the idea here is to provide safe scripting by running a RISC V emulator. The "scripts" would be written in C/C++ compiled to RISC V. And then these compiled scripts would be run inside the game engine's emulator. The emulator's library then will allow to share some memory between the emulated program and the host game engine by sharing some memory.

All this sounds like a poor re-invention of Web Assembly 1.0.

I think Wasm is a better option for most cases because:

- There are more advanced Wasm runtimes that can do JIT compilation and be very fast.

- There are probably more languages compiled to Wasm than to RISC V. Especially for higher level languages, which is attractive for scripting.

- There is better tooling for debugging Wasm.

- Interoperability is better specified in Wasm, it was designed from the ground up for that. And with Wasm components it's even better. This is specially important for different host architectures.

Very nice project! I love the fact that you have almost no dependencies for the compiler. I'm interested in learning how to build a compiler for web assembly and your code seems very clean, simple and easy to follow. Thanks!

I'm a happy Wayland user for years already.

But on a different topic, it's a bit hard for me to read such harsh critical posts on open source software. Wayland is free software, I don't have to pay a penny for it. It's truly free! not like Google/Facebook free when you pay by allowing the companies to spy on you and get all your data. It's also open source. And many people working on these things are volunteers.

Nowadays, most software is written iteratively. You start with minimal features, and start fixing, improving things. Not only Wayland, most products are like this. You could argue that this in the only way to have a successful software product. Waiting years until everything is perfect is simply not feasible.

All this time, while devs have been iterating on Wayland, X11 has always been available. And this is open source, X11 will always be available. Use it if you want. It's also open source, so you can even improve it if you want or dare to do it. So why being so harsh with those trying to make things better?