What should I be looking for here that distinguishes it from other lightweight statically-typed scripting languages? Performance? Tooling? Particularly good FFI?
There are some syntactic quirks that don't convey any obvious benefit, like the use of '>' to indicate a return type. Since this language uses C-style prefixed type identifiers, why not do that for functions as well? Alternately, why not use the much more common ':' or even '->'? The use of a doubled return type (`> str > int`) to indicate yields is obscure, and the fact that the second type is the yielded type is surprising (yields come before the final return, so I'd expect the types to be in the same order).
Similarly, I understand the mimetic quality of '[str]' for 'array of str', but '{str, int}' doesn't have the same ring since key/value pairs are separated by ':'.
Comments starting with '|' feels like pure quirk. I don't really mind quirk in a tiny language like this, but there's a point where "funny syntax" becomes a bigger takeaway from the documentation than any actual features.
> There are some syntactic quirks that don't convey any obvious benefit, like the use of '>' to indicate a return type. [...] why not use the much more common ':' or even '->'?
Agreed. New languages should use similar conventions to popular existing languages, for the sake of familiarity, unless there are obvious benefits to doing something else.
> Similarly, I understand the mimetic quality of '[str]' for 'array of str'
It's quite Haskell-like.
> but '{str, int}' doesn't have the same ring since key/value pairs are separated by ':'.
Re: comment char: I couldn't agree more, went in excited by static typed, and was immediately turned off by this seemingly arbitrary divergence. I kept looking for other uses of, for example, `#` in the language that might explain this quirky comment char, but got to the end of the guide w/o finding any. Maybe the author will reconsider :)
> Comments starting with '|' feels like pure quirk.
Yeah... | is a pipe (shell) or an "or" (programming) symbol. Seeing it in the code to indicate a comment just rubs me the wrong way. It's almost as if it was chosen just to be different.
This comment section is very "why write a Language?" oriented.
I love reading about new languages!! I work with data scientists a lot so I'll probably always use Python professionally, at least for the foreseeable future.
But Python, JavaScript etc are huge languages with massive histories of practical trade offs and compromises. It's always exciting to see what someone's dream language looks like!
Besides, learning languages like Rust and Clojure has taught me a huge amount that's transferable to coding in other languages like Python.
I like the idea of a lightweight json focused / typed scripting language a lot!
For me, it's that this language already exists in F#. Other than "lightweight" (.NET probably inatalls just as fast as Python these days, though), it is the statically typed scripting language, in my opinion.
I love me some F#, but F# isn't a scripting, and it's compile times were pretty terrible the last time I used it on Linux. It's been a while, though, so maybe things have improved.
Why do you say it's not a scripting language? You can write .fsx files and run them as scripts, and there's a nice REPL. Using Polyglot Notebooks, you can even combine several languages, including F# and PowerShell, and documentation and run the notebooks as scripts.
Were you running F# with modern .NET, i.e., .NET5+?
Why does that matter, exactly? What affect on scripting does that have?
You can run a script file via `dotnet fsi script.fsx`. You can load and run a script inside FSI (F# interactive, the F# REPL) via `#load script.fsx`. You can run a notebook as a script via `dotnet repl --run notebook.dib --exit-after-run`. There is no "compilation" visible or required by the user.
This is nearly identical, except that it's improved and more featureful, to how one runs a script in Python. Whether F# is compiled or not is immaterial.
> Objects, list and maps variables are only reference to them. Meaning you can't assign a new list to a constant variable but you can modify the list itself.
In what contexts is this useful? I know it matches some other languages view of `constant`, but I feel that this sort of behaviour is very surprising to a user.
Assuming the following code:
object Person {
str name = "Joe", | Fields can have default values
int age = 35,
}
const me = Person{...}
const [int] list = [4, 5, 6]
In what contexts is it useful to allow the name of `me` to be changed, or the length of the list to be changed, while disallowing the variable to reference a different underlying object?
Wouldn't the expectation of a programmer be the other way around? IOW, a symbol that is declared as constant can be a reference to any constant object, so the programmer can always assign that symbol to another constant object, but the objects themselves should not be mutable.
Java too. Rust is the only language I’ve used where “immutable” means everything through the whole reference tree is also immutable. Well, only language that allows mutation at all.
And C/C++. Probably other value based languages like Go and Zig.
JavaScript probably behaves like that because `const` was tacked on (and it's dynamically typed so there's no place to mark parameters as const). There is Object.freeze() which sort of makes something immutable, but it's not really the same.
Java doesn't even have const so I guess they just didn't care about const correctness or didn't have time to add it.
In Go, consts can only be used for primitives like 42, "foo" etc. - not structs, because the language doesn't have a concept of immutability (and so wouldn't be able to enforce const-ness) except for primitives.
Afaik for C & C++, that's not true – you can turn const references into normal references and are even allowed to mutate the object they point to unless said object is declared as const.
Yes! We're finally challenging the notion that scripting languages must inheritly be dynamically typed.
Some say that types are too much of an overhead for small programs but I find it impossible to reason about the design of software without types. I even opt for TS over JS for throwaways...
NimScript comes to my mind. You get most of the Nim language, which is statically typed and versatile. But NimScript is interpreted immediately, like running a Python script, instead of compiled to an optimised binary like regular Nim.
There are no such things as "scripting language" -- any language is a scripting language if you write a script (i.e. a program that automates another program) in it.
All languages are both statically typed and dynamically typed. Or, if you want to be precise: statically checked and dynamically checked. Static vs dynamic refers to whether a check is performed before the program is run or when the program is run.
It's upsetting that even people who write languages use this nonsense taxonomy to describe what they do.
----
As a consequence, your enthusiasm... sort of comes from the place of not understanding something. My guess is that you are happy to see that there are type annotations in the language and they seem to be mandatory (? -- I haven't explored the language in detail enough to tell, but usually if the type annotation precedes an identifier in the grammar is not possible to make it optional).
What I think you (or the language's author) might be happy about is that there aren't built-in mechanisms in the language to convert between different types (or interpret the data stored in a variable in different ways). Such mechanisms exist to various degree in languages programmers don't normally call "dynamically typed" (even though, like I wrote before, this taxonomy is nonsense). For example, in C, everything is and integer in the end of the day, which makes a lot of implicit conversions possible. Or, for example, it's possible in Haskell to overload string literals making them something other than strings (eg. SQL prepared statements) making the meaning of the program depend on an annotation / compiler argument.
There are instances where it's genuinely convenient to have the language guess the type of data and there are instances where it leads to frustrating and difficult to discover bugs. Since a language has to make a decision for all such cases it's difficult to find a good middle ground. Below are some examples of when implicit type conversion is convenient:
* When everything in the language can be "printed" and operations involving strings implicitly convert everything to string. Alternatives involve complicated mechanisms of defining printing methods for various objects, while still not being able to write generic code that prints any inputted objects. Or creating automatic methods that print "something" about the object that usually ends up being useless (eg. the memory address of the chunk of memory occupied by the object). And so on.
* Reading user's input, especially interactively. If I had to spell out the types of arguments I pass down to Unix "find" command every time I use it, I'd have invented a language that would allow me not to do that and would've guessed the types from a more concise input.
* Arithmetic involving different flavors of numbers. Imagine there are languages where it's a tradition to define a special sub-type of some integral type for indexing of every array type the program uses. Imagine now that these types usually cannot be converted between each other. You probably haven't worked with a language like that, but if you want to see how you might like it, you could try Ada.
There are no such things as “serving spoons” — any spoon is a serving spoon if you serve something with it.
There are no such things as “desert spoons” — any spoon is a desert spoon if you eat desert with it.
Don’t get me started on whether or not teaspoons exist.
This is such a pointless observation given the world has really come down heavily on the side of sanity, which is to say yes clearly any language can be used for scripting but “scripting languages” are those languages for which writing scripts is the primary purpose. Just like, while you can serve food with any spoon in a pinch, if you really want a spoon that is specialised for serving, a serving spoon is what you are crying out for.
If everyone understands exactly what they mean when they say “scripting language” or “statically typed” and these terms are frequently used to bootstrap understanding of other languages, are they really wrong to use those terms? This isn’t “nonsense taxonomy”, it’s using language in the normal way for the purposes of communicating with human beings, which is something most people try to do.
It seems like the term "scripting language" has become a pejorative; denigrating a programming language as somehow less worthy for "serious" programs than non-scripting languages. To me, when I hear someone describe a language as a scripting language, it says more about how they think about programming than the functionality and applicability of a language for solving different classes of problems.
I'm coming to think different programing languages are more like a patois or creole. an expression of ideas shaped by the speaker's thoughts and experience in the world. Sometimes the patois de jour taps into a common experience (e.g. python) or not (e.g. forth).
100% agree. And just like you don’t talk to a new-born child in quantifier logic and you don’t attempt to write a PhD thesis in babytalk, there are places where more or less rigorous and exacting language is appropriate.
It used to be the general consensus was that “scripting” comprised quick and temporary automation of tasks and therefore the emphasis in a language was on something convenient and expressive that could get a bunch of stuff done quickly even if the semantics were a bit janky (I’m looking at you bourne shell). Then perl really opened a lot of people’s eyes to what could be done with “scripting languages” (both in terms of power and in terms of the horror that could unleash in the wrong hands) and there has since been a gradual shift towards simplicity and understandability given that there are few things more permanent than a temporary script.
> There are no such things as “serving spoons” — any spoon is a serving spoon if you serve something with it.
> There are no such things as “desert spoons” — any spoon is a desert spoon if you eat desert with it.
That's not how that works. Eating a dessert is not what makes a dessert spoon what it is. There are multiple criteria which all go into deciding whether a spoon is a desert spoon. For example, dessert spoon cannot be bigger than a table spoon if they are sold as a set.
This isn't true for languages. There's nothing to warrant a title of "scripting" to a language. Nothing that would allow you to discern a "scripting language" from a non-scripting one. This terminology lack internal consistency. You could try to define what that means for you, and that could make the definition valid, but there isn't a shared coherent explanation for how to tell a scripting language from a non-scripting.
> If everyone understands exactly what they mean when they say “scripting language”
Well, here's where you are confused: no, nobody understands what exactly they mean when they say "scripting language". Far from it. It's similar to the situation with fruits and vegetables. Unless you know about the controversy, you might be convinced that you know very well what is a fruit or what is a vegetable, but you will find that not only there isn't a consensus on individual plants, but that there isn't even a consensus on the definition.
So, similarly, if you want to be precise, and you want to use the word "fruit", you need to consider the context in which you are using it and make sure that whoever you are talking to knows what sort of a definition you are using.
But, it's even worse with "scripting languages" because any of the definitions I know are without merit. They don't describe any useful property of a programming language. Knowing that some language is a scripting language doesn't help you understand what can it be used for or what to expect from it etc.
The unfortunate reality is that beyond various aspects of extensions of context-free language group we don't have any useful means for creating of language taxonomy. All we have is a bunch ob b/s often inspired by marketing departments of companies pushing those languages. But we crave taxonomy. It's just the one that we have is worthless...
I admire people who make projects like this. But it is so alien to me to try making something like a language.
What is the motivation, and the goal? Surely it is practically a one-in-a-million chance to actually unseat Python or bash or Lua. I could never really justify using something like Buzz in a professional setting, just because it is too obscure and new.
And look - if it is just for the joy of it, I get it! But I wonder if there is ambition in there too.
It’s surprisingly easy to write an interpreted language and I’d highly recommend it as a learning tool. You get a really good intuitive sense of how programming languages work by doing it.
It's useful to have embeddable languages that fit one's preferred style and featureset. It's also not as hard to implement as you'd think. Common usages are anything requiring configurable behavior: game scripting, feature extension, distributed computing plugins, etc.
These languages each have enough warts that lots of people and languages are chipping away at them.
Go and Nim are doing the strong static typing that "feels like scripting" thing. Even Rust is making a bit of a dent, despite it being a systems language with memory semantics.
There's plenty of room for all sorts of projects to try. Don't count anyone out. Even if the language never gains momentum, its ideas or developers might have some other effect. And even Nimrod was once in this state.
This is an excellent point and I think that while most languages will fade away in time, if they even contribute one new idea the project is worthwhile. If we had asked programmers in 1991 what the point of Python was, the responses would have probably been similar to the parent comment, and look at where it is now.
I played around with Vala (a C# style language that compiled to C on Linux) back in 2010 and while I never used it for anything serious, it was fun to try out new ideas and see how they could work. There is value in these projects, maybe some of it will carry over into other languages, in others they may be the dominant language in 10 years.
> If we had asked programmers in 1991 what the point of Python was, the responses would have probably been similar to the parent comment, and look at where it is now.
> This is Python, an extensible interpreted programming language that
combines remarkable power with very clear syntax.
> This is version 0.9 (the first beta release), patchlevel 1.
> Python can be used instead of shell, Awk or Perl scripts, to write
prototypes of real applications, or as an extension language of large
systems, you name it. There are built-in modules that interface to
the operating system and to various window systems: X11, the Mac
window system (you need STDWIN for these two), and Silicon Graphics'
GL library. It runs on most modern versions of UNIX, on the Mac, and
I wouldn't be surprised if it ran on MS-DOS unchanged. I developed it
mostly on an SGI IRIS workstation (using IRIX 3.1 and 3.2) and on the
Mac, but have tested it also on SunOS (4.1) and BSD 4.3 (tahoe).
> Building and installing Python is easy (but do read the Makefile).
A UNIX style manual page and extensive documentation (in LaTeX format)
are provided. (In the beta release, the documentation is still under
development.)
If the authors don't even make a value proposition themselves, I assume the language is a learning exercise and won't take it seriously. Also not really worth critiquing things I don't like about it. Indeed, I see on the introduction:
> It started as a toy language following the excellent book Crafting Interpreters by Robert Nystrom.
Nothing wrong with that! Sometimes the value is mainly for the author, and that's great. Probably not going to contribute any new ideas though.
Completely agree... but when people like a language, they may still want to write scripts in it even though it may be really uncomfortable.
That said, Nim is actually designed to feel like a scripting language... for example, you don't write a main function at all, just code away (this is an actual hello world program in Nim):
echo "hello world"
So, out of statically typed languages, Nim is probably one of the best choices for scripts.
interesting. has chatgpt/copilot been trained on nim to the point where they creates code as good they do with python?
I ask because I've always treated coding as a necessary evil. When I worked as a programmer, I never gave 2 shits about the language I was required to use. I'd write a specification, code to the specification and tried to update the spec if I need to deviate from it.
Because of my damaged hands, now, I do not have enough typing capacity to learn a new language the old trial and error way. chatgpt is my accessibility tool for creating code.
I've learned how to give chatgpt a spec, skip the coding step and goto validation. I've trained myself and chatgpt/copilot to generate python code like I had created it, making desk and unit testing easier and faster.
Learning a new language would start with a specification of the problem as above, then seeing what chatgpt/copilot generates. However, it is easier to learn if the LLM model understands the language. It is sometimes hard to tell the difference between hallucinations in the code vrs hallucination in the specification.
It ultimately depends upon what you mean by "as good". There is no clear single metric. Once you have >1 metric it becomes a subjective "who's priorities?" game of weighting them / projecting them into a single metric.
The best answer to a question like yours is: give it a try on some easy problems and see what you think yourself. No one else can really know the kinds of problems / answers / code you most work with (and sometimes the future is pretty murky even to oneself, even in these vague categories).
Disclaimers issued, some things can be said which might help. Since Nim is primarily a highly ergonomic static ahead-of-time compiled language with code running as fast as C often does, errors may be caught more conveniently. Because Python is popular, especially for teaching programming, training coverage will always be better, but Nim has some core features & keywords "kinda similar" to Python which may help on the other side.
Not sure about 4.0, but ChatGPT-3.5 does poorly on basic Nim things without Python equivalents. To give just one concrete example (out of many), `a,b = b,a` is a common way to manifest swapping in Python while in Nim one uses `swap a,b`.
So, if you are willing to do more "compiler-assisted clean-up" or have a/develop a knack at steering the random sampling toward code which compiles, Nim could be about as effective as Python used this way.
In terms of code entry work for your specific hands problem, parentheses can often be left off in Nim code and in general it seems to have much less punctuation / syntactic noise. Of course, keys can be rebound & such & maybe you do that, too. Nim definitely has more powerful abstraction mechanisms like user-defined operators, templates, and syntax macros.
Your suggestion at the end is a form of "speaking the keyboard" problem that has plagued speech-driven programming for years. It is so wonderful that I can dictate the specs and then verbally cut and paste them into the LLM. If I had the energy, I would build an LLM interface that used speech recognition-friendly text areas that one could use speech for editing and revising results.[1]
Your response, however, touches on the meta-problem of adding additional information to a training set. For example, as people learn and generate more nim code, the community can expand the LLM capabilities without going through open AI or whoever. I know training requires a lot of GPU time, so training over distributed GPUs is necessary. For example, I would buy one or two GPUs and pay for the electricity to contribute to community LLM training efforts.
[1] For anyone interested in helping, it would be a simple two-panel design: top for editing, lower for LLM results, and two buttons, first for "copy to clipboard," second for "submit to LLM."
I have seen a few comments expressing a desire for a statically typed scripting language. I’ve been using a new workflow for a couple of years I’d like to share.
Install .NET 8, and create a new C# Console application. From .NET 6 onwards, it uses the new “top level statements” style which is effectively like the blank slate of a script file. The barrier to entry has never been lower.
(https://learn.microsoft.com/en-us/dotnet/core/tutorials/top-...)
This lets you take advantage of a really healthy toolchain/package manager ecosystem.
Not explicitly mentioned in the guide, but Buzz has a garbage collector [1] (can also be inferred via a casual mention of upvalues). So it has more focus on scripting than static typing I guess, but the language design doesn't look so to me.
Yes, but "statically typed scripting language" is a quite unusual combination of words [1], and there seemed nothing to back up the "scripting" concept, so I thought it might be something more akin to Nim or Zig (i.e. "scripty system programming"), and it wasn't. That was a missing line of thought that I should have explicitly stated, sorry for the confusion.
[1] Especially when no type inference was mentioned.
Statically typed languages with a garbage collector are just as common as those without. So I don’t really follow why you’re surprised that this had a GC.
Not at all, it means independent from each other. Like the x and y coordinates of a point in a plane: you can set one of them to the value you want and it won't affect the other. This only happens when the x and y axes intersect at 90°, hence the "orthogonal".
Something that the page does not seem to comment on: will easy embeddability, like with lua, be a priority for this project? Especially in Zig (obviously). It's the most interesting question and use-case that comes to mind.
We don’t need any more computer languages. Still, you will run right off and invent another one. Let me guess, your amazing new language uses IEEE-754 math and fixed-precision integers. Your amazing new language is broken.
A language without easy access to IEEE-754 math and fixed-precision integers that is supposed to run on common/standard hardware (i.e. not for FPGAs or more specialist hardware) is broken for the majority of the tasks it will be doing. That's not preventing you from having other numerical types which meet the needs of various groups (e.g. arbitrary precision types or types for financial maths), but to explicitly exclude them even though the hardware provides them is a problem.
Classic premature optimization, assuming that hardware functions must be revealed in language features. If you can't get your integers closed under addition from the get-go, what hope do you have of writing a secure programming language?
2. It looks like objects have to explicitly declare what protocols (interfaces?) they implement when the object itself is declared. Is that true? If so, why did you opt for that rather than the typeclass approach where the struct is declared separately from its interface implementations?
ZVM (https://github.com/tristanisham/zvm) is a good alternative to keep uptodate with Zig nightly versions and also quickly switch to a stable version when needed.
For me it's when it's useful for writing adhoc utility tools distributed as source, and directly runnable from source code in the terminal and without requiring a manual compilation step (but maybe requiring installing a runtime).
E.g. Python, JS/TS with node.js/deno, Lua, Bash, Powershell qualify as scripting language, but C, C++, Rust are not.
Of course there's a grey area of compilers which allow compiling and running a "script" via shebang.
Sorry, but I strongly disagree with your explanation. It seems to categorize languages on the basis of what tools are available or widely used. That's not a property of languages.
A language can be designed once and then interpreters and compilers (and transpilers) can be made available for it.
Python is a classic example: it's most commonly interpreted, but can be compiled when performance matters.
C is usually compiled, but tcc offers the option to directly run it from source (-run).
History has given us both compilers and interpreters for various dialects of BASIC since the 80s.
Honestly I can't imagine why a language designer should decide upfront if the result of their study will be interpreted or compiled. And I have no idea what choices should they make to characterize it as a "scripting" language.
> A language can be designed once and then interpreters and compilers (and transpilers) can be made available for it.
While strictly true, some language features are awkward or unsuitable for scripting purposes. For instance, C++ templates and Haskell's type classes with extensions that make overload resolution Turing complete. You can do this, but it seems like a poor choice where the language ostensibly has runtime evaluation and type information available, and so you don't need to so strictly stratify the types and values. This collapses effectively two programming language levels into one, and considerably simplifies quite a bit of the runtime, compiler/interpreter, and the programs that can be expressed in the language
I think it’s the ease of doing common operations and writing common programs. Maybe it’s easier to classify what isn’t a scripting language.
I like Go, but to me it isn’t a scripting language like Python and Ruby because it has less ergonomic APIs for common operations (especially for strings and slices). Rather, Go prefers a literal representation of what’s going on in memory. For instance, there’s no “str1[1:5] + str2[1]” api, or you append to a slice with “s2 = append(s1, newElement)”. You can’t just “s1 + newElement”. I think Go’s reasoning is that it likes to avoid less literal features like operator overloading, and append() hints that a heap allocation might occur. But in a scripting language, you shouldn’t care that a heap allocation occurs and instead should choose a more concise and ergonomic api.
Java isn’t a scripting language because it’s so wordy.
Rust isn’t a scripting language because its type system and borrow checker are a bit too much.
Haskell isn’t a scripting language because monads and lazy execution are a bit much.
When I think of scripting languages like Python and Ruby, they focus on making common scripting type tasks easy, which often involves giving the programming less control over the machine. But at the same time, they don’t introduce any opinionated language abstractions like monads, a borrow checker, and actor threading model, etc. It also just shouldn’t be that wordy or type-heavy in a way that would slow down prototyping.
Traditional scripting languages have been dynamically types. But I think they can still be statically typed (like this language is trying to do). There isn’t a hard boundary, but once you are “too far into the weeds”, you notice that you are too far into weeds and not in scripting language territory anymore.
Fun! I’m always on the lookout for a new scripting language. I hate Bash, and Python just isn’t my style, even though it’s currently my default. Something like Kotlin would be my dream, but that’s still pretty hard to use for quick scripts. Going to look closely at this.
If you are interested in writing down more of what problems you have with scripting languages, feel free to shout me an email. Should be in profile.
I have been slowly working on a model of what problems i see in this domain and my own ideas to "fix" (or more like try to) them. So would love to see other perspectives.
Is there a compiled list of all these new languages?
Also, my only concern in the future is that I have to download 10+ different runtimes to my machine to be able to co-operate with others. But I guess Docker solves this.
Honestly, except for some of the syntactic quirks, this looks fabulous.
I definitely think there's a need and space for type-safe embeddable scripting languages like this. Lua usually dominates this space but the lack of type-safety always kept me from adopting it wholeheartedly.
With Zig also in the picture, I can totally imagine an ecosystem that uses something like Buzz for scripting the high level parts of an application, Zig for the lower level performance critical stuff, and leveraging interop with the vast abundance of C libraries out there.
I mean this looks awesome and all but I feel like constantly developing/learning new languages and frameworks has been such a giant waste of resources in our community in general. I hope things stabilize in the future. I've got 15 professional years under my belt at this point and I don't feel like an expert in anything.
I think the only reason why there was a temporary "language bottleneck" in the late 90s and early 2000s was that CPUs got too complex around that time to deal with the resulting code generation complexities in a "homebrew compiler". LLVM and later projects like Cranelift changed that, and now it's possible again for individuals and small teams to create new languages which have competitive performance. In my book that's great, competition and experimentation is always a good thing for progress (even when it means there's also many more hobby projects that won't move the needle).
There are some syntactic quirks that don't convey any obvious benefit, like the use of '>' to indicate a return type. Since this language uses C-style prefixed type identifiers, why not do that for functions as well? Alternately, why not use the much more common ':' or even '->'? The use of a doubled return type (`> str > int`) to indicate yields is obscure, and the fact that the second type is the yielded type is surprising (yields come before the final return, so I'd expect the types to be in the same order).
Similarly, I understand the mimetic quality of '[str]' for 'array of str', but '{str, int}' doesn't have the same ring since key/value pairs are separated by ':'.
Comments starting with '|' feels like pure quirk. I don't really mind quirk in a tiny language like this, but there's a point where "funny syntax" becomes a bigger takeaway from the documentation than any actual features.