Bog – small, strongly typed, embeddable language
github.com
github.com
(Not affiliated with either, just can be easy to miss stories on here sometimes, and I figured anyone interesting in Bog might also be interested in Cyber)
Cyber also seems to be under more active development at the moment.
https://github.com/vexu/bog/graphs/contributors
https://github.com/fubark/cyber/graphs/contributors
[0] https://github.com/fubark/cyber/blob/master/docs/docs.md
I'm not sure how I would embed this in a non-Zig project, though.
- https://luau-lang.org (interpreted / sandboxed)
- https://terralang.org (JIT interpreted)
- https://nelua.io (Lua -> C)
- https://typescripttolua.github.io/ (TS -> Lua)
- https://github.com/teal-language/tl (Teal -> Lua)
- https://github.com/sumneko/lua-language-server (IDE only typing)
With minimum effort you can get a lot of benefit from using Sumneko's Lua language server.
There's another one you missed in Pallene[2]. But again, it's goal was to optimize the stack sharing involved in using the C API. It also adds types though and maintains Lua idioms as much as possible.
Edit: Oh yes it's still like that 'When loading and running the Teal module from Lua, there is no type checking! Type checking will only happen when you run tl check or load a program with tl run.' from https://github.com/teal-language/tl/blob/master/docs/tutoria...
Much of the functionally has been wrapped or customized to disallow any system access that doesn't go through an access control layer, including for require, and disallowing catching certain errors with pcall and through coroutines. Anything that could feasibly break the sandbox is also removed, like the debug package, and the ability to load bytecode (text sources only). The actual Lua sources are 100% vanilla, though we complete it with C++ to be compatible with the rest of the codebase.
See also this list for comparison https://github.com/fubark/cyber/issues/6, if you dont want lua by a meta-compiler.
If you want non-allocating scripting for optimal performance (and io limited to what you provide as buffer), go for https://dascript.org/. I dont think there are currently other projects with that performance (+ also inspired by Zig). Though, not sure how clunky it is to use.
> let {print} = import "std.io"
An idea obvious in hindsight that I hadn't thought before - if import returns an environment and let can destructure, then a pattern match can bind an explicit subset of that import. Something like:
`(let {print read} (import io) (print (read)))`
Further down I find essentially that example (with input instead of read) and destructuring assignment within function arguments:
`let add = fn ((a,b)) a + b`
though the grammar suggests that {} is initialisation and not a map/dict/hash/assoc/environment style thing, so you probably don't have `fn ({key value}) value + 4` or similar for taking maps apart as they are passed to a function. Thus I think import is special cased.
The bytecode layer knows what maps are though, so maybe they're just missing from the syntax
Some languages have foo.somefunc() which I think works quite well although iffooisrealllylong.function() is a risk.
I suppose this gets you the best of both worlds.
Although using let does seem a bit weird to me. It seems conceptually misleading.
I think you mean something you hate about not using an IDE with the language. One can do `from onoz import *` in python and Java to have a similar "wait, where did do_magic() come from?" experience, and then Scala will see your wildcard import and raise you implicit methods, which can die in a raging fire tornado
Well it's a 'feature' of the language so the criticism still stands. Ides could solve a lot of language warts but we still rightfully criticise the language for the warts. C's lack of memory safety could be solved by good programming practices, but we still criticise c for the lack of memory safety.
One would imagine that
let {print} = import "std.io"
is equivalent to let print = (import "std.io").printThis kind of destructuring syntax is common in many newish languages -- Rust, Clojure, newer flavors of JS, Typescript, etc -- and becomes second nature pretty quickly. What you're seeing is really two things: first that you can pull apart a map as part of assignment, and second that there's sugar to name the variable after the map key.
In JS, you could write:
const { foo: bar } = something
And that's sugar for const bar = something.foo
At the same time, JS many other languages have pervasive support for the idea that often you want the same name for a variable as the map key where you're going to use it. So, e.g. const mapOfFoo = { foo }
is equivalent to const mapOfFoo = { foo: foo }
Combining these things, you get: const { foo } = something
Equivalent to const foo = something.foo
i.e. the variable/property auto-aliasing works in the destructure too. When you consider that you are importing a big object with a bunch of fields and functions hung off of it, it becomes natural for that to work the same way: import { foo } from "someplace"
I'd argue that it's not actually opaque, let alone obtuse; it's merely unfamiliar because it's (I'm guessing) a combination of unfamiliar syntactical motifs. But as you get more familiar with that kind of syntax, you'll find it natural, and would be surprised if, say, it worked for regular objects but not in imports. When I picked up Rust, for example, I found myself right at home with it (same for the pattern-matching assignment stuff, which feels very similar to Clojure's).As for errors, you'd get the same error as in the desugared version: ptint is not a property on the object it's pulling apart.
There's not much difference between `obj.attr` and `obj['attr']`.
To expand, the following was common before destructuring but with CommonJS:
var some_func= require('some_module').some_func
Which, as you know, would probably usually be done like this today, where we have destructuring: let {some_func} = require('some_module')Aside from my biased nitpick, it looks pretty neat!
I don't think you need to call out strong typing. Who would make a weakly typed language in 2023?
Interactive programming and programming on data (e.g. SQL) both make sense to have weak typing to me.
But yeah I did misread strong typing in this as static typing. Thanks for calling that out.
How are coroutines scheduled?
Can suspend return a value?
Or do you think most people will automatically adjust and think "hello world in itself doesn't show much, so the author decided to include something more informative and keep call that hello world" ?
Sample code is great, but I'd be happier with a README that says something about the language (and, to a lesser extent, about its implementation).
Apparently Bog is based on Zig, but I didn't learn that until after reading about 80% of the README -- and since I'm not particularly familiar with Zig, I don't quite know what to do with that information.
Probably the author had a narrower audience in mind when writing the README.
Looks like a LuPyrby language.