Buzz: A lightweight statically typed scripting language
buzz-lang.dev
buzz-lang.dev
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.
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 ':'.
Indeed. `{str:int}` would be better.
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.
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!
Were you running F# with modern .NET, i.e., .NET5+?
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.
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.
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.
More info here: https://go.dev/blog/constants
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...
Yes you can Google pretty much anything that you can have a conversation about and never speak to anyone. What is your point?
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 “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.
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).
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 “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...
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.
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.
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.
I disagree, because back in 91 Guido released some rationale along with the language: https://www.tuhs.org/Usenet/alt.sources/1991-February/001749...
> 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.)
etc. Docs/tutorials were later fleshed out even more but always had some rationale: https://docs.python.org/release/1.4/tut/node4.html
Clojure has an explicit rationale page: https://clojure.org/about/rationale
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.
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.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.
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 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."
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.
You can take this a step further by using VS Code with the Polyglot Notebooks extension to get a Jupyter-style experience with C# code. (https://marketplace.visualstudio.com/items?itemName=ms-dotne...)
[1] Especially when no type inference was mentioned.
I love the syntax and will definitely try the language
https://www.quora.com/What-are-some-things-that-only-someone...
Couple of questions:
1. Does it support any type inference?
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?
> You have to use the nightly build of zig.
ie. `brew install zig && zig build` will not work.
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.
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.
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 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.
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.
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.
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.