[Feature] echo to stderr?
afaik it is not a thing in amber. it would be nice if it were, since i always have problems with that in plain bash.
there is a way to do it in plain bash:
>&2 echo "error"
but i think that with amber we could just have an errcho builtin or something
or just:
error "You cannot do that!"
We have an error function in the stdlib now that exit the program.
The error function doesn't use stderr.
Maybe a global keyword that redirects the expression to stderr or stdout (or an arbitrary fd) could be used?
I'm thinking something like this:
stdout my_fun() // The default, or to "carve out" of an stderr'd function
stderr echo "hello world"
out:3 trust $zcat myfile.gz$
Alternatively, introduce an IO type? Here's what it would look like with C++ syntax:
import { stdout, stderr, pipe } from "std/io"
let my_pipe = pipe()
stdout << my_fun()
stderr << echo "hello world"
my_pipe << trust $zcat myfile.tar.gz$
// Can also be used as input
trust $tar -x$ << my_pipe
// Sugar for writing to paths
"/my/file" << echo "overwrite file"
"/my/file"+ << echo "append to file"
// Or to arbitrary file descriptors
3 << echo "write to fd 3"
This proposal could be made into its own Feature request, and would promote I/O as a first-class citizen, like in bash
The proposal for stdout/stderr/io I think is perfect and we can integrate it in the other functions that amber offers.
@Mte90 Glad to hear that! Which proposal would that be, the keyword-based one or the C++-like one? Personally I prefer the C++-like approach
I am for the second approach, in this way it is more functional programming and we can implement quickly in the stdlib.
About the keyword approach it is the case to see what @Ph0enixKM @hdwalters think about it.
I'm down for the << as it's an incorrect syntax in Bash. This means that this operator will not confuse people that much because it is not an >> operator but rather more of a pipe operator |. I also like how it's similar to assignment statement.
let a = "Hello" // Memory assignment
b << "Hello" // Redirection assignment
I'm not against introducing new Amber syntax, but I would argue that we should make it more like Bash, not less, for a couple of reasons:
- The principle of least surprise dictates that people used to Bash should be able to write intuitive Amber code.
- The proposal as stated does not support the full set of redirection options that Bash command pipelines do, notably piping the output of one command to the input of another, with the option of multiple chained commands.
I would suggest a counter-proposal, to more closely mimic Bash syntax. This also makes your proposed stdout and stderr into functions, like your proposed pipe(), and introduces a new stdin() for symmetry:
import { stdin, stdout, stderr, pipe } from "std/io"
let my_pipe = pipe()
my_fun() | stdout()
echo "hello world" | stderr()
trust $ zcat myfile.tar.gz $ | my_pipe
// Can also be used to read pipes or standard input
my_pipe | trust $ tar -x $
stdin() | $ cat $
// And for piping one command to another
$ ls $ | $ tac $ | $ more $
// Sugar for writing to and reading from paths
echo "overwrite file" | "/my/file"
echo "append to file" | "/my/file"+
"/my/file" | $ cat $
// Or to and from arbitrary file descriptors
echo "write to fd 3" | 3
3 | $ cat $
I also like the idea of using the same special symbol (here |) to denote piping to (i) files and (ii) other commands (where Bash needs separate symbols > and |). Amber can infer the context because of its type system, where Bash cannot.
@hdwalters thanks for your input!
I have a couple problems with the proposal: first of all, the "principle of least surprise" is a double-edged sword: presenting syntax that looks like bash tricks users into thinking it should work like bash. There's a good chance it won't (and in fact in your examples it doesn't), and that will lead to friction. If someone is using an ECMA-esque language to write Bash, are they more likely to come from the world of Bash or that of JS and co? What's the least surprise then? I believe we need to be able to leverage surprise to teach users that it's fundamentally not the same thing.
The second issue is that Amber has ambition when it comes to handling numbers, and that absolutely requires leaving the pipe operator for another operation: bitwise or. Reserving the pipe will tie up valuable syntax for math expressions.
Also, the << proposal does support piping commands together, even though I may not have mentioned it explicitly. Read #677 for a more detailed view of how that would work.
My main problem is not with the particular symbols used, << vs |, but with the direction of flow. If we want to connect program A's output to program B's input, we would write Bash like A | B. I think you're proposing Amber syntax B << A?
This seems the wrong way round to me, especially if we want to send A's output via B to C's input, with C << B << A. You're worried that users might have preconceptions coming from either Bash or JavaScript, but (as far as I'm aware) neither has this direction of flow concept. Perhaps A >> B >> C would make more sense?
As detailed in #677, in Amber we are dealing with functions that have two return paths: their statement value and their standard output. This means that we somehow need a way to clarify which "statement" an I/O flow is equivalent to, and in my proposal the leftmost item gets priority, meaning in an assignment it is closest to the equals sign.
Okay, fair enough. For those of us who are less familiar with Haskell syntax, and to make sure we're all on the same page, it would be helpful to enhance the proposed Amber snippets in #677, with examples showing:
- Three subcommands in a pipe chain (e.g.
ls | tac | tailin Bash). - Using script standard input as a pipe source.
- Using subcommand standard error as a pipe source (e.g.
foo 2>errors.txtin Bash). - Using text file as a pipe source (e.g.
cat <input.txtin Bash). - Using file descriptor as a pipe source (e.g.
cat <&3in Bash).
Also, can you clarify whether your proposal will support:
- Standard streams with function syntax
stdout()likepipe(), orstdoutas in your snippet? - Piping standard output and error from the same subcommand? (I do not think this would be supported, and we can probably live without it)
- Piping standard output to
tee? (I think this would automatically be supported if we wrappedteein a standard library function)
Using subcommand standard error as a pipe source (e.g.
foo 2>errors.txtin Bash).
Perhaps it would make sense to Bash users, if we used <<2 as an analog of <<, but reading stderr instead of stdout:
"/my/file" << echo "overwrite file"
"/my/err" <<2 $ grep --bad-option $
The <<2 proposal looks good, piping stdout and stderr from the same command isn't supported, and is expected to be handled with stdout being a return value and stderr an I/O flow.
+1 to wrapping tee in stdlib too