Hi @JasonSteving99, awesome work!
I'm reading the reference guide carefully and I find Claro a nice and pleasant language.
I love the pipe operator (that I first met with Elm) and, as you explain here it allows program text and data to flow in the same direction (thus its easier to read than the pipes-free version)
(BTW, I found the ^
back-reference operator very clean and clear)
That property of program text and data flowing in the same direction is somewhat broken in the case of list comprehensions because identifiers are used before they are defined. For example, in
[strings::repeated("*", x) | x in [1, 3, 99, 2, 1] where x <= 10]
x
is referenced (in strings::repeated("*", x)
) before its definition (as x in [1, 3, 99, 2, 1] where x <= 10
)
In short and simple list comprehensions, as the above one, the syntax might not be an obstacle for understanding but in longer comprehensions understanding is hindered. For example, in the following code:
|
files::readOrPanic(resources::Input) |
|
|> strings::split(^, "\n") |
|
|> [ |
|
[ |
|
ints::parseInt(strings::fromChar(x)) |
|
| x in strings::splitChars(line) where ints::parseInt(strings::fromChar(x)) instanceof int |
|
] |
|
| line in ^ |
|
] |
The reader needs to go until line 9 to find the definition of line
and then go back to line 7 where line
is used to define x
that is first referenced at line 6.
I know the roots of the syntax for list comprehensions is the set builder notation but IMO that syntax is OK for simple cases (as is the case of all the examples provided in the description of the notation) but for more complex cases the syntax that reverts the order use-def into def-use is more clear. There are languages, like Scala, with a syntax like that.
I think something like
files::readOrPanic(resources::Input)
|> strings::split(^, "\n")
|> [ line in ^ ->
[ x in strings::splitChars(line) where ints::parseInt(strings::fromChar(x)) instanceof int ->
ints::parseInt(strings::fromChar(x))
]
]
reads better than
|
files::readOrPanic(resources::Input) |
|
|> strings::split(^, "\n") |
|
|> [ |
|
[ |
|
ints::parseInt(strings::fromChar(x)) |
|
| x in strings::splitChars(line) where ints::parseInt(strings::fromChar(x)) instanceof int |
|
] |
|
| line in ^ |
|
] |
What do you think?