HNHacker News
TopNewBestAskShowJobs

marcus_cemes

401 karma · joined September 21, 2020

Switzerland, studied at EPFL.
submissionscomments
marcus_cemes··on An animated introduction to Elixir
I've been using WSL, which you can get from the Store now. Works for development and building releases, which then deploy to an Ubuntu VPS.
marcus_cemes··on Ntfy.sh – Send push notifications to your phone via PUT/POST
From the repository that I found, it seems that you wrote the backend in Go. How did it hold up? Any lessons learned?
marcus_cemes··on Blessed.rs – An unofficial guide to the Rust ecosystem
I've done some C/C++, a lot of JS/TS due to its web dominance. I found Elixir a year ago and fell in love with it.

I love the functional style of Elixir, it's elegant to write and read, but feels unsafe. The lack of a type system is hard for me and has been a nightmare when trying to find the origin of a particular error tuple and refactoring code, running the app to see if it works. Running it in production feels like a ticking time bomb, even if it does handle fault tolerance gracefully.

I've reached for Rust for the occasional project and have never regretted it, I couldn't justify its use for everything though. Very high-quality ecosystem, rock solid and predictable performance and tiny footprint. I've made a VPN supervisor process that fits in a few MB Docker image (without OS), uses a few MB of RAM, no idle CPU and wonderful latency.

Perhaps Erlang can manage tail latencies better under load, pre-emptive scheduling is awesome, but my personal experience has been that Rust is just much more efficient at doing the same task, giving you more free CPU time, predictable memory freeing that rivals Erlang's per-process GC. You finish that blocking computation before it even becomes noticeable. Erlang’s fault tolerance is matched by Rust’s type system and memory safety guarantees. It's hard to compare C++/Rust to Erlang/Python/Ruby, they're just different.

It's slower and more frustrating to write, but the language server gives you so much feedback and useful comments. I find the linter amazing, it finds some pretty obscure and neat improvements with the additional type information it has, and Option<T> and Result<T,E> have an almost functional-like chaining pattern.

For a small hobby project, Rust 100% of the time. No painful dependency management, no complex build process. For a more serious project, or for a client, not always justifiable. I always miss Rust’s language features and libraries when coding in another language that has the upper hand in their respective dominant fields, although I like that a lot of tooling (ESBuild, swc, Tailwind's compiler, fnm, Rome, ...) is being remade in Go/Rust, it benefits far more people than it inconveniences.

marcus_cemes··on The type system is a programmer's best friend
This is brilliant. Just made my day
marcus_cemes··on The Future of the Web Is on the Edge
That's perfectly sufficient for a large number of use cases, keeping things simple.

The edge isn't just where the cool kids hang out, through. There is a very noticable latency hit over long distances, amplified by the number of round trips needed. If you have a local business, this isn't a problem.

Making it super simple to deploy things to the edge, and developing systems to make it easier to push data that can be cached to the edge to avoid trips to a central database, is awesome even for hobbist programmers, like Heroku made it easy to deploy applications without worrying about VMs.

marcus_cemes··on ReScript 10.0
The type inferrence only applies to ReScript code, it's not a magic compiler that can statically analyse JS code and generate interfaces for any arbitrary npm package. For Typescript interop, it can "trust" the TS declaration files, but there is no real guarantee when you're crossing language boundaries. ReScript is it's own language, with it's own type system that compiles down to JS. I don't think there's a reasonable alternative to this.

Take Rust, calls to C code are inherently unsafe, and must be marked as so. You're leaving Rust's source code and type system and calling into external functions that you may not even have access to source code for and that the compiler just can't feasibly vouch for.

marcus_cemes··on ReScript 10.0
I don't understand why ReScript is trying to sell itself as a language for React. React is already "kind of" functional, has a rich JS/TS ecosystem and there are fantastic alternatives such as Elm.

I think this would have huge potential in the backend space if it had good interop with Node.js and TS, with perhaps a functional framework similar to Elixir's Phoenix. Elixir proved it can have fantastic integration with Erlang.

* More robust applications with the Result type

* An actual integer type (for 64-bit database keys, Prisma uses BigInt)

* Finite state machines for stateful logic, games, websockets (enums and a sound type system)

* Benefit from the JS-centric serverless ecosystem

We've already been "compiling" or "transpiling" JS for years, most of written JS code has little in common with what is actually run.

In its current state, I don't even want to imagine what it would be like to set this up alongside ESM, TS, Prettier, ESLint, Jest, Storybook, ESBuild, Vite, (insert cool tool here). I've already spent literal days trying to setup a "modern" Node.js project, only to give up and go back to CJS for simplicity and import older non-ESM versions of packages[1], wish I wasn't using Node.js, then remember how many things I miss from JS when trialing another language.

[1]: https://github.com/ai/nanoid/issues/365

marcus_cemes··on How to build a personal webpage from scratch
It takes time to establish discoverability with a website, you either rely on a search engine, word of mouth, business cards, etc. A new small-business website won't magically start generating traffic without some significant effort.

Using a platform like Facebook or Google Maps makes it easier to for other people to find your page when they want to look for it.

marcus_cemes··on Age – a simple, modern and secure file encryption tool, format, and Go library
I'm not an expert, but here's my take.

The public key is generally not considered a secret and is therefore "less guarded". Anybody with access to the public key is able to encrypt and create legitimate looking files that are indistinguishable from the original files. You can still only decrypt them using the private key, but you can no longer trust the contents of the file as your own.

A solution would be to encrypt with the public key, and then _also_ sign with the private key. When reading, you work in reverse order. You verify the signature using the public key, and then decrypt the file using the private key.

But then if you're just using both, why not use fast and robust symmetric encryption instead? Not only will decryption be garbage if the file has been tampered with, but you can also create a signature to detect it (HMAC).

marcus_cemes··on JIT/GPU accelerated deep learning for Elixir with Axon v0.1
Unfortunately, I have to agree. I've been using Elixir for the last year and it's one of the very few languages that I've really enjoyed using, a lot. I would love to see it get traction, but it doesn't have the same momentum as Python, nor Rust for that matter.

I don't think there's anything special about Python and data science/ML, it just happens to be everyone's go-to wrapper language around C code. Personaly, I dislike Python, it has been nothing bit pain for me in the past (not necessarily the language, but the design of popular libraries such as matplotlib), but it's always handy when you need to get something done.

That being said, there are a lot of really high-quality Elixir projects being developed at the moment, Liveview, Livebook (that I think far exceeds Jupyter in innovation), Nx, etc. Perhaps that's one of the benefits of having a smaller community. I like how Elixir has slowly developed into a mature and beautifuly designed language, with focus on stability and not hype.

marcus_cemes··on The benefits of “low tech” user interfaces
I guess the "digital but with physical buttons" is the middleground. It still gives the designers the ability to mess around with acceleration curves that amplify fast movements, or to not sample the value fast enough to get coherent digital readings. I don't understand why they do this. As a university engineering student, I have a great love for linear systems, which usually is anything analogue. It makes everything easier.

For example, the focus ring of a consumer digital camera lens drives me nuts, it's practically impossible to do a pull focus reliably between two objects. If you do it a little faster or slower, it will be off, regardless of the travel distance. On the other hand, professional cinema lenses usually have actual mechanical focus wheels attached to ensure perfect reproducibility.

marcus_cemes··on Fly.io: The reclaimer of Heroku's magic
I've actually been deterred from Heroku because of the pricing. I find $7/month too much for a website or a blog, especially as I like starting new projects. There may be months where nobody visits my sites. I pay 2.49 euros/month for a VPS in Germany with 20 TB of free monthly bandwidth, 2GB RAM, 20 GB of disk space, no brainer. It's just a bit more manual.
marcus_cemes··on Deno.js in production
Most people trust that the script is not malicious, including me. There is wrong with this approach, it is extremely convienient to try something out that has good reputation.

For these people, running the script or downloading a signed GitHub release is equivilent, in both cases they do not read the source code of the software that they are running.

There is nothing stopping you from 1) reading the script before running it 2) reading the source code of Deno and any dependencies 3) compiling from source yourself. For most people, this is a waste of time. Trust has to start somewhere to build something great.

marcus_cemes··on Four Eras of JavaScript Frameworks
A website that is able to function without JavaScript increases its accessibility, that doesn't mean that the user explicitly disabled JavaScript. You could be on a train in a 5G-equipped country with an unreliable connection. Have you came across a website having problems with stylesheets completely missing, due to CORS, caching, etc?

If the document is able to carry out navigation, without having to rely on downloading a non-negligeable amount of JS to hydrate the page, it improves the experience for that 90th percentile enourmously. Us web developers are often privileged with a very good internet connections. It's not necessarily anti-JS thinking, and SSR for crawlers generally as no longer been relevant for a number of years, it improves UX.

Edit: this also reminds me of [1], a 8.5 MB HTML file with 27.5k tweets was faster to paint than a single tweet in a React application. It depends on whether the UX can be improved by using more JS, for most websites I think less is more.

[1]: https://twitter.com/zachleat/status/1169998370041208832?s=20...

marcus_cemes··on Four Eras of JavaScript Frameworks
I'm in love with the design of that website. It's clean, there are subtle graphic changes such as the pixel art that changes when you toggle the light switch, a really fantastic job there (one small remark, hovering over the pixel art on Chrome makes a scroll bar appear due to the transform). I want one.

It's also proof that you can make a simple and pleasant experience with a JS framework, if you focus on the essentials, there's no need to boycott JS entirely in favour of the old web, these frameworks get rid of a lot of the boilerplate when starting from scratch.

I'm an avid supporter of SvelteKit (the framework used on that website) and how they want to make the web less SPA/JS again. In this example, navigation is fast and client side, but can fall back to SSR if JavaScript is disabled, fails to load or hasn't loaded yet. There is no heavy runtime with virtual DOM diffing. Resources are cached and a page reload only sends ~17 kB over the wire on a large blog post, showing an excellent use of Tailwind CSS. It renders on Cloudflare Workers close to the user wherever you are in the world, with zero vendor lock-in if you want to stick it on a VPS.

marcus_cemes··on The absurd complexity of server-side rendering
It's easy to server-side render Next.js apps, but usually they still have to talk to a backend. I don't think Next.js' API routes are good for this, especially if you need messages queues, cron jobs, etc. Now you have three distinct parts, client-side rendering, server-side rendering and the API, usually all communicating via JSON.

Traditionaly with PHP, C#, Ruby, Elixir, etc, your backend and frontend was tightly coupled, your code has complete access to backend resources, and the view/template would map the state to a HTML document.

Now, for the sake of interactivity, the view has effectively moved from the backend to the frontend with the introduction of SSR/SPA, JSON everywhere and code duplication so that they can all talk and understand each other. It's cool when it works, but it is easily at least 3x the amount of work.

There is of course the argument of "just write both the client and server in JS/TS and use a monorepo", that brings its own challenges. Limiting the backend stack to what browsers support is not great, especially when Node.js is single-threaded with cooperative scheduling. No, lambda functions don't solve this entirely, and they're freaking expensive for CPU time. Honsetly, other ecosystems have it so much simpler IMO, even if it isn't as flashy.

I say all this as a svelte developer, guilty.

marcus_cemes··on Node.js packages don't deserve trust
I think the machine has just gotten too big, it would require a huge effort, even the original creator or Node.js, Ryan Dahl, is strugling create sufficient displacement with Deno. Innovation over safety? Like cheap products I guess, either you join them or get driven out of business, leaving only the cheap products anyway.

Also, if you want to spend a lot of time, effort or money to vastly improve something, would you put it into JS or would you perhaps focus on another language that has better foundations and hope it catches on, where there is the potential to outperform (in quality and consistency) the JS ecosystem? Perhaps those with more sense move to other ecosystems, such as C#, Go, Java, Elixir? I say this as a long-time user of JS who has recently enjoyed his foray into Elixir.

marcus_cemes··on Node.js packages don't deserve trust
It makes me deeply sad to see these sort of interactions in open source [1].

> Hmm, I think it's a worthwhile fix. Where did you see malware here?

> I think the author of this repo is free to decide what code he publishes. Say thanks to that it's for free

An incredible amount of people have dedicated sweat and tears and foreheads (from banging against the desk in frustration) to open source across the entire stack, from the contributers to OSs such as Linux to those working their arses off to create better frameworks, languages and runtimes, that we can all benefit from and use with a reasonable expectation of security, respect and privacy.

As a university student, I feel privileged to have been able to grow up in a world where so much work and knowledge is provided for free with no strings attached, regardless of demographic/location, I would not be where I am without it. A century ago this would not have been possible. To all of you who have tirelessly and selflessly worked on OSS for others, without expecting anything in return or imposing politics, ideologies, infringing on privacy, causing damage, collecting vast quantities of marketable personal information or monopolisation, I give you my heartfelt thanks for your efforts, you know who you are. You have created something that will have forever helped to improve our society and empower those that want to learn and create their own designs.

From my own personal experience, I want to give a shout-out to the smaller projects of Rust, Svelte and Elixir. I think it's incredible that the work and ideas of (often) a single person (Rich Harris, José Valim) can grow into larger extremely welcoming and helpful communities with many more motivated contributors that are proud of being parts of those projets and put in an extraordinary effort to try and do things better than before. I'm sure there are plently of other worthy names I'm too young/ignorant to know.

Love it or hate it, Node.js has been very empowering for a large number of people to learn and publish their own full-stack applications, the JavaScript ecosystem has improved enormously since its beginnings, but has a tendancy to change slowly due to its size, unless a disruptive technology comes along such as TypeScript. Websites are a great way to introduce people to the joy of programming with its visual feedback, you can make a small penguin move across the screen, then move on to play tic tac toe. Even as a younger developer, I admit that the days of FTP, no-build-step pages with a sprinkle of JQuery were easier to understand and actually safer for newcomers than introducing someone to a SPA stack (which can easily have thousands of transient dependencies) nowadays.

[1]: https://github.com/Yaffle/EventSource/issues/202

marcus_cemes··on PSA: React 18 calls code twice in strict dev mode to detect side effects
Also, these types of global modifications make such libraries fundamentally incompatible with projects such as Tauri that focuse on safety and security. In a recent video of theirs they mentioned that of the popular frameworks, the only one that didn't seem to do any dodgy modifications of the global scope was Svelte (they didn't mention which frameworks failed the test, but I imagine React was one of them).
marcus_cemes··on PSA: React 18 calls code twice in strict dev mode to detect side effects
If anyone is curious as to why, I believe it's the only way that React can "poke" your code to see whether it really is side-effect free, and therefore concurrent mode/suspense compatible. The idea is that React can re-render your component whenever and however often it likes whilst getting the same results for the same input state, without this assumption, new patterns such as concurrent mode and suspense become very difficult to implement. Double rendering is a rudimentary dev-time test to see whether the output is actually the same to try and help you avoid bugs later on (data races for example), without enforcing a language, such as ReasonML or Elm. Alternatives would require really complex static analysis or strict ESLint rules. There may be other reasons as well.

Sometimes there's a need for side effects, the DOM is very stateful and unfortunately React is not quite fast enough for smooth animations at 60fps on most devices, it's also a lot easier to use global variables (no judgement) rather than properly organising state hooks and component props.

React started to move away from OOP and more towards FP, starting with hooks and function components. One of the driving reasons behind this was that function components could be minified a lot better than classes. Reducers, side effects, pure, memo, are terms that are more known in the FP land. I also think it gave them a lot more control as a framework to implement patterns such as concurrent mode as functions are stateless unlike classes, moving the state up into the React framework itself. This means several versions of the state can exist at once, and React just runs them through your function to generate the view. Side effects introduce unpredictability and nondeterminism using this pattern.

This FP style can be confusing to new programmers (anyone feel like trying to explain useEffect() to a 5-year-old? Anyone?), especially those that are used to global variables or manipulating the DOM directly (JQuery), but understanding the OOP render cycle had its own learning curve. Frameworks such as Elm are met with much love, even if React's hook-based approach is a little different.

Small aside, I also think that's where useEffect() got it's name from: side effects. It's where you put all those nasty network calls and setTimeout()s, and then scratch your head when you forgot to cancel/unregister them when the component unmounts and React complains that you tried to change the state on an unmounted componment. Suspense (hence the need for side-effect free functions, hence this double-rendering problem) should help with avoiding putting "if (stillMounted) { ... }" everywhere in useEffects with async code by giving React more control over the render/update process.

Full disclaimer, I haven't actually written React in a while, not since I found out about Svelte, I'm curious, how to authors of libraries such as React/Framer Motion handle the double rendering issue when interacting with the DOM directly? Other frameworks that I know of that avoid the complexities of concurrent mode/suspense either very stricly enforce this FP style, such as Elm, or try to be fast enough to forgo the virtual DOM and embrace mutable state, events and two-way data binding such as Solid and Svelte.

marcus_cemes··on I Believe Zig Has Function Colors
This is my sentiment as well, I understand some people's reservations and the fact that "async pollutes every calling function, as now everything must async as well", but to me this is correct behaviour and beneficial for the programmer. To me, this is akin to the pure/unpure function classification in FP, it makes sense that calling an unpure function would also "taint" the caller. Why should "fetch_user_db_which_may_be_on_the_other_side_of_the_world()" look the same as "Math.abs()", when their behaviour for the caller is so different?

I recently tried Go to speed up some Cloud Functions that use Firestore, it's very difficult to know which of the chained method calls of the Google-provided SDK is the one to actually "blocking" the green thread, perhaps they are all are unnecessarily? Without studying the source code, it's hard to know. I prefer explicitness over absolute simplicity. It also makes it easier to optimise code in my opinion as it's easier to identify sequential async calls that could actually happen concurrently, either by merging SQL queries or by using Promise.all() or the equivilent.

JavaScript does a good job with the await keyword in my opinion, you know exactly when something could take a significant delay, when it's doing something more behind the scenes. Rust does one better by making ".await" a suffix, allowing for nifty call chains. It communicates that this is an explicit yield point and could take a while.

marcus_cemes··on Ruby 3.2 preview 1 with support for WASM compilation
I've been very attracted to learn Ruby a couple of times, being exhausted of the JS ecosystem. Everybody who's used it seems to fall in love with it, but I can't get over just how slow it is... It takes a fresh installation of Discourse over 10 minutes to start-up again on a small underpowered VM and uses 10x as much RAM as an alternative platform such as Flarum.
marcus_cemes··on Seriously, Stop Using RSA (2019)
I'm not familiar with NaCl, websites that don't seem to have been updated in 7 years (version states 2016?) make me a little suspicious about the future viability of said projects. Perhaps it's not something that needs to be updated very frequently, but my knee-jerk reaction is that it looks abandoned, especially considering that they have an "upcomming features" section.

What made you choose it? Could PGP/GPG with ed25519 keys not have been sufficient? What makes NaCL "fun to work with"? For me, fun to work with would be Age [1] or Ring [2] with a elegant and well designed API. I'm also aware that the older something is, the more likely it has undergone peer review and security audits, unlike new Rust crypto libraries.

[1]: https://github.com/FiloSottile/age [2]: https://github.com/briansmith/ring

marcus_cemes··on Supabase Edge Functions
> Using golang cloud functions. I have a constant stream of hits, so there are always available functions.

There is no way to avoid cold starts althogether, there will always be tail latencies unless there is a generous amount of idle instances running that GCP charges for.

> under 1s. Hot request/responses are ~20ms.

Those numbers are great, I think Go plays a huge part in this. Google's Node.js firestore SDK is terrible... I've had 15 second cold starts, which is unacceptable for client-facing functions, there's a whole thread about it here [1]. GCP doesn't have a very wide range of language SDK support for those that don't want to use Go or Node.js...

> My hits are all US based

Edge compute, like Fly.io or Cloudflare Workers truly shines when you need to serve traffic close to the user around the world. Otherwise normal region-locked functions are fine. Vercel requires you to choose a single region, and it's locked to US-east for free-tier users. For us Europeans over here, SSR has to effectively cross the Atlantic ocean.

[1]: https://issuetracker.google.com/issues/158014637

marcus_cemes··on Supabase Edge Functions
Static pages relied on the client being able to run JS to populate user-specific data. Also, a lot of data is fine with being eventually consistent, which is a good fit for edge functions. An example is rendering the account icon and username on the top write, without hitting a central database/static file server.
marcus_cemes··on Supabase Edge Functions
Amazing work, kudos to the Supabase team!

> However, Supabase already offers a flexible solution for that - Database Functions! As such, for Supabase [Edge] Functions, we decided to deploy far-and-wide so that they are as close to your end-users as possible.

Does this mean that a choice has to be made between high latency (Edge Functions) and specialised SQL-only functions (Database Functions)? I see that cron-like triggers are still on the roadmap, is there a plan to have TypeScript functions that can run close to the database (or other resources)? Call me new school (as in not old school), but I prefer processing complex queries in a language that I feel comfortable working in, SQL is not that.

I know a lot of folks are huge fans of writing pure SQL, the lack of type safety and lack of good intergration with source control (I dream of a world where database schemas, functions, security access and the rest can be saved to source control for reproducibility) scare me.

marcus_cemes··on Lapce – Fast open-source code editor
Great work already! I do have one nitpick, however. Instead of handling click events, it seems to be using a more direct mouse input and acting on the mouse button being pressed. In webpages, this is the difference between onmousedown and onclick events.

This is extremely frustrating, perhaps it was done to give the illusion of speed, or it's a side-effect of the immaturity of the GUI framework? If you click and hold on the tab close button on your browser, and then move your mouse away and depress the button, you have the possibility to abort the action.

Another side effect of this seems to be that the GUI does not respond to presses from a touchscreen (on laptops), which does not behave like a mouse input, but still fires click events that most applications happily accept.

marcus_cemes··on '50% of transactions were fraudulent' when Steam accepted Bitcoin for payments
> There are many context where a 0conf tx makes sense, mostly IRL.

I'm curious, like what? To me this is more like "someone wrote a cheque but there's no guarantee that they'll give it to you".

marcus_cemes··on Military gap between Russia and Ukraine
I think that their leaders should sit down and negotiate, rather than stick weapons in the hands of ordinary people and deter Russia with the threat of causing genocide. Nobody wins in that scenario, unless Russia backs down which seems unlikely at this point in time. Dialogue is the way forward, not improvised video game weapons.
marcus_cemes··on I'm so sorry everyone. Or: why I'm switching to Cloudflare
> I'm about to graduate from a broke high-schooler to be a broke college student. I could reduce costs and run a minimal VM that acts as a WireGuard VPN server and proxy TCP using fancy firewall rules or whatnot, but that would also cost money.

Fellow student here. I love free tiers, but they can also be extremely frustrating. I actually prefer paying for reasonable priced services, that way you know what you're getting. For example I pay 2€/month for a 1vCPU/2GB Hetzner VPS with 20GB of storage, with 20TB of free egress (prices increased recently due to IPv4 shortage, they still charge me only 2€ however). That's about as much as a cup of coffee in CH, I can't recommend Hetzner enough. It could easily handle all traffic without Cloudflare. Having started to get a lot of spam through that domain, I'll take any protection that CF might be giving me. Also, setting up/maintaining Ubuntu from scratch has been extremely beneficial for me.

If you're limited by your location, there's nothing wrong with offloading to a VPS or running a reverse proxy. Considering you mentioned port 80/443, I imagine that a NGINX reverse proxy would be sufficient? It's basically your own mini-cloudflare proxy, only you're in control.

> I had used Cloudflare briefly before. My issue arose when I realized that they remove your SSL certificate, then use their own. Cloudflare is a big MITM service.

Why is this an issue? Any platform that serves requests on your behalf must be able to decrypt the request payload, I think any security expert would argue that having them use their own trusted certificate is much, much better than giving up the private key associated with your own certificate. Trust me, nobody (+/- 0.1%) checks the certificate when visiting your website... If they found a way to just forward on TCP packets, what useful service would they provide? A port-forwarding alternative? It's not so much a man-in-middle attack, you agree to a ToS and they provide a service. Ultimately, the DNS record is the authority on domain ownership, any server that is pointed to by the DNS record is authorised to represent that domain, and is sufficient to request a unique certificate from Let's Encrypt, for example.

> But I still don't like you.

Why not? I've been using Cloudflare for years, if only for the great DNS management panel. Of the "cloud" companies, they're my favourite. I believe Vercel use their infrastructure (they run their own datacentres), they're great to listen to on podcasts and have some interesting disruptive tech coming out, namely R2, which as a small filmmaker hobbyist, is truely a gamechanger for me. If their interests diverge from mine, I simply terminate my account and reasign the nameservers with my registrar. There's no lock-in.

← PreviousPage 2 of 5Next →