amber-lang / amber

💎 Amber the programming language compiled to Bash
https://amber-lang.com
GNU General Public License v3.0
3.8k stars 81 forks source link

[Feature] syntactic sugar for piping streams #295

Open Sod-Almighty opened 2 months ago

Sod-Almighty commented 2 months ago

Presumably it is currently possible to pipe inside a $ command?

echo $ ls | wc $

But it would be useful to establish some kind of native syntax for piping that would work even if the commands were wrapped in functions. Something like this:

pub fun list(path): Pipe {
  yield from $ ls -l {path} $
  ...do other stuff...
}
pub fun count_words(input: Pipe) {
  feed input to $ wc $
}

list(".") => pipe1
pipe1 => count_words
list(".") => count_words

That general idea anyway. It'd need to support asynchronous commands, both self-forking and non-self-forking. Or possibly some kind of "composition":

cmd = compose list(".") => count_words
run cmd
Ph0enixKM commented 2 months ago

This is great. I'm giving it a stable release milestone for now. We need to focus on other things for now.

KrosFire commented 2 months ago

This syntactic sugar doesn't seem very sweet to me. I would much rather see some amber pipe keyword (this keyword could be | or pipe), with combination of "command strings".

Currently, the only way to combine/pipe some predefined commands is to do something like this:

let cat_cmd = "cat file.txt"
let grep_cmd = "grep \"READY\""

unsafe ${cat_cmd} | {grep_cmd}$

This doesn't feel quiet right to give ground to bash in this way. We need to be able to pipe commands in amber itself and make it more powerful. In order to do this, we need to know, that all the expressions on the left and right of amber pipe evaluate to command strings.

We cannot do this:

$cat file.txt$ | $grep "READY"$

Because it would eval to something like this:

cat file.txt;
| grep "READY";

And it's ok. $$ syntax is like running a function. We just need to be able to handle function bodies to compose them. We can create command strings using "`" or even current "$", with additional run keyword for running a cammand. Thanks to this, we will be able to create code like this:

fun test_cat_cmd(file: Text): CmdText {
  $echo "NOT READY" > {file}$

  return `cat {file}`
}

fun grep_cmd(text: Text) {
  return `grep "{text}"`
}

test_cat_cmd("myFile") | grep_cmd("READY")