[Feature] Functional operator for input/output redirection
- 主要言語
- Rust
- スター
- 5.2k
- フォーク
- 145
- 平均マージ
- 5日 3時間
- マージ済み PR(30日)
- 7
説明
This proposal aims to introduce an `IO` type for handling `stdin`, `stderr` and `stdout` as a first-class citizen in Amber, and an accompanying infix operator, `<<` which guides I/O flow from inputs to outputs, inspired by C++ syntax.
Below is an example of what that syntax would look like in action:
```js
import { stdin, 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
trust $cat$ << stdin
// Or chained together, in which case the resulting statement is the return value of the leftmost
// statement, unless it is a 'sink' (a file path, fd number, or the stdout/stderr/stdin builtins)
stderr << rainbow() << trust $cowsay$ << my_fun() << "./my_file.txt"
// ^~~~~~~~~ meaning this one!
// 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"
// Redirecting a command's standard error
"log.txt" <<2 trust $something$
let my_output = "log.txt" <<2 trust $or_other$
// Splitting stderr and stdout is expected to be handled implicitly, as a command's return value
// in Amber is its standard output.
```
And this is how it would interact with other types, using Haskell type syntax:
```haskell
-- Implicit cast: here, Cmd is the type of a bash escape expression (`$echo "this syntax"$`)
Cmd -> IO Text
-- Implicit cast: If not handled, the IO type is dropped (existing use, such as `let a = $echo b$`)
Any t => IO t -> t
-- Type interactions for the proposed `<<` I/O chain keyword:
-- Here, the left-hand operator is an IO sink (i.e. builtins `stdout` or `stderr`),
-- so we drop IO to forbid re-chaining.
(<<): Any t => (IO Null -> IO t) -> t
-- The explicit concept of an IO sink as a type may be dropped seeing as functions may bear
-- the `IO Null` type signature. Using Text and Number as below for builtins like
-- `stdout` or `stderr` would be enough. Maybe pipes would be their own type, or just the
-- path to a FIFO file under the hood.
-- Here, the left-hand operator's expression wins out if not a sink, such as chaining functions or commands together
(<<): Any t, Any u => (IO t -> IO u) -> IO t
-- This syntax allows writing into a file path:
(<<): Any t => (Text -> IO t) -> t
-- ... and reading from it:
(<<): Any t => (IO t -> Text) -> IO t
-- Same, for file descriptors:
(<<): Any t => (Number -> IO t) -> t
(<<): Any t => (IO t -> Number) -> IO t
```
Right now this type system makes no distinction between a source and a sink, merely preventing a sink (`IO Null`) from being placed in the middle of an I/O chain.
Whether `IO` should be specified explicitly in function return types, or be implied for all functions is undecided.
_Originally posted in [#235](https://github.com/amber-lang/amber/issues/235#issuecomment-2647442887)_
コントリビューションガイド
このリポジトリのコントリビューションガイドは索引されていません
評価
この issue はまだ評価されていません。