The `if-let` construct - together with the fact that only `nil` and `false` are falsey - is very handy to express monadic chains over maybe/optional values:
```janet
(if-let [resp (make-http-request) # is nil on failure
{:status stat :body body} resp # always truthy, binds `stat` and `body`
check (= 200 stat) # continue only on 200 OK
json (json/decode body true) # is nil on failure
{:foo foo} json]
foo)
```
However, none of the bindings are available in the false branch, which
could be helpful to have for error reporting or fallback logic:
```janet
(if-let [resp (make-http-request)
{:status stat :body body} resp
check (= 200 stat)
json (json/decode body true)
{:foo foo} json]
foo
(if (= 401 stat) # unauthorized, refresh the token
(try-again)
nil))
```
This PR makes all symbols introduced by the bindings of an `if-let` available in all branches.
Also match shell convention, with strict searching from left to right
instead of right to left by default. The _first_ element will be bound
to (dyn *syspath*), not the last.
Potentially breaking change for complicated, custom setups
Flag collisions was causing some unexpected behavior in some situations.
Removing the source of collisions resolve odd cancelation behavior in
the ev/ module where multiple calls to ev/cancel on the same fiber would
mess with the internal fiber flags and cause bad behavior and the wrong
error message return (but still otherwise behave correctly, so unless
you were parsing the returned error messages, things likely worked).
Also leave comments and test to avoid regressions.
Rather than needing to create wrapper scripts for utilities, `janet -t
mylib <args...>` can be a simple, if somewhat awkward, alternative for
portable command line tooling. Also use spork/fmt on boot.janet.
Passing in the wrong number of keyword arguments could be problematic
and cause compialtion issues. Handle that more gracefully and at least
be clean in valgrind.
This also improves the error behavior of malformed automatic parameters
so that the error conditions are better defined. Previously, large
indices like 88888888888888 would actually simply be converted to
symbols and fail later. This change puts strict limitations on this
conversion process - If a symbol is of the form "$<str>" and
(scan-number str) returns non-nil, the result must be a valid index. In
this way, symbols like `$1.1` will result in an immediate macro expansion error
rather than (usually) and unknown binding error.