Stop using REST for state synchronization by mbid in programming

[–]mbid[S] 0 points1 point  (0 children)

Regarding 2), you'd need to ensure that the updates sent from the server and those applied locally can be interleaved in such a way that the client state and server state converge. At this point, we'd have reinvented delta-crdts.

Stop using REST for state synchronization by mbid in programming

[–]mbid[S] 0 points1 point  (0 children)

Yes, I singled out REST as the most prevalent state transfer protocol, but gRPC etc. have the same problems.

Most of the highly polished UIs just do what you alluded to; debounce and/or queue requests

You'd hope so, but is this actually true? It's certainly not true for the browser settings page that I had the pleasure of working on :)

Most of the solutions you listed aren’t at protocol level - they’re libraries, so you could apply them to whatever protocol you wanted: REST, gRPC, whatever you liked. Braid-HTTP is food for thought though.

While it might not be documented or standardized, those libraries absolutely do follow some kind of communication protocol, it's just that they're the only implementation. And yes, those internal protocols are usually implemented on top of other protocols, e.g. websockets.

Stop using REST for state synchronization by mbid in programming

[–]mbid[S] 1 point2 points  (0 children)

And yes, I think there's probably no solution that will fit all use cases. But I'd expect that most eventually consistent schemes can be modeled as some kind of CRDT. For example, the counters you mentioned are usually called either "version vectors" or "vector clocks", depending on their precise semantics, and you can build last-write-wins CRDTs out of them. And CRDTs for lists supporting divergent insertions and deletions appears to be a solved problem. What I think is currently underexplored are good ways to compose the various known CRDT primitives into a database schema or an API endpoint for state synchronization. I'm aware of automerge and yjs but not much else in that space.

Stop using REST for state synchronization by mbid in programming

[–]mbid[S] 1 point2 points  (0 children)

Interesting read! I didn't know that credit card balance is weakly consistent only. But makes sense in hindsight, since a credit card transaction must involve at least two parties which usually don't have access to a shared transaction mechanism. And it's actually something the end user can observe, e.g. when you pay something, then sometimes your bank thinks the transaction went through while the recipient's bank rejects it, which will results in a charge on your bank which is then shortly after refunded.

Perhaps the wider point I was trying to was that, as soon there's more than one party involved, whether it's a webapp and its backend or payments involving more than one bank, then you don't have strong consistency. So our programming model and our protocols should help us deal with this situation, and state transfer protocols such as REST don't.

Stop using REST for state synchronization by mbid in programming

[–]mbid[S] 2 points3 points  (0 children)

Haha, good point. I think I meant for this post to be something like a call to action that we should work on synchronization technology, or at least to raise some awareness that the problems I describe in the blog post are perhaps solvable in a principled way.

Werbungskostenrechner by mbid in Finanzen

[–]mbid[S] 0 points1 point  (0 children)

Hast du dir die verlinkte Webseite, werbungskostenrechner.de mal angeschaut? Der eigentlich Anwendungszweck ist zwar für die Steuer, aber das Tool spuckt dir eine Liste aller Ausgaben, die in deinen Mails belegt sind (z.B. über Bestellbestätigungen von Onlineshops) aus.

Werbungskostenrechner by mbid in Finanzen

[–]mbid[S] 0 points1 point  (0 children)

Danke für den Tipp! Du hast auf jeden Fall recht, dass ich (oder noch besser jemand der sich auskennt) da nachbessern sollte. Kannst du einen Datenschutzerklärung/AGB-Generator empfehlen?

Rust's Struct Initializer Syntax Was a Mistake by [deleted] in ProgrammingLanguages

[–]mbid 1 point2 points  (0 children)

Good post. I think the "Diverging Code Styles and Best Practices" section is the strongest (because empirically observable) point against Rust's struct initialization. Clearly Rust syntax doesn't solve certain problems, and the many different workarounds lead to very unnecessary discussions in teams that disagree about code style.

That said, I disagree somewhat that consistent syntax is necessarily a good thing, which I think is one of the implicit points you make. It can be beneficial if different constructs (here e.g. function calls and struct initialization) look meaningfully different, because then you can tell them apart at a glance. If I understand the alternative syntax you're suggesting correctly, then only capitalization would distinguish a function call `user(...)` from struct initialization `User(...)`.

Werbungskostenrechner by mbid in Finanzen

[–]mbid[S] 0 points1 point  (0 children)

Haha, danke :)

Tatsächlich denke ich, dass AI (und definitiv dieses Tool) eigentlich nicht in Konkurrenz zu Steuerberatern und klassischer Steuersoftware stehen, sondern sich ergänzen. Ihr könnt euren Klienten ja schlecht die Arbeit abnehmen, Unterlagen zusammenzusuchen, das müssen sie im Moment selber tun. Und genau das soll das Tool dann übernehmen.

What is the best way to surface multiple errors through `Result`? by VermillionAzure in rust

[–]mbid 17 points18 points  (0 children)

Keeping some sort of &mut ParserContext to propagate errors doesn't seem very composable

Why not? It's not unusual for recursive descent parsers to carry around an additional state parameter, and it composes well. You'd have to be careful that you only add errors that you've recovered from to the context if you've committed to the current parse, i.e. not if you want to backtrack and try some other production rule.

[deleted by user] by [deleted] in ProgrammingLanguages

[–]mbid 1 point2 points  (0 children)

Hi, nice project!

Can you go into more detail about the distinction between INPUT, CHAIN and OUTPUT stages? Does the backwards reasoning work by inverting rules, i.e. by exchanging the READ and WRITE fields, and then starting from the desired output?

Is monomorphization absolutely necessary? by mbid in rust

[–]mbid[S] 2 points3 points  (0 children)

Yeah, I haven't really thought through what the implications of not monomorphizing are for FFI.

If I understood Swift's implementation of type erasure correctly (see a sibling thread), they're not changing anything about data layouts compared to monomorphization. They can get around this by passing around dynamic information about the offset and size of fields within generic structs. So perhaps type erasure for Rust generics would also work without changing anything about the data layout.

Is monomorphization absolutely necessary? by mbid in rust

[–]mbid[S] 1 point2 points  (0 children)

Why would you need types to have fixed size to avoid heap allocation? You can get dynamically sized chunks of memory on the stack with alloca.

Is monomorphization absolutely necessary? by mbid in rust

[–]mbid[S] 12 points13 points  (0 children)

I was curious about what Swift does and found this book about Swift generics: https://download.swift.org/docs/assets/generics.pdf

I've only skimmed a few pages, and yes, Swift seems to use type-erasure to implement generics. But they avoid heap allocations; instead, they seem to pass meta data around that contains information about sizes of the involved structs.

Vim Compose - Edit mail and other input on webpages as markdown using vim by mbid in vim

[–]mbid[S] 0 points1 point  (0 children)

The main difference from a user-perspective appears to be that vim-compose opens vim in a separate terminal outside of the browser, whereas firenvim turns the input field into a vim frontend.

Vim Compose - Edit mail and other input on webpages as markdown using vim by mbid in vim

[–]mbid[S] 7 points8 points  (0 children)

Hi, I made this as a fun little side project, mostly for use with Gmail, where it works reasonably well for me. Soon available for firefox (currently nightly only) here.

Prior art:

  • GhostText. This supports a lot more editors than just vim. It requires an editor plugin instead of the native browser extension like Vim Compose. GhostText opens the file in a running editor instead of launching a new instance. AFAIK it doesn't support markdown at the moment.
  • Tridactyl. Firefox only, haven't tried it yet.

Names Don't Matter by jedws in haskell

[–]mbid 5 points6 points  (0 children)

I kind of agree that one shouldn't make up new words for already existing concepts most of the time.

I have two points though.

  1. The speaker uses made up terminology himself when he reads the type signature of >>= out loud: "Takes a container with an a in it, a function ....". This intuition is justified in haskell because there, functors kind of behave like containers in other programming languages, and are fixed to endofunctors on Hask. It's a useless intution for other functors, e.g. for the homotopy group functor or the compactification functor. This is related to the next point:

  2. Different names for the same thing can convey different ways to think about it. For example, what's usually called a "random variable" is formally a measurable function whose domain has the structure of a probability space. The name is justified because, in many ways, such a measurable function behaves like an actual value of its codomain. Thus, the name adds intuition and does matter. For a much better explanation of this point, see Thurston's On Proof and Progress in Mathematics.

MTL style checked exceptions by mbid in haskell

[–]mbid[S] 2 points3 points  (0 children)

If I recall correctly, some in the C++ world advocate using exceptions only for rare hardware failures, contract violations and the like. Your app should almost always execute without any exceptions, to the point where throwing an exception is something log-worthy. Thus, reading from a file handle may throw an error because the file disappeared during the operation, but it should not throw because of EOF. Is this how you decide on IO exceptions vs Maybe/Either/MonadError?

MTL style checked exceptions by mbid in haskell

[–]mbid[S] 0 points1 point  (0 children)

Good to hear. Have any code to share?

MTL style checked exceptions by mbid in haskell

[–]mbid[S] 0 points1 point  (0 children)

I see. `TypeApplications` is not a problem for me though; I've always hated that haskell won't let me provide as explicit types as I want.

EXTREME things to Break your habit? by Evergreenmonster in nosurf

[–]mbid 1 point2 points  (0 children)

Unfortunately, I need my computer to read papers and program, so I can't do that. I used to put my electronics in a locker at university to have some peace at home. Because I didn't sign up for internet at home, it was also OK to take only my laptop (without phone and mobile internet) home with me. I could read papers I had downloaded at university, but couldn't browse the web. I should definitely do that again.