oils-for-unix / oils

Oils is our upgrade path from bash to a better language and runtime. It's also for Python and JavaScript users who avoid shell!
http://www.oilshell.org/
Other
2.85k stars 157 forks source link

Interpolation of function calls #1457

Closed tfga closed 1 year ago

tfga commented 1 year ago

This works:

oil$ echo $join(%(a b c))
abc

Shouldn't this work too? 🤔

oil$ echo "$join(%(a b c))"
  echo "$join(%(a b c))"
  ^~~~
[ interactive ]:106: fatal: Expected string-like value (Bool, Int, Str), but got <type 'function'>

Instead, what I have to do is:

oil$ echo "$[join(%(a b c))]"
abc
andychu commented 1 year ago

Thanks for trying it! Great feedback

This is actually a known "wart", documented here:

https://www.oilshell.org/release/0.13.1/doc/warts.html#function-sub-isnt-allowed-in-double-quoted-strings

My plan is to simply remove "function sub", which is only a shortcut for expression sub. So the way to do it after that change will be

echo $[join(%(a b c))]
echo "$[join(%(a b c))]"

It will simplify the language -- there are too many kinds of substitutions now.

https://www.oilshell.org/release/latest/doc/oil-language-tour.html

At the time, thought the function sub was "pretty" -- it avoided the []. But now when I look back, it's too clever.

And it causes inconsistency with double quoted strings.

In a double quoted string, "$join()" already means something -- the variable $join, and then literal ()! We try not to break existing syntax, except in very rare cases


Let me know what you think!

I might prioritize this for the next release, now that you mentioned it ...

tfga commented 1 year ago

Hi, @andychu! 👋
Thank you for your reply.

This is actually a known "wart", documented here:

Oops... Sorry about that. 😬

My plan is to simply remove "function sub"

Really?
As a user, I was really hoping that you went in the opposite direction. 😔
IMHO, Function Subs make the syntax cleaner and more intuitive.

Not only would I keep Function Subs (and make them work inside strings): I would unify the Expression and Variable subs.

Think about it: a variable is an expression. Why not use the same syntax for both (which, BTW, is the same syntax used in JS)?

${a}
${1 + 2 * 3}

We try not to break existing syntax, except in very rare cases

Yeah... I see your point.

What if... you only did it in oil?
osh could continue with the old behaviour.

andychu commented 1 year ago

Yes great point, this has occurred to me -- variables are expressions. So right now, $[a] and ${a} are redundant.

My hope was that $[a] can be used for some kind of escaped string interpolation. But here I had different idea, using a suffix like C++ to express some kind of JavaScript-like template literal, where $a or $[a] or ${a} is escaped.

echo "foo $var"
echo "foo $var"html

https://lobste.rs/s/9ttq0x/matchertext_escape_route_from_language#c_tlubcl


The general principle is not to break existing syntax, and instead add new syntax. (even taking into account OSH vs. Oil, because it's a GRADUAL transition)

https://github.com/oilshell/oil/wiki/Language-Design-Principles

So everything within $[] is basically new. I'm hesitant to break anything in ${}.

Example: ${a-1} and ${a+1} already mean something in shell! They mean test if a is empty or not.


So not sure yet what we should do ... I believe the consistent $[] rule is much easier to explain. I think $join() is prettier than $[join()] but harder to explain -- other people have had problems with it.

Definitely feel free to join https://oilshell.zulipchat.com if you want to brain storm ...

The main issues are constraints around breaking things ... A few years ago, I was much more aggressive about that, and then it caused problems. One main problem is that you don't want to have to check the top of the file every time to see what language you're writing in. It should be obvious without extra context the reader has to keep track of.

e.g. from ${a-1} you can't tell what language it is, but from $[a-1] you can.

andychu commented 1 year ago

There is also a fair bit of implementation complexity:

tfga commented 1 year ago

Wow. You clearly have thought a lot about this. 😲

Yes, backwards compatibility brings about all kinds of crazy constraints. It must be hard for you to keep them all in your head at once. 

Not only that: they hurt the language design, complicate the mental model, and make the whole thing puzzling and mysterious for the newcomer. 

But this is the path you've chosen. I'm not here to judge. 🙏🏻

Once again, thank you for the nice and thoughtful replies. And thank you for the project. Great stuff! ♥️

andychu commented 1 year ago

I removed the $join(x) in favor of $[join(x)] in a recent release - https://www.oilshell.org/blog/2023/06/release-0.16.0.html#headless-shell-screenshots

Sorry it's longer, but at least it's consistent between unquoted and quoted now!