Amber icon indicating copy to clipboard operation
Amber copied to clipboard

[Feature] echo to stderr?

Open b1ek opened this issue 1 year ago • 15 comments

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

b1ek avatar Jun 22 '24 04:06 b1ek

or just:

error "You cannot do that!"

Ph0enixKM avatar Jun 27 '24 08:06 Ph0enixKM

We have an error function in the stdlib now that exit the program.

Mte90 avatar Jul 25 '24 15:07 Mte90

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

Thesola10 avatar Feb 10 '25 09:02 Thesola10

The proposal for stdout/stderr/io I think is perfect and we can integrate it in the other functions that amber offers.

Mte90 avatar Feb 10 '25 10:02 Mte90

@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

Thesola10 avatar Feb 10 '25 19:02 Thesola10

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.

Mte90 avatar Feb 11 '25 09:02 Mte90

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

Ph0enixKM avatar Feb 11 '25 19:02 Ph0enixKM

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:

  1. The principle of least surprise dictates that people used to Bash should be able to write intuitive Amber code.
  2. 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.

hdwalters avatar Feb 16 '25 17:02 hdwalters

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 avatar Feb 16 '25 17:02 hdwalters

@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.

Thesola10 avatar Feb 16 '25 18:02 Thesola10

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?

hdwalters avatar Feb 16 '25 20:02 hdwalters

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.

Thesola10 avatar Feb 16 '25 23:02 Thesola10

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 | tail in Bash).
  • Using script standard input as a pipe source.
  • Using subcommand standard error as a pipe source (e.g. foo 2>errors.txt in Bash).
  • Using text file as a pipe source (e.g. cat <input.txt in Bash).
  • Using file descriptor as a pipe source (e.g. cat <&3 in Bash).

Also, can you clarify whether your proposal will support:

  • Standard streams with function syntax stdout() like pipe(), or stdout as 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 wrapped tee in a standard library function)

hdwalters avatar Feb 17 '25 12:02 hdwalters

Using subcommand standard error as a pipe source (e.g. foo 2>errors.txt in 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 $

hdwalters avatar Feb 17 '25 14:02 hdwalters

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

Thesola10 avatar Feb 18 '25 20:02 Thesola10