How big should a programming language be?
tratt.net
tratt.net
If that's not the case it gets much harder to get your head around how it all works as you cannot effectively apply some simple pattern to all the stuff you see and you need to juggle different ways of thinking when doing basic stuff. And this propagates even further and harder to other libraries.
Adding new features to a language is always costly because you not only have to deal with the new semantics of the new feature, but with the emergent semantics of how that feature interacts with the existing feature set. The cost of adding some new semantic and syntax is not just N, but N*M, where M is the subset of existing features that the new feature may interact with in some meaningful way. For example, if you add support for declaring a constant (separate from a variable) this is not just the addition of some new, isolated meaning, but introduces semantic difference—the programmer now needs to reason about variables as opposed to constants and also needs to discern this difference in all scopes in which the distinction is valid...
It started out as a very usable, mid-sized language, with many tooling issues. Now it is a kitchen-sink language with almost every imaginable feature (and more coming!) that still has tooling issues. It's no longer as pleasant to read unless you keep up on the latest additions. You can't easily read code that uses the myriad of new features without a long weekend learning what every property wrapper in this particular program means and how to use the new feature of the month.
In my opinion while it was still a mid-size language, they should have fixed all of the tooling issues, and then very incrementally over a long period of time added new features. Instead it's more of a "move fast and break things" culture. Which is not what I want in the evolution of a programming language.
I looked at Kotlin and Swift at the same time some years back and they seemed extremely similar. I didn't enjoy ios development and am currently an Android developer. I've been using Kotlin for a while now and it's easily my favorite language.
Did Swift take a wrong turn somewhere that set it on such a different path from Kotlin?
Go tries to solve that, but gets criticized for its simplicity.
Also, I suspect part of the friction writing Swift isn’t language complexity but tooling issues. to what effect that’s true is hard to say of course. For example, compilation slowness introduces friction, but I wouldn’t know whether that’s inherent or solvable.
There also are a lot of “the compiler could be smarter” things that do not change the vision of the language, but do affect its ease of use. Such warts make the language harder to write than necessary. If those issues can be fixed, the language can become easier to write. An example is https://github.com/apple/swift-evolution/blob/main/proposals....
As to that if, I wouldn’t know whether that holds. For example, https://github.com/apple/swift-evolution/blob/main/proposals... begot https://github.com/apple/swift-evolution/blob/main/proposals.... Both were implemented in 5.7, but I wouldn’t know whether those left any rarer warts or even introduced new ones, or if that process ever will stop.
If that process cannot stop, I think it’s better to leave a few warts that programmers will soon encounter and learn about than many very rare ones that, when encountered, will make programmers pull all their hairs out because googling them only produces “I changed Foo and the compilation error went away” results or StackOverflow pages without answers.
There’s definitely a space between Go and Swift. Go is to C as Swift is to C++. That analogy is not necessarily a compliment for either.
A minimal language that doesn't have resources like Golang to put in the stdlib is just not gonna work.
You just really don’t need much to get stuff done with a lisp.
(remove-if-not #'oddp #(1 2 3 4 5))
you have to write a loop from scratch, and then everyone has to read it carefully to learn what it’s doing (and especially what it’s not).Don’t get too excited about having HTTP or JSON built in, we weren’t using those in 1990 and they’ll surely be replaced by 2050.
That probably wouldn't be the case if it had been named retain-if or keep-if; the issue is likely the double negative.
A function which pares down a sequence to just those elements which match a predicate is very useful; why would you deprecate such a thing.
These days the function is usually called filter, but I'm not sure it was a commonly used term then.
It'a terrible name, by the way. A filter separates; it has two outputs. Does a function named filter return the filtrate or the residue? And I just had to look up filtrate to check which one of the two it refers to and what is the opposite term. From now on I will remember that there is residue captured in a filter, and filtrate is not that.
That would be terrible, those loops are crazy dangerous. I would avoid writing a loop and rather come up with a whole different programming paradigm. Maybe a macro system or something based on category theory?
Functionality moves (c) => (b) => (a).
Unless it's a DSL, the osmotic power is strong.
Yes io.Copy works with any Reader and Writer but dig into the documentation and there's a runtime check for the revised ReaderFrom and WriterTo interfaces that you might also implement for faster performance. It's just something you have to know, otherwise you will not get an optimal copy.
Go 1 is right on the edge of being a big language, but what might stop it is that Google don't need it to get any bigger.
Go on the other hand, is a language I’m still confident I can teach a junior enough to be useful in an afternoon.
The restraint shown by the Go team is admirable in how well they’ve stuck to their vision.
Yes. Rust suffers from this problem. The language is now reasonably solid, but library quality and stability is all over the place. I've been annoying people in the Rust community by saying that it's time to get all widely used crates (over a million downloads, or depended upon by a widely used crate) to version 1.x. After that, no breaking changes without a major version change. Crates with re-exported types from lower levels force groups of crates into lockstep update.
The big advantage of Go is that the libraries for doing server-side web stuff are the ones used internally by Google. So they've been thoroughly exercised. The obscure case that comes up once in a trillion transactions probably happened a hundred times in the last hour in a Google server farm.
It annoys me to no end the huge number of packages I pull in for doing something "simple". It is great that packages can be so small and focused, but now I have a real trust problem. How am I possibly supposed to ensure there are no malicious actors in my dependency tree?
The Rust foundation's crate manager job is apparently vacant until at least April, so nobody is officially in charge of this.
Relevant XKCD: [1]
My take on this for game development: [2]
[1] https://imgs.xkcd.com/comics/dependency_2x.png
[2] https://www.reddit.com/r/rust_gamedev/comments/11b0brr/were_...
They make the claim that it’s about pushing them into the standard library but some of those libs have been in there forever.
How far along the ridiculous dependency spectrum towards NPM is crates.io?
For example, if I release a piece of nontrivial software built with Rust, how many copyright notices am I going to have to include? (To say nothing of vetting the set of transitive dependencies!)
Not a single interviewee has even had a good guess in 2 years of open job recs.
It really has me reconsidering. I’m a language nerd through and through. I love C++. But I also have to be honest and say there’s such a thing as “the average amount of c++ the team knows”.
To me, the biggest threat to C++ isn’t rust, but rather the speed at which the language is changing. It’s already past the tipping point.
In my domain, embedded programming, I’m keeping an eye on zig with fingers crossed.
But I think the concern is not about being able to use it, but to understand what it does, std::move is nothing but a cast. Itself it doesn't move anything. And then there is the whole fun with the state of the noved-from object afterwards. Quite some depth to uncover.
And that doesn't even begin to touch on the absolute disaster of the net framework/core/standard/mono/uwp runtime situation.
C# as a language just doesn't seem very stable. I really don't enjoy using it anymore.
(I can't justify why I feel that way. I have middleware-corporate-lang dysphoria for some reason.)
In what way do you think it isn't stable? I've upgraded code written in C# v1 to the latest and greatest and never had a breaking change (well except for one time where it was my own fault for abusing reflection).
Ultimately you can use as much of the language as you want to, the "old" ways haven't been removed and you can still code like it's 2002 :)
But I just really, strongly dislike the way Microsoft went with the problem. Declaring types nullable with the `?` just puts me off. `Nullable<T>` was always something to be avoided, and I find the syntax just as annoying as null checks.
Ultimately most of my complaints can be boiled down to "too much changed and now things are different"
They're just enums, geez.
That's from someone who has written C++ compilers.
Some of the insane complexity being added to C++ comes from trying to emulate Rust move semantics without a borrow checker. An xvalue is what's left behind after you do a move. In Rust, the compiler guarantees that you can never access the remnants after a move. But in C++, someone will somehow manage to leak a raw pointer to something, then move it. So users have to know about xvalues.
(Could be worse. Trying to emulate Javascript async semantics in everything else has resulted in some real horrors. Only Go has a sane solution.)
And Java Project Loom IMHO, which copies a lot of Go's sane solution. (Not released in an LTS version of Java yet, but hopefully soon!)
Unless a good explanation is an insta-offer, why do you still ask a question you've gotten zero signal from?
Interview questions aren’t just for comparing candidates with each other. It’s also useful to know how a candidate’s knowledge compares to the knowledge of the team. The best of a bad bunch might still be unhirable. It’s often better to leave a role vacant than fill it with someone mediocre.
If the GP can’t find anyone in the hiring pool who knows C++ well, that’s a valuable insight. Maybe they need to expect less C++ from candidates and plan for more on the job training.
Or change languages.
How someone handles that inevitable "I don't know" moment is an important data point.
Honest question: what do you expect the answer to be? Pedantically, the "correct" answer is that it statically casts its argument to an xvalue. Is this a way to tell if the candidate understands value categories?
Someone who doesn't know how it works but successfully have ever written a move constructor (which is a bit more advanced than merely using one) are going to come up with an answer that I would personally (as not the person who said this... for all I know they also will be super pedantic) claim is "close".
But, I would fully expect the majority of people you ask that question to will, for example, actually claim stuff like that the prior value is completely destroyed... not even merely deconstructed (which is already problematic), but somehow deallocated even if located on the stack, which is way more wrong than merely thinking std::move "takes ownership".
I don't know if you play chess at all, but a book I really enjoyed (and read probably about when I was your age? and the existence of which--honestly more than the specific content--massively informed my teaching style) was The Amateur's Mind, which was a chess master going back and attempting to not as much teach chess from his vantage point to an amateur but to go back and explore the misunderstandings amateurs have about chess by way of interviews with amateurs about games and then trying to work within that mental model. I think that, even though we were all amateurs at one point--or even might have a long way to go still--it can be difficult to really conceptualize the gulf between what an amateur thinks and what you might even assume is the mistake they are making.
I have 30+ years of experience, and have hired many C++ developers, while working for different companies around the world. And my success rate in hiring good developers have been very high. Using exactly the questions I mentioned above.
Maybe it’s just the rose-colored memories of a first love.
JavaScript used to have the same appeal, before it started evolving. Despite the rough edges and some poor decisions, you could still grok the entire thing pretty quickly and appreciate how it works.
Of course, I have my own bias here, but it really did feel like they fit well together in Objective-J.
For example, consider Rust that is built around the idiom of composability (aka: Traits).
Is nice, until you get async, custom allocaters + runtimes, const, how do macros, type reflection, code generation, etc...
Each thing is something user want to make code more composable and flexible. But each thing is also a big thing: You can make a WHOLE LANG around just one of that!
---
Lisp, Forth and similar make easy "syntax composability" -not solve all the rest- that is probably the bare minimum. This is the MAJOR "flaw" of algol-like languages.
For example, I wish Rust allow:
struct Person {name:String}
struct User: +Person {pwd:String} //not inheritance: Copy of fields!
let u = User {..}
let p = Person::copy_from(u)
for f in p.iter_fields(): //walk over name:String, pwd:String
With lisp/relational/array like paradigms this stuff is easy. But algol-like languages are too "nominal" and lack the ways to manipulate the construct without resorting to macros, that are for most cases a band-aid.[0]: https://chadnauseam.com/coding/pltd/four-issues-facing-fp
val print_name: <name: string; ..> −> unitWhat kind of problems would this solve? Not trying to be snarky, just to understand the feature.
struct Person{name:String} + struct User{pwd:String} = FAIL!
["Person", ("name", "String")] + ["User", ("pwd", "String")] = possible!
Because types are not even third-class, you need to resort to "hacks" like macros, generics and other stuff like that.Now, what it solve? almost everything.
(you can see how this could work in static lang with Zig comptime https://kristoff.it/blog/what-is-zig-comptime/)
In short, you get what inheritance promise without the OO, easy reflection, easy code generation, simpler macro implementation, easy way to do generics, easy way to copy to/from different types that are almost similar (ie: structurally)...
The amount of stuff you will simplify is massive.
Some of this feel is what make the "dynamic" languages their power. Now making it work on static lang is more tricky (you wanna keep everything as if you were coding it by hadn't and the types all resolved at compile time) so is likely required to be restricted and only a second-order citizen, but it will make some much easier!
However, personally I strongly dislike dynamic languages for anything beyond simple programs, ie <100 LOC. Gets way to hard to reason about the code, since you never know what a function returns. In Python for example I invariably end up sprinkling dir(...) all over when modifying code.
So it would have to be used sparingly I think.
I poke around in the pybindgen code base semi-often and it’s fairly large. No problems that would call for sparing use.
Bash is a small clean language that has maintained its clean core
Golang is the archetype of a small clean effective language that has tried intentionally not to become cpp and it shows the amount of wrangling needed to add generics to golang is a testament to their focus on a small language albeit imperative
Of course, the scope of the language is not the same as general purpose languages, but there's always pressure from the users to add more things. I also think many people underestimate the cost of adding new features: it's not just about adding the code in every compiler/interpreter, specifying every edge-case in a spec, updating all the tooling for the language and writing tutorials; it's also a cost on everyone who will have to read any of the code.
Everyone who will have to read the code in the compiler or interpreter? Or everyone who reads code in the language?
I'm not so sure the latter should be a consideration. If you don't give people some feature they would use, they will develop their own idioms to accomplish the same with what the language does provide. And the reader then has to become familiar with those idioms, and repeat the process for every new codebase they encounter in the language. Better to have one good way to do it.
If something is used a lot, you can expect the reader to learn the pattern quickly. If something is not super common and not intuitive, it can make the code less readable (and the reader might spend a lot of time searching in the documentation).
Two examples I've seen this week: - Python has a new keyword `except*` - C# has a prefix operator ^
It's not obvious to me that these features are beneficial in general.
Prior to Java 5, the language was quite simple, the spec readable and understandable without requiring deep knowledge of compilers.
The introduction of generics and lambdas massively complicated the language specification. But those features also were huge improvements that pretty much anyone would consider worth the cost.
New features can be discussed on the GitHub issue tracker, but I expect very few additions in the short-term. I consider the language quite stable now, and it has three mature implementations.
The language itself should be small but its standard library should be extensive, and largely written in itself. If the language's own implementors don't want to program in it neither do you.
Some would argue that R6RS is too large, while others argue that R7RS (small) is too small. Maybe there's a Goldilocks Scheme in the middle that's just right. :-)
Of course, most types of Lisp-ish languages let you grow the language in a way that C doesn't really (yeah, there's the C preprocessor, but it's far more limited that the macro facilities provided in most Lisp-ish languages).
Yes, LOOP has a lot of syntax to make it look somewhat like "hey, you can code this in English" and FORMAT is discount Turing complete, but there are a lot of language features out there with complicated syntax (regular expression, for example) and X86 Assembly's MOV is also discount Turing complete.
You can always put extra features into a library, and identify certain libraries as "standard." So it seems reasonable to demand that actual language changes are limited to those where the readability benefit outweighs the need for everybody to learn the new feature in order to read code.
As mentioned in other posts, a huge sprawling language makes it hard to gauge whether someone is proficient in a language when applying for a job. I don't really know how important that should be.
In my case, I got a low score on a Python knowledge test because I've been programming in Python for a decade but haven't kept up with the latest features. Not that I'm looking for a job, but I was just curious, and it was part of figuring out what kind of training I should get.
A good watch for the fine people in this thread (and please ignore explicit or implied linkages to Java--it's full of the broad concepts, not narrowly JVM stuff)
Niklaus Wirth, the creator of Pascal, Modula-2 and Oberon, believe strongly that teaching programming is most effective when students can grasp the entirety of a small language.
From a 2018 interview with Wirth on the topic:
> "In order to do a good experience, you have to have a clean language with a good structure concentrating on the essential concepts and not being snowed in."
> "That is my primary objection to the commercial languages – they’re simply too huge, and they’re so huge that nobody can understand them in their entirety. And it’s not necessary that they’re so huge."
> Pico is a tiny but expressive programming language that was especially designed to teach advance computer science concepts to students in other sciences than computer science … Currently Pico is no longer used as a tutoring language for its target group, but this is more a consequence of politics than of the astounding results we got with teaching Pico. Today, Pico is used as a means to teach principles of language design, interpreters and virtual machines in a sophomore course for computer scientists and in an adjacent course in a masters program in applied computer science.
The complexity of boilerplate does not only exist for the author but every future author.
It is not my experience that LLMs and other complex automations are nearly as good as refactoring and changes as they are at generating boilerplate in the first place. In the end this code lives on as a human concern despite the automation.
I do think however that programming languages and libraries are the assembly language for AIs to interface with legacy systems targeting human usage.
So it's important for these to be easily understandable.
Go fills that sweetspot better imo. Until something else appears perhaps.
But you're absolutely right that we should make sure to still improve these languages and it is right to worry that LLM don't incentivize new languages (smaller code corpus, less data?). As for Go, it is improving steadily so I'm still confident in that regard.
100% true, it is. More keywords in each release. More ways to do things.
e.g. Now we use "record" and "with" keywords, and operators such as "a!.b" or "a?.b" .
And we set projects up with "implicit usings", and "file-scoped namespaces" which do the same thing will less indenting.
While I like all of these, the downside is yes, it's an ever-expanding language.
then definitely disagree about implicit using or file scoped namespaces
There's nothing new in terms of keywords about them, concept itself very simple
and makes code more readable and shorter, that's it.
It's just: "hey, some namespaces are very, very popular - let's make it this way, that you don't have to include them everywhere"
and "hey, why every code is one level indented if everyone is using one namespace per file anyway?"
It just simplifies stuff, can we honestly call it an expansion of language?
I would even take it 1 step further. Specify the class name at the top of the file, 0 indentation for functions.
The same _could_ be done with type declaration such as classes and interfaces. If it would be beneficial idea is another thing.
Multiple classes per file with would still be an option of course.
How would you group things without namespaces?
by their physical location?
And I didn't imply that they were new keywords, they were examples of the second category, "new ways of doing things". The text "do the same thing" alludes to that.
> and makes code more readable and shorter, that's it.
Correct, but each new ways of doing things comes at the cost of there now being (at least) two ways to do the same thing.
> It just simplifies stuff, can we honestly call it an expansion of language?
If a source file that was not legal in language version 9, is now legal in language version 10, then yes we honestly can and must call it that. It is literally an expansion of the subset of all possible source files, that are legal source files in the language.
Does it "simplify stuff" if there are now 2 ways of doing a thing, when previously there was only one? The parser has to deal with both now. It depends on how you look at it, I think. e.g. It depends on if your code mixes them. If not then the code can be simpler, but as coders we have to still know both as we might encounter both.
I’d love to have a TypeScript language with the standard library, single binary output, and build speed of Go.
- start with two underscores
- start with one underscore (file scope)
- start with is, to, str, mem, atomic_ or a bunch of other prefixes and continue with a lower case letter, consist of E followed by a number, and more.
So the list of reserved words is rather long (infinite), and includes words like `string`.
There's difference between adding features randomly and putting effort into making it obvious, transparent, integrated well into the ecosystem and overall UX.
UX is something that languages and API designers must put more effort into.
Start creating APIs with assumption that people have no access to documentation - it makes everybody's life easier. Just take a look at .NET BCL - it's very well designed. They even wrote a book about framework / libraries design basing on their decades of experience.[0]
Also "small language" is relative.
If you have started doing X lang development decade ago then that version of language is "small" to your perception. For somebody who started 5 years ago it was small 5 years ago.
The point is that at every point language have some features which aren't popular because they serve some specific cases which are required for somebody.
Very often those features are required for base class libraries makers so they can create either good API, or have good performance/safety, or anything else.
For me it seems like programming languages and its ecosystems lack of deprecation process which actually removes stuff.
[0] - Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .Net Libraries
There's really good new stuff like switch expressions and pattern matching.
But it feels like TypeScript is in a better place. I would love to see a "T#" - a trimmed down, more modern C# that makes certain tradeoffs and defaults.
Maybe that's F# (spent some time with it), but it diverges a bit too much from C family syntax.
In the end I opted to avoid most conveniences since they can easily be built using a few common macros such as `u16(v) = ordered(uint(16,v))` and the like, except for cases where it would be just silly not to (like strings as syntactic sugar for concatenated codepoints, and regex-style repetition chars ? * + instead of {0|1} {0~} {1~}).
But even then the spec is over 2000 lines long (admittedly the examples take up a fair bit of room, though).
[1] https://github.com/kstenerud/dogma/blob/master/v1/dogma_v1.m...
From https://elixir-lang.org/development.html
> Since v1.0, the language development has become focused to provide a compact and consistent core. The Elixir team focuses on language features that: > > 1. are necessary for developing the language itself > 2. bring important concepts/features to the community in a way its effect can only be maximized or leveraged by making it part of the language
In other words, as I've heard it put, the language is mostly not growing anymore. It probably helps that it has strong metaprogramming facilities.
I primarily work in a language out of the APL family.
When I first started it, the entire reference page of every function/command/flag fit on a double sided printout in regular sized font.
Past a certain point you just end up with overlapping versions of the same thing maintained for backward compatibility or slight differences of opinion & behaviour.
I feel the same way about framework ecosystems. Some languages almost have too many, to the point that they are constantly being introduced, changed in ways that make old code non-portable, and then sunsetted. It's hard to keep internal corporate software running when if you choose something mainstream it's less than 5 years from EOL, but if you choose something emerging it may never go mainstream. A lot of it seems like reinventing the wheel.
- asking about the scope of a programming language is asking about the intended programming situations one wants to cover.
- what is a good balance between convenience (sytactic sugar, "features" and abstractions) and asking the programmers to write out things explicitly.
- more subtly: who is using the language, what concepts can be expected to be known to the programmers.
These are of course connected: a particular type of recurring programming situation may lead one to think of patterns and a need to abstract them, whereas to someone who intentionally constrains the scope to a specific area, it can be easier to keep the number and kind of source or "programmer intent" abstractions low.
Often these discussions happen in the context of a general purpose language but there is little consideration that some programming situations are better served by DSLs.
Also a decision on "MIT vs "New Jersey" (worse-is-better) style affects the whole thing, as the notion of correctness is at some level always one of programming situations (a higher level discussion on using the API right way, checking error conditions etc)
Thus is a long-winded way to say: in the end the starting point matters. C++ can be considered a failure language design if you consider it from the readability/cognitive load angle but design choices seem to consistently be about permitting all possible choices. This is why Stroustrup can claim things like "you can write memory safe C++" and not even be wrong. Java can be considered a failure in concision but tool support means that programmers do not pay the cost of writing everything out explicitly.
Haskell and anything in the academic tradition will emphasize abstractions and demand more and more knowledge from users whereas industry tradition will be biased towards low (or lower) cognitive overhead, but if one is willing to specialize, there is an infinite number of nuances of possible points in the design space. We will see more programming languages and come to accept that there will be many that we use at the same time.
So rather than asking how big, maybe we should wonder how to understand the involved trade-offs.
1) Not in the language spec, just options in the de facto-standard compiler 2) Are often shunned by industrial users, see “Simple Haskell” 3) Are, among other reasons, there to support experimentation and research which is an important use case for the language 4) Are opt-in and largely unnecessary in practice, in my code I generally only use a couple of well known extensions.
If a competent professional can’t become fluent in a year, it’s too big. But I have pretty low regard for people who complain when it takes longer than a weekend. This is part of what we’re paid to do, and the investment in your toolbox will pay off for the rest of your career. I still use ideas that came from languages I can’t officially use right now.
Evolution, or incrementing version numbers, don’t necessarily equal increased size.
For example Python now has async functions. But it had them in Python 2.5 as well when it introduced generators (see the twisted.deferred decorator) - you’d just use “yield” rather an “await”.
- new syntax for exception groups (except*)
- assignment expressions (the := operator)
- positional-only parameters (with a / in the parameter list)
- `=` support in f-strings, e.g. f'{user=!s} {delta.days=:,d}'
- new type annotation features, e.g. for variadic generics, type guards, unions
- structural pattern matching
Does it mean Python is small? No. But that doesn’t make it big.
At a feature level there are things like descriptors and metaclasses, which are complex and rarely-used.
There's a huge number of obscure magic methods/attributes: __origin__, __orig_bases__, __prepare__, __mro_entries__, etc.
It's full of gotchas: methods are looked up on the instance, except magic methods which are looked up on the class, except except __getattr__ and __dir__ on module types. There are both __getattr__ and __getattribute__ and they do different things. Most `typing.Foo` (and also modern `list[int]`) aren't `isinstance`-able. The use of += with tuples. The lack of any coherent numeric tower. Etc. etc.
I think it's very clear that Python has grown organically, and is now struggling under the weight of all its bolted-on extra bits, or sheer unnecessary complexity. I would love to throw it all out and start again.
Personally, I'm not enthusiastic about the things that came after the f-string. (Although dict unions should have landed a decade prior.)
Metaclasses are widely used, but unless your specific problem calls for their use then you won’t use them. Usually these problems are related to authoring a library.
How would isinstance work with List[int]? Would it do O(n) isinstance calls on each element? Python isn’t typed like that, and a list is not and never will be an instance of List[int].
The magic method resolution order is also pretty natural and fits (slots?) nicely into the mental model you develop whilst using Python.
As big as it needs to be and no bigger.
A programming language is almost always built for a purpose - to solve a problem or fit into a certain domain. We've all seen the needless complexities in programming languages that accrete new features, year after year, just to have new features.
Is it? Most general programming languages have certain design goals, but I find these often unrelated to the domains in which the language ends up being used.
Maybe a language with 10,000 keywords would actually be better in LLM world?
var _xx = 100;
mystruct =
{
a : 10,
b : "Hello World",
c : int64(5),
d : _xx + 50,
e : function(a, b)
{
return a + b;
},
f : [ 10, 20, 30, 40, 50 ],
g : image_index
};
It's been a long time since I've look at GML but it looks like it's turned into Javascript-lite. I do wish C had flexible array shorthand and something higher than function pointers to work with.As counter-examples, I'd raise the Wolfram language (and maybe Matlab, but I haven't used that) as an example of a truly vast language – in terms of "standard library". On the other hand almost all criticism of Go has historically revolved around it being too small.