I agree and think the same way. The "just make numbers go up" mentality of happiness is a fallacy. If this was the case, plugging everyone up to heroin hibernation machines would be the most optimal path. But anyone with an iota of human sensitivity will see that as horrific, unhappy and a destruction of the human spirit.
Happiness needs loss, fulfillment, pain, hunger, boredom, fear and they need to be experiences backed up by both chemical feelings and experiences and memory and they have to be true.
But here's the thing, already the damage is done beyond just some art. I don't mean to diminish art, but frankly, look at how hostile, ugly and inhuman the world outside is in any regular city. Literal death worlds in fantasy 40k settings look more homey, comfortable, fulfilling, and human.
I love Rust and use it everyday but the syntax bloat is something I will never get over. I don't believe there's nothing that could be done about it. There are all sorts of creative grammar paths one could take in designing a language. An infinite amount, in fact. I would really like to see transpiler that could introduce term rewriting techniques that can make some of that syntax go away.
It's a pain to write all that boilerplate, I agree. I don't think it's bloat though - I've been doing rust for a few years now, and when I revisit old mostly forgoten code, I love that boilerplate. I rarely have to do any puzzling about how to infer what from the current file, it's just all right there for me.
I feel this way about all the verbosity in rust - some of it could likely be inferred, but but having it all written down right where it is relevant is great for readability.
Having done a bit of C lately (lots in the past) and quite a bit of Rust, Rust is not verbose!
The functional syntax the author of this (good) article complains about is what this (long experience in procedural C like languages) old programmer has come to love.
>when I revisit old mostly forgoten code, I love that boilerplate. I rarely have to do any puzzling about how to infer what from the current file, it's just all right there for me.
This is going to sound absurd, but the only other language I had this experience with was Objective-C.
Verbosity is super underrated in programming. When I need to come back to something long after the fact, yes, please give me every bit of information necessary to understand it.
This is a really good point, IMO. I've never written extensive amounts of Objective-C, but in my adventures I've had to bolt together GUIs with Objective-C++ and I learned to love the "verbose" nature of Obj-C calls whenever I had to dive back into the editor for a game engine or whatever because it meant I didn't have to rebuild so much state in my head.
That's true, I found this writing F# with an IDE vs reading F# in a PR without IDE it really becomes easier to read if you at least have the types on the function boundary.
F# can infer almost everything. It's easier to read when you do document some of the types though.
> F# can infer almost everything. It's easier to read when you do document some of the types though.
F# is also easier to avoid breaking in materially useful ways if (like TypeScript) you annotate return types even if they can be inferred. You'll get a more useful error message saying "hey stupid, you broke this here" instead of a type error on consumption.
"Creative" grammar introduces parsing difficulties, which makes IDE tooling harder to build and less effective overall. My overall guess is that Rust made the right choices here, though one can endlessly bikeshed about specifics.
Creative grammar can introduce parsing difficulties, but it doesn't have to.
I've made a couple small languages, and it's easy to end up lost in a sea of design decisions. But there are a lot of languages that have come before yours, and you can look to them for guidance. Do you want something like automatic semicolon insertion? Well, you can compare how JavaScript, Python[1], Haskell, and Go handle it. You can even dig up messages on mailing lists where developers talk about how the feature has unexpected drawbacks or nice advantages, or see blog posts about how it's resulted in unexpected behavior from a user standpoint.
You can also take a look at some examples of languages which are easy or hard to parse, even though they have similar levels of expressivity. C++ is hard to parse... why?
You'd also have as your guiding star some goal like, "I want to create an LL(1) recursive descent parser for this language."
There's still a ton of room for creativity within constraints like these.
[1]: Python doesn't have automatic semicolon insertion, but it does have a semicolon statement separator, and it does not require you to use a semicolon at the end of statements.
> you can look to them for guidance. Do you want something like automatic semicolon insertion? Well, you can compare how JavaScript, Python[1], Haskell, and Go handle it
You can't look at JavaScript/Python/Go (I don't know about Haskell), because Rust is a mostly-expression language (therefore, semicolons have meaning), while JavaScript/Python/Go aren't.
The conventional example is conditional assignment to variable, which in Rust can be performed via if/else, which in JS/Python/Go can't (and require alternative syntax).
> You can't look at JavaScript/Python/Go (I don't know about Haskell), because Rust is a mostly-expression language (therefore, semicolons have meaning), while JavaScript/Python/Go aren't.
I have a hard time accepting this, because I have done exactly this, in practice, with languages that I've designed. Are you claiming that it's impossible, infeasible, or somehow impractical to learn lessons from -- uhh -- imperative languages where most (but not all) programmers tend to write a balance of statements and expressions that leans more towards statements, and apply those lessons to imperative languages where most (but not all) programmers tend to write with a balance that tips more in the other direction?
Or are you saying something else?
The fact that automatic semicolon insertion has appeared in languages which are just so incredibly different to each other suggests, to me, that there may be something you can learn from these design choices that you can apply as a language designer, even when you are designing languages which are not similar to the ones listed.
This matches my experience designing languages.
To be clear, I'm not making any statement about semicolons in Rust. If you are arguing some point about semicolon insertion in Rust, then it's just not germane.
Not the parent, but you can certainly have an expression-oriented language without explicit statement delimiters. In the context of Rust, having explicit delimiters works well. In a language more willing to trade off a little explicitness for a little convenience, some form of ASI would be nice. The lesson is just to not extrapolate Rust's decisions as being the best decision for every domain, while also keeping the inverse in mind. Case in point, I actually quite like exceptions... but in Rust, I prefer its explicit error values.
> I have a hard time accepting this, because I have done exactly this, in practice, with languages that I've designed.
I don't know which your languages are.
Some constructs are incompatible with optional semicolons, as semicolons change the expression semantics (I've given an example); comparison with languages that don't support such constructs is an apple-to-oranges comparison.
An apple-to-apple comparison is probably with Ruby, which does have optional semicolons and is also expression oriented at the same time. In the if/else specific case, it solves the problem by introducing inconsistency, in the empty statement, making it semantically ambiguous.
Have you also written tooling - e.g. code completion in an IDE - for those small languages? There are many things that might be easy to parse when you're doing streaming parsing, but a lot more complicated when you have to update the parse tree just-in-time in response to edits, and accommodate snippets that are outright invalid (because they're still being typed).
Yes, that's a good example of exactly what I'm talking about. Code completion used to be really hard, and good code completion is still hard, but we have all these different languages to learn from and you can look to the languages that came before you when building your language.
Just to give some more detail--you can find all sorts of reports from people who have implemented IDE support, talking about the issues that they've faced and what makes a language difficult to analyze syntactically or semantically. Because these discussions are available to sift through in mailing lists, or there are even talks on YouTube about this stuff, you have an wealth of information at your fingertips on how to design languages that make IDE support easier. Like, why is it that it's so hard to make good tools for C++ or Python, but comparatively easier to make tools for Java or C#? It's an answerable question.
These days, making an LSP server for your pet language is within reach.
I'm not an expert as I do not work on these tools but I don't think IDEs can rely solely on ASTs because not all code is in a compilable state. Lots of times things have to be inferred from invalid code. Jetbrains tools for example do a great job at this.
In practice though, getting the AST from the text is a computational task in and of itself and the grammar affects the runtime of that. For instance, Rust's "turbofish" syntax, `f::<T>(args)`, is used to specify the generic type for f when calling it; this is instead of the perhaps more obvious `f<T>(args)`, which is what the definition looks like. Why the extra colons? Because parsing `f<T>(args)` in an expression position would require unbounded lookahead to determine the meaning of the left angle bracket -- is it the beginning of generics or less-than? Therefore, even though Rust could be modified to accept`f<T>(args)` as a valid syntax when calling the function, the language team decided to require the colons in order to improve worst case parser performance.
It's not impossible to handle the ambiguity, it's just that you may have to look arbitrarily far ahead to resolve it. Perhaps C# simply does this. Or perhaps it limits expressions to 2^(large-ish number) bytes.
Rust macros are one of the more annoying features to me. They're great at first glance but whenever I want to build more fancy ones I constantly bump into limitations. For example they seem to be parsed without any lookahead, making it difficult to push beyond the typical function call syntax without getting compiler errors due to ambiguity.
But proc macros are limited by requiring another crate (unless things have changed in the last year). Sure, it’s just one extra crate in the project, but why must I be forced to?
Why is that weird? Procedural macros are compiler plugins. They get compiled for the platform you're building on, not the one you're building for, and so they need to be a separate compilation unit. In Rust, the crate is the compilation unit.
Nim allows you to chose what memory management method you want to use in a particular piece of software. It can be one of various garbage collectors, reference counting or even no memory management. It allows you to use whatever suits your needs.
I don’t understand why you all are posting tedious details and well actuallys when the original assertion was (way back):
> Nim, which technically accomplishes all (I assume) of the Rusty things that require syntax, manages to do it with quite a lot nicer syntax.
Nim does not have something which gives both memory safety and no ((tracing garbage collector) and/or (reference counting)) at the same time. End of story.
The fact that Nim has an off-switch for its automatic memory management is totally uninteresting. It hardly takes any language design chops to design a safety-off button compared to the hoops that Rust has to jump through in order to keep its lifetimes in check.
You are simply incorrect, appear unwilling to research why/appear absolutist rather than curious, and have made clear that what I think is "clarification" or "detail expansion" you deem "tedious" or "nitpicking" while simultaneously/sarcastically implicitly demanding more details. That leaves little more for me to say.
You have managed to point out that tracing garbage collection and reference counting are indeed two ways to manage memory automatically. Three cheers for your illuminating clarification.
While tracing garbage collection is indeed one possible automatic memory management strategy in Nim, the new --mm:arc may be what darthrupert meant. See https://uploads.peterme.net/nimsafe.html
Nim is choice. :-) {EDIT: As DeathArrow also indicated! }
Terminology in the field can indeed be confusing. In my experience, people do not seem to call reference counted C++ smart pointers "garbage collection" (but sure, one/you might, personally).
"Automatic vs manual" memory management is what a casual PL user probably cares about. So, "AMM" with later clarification as to automation options/properties is, I think, the best way to express the relevant ideas. This is why I said "tracing GC" and also why Nim has recently renamed its --gc:xxx CLI flags to be --mm:xxx.
Whether a tracing collector is even a separate thread or directly inline in the allocation code pathway is another important distinction. To muddy the waters further, many programmers often mean the GC thread(s) when they say "the GC".
What runtimes are available is also not always a "fixed language property". E.g., C can have a tracing GC via https://en.wikipedia.org/wiki/Boehm_garbage_collector and you can get that simply by changing your link line (after installing a lib, if needed).
People don't call reference counted C++ smart pointers "garbage collection", because they aren't managed by the runtime, nor optimized by the compiler, rather rely on basic C++ features.
But they call C++/CX and C++/CLI ref types, automatic memory management, exactly because they are managed by the UWP and CLR runtimes respectively,
I doubt you are, exactly, but I think it's really hard to argue that the terminology, as often used by working programmers, does not confuse. ("Need not" != "does not"!) All that happened here is darthrupert made vague remarks I tried to clarify (and j-james did a better job at [1] - sorry!). Most noise since has since been terminology confusion, just endemic on this topic, embedded even in your reply.
I may be misreading your post as declaration rather than explanation of confusion, but on the one hand you seem to write as if "people not calling RC smart ptrs 'GC' is 'reasonable'" yet on the other both your two books include it as a form of "direct GC" - GC Handbook: The Art of AMM with a whole Chapter 5 and the other early in the abstract. darthrupert just reinforced "working programmer usage" being "not academic use" elsewhere. [2] GCHB even has a glossary - rare in CS books (maybe not in "handbooks"?) So, is your point "Academics say one thing, but 'People' another?"
C++ features you mention were intended to blur distinctions between "compiler/run-time supported features", "libraries", and "user code". Many PLs have such blurring. Such features, basic or not, are optimized by compilers. So, neither compiler support nor "The Runtime" are semantic razors the way I think you would like them to be (but might "explain people/working programmers"). If one "The" or "collection" vs. "collector" are doing a lot of semantic work, you are in confusing territory. Also, human language/terms are cooperative, not defined by MS. MS is just one more maybe confusing user here.
Between intentional blurriness, loose usage, and many choices of both algos & terms used in books, papers, documentation and discussions, and the tendency for people to just "assume context" and rush to judgements, I, for one, don't see existence of confusion as mysterious.
Given the confusion, there seems little choice other than to start with a Big Tent term like "memory management" and then qualify/clarify, though many find "not oversimplifying" tedious. I didn't think this recommendation should be contentious, but oh well.
I see now that the GP wrote “a garbage collector” (not the article). Oops! “A reference counting method” doesn’t roll off the tongue. So it appears that your nitpicking was indeed appropriate.
See the neighboring subthread: https://news.ycombinator.com/item?id=31438134 (which has details/links to more information and is more explicit than just the 4th footnote at the end of the mentioned twice before peterme link.)
I'm curious what that assumption is based on. Rust and Nim are pretty different, and both of them have features that the other doesn't even try to have.
Nim's modern memory management (ARC/ORC) is fairly similar to Rust. ARC functions by reference-counting at compile time and automatically injecting destructors: which is broadly comparable to Rust's ownership + borrow checker.
(A big difference is that Nim's types are Copy by default: this leads to simpler code at the expense of performance. You have control over this, keeping memory safety, with `var`, `sink`, and others, as highlighted in the above link.)
Nim passes by value by default, which eliminates much of the complexity overhead of lifetimes and borrowing in most programs. (the compiler does optimize some of these into moves.)
But when you do want to pass by reference: that's where Nim's move semantics come in. These are what are fairly similar to Rust's lifetimes and borrowing, and what the paste.sr.ht link briefly goes over.
If you're interested, you can read more about Nim's move semantics here:
Tongue in cheek: Then it's exactly like (modern) Nim, only that Nim does the fallbacking automatically as needed ;) There are lots of devils in the details, I assume.
Rust had a lot to go against so I can't blame them for somehow subpar syntax. Maybe it's gonna be revised.. maybe some guys will make a porcelain layer or a rustlite.
I work mostly in terminal and won't use clunky IDE programs. I need to be able to
0. Export/upload my source
1. Import/download my remote source
2. Compile my source for different targets
3. Cleanup my source and my compiled source
5. Do all the above for different versions/locations of my source
6. Do all the above for source not my own
7. Do all the above with a simple command and or a simple key->value in a config file
Then I need to do all the above with
8. using a terminal on my personal computer
9. on a remote server using ssh'ed terminal
10. in a script automation file like a docker file or maybe a vim script that setups my dev environment
11. Have 0 - 10 be so easy to do, basically a simple command or two, that I don't have to spend days figuring out tooling FOR EACH TASK and googling mystical error messages for solutions on obscure forums posted 2009.
I stayed with Rust because it has good tooling. Because it's the one thing that hasn't driven me insane at one point or another. I wanted to program in Haskell and c, but I am so sick of the terrible tooling and the terrible conventions of the communities (something Go at least gets right) that I instead program in Rust, a language I enjoy less for it's merit as a language.
Mind you I haven't even mentioned the complexities involved in making dependencies optional, platform specific.
I haven't mentioned conditional compilation.
I haven't mentioned respecting the configuration options of dependencies.
The tooling has to at least do all that using the same syntax for commands and configuration. It has to be predictable enough that I can almost figure it out myself. No black magic.
You have to do a lot of things. I don't envy you at all!
I work mostly in IDEs and won't use the clunky command line if I have an alternative. After all, it's the year 2022. Why working like it's 1991? I don't want to spoil you the end of the movie, but I have this hunch that graphical user interfaces are the future.
And I don't see what you can't do with VS or Qt. Maybe setting up your toolchain with a script or using terminals (which I don't know what have to do with programming IDEs).
I do most of the above with fricking KEIL uVision for a myriad of microcontrollers!
I compile and edit whole Android OS with VSCode and the integrated SSH terminal! (I hate to use the command line, though!).
The point of not strapping a clunky IDE to my workflow is that a terminal offers flexibility and mobility that I (and everyone who programs in 2022. Maybe not you tho) need to fulfill line items 0-10.
Cargo add pkgname on my computer.
Cargo add pkgname on a ssh session.
Cargo add pkgname in a docker script.
Wow the same process for doing it on my dev pc is the same everywhere else! Amazing. What do you do to automate deployment? ssh in and install your whole graphical tool then write a mouse macro to click the compile button?
You are taking a vacation with a U-Haul truck filled with your furniture. I am taking a vacation with a backpack.
It seems we don’t go on vacation to the same places.
There is no need for ssh’ing or recompiling.
For embedded I just give a bin file with everything in it. Use your favorite flashing tool.
For the rest, I can make an installer right from the ide. You know, the kind of 3 click installers the whole world is used to in 2022. An installer I can give grandma. Huge success from the 90’s.
Or maybe redistribute my program with a mobile app market. I can do that from my ide too!
Or maybe I’ll just handle a zip file with everything in it.
I’m afraid you can’t see it’s YOU who are in a niche, and not the other way around.
App store? A windows installer? So you just make user apps? Then publish them on existing platforms built by programmers who had to think about all the complexities you blissfully pretend don't exist?
Just email me a binary to flash with a usb stick? Here's a link to download a zip file, just drag and drop into file explorer. Totally scalable stuff. But then again you just make calculators for the android app store, so I guess you're fine.
Nope. I do embedded C/C++ and what you can read above. I occasionally do some tooling for desktop or low level APIs. But I know what ides are capable of.
Dont make the mistake of thinking you are better than others, otherwise you’ll keep feeding the general feeling of Rust cultism and you’ll end up programming in niche languages from the command line, 1991 style.
You are really obsessed with this 1991 stuff. And here I thought the common prejudice was that only boomers were still stuck using IDE programs. I think you believe yourself to be in an ego battle and that's just not the case for me.
I was discussing "work you have to do to setup and actually understand your development tool chain in C as well as C++", and I mentioned IDEs' easy of use. Then you came along saying that the command line is the way for "everyone who programs in 2022"... which is clearly the opposite. If you don't want to see that... I'm sorry but this conversation doesn't have a point.
And you mentioned "boomers" so I know exactly with who I am talking to.
My ego walks away unharmed from this conversation.
Actually, I did not start by mentioning anything about years or what is up-to-date. You were the first one to bring up 1991 and current year as a derision.
I believe you have a capable need for the tools you choose to use. I wish I could have sympathized, but the snark you engaged with set the wrong tone.
This place like all reddit clones is an echo chamber. I have to carefully manage my unpopular opinions lest I sink into shadow ban territory. Which has happened before and I had to request an unban from a mod. In fact, by writing this reasonable and calm opinion (even if you disagree with the opinion), I expect many many downvotes.
I don't understand this sentiment. Rust is the only language ecosystem where I find that anything works at all. Whenever I have to build something not built in rust, I'm praying. With rust made tooling, I just never have problems.
I don't know of any essential tool coded in Rust. Literally every single thing I rely on is coded in other some other language, and works. There is exactly one in Haskell: pandoc. No Java or C# (although I guess some people feel they need Minecraft or Kerbal Space Program). No Lisp, except Emacs. No Erlang, Clojure, Scala, OCaml, Dart, or Ada. Does TeX still count as Pascal?
The only case I know of where I would need a Rust program is to check a blake3 hash. That won't last.
Ripgrep is my essential codebase search tool. It's incredibly fast, very clear, and it just works how I expect. I use it a lot if I'm refactoring a larger codebase, particularly because it works well for more dynamic languages (where a compiler won't help) and for comments and documentation (where I want the naming to remain consistent).
I've heard good things about Bat and Exa - I personally have never felt a huge need for them, but other people claim that they're pretty essential to them.
I am not sure what "essential tool" means if pandoc included in it. For me Intellij, Eclipse, Dbeaver are more essential (+ few other Specific tools based on Eclipse).
No, the west has been monomaniacal and there is no reason to expect succeeding world orders to crusade the same way. Indeed, preceding hegemonies did not behave this way.
In respect to Iran US has poor history as it relates to the Iranian Revolution, but with things as they currently are - do you believe Iran should be unopposed?
By the way, it’s not that I think people should ignore what happened 80 years ago, but at the same time I think it’s a long time, politics change and old conflicts are not as relevant as some like to argue. UK is not the colonial Britain, modern Germany and Japan are not the Axis of WW2.
Though Russia appears to be good ol’ scarecrow Russia, so I guess some things change and some stay the same…
And call me naive, but I am of the opinion that US of the last 30 years honestly tries to be on the right side of history and it’s not the hegemon real despots of the world try to paint it as.
And lastly Afghanistan - I mean you can argue with me I guess, but I think the 20 years and trillions spent can serve as an evidence that there US really tried to do something at least well intentioned.
I guess what I am trying to say that these days I hear a lot of “but look over there!” kind of argument, and they often even contain some truth to them, but I think they also contain a lot of differences that are overlooked to better serve the argument.
But even if they were exactly the same - you don’t justify an atrocity by pointing at another atrocity.
You stated that the west, in scare quotations, was only weaponizing commerce because of the exceptional circumstance being that the target was engaged in an invasion of a country. Contradicting the assertion of the parent comment that the imperial core countries will weaponize everything that they have against countries that don't align with their interests.
I brought up an example of three countries that have been similarly condemned and were not invading anybody.
Regarding The Iran comment. Why are you even thinking about a far-away country needing to be "opposed"? This is a very weird world police mindset to me. Do you think NATO shouldn't be opposed?
America spent 2 trillion on it's own military budget in Afghanistan. Half of which were interest payments. The US didn't spend trillions to sponsor Afghanistan's infrastructure.
The US occupied that country for 20 years and destroyed not only it's infrastructure but the fabric of that society as well as the mental well-being of several generations of Afganis. The toll is incalculable. How you spun 20 years to be evidence of benevolence, I'll never know. So I assume Russia occupying civilized Ukraine for the next two decades, despite violent, traumatic and desperate resistance will also be seen as benevolence?
In ~May 2020 when US and Colombian mercenaries sponsored by the CIA attacked the country in military speed boats near the capital Caracas with the aim of killing/capturing the President and linking with dissident groups inside Venezuela and do a coup
I mean to say that I am sure Maduro will claim that he foiled a CIA plot there, but I haven’t seen any evidence that US government has anything to do with that action.
Sorry, 60 of them. This is what wikipedia has to say about that:
“ Commentators and observers, including Guaidó officials who initially contacted Silvercorp, described the operation as amateurish, underfunded, poorly-planned, having little or no chance of success, and a suicide mission.”
Just some randos out for a little assassination fun. Happens all the time in the world that a bunch of foreigners attempt a stupid but audacious assassination attempt right in the middle of a concerted effort by an adversary to overthrow a government. You know the CIA wasn't involved because American movies depicts them as superhuman secret agents and these guys were the opposite of that.
I am sort of running out of steam keeping this up here.
I was honestly keeping an open mind to hearing some convincing evidence or even some mainstream reporting sources that this wasn’t a poorly put together private mercenary action.
Happiness needs loss, fulfillment, pain, hunger, boredom, fear and they need to be experiences backed up by both chemical feelings and experiences and memory and they have to be true.
But here's the thing, already the damage is done beyond just some art. I don't mean to diminish art, but frankly, look at how hostile, ugly and inhuman the world outside is in any regular city. Literal death worlds in fantasy 40k settings look more homey, comfortable, fulfilling, and human.