5 ms·
What is very, very tricky is that the language get bigger the harder is to do composability. And "composability" is far bigger and broader than the normal under
by mamcx 4y ago
What is very, very tricky is that the language get bigger the harder is to do composability. And "composability" is far bigger and broader than the normal understanding.
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.
- ChadNauseam 4y agoType theorists have been talking about this too. The search term is "rows" or "row polymorphism". They're awesome but no mainstream language uses rows. I wrote about them in my blog post about 4 issues facing functional programming [0]. Also, check out Unison [1], which is mostly structural but "pretends" to be nominal in a way that I feel would be very appealing to most programmers. [0]: https://chadnauseam.com/coding/pltd/four-issues-facing-fp https://chadnauseam.com/coding/pltd/four-issues-facing-fp [1]: https://www.unison-lang.org/ https://www.unison-lang.org/
- justinpombrio 4y agoOCaml has row polymorphism. The syntax for a function that prints `name` from a record that has `name` and possibly other fields is: val print_name: <name: string; ..> −> unit
- magicalhippo 4y ago> For example, I wish Rust allow: What kind of problems would this solve? Not trying to be snarky, just to understand the feature.
- mamcx 4y agoWhat this example show is that you can't manipulate the "things" that are expressed in syntax as data, so you can't have the same way to deal with both types and values: 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/ 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!
- magicalhippo 4y agoSeems like you want a code generator. For some problems I admit I have missed a proper, integrated code generator. C macros is, like you say, hacky. 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.
- UncleEntity 4y agoYou could add type hints. I poke around in the pybindgen code base semi-often and it’s fairly large. No problems that would call for sparing use.