u/mamcx
mamcx
mamcx
None of your solutions is what could matter, and btw, Rust is the best possible option in this case for the opposite of what you think: is verbose, strict, excelent errors, strict, good tooling, strict.
Is also strict, that make lots of of errors and ambiguous stuff in other langs just impossible and the little it don't is much more tractable.
BTW, even if is imperfect, the idea is that LLMs are biased to what a human that knows is biased to, so if good developers pick Rust (with good reasons) then LLMs will use it much better.
mamcx
I have use all fads, kool-aids and silver-bullets (mostly do enterprise development), and js dev is one of the worst among all things I have done (and trust me, I'm the guy that take weeks evaluating).
JS only gives you fast initial speed and lots of people that allegedly knows about the current -6months js way of do things.
IF you actually know how extract the good parts of js and all the surrounding things (like with everything a PRO can polish a turd very well) it can work.
Rust is, as other said, slow to compile and you need some knowledge of how architect things, in a way that cost you up-front, but once there is smooth sailing.
This is what I recommend:
- The major mental switch is not test the html but your Rust UI model
This is the major win, have struct/enums that describe the UI with all the localization, formatting, etc and just use the expect crate (or similar) and compare json outputs:
rust
expect![[r#"
{
"next_path": "/manager/users",
"passkey_login_failed": "Could not sign in with a passkey. Try again.",
"passkeys_unsupported": "This browser does not support passkeys.",
"shell": {
"brand": "Ledger",
"lang": "en",
"title": "Workspace access"
},
"skip_to_form": "Skip to form",
"state": {
"state": "empty"
},
"submit_label": "Continue with passkey",
"subtitle": "Use your passkey to continue.",
"title": "Sign in",
"username_label": "Username"
}"#]].assert_eq(&json(&from));
and so most of your time is just running test, that is fast. Also, you avoid the anti-pattern of test strings instead of well-formed types.
- Separate your domain from you ui building from your http handling
This comes from above but is the main architecture that allows for fast AND correct by construction iteration. Once done, the productivity is very high and I work way faster than with python/django/vue/etc
- Use htmx, tailwindcss
This is the main tip for most cases, reaching for reactive client-side js frameworks is something that must be considered very very well, and most cases? use react is wrong.
BTW I bet adapting some of this to any other tool will work fine.
mamcx
I find weird “u32 is 0..4096”.
Pascal has it:
pascal
Type
TDay = Set of 1..31;
So is a new type, and the good thing is how this allow to have a static range on arrays:
pascal
for i := Low(array) to High(array)
that I find very nice. I dislike how in langs like Rust I must manually cast back positions, when in Delphi I can do days[Monday] naturally.
mamcx
As I read your question, the problem is not make a language like that, is how make it ergonomic and not complex to write it.
The hidden complexity (that hit Rust for example) is having many complex features and make them work, a lot of the complexity of Rust is not the borrow checker, is all the other things like async, generics, traits bounds, etc.
So, the way to make a language without huge complexity is to remove features.
A example is zig, pascal and such. The more things your language not do the less things will impact what model of memory management you use, because there is less intersections that need to prove to be sound or correct.
The other thing is to accept that whatever model or semantics you chose will work fine 80%-ish of the time except when try to do fancy things or edge cases. As long you hit most cases that's ok, then you can do like Rust and provide equivalents to "unsafe" for the rest, use macros, provide a built-in impl of something that will too hard to do by the users, etc
mamcx
My pet peeve is that integers and floats go in different ways (floats has inf, nan) just because the CPU say so.
I wish it was viable to use both under similar semantics without cost on perf, that is honestly the main reason nobody go in a more principled way.
P.D: And my main gripe? that decimal is not CPU accelerated!
mamcx
I use Claude too, but the drop on usability with GPT is what I wanna fix
mamcx
Well, not use gcc and clang? you can do clang on linux too.
Then use docker (with orbstack is faster) to run checks.
mamcx
I worked on SpacetimeDB, after lurking around a decade or so looking at RDBMs impl in general.
Rust is a game changer for system programming, is the whole point of their existence!
But what are the selling points being written in Rust?
The one displayed here point to something important: Rust allow for experimentation and revitalization of long dormant system development.
Doing a RDBMs is brutal, is one of the projects that demands the highest reliability, and combine with how bad is from the dev side the experience of C/C++ it means before was triple-lunacy to even dare to start a project like this.
This is a testament of the power of Rust: You can do a RDBMS.
And is only if people try that is possible to break from the "innovation jail" that has plagued the RDBMS for long time.
Granted, not many of the new exponents do something more interesting that just a improvement on a fraction of what PG do (you see: Doing a RDBMS is brutal) but there is interesting movement in the area even if many are not aware of it.
For example, one of the things I proud of when worked on SpacetimeDB is that it implement algebraic and structural type system and means that the users not even see how profound is it (their Rust types store basically as is). Is one thing that sound small, but is breaking one of the major limitations of the relational model as conceived long ago (the one that brings us the nightmares of three valued logic and NULL!).
Sadly, like others, the requirement of support SQL and the financial pressure means not go as far as we could (yet!) and I wish we could work further with a team unconcerned about it so the full power of what we want can be done (ie: I certain we are getting closer to a "Rust is to C++ what ??? is to Pg" moment).
And I bet, that will be done in Rust.
mamcx
The holy grail of language design is that the language can last as long as conceivably possible.
Whoa! that is the opposite of "holy grail", that is totally admit defeat, wanna fix something major with the language? MIGRATE in total to another (see C++ to Rust).
There is NO reason to believe that do breaking changes must be avoid to all costs neither get defeated because a few bad cases of doing as bad as it get.
And the best part? This a programing language that generate static outputs not a live database that must be migrated online while supporting millions of monetary transactions without downtime! If that is possible, do for a static output generator is much easier.
Ad even better: You only migrate on compile time, Rust is already insanely good for do refactoring, most code will not need changes, what need changes will flare up LOUDLY, this is not a interpreter language without good type systems, this is Rust. Plus, there is clippy, there is AST transformation that can run on the fly, etc.
If there is a kind of language where this is doable, is one like Rust.
And this totally async work! Can be worked to execute in terms of months, heck, lets work a year or 2 (ie: piece meal), this is not a live database!
mamcx
Yes! even better is to think of data projected as indexed:
[c, a, b]:
AsStored: [c, a, b]
AsSortedAsc: [a, b, c]
AsSortedDesc: [c, b, a]
AsSlicesStored: [c, a], [b]
....
mamcx
This kind of limitations (that in part derive from SQL, not relational model) are part of why RDBMS are too anemic.
There is not reason to add it as part of the core. As you pointed: "immutable tuple key specialized" this is an engine/implementation specialization.
Now the main problem is that you are creating a "odd case" that go against the "normal case" and because is not a fundamental part of the model then anyway you are building all the machinery for the normal case, then say "but here is the other way!" somewhere.
That its: You build a coherent "all is immutable" or "all is mutable" as the base, THEN, you add "this are the rules to invert this", that is what Rust do.
What is trouble is making "edge cases", you will regret it and will be pain with the impl of all main components.
ie: If you idea is good, must be good not only for this case but most. If not, at best, is a hidden specialization on the query optimizer.
mamcx
the problem with that is what is the "topology" of the interface.
Thinking just on the method/function is not enough, a remote interface has tons of stuff that need to be deal with (see how for example https://swagger.io), so this alone not buy much.
Erlang has the concept of https://www.erlang.org/doc/apps/stdlib/gen_server.html that I think is much better as starting point of something like this.
mamcx
No existe ningúna razón para tener ese miedo.
Gente aprende como su primer lenguaje C, C++, Haskell, APL, Perl, PHP, Cobol y muchos similares que son mas complicados que Rust (Rust, en cambio, es complejo (mira el zen de python sobre la diferencia)).
Rust, al nivel de quien aprende, es MUY simple. El único error es tratar de hacer un proyecto como "toda una app web que mezcla todo lo del lenguaje incluyendo async".
mamcx
suggested by the product owner?
What was the reason for use it?
In general, when spec a project, I try to solve first the hardest problems and see what already solve it.
If there is not a good solution, then first solve the design of what I need to build, THEN see what else to add (because your hard problems will constrain and shape everything else, not should be the other way around!)
mamcx
How would you approach file locking and conflict resolution across multiple clients?
This is the actual hard part. The question is: This is native to the Cloud Files API? If not, then is likely you need to reconsider that deps.
P.D: here the assumption is that the lock is on the "server" and hopefully the api also handle the client.
mamcx
Would LLVM be a good backend, or is there a simpler alternative?
LLVM is complex AND complicated. You can can archive most of your goals going with Web assembly (granted not native gen directly) and the perf will be close (or just do a simple interpreter)
When doing this stuff first time try to not mix too many complications at once. Simplify your backend and your front end so you can learn how to deal with the semantics and internals, that WILL prove to be challenging.
In fact, assume your first try WILL go to the trash. So, think like "is in version 10 of this journey that I will worry about squeezing the last drops of perf and complexity".
P.D: I recommend if "I'm still learning programming, so I want a language and ecosystem that are relatively easy to understand. " that you avoid the other stuff (by avoid, learn at the side, yes, but focus instead) and just sketch the AST and learn how solve things like "type checking ". Also check https://learnxinyminutes.com so pick anything that is already designed and only change a little thing (complicate syntax and how the language will look is another easy mistake! you need more exposure and experience to do so in a sensible way!) and https://craftinginterpreters.com to see what means to do a full "simple" end-to-end PL
mamcx
Others has touch to the ease of integration, ownership, simplicity or just I wanna, that are good things: you must answer if the cost of a deps vs the cost of maintaining your own smaller thing.
But not WHY somebody will do another OS, game engine, browser, RDBMs against a strong, solid and established thing?
This has happened: LLVM is a answer VS GCC.
Apart of commercial, politics, corporate reasons, the best reasons are:
- A MAJOR architectural change
For example, RDBMs start to see competitors once we are talking how have a store distributed across many machines, or the need for new columnar storage
- A significant change on the underlying tech
Like how CPU, 64 bits, lots of RAM, DISK, need to deploy to many arcs, etc means that the old features become negative
- A *major shift in the landscape (Comercial, culture, socio political)
There is a "mandate from the heaven" to cut ties to a perceived adversary depending, the internet, the emergence of PC, the emergence of IA, etc
mamcx
If you are young, your horizon is larger, so, you will probably need:
- Do what could give you food now
- Care about what could help you to be better than the median
- Bet on what will be good in the near future
The main issue is that, focusing only on programming langs, some do 1) but are eventually dead ends on 3 or not help much with 2.
Rust is gaining traction and eating the C/C++ world and being a factually better language means is better at 2), and for what signal we see now look the best bet for 3.
I will not waste time with C/C++ outside curiosity and enough awareness to understand that are in some cases unavoidable suck.
BUT, is not easy to predict what will give you 1! Without enough experience is hard to "demand" what you wanna do or use, and for a while you are at mercy of what pays. Could be Rust? Sure,but could be in games? Who knows!
So factor all in: Start planning on all lanes, try to secure a way to be as independent as possible, eventually and with enough savings! and enjoy the fact that learn more than 1 tool/lang not only is fun, is basically unavoidable...
mamcx
I working on a new version for my ERP and found
mamcx
The main thing is that you need a typed return for whatever is consuming the tokens:
```rust
enum FmtString { Token(Ast), String(String) }
enum Ast { Token(Whatever), FmtString(FmtString). }
struct FmtString { token: Vec< FmtString> }
fn consume_fmt_string(..)-> FmtString
```
So you can check and be certain what is eating will end into a normal string.
mamcx
The major thing, IMHO, is what exactly is the control flow to be implemented (see the phischu link).
I means, how will things look on execution? where are the tasks? how can I manipulate(if any) them? can they move?, etc.
So, imagine put all of this into a graph/flow visualization.
And very important!
- What happens if the task is stuck or failed?
- Can I predictably cancel it?
- How handle timeouts?
- How handle the load of the job (ie: can I say if this is CPU or IO bound, priority, pin the OS thread, etc)?
- How I coordinate among tasks?
- and what happened if the coordination broke?
I don't care about the types but how the hell I will manage all this stuff!.
I think is missing in all of this do the whole analysis before start implementing the solution.
P.D: Also look at https://without.boats/blog/the-registers-of-rust/
P.D.2: I fan of https://zguide.zeromq.org/docs/chapter2/ because it illustrates what are the actual patterns your user will wanna do themselves. Sadly, I don't think any language actually help with this
P.D.3: Check the Erlang papers and special the idea of using supervisors. That is very neat!
mamcx
This is one of the smallest I know:
From what I have gathered and remember:
Primitive and user-defined types: Super-easy
Module/import system
This one is weird, is not hard (each part) but is deceptive in how will impact everything else, is much more a matter of look inside-out/out-inside in how everything is packaged and it could clash with build systems, versioning, modularity, etc.
I don't think exist a great one in any mainstream language but 1ml is one that many recommended read.
- Static type system
This is another that is deceptive in terms that is not having "static" annotations the actual problem but which kind of semantics have your type system, so looking at one in certain codebase is not that useful: You need to know what kind of type system and to make complicated this even more, why and how interact with the rest.
From the ones that are recent, I feel this one is good in terms of how "easy" is to grasp the idea and how flexible could be the implementation:
https://elixir-lang.org/blog/2023/09/20/strong-arrows-gradual-typing
But, just have clear the semantics before dive in (everyone will have their bias, and I give you my example: anything that touch relational is my jam)
Implement one is not hard, and the first link show you the broad idea. What will eat your time is to make it work once everything else is done. in special when combined with:
- Generics, traits/interfaces, polymorphism (and macros, introspection, etc)
All forms of metaprograming is the other rabbit hole, in special by how will surface any trouble that was lurking inside the decisions of the core language, and not all integrate well with the rest (ie: you need your type system clear, and sadly, I think you must co-develop this and the type system so you avoid hit a main block later).
So, what is missing here is to be more concrete of which kind of language you are looking for, because that could even turn "primitives" in some interesting puzzle!
mamcx
No, Rust-> because moves, obviously!
mamcx
I worked on SpaceTimeDB on the query engine and sql support and boy, the query engine ended being easier that the sql! (query engine are more challenging and I learn tons! but sql is more crazy, so...)
RDBMS are all-around fascinating, I think even more than OS or Browser in concrete because are so "pure"(?) in the sense that inside there is a world that is more consistent and precise and despite the fact the major complications is how connect to the outside world (that is nuts and wrong) once you fix that else is nice.
However, by orders of magnitude the MOST challenging project is one that I"m working on since around the year 2000: ERPs.
I reworking my ERP engine for who know now how many times already (ship of Theseus style this has so many changes) and comparing to the RDBMS (that I found relaxing) nothing, nothing is as hard as a half-decent ERP.
Also some ACID filesystem?, but what make AI unsafe to use has not much to do with storage, but execution, what is need is a isolated environment with a set of well define tooling for exploring (read) and capability-based rules for writes and arbitrary execution outside editing code and run blessed compiler/tooling