Just values are all strings. This is convenient, because it means that Just is effectively statically typed. It is impossible to provoke a type error.
However, it means that many desirable things are impossible:
- Can't have lists.
- No way to represent a
*arg. Currently arg is a space-separated string, but users may want to do something with each entry in the list, and re-splitting is error-prone.
- Representation of booleans is tricky. Some functions return
true/false, but these are also valid strings.
We could add a type system, see #528. But another interesting option would be to change our single type from strings to lists of strings. This is done in rc, Plan 9s shell.
This seems crazy! Everything is a list? However, consider this: The shell, and Just, benefit from enormous simplicity because everything is a string. No type errors! No type system! We could abandon this, and add a type system, but another path is to make the one type we do have more powerful.
All current values, instead of being strings, would be lists containing single strings. When used in interpolations, or as arguments to / and +, an list of a single string would behave in exactly the same way as a string does now, so this would be a backwards compatible change.
This would allow the following nice things:
- The only
false value would be the empty list, and any non-empty list is true. [''] is true, so it would be possible to provide the empty string as a value, and still allow a fallback with value || fallback.
make has a ton of functions which treat a string as a space-separated list. These are useful, but error prone, so I haven't wanted to add these. We could add useful, non-error-prone versions of these.
+ could append an extension to every element of a list: ["hello", "goodbye"] + '.c' -> ["hello.c", "goodbye".c]
- Ditto for
/: ["/", "/usr"] / "bin" -> ["/bin", "/usr/bin"]
false could be represented by the empty list, and all other values would be interpreted as true. This [''] would be true, allowing the user to provide the empty string for a value.
for which evaluates to a list: for a in var { a + ".c" }
The main downside, I think, is that it is very unfamiliar and counter-intuitive. Users are used to shell-like languages, including make and just, where everything is a string. Everything is a list of strings is very weird. rc implements and makes a compelling case for lists of lists being the single type, but it's unfamiliar and mostly forgotten.
Open questions:
- Should we call them lists or arrays?
- Should we go even further and make the only type associative arrays? Associative arrays are more powerful, but emulating lists with associative arrays is problematic, and lists are a popular type. Plus we're really going down the dynamic language path at that point, since property access can fail.
- Is this totally crazy and we should not do this?
- What other features would be easy to add if we did this?
Just values are all strings. This is convenient, because it means that Just is effectively statically typed. It is impossible to provoke a type error.
However, it means that many desirable things are impossible:
*arg. Currentlyargis a space-separated string, but users may want to do something with each entry in the list, and re-splitting is error-prone.true/false, but these are also valid strings.We could add a type system, see #528. But another interesting option would be to change our single type from strings to lists of strings. This is done in rc, Plan 9s shell.
This seems crazy! Everything is a list? However, consider this: The shell, and Just, benefit from enormous simplicity because everything is a string. No type errors! No type system! We could abandon this, and add a type system, but another path is to make the one type we do have more powerful.
All current values, instead of being strings, would be lists containing single strings. When used in interpolations, or as arguments to
/and+, an list of a single string would behave in exactly the same way as a string does now, so this would be a backwards compatible change.This would allow the following nice things:
falsevalue would be the empty list, and any non-empty list is true.['']is true, so it would be possible to provide the empty string as a value, and still allow a fallback withvalue || fallback.makehas a ton of functions which treat a string as a space-separated list. These are useful, but error prone, so I haven't wanted to add these. We could add useful, non-error-prone versions of these.+could append an extension to every element of a list:["hello", "goodbye"] + '.c'->["hello.c", "goodbye".c]/:["/", "/usr"] / "bin"->["/bin", "/usr/bin"]falsecould be represented by the empty list, and all other values would be interpreted as true. This['']would be true, allowing the user to provide the empty string for a value.forwhich evaluates to a list:for a in var { a + ".c" }The main downside, I think, is that it is very unfamiliar and counter-intuitive. Users are used to shell-like languages, including
makeandjust, where everything is a string. Everything is a list of strings is very weird.rcimplements and makes a compelling case for lists of lists being the single type, but it's unfamiliar and mostly forgotten.Open questions: