src.elv.sh@v0.21.0-dev.0.20240515223629-06979efb9a2a/pkg/eval/builtin_fn_flow.d.elv (about)

     1  # Run several callables in parallel, and wait for all of them to finish.
     2  #
     3  # If one or more callables throw exceptions, the other callables continue running,
     4  # and a composite exception is thrown when all callables finish execution.
     5  #
     6  # The behavior of `run-parallel` is consistent with the behavior of pipelines,
     7  # except that it does not perform any redirections.
     8  #
     9  # Here is an example that lets you pipe the stdout and stderr of a command to two
    10  # different commands in order to independently capture the output of each byte stream:
    11  #
    12  # ```elvish-transcript
    13  # ~> use file
    14  # ~> fn capture {|f|
    15  #      var pout = (file:pipe)
    16  #      var perr = (file:pipe)
    17  #      var out err
    18  #      run-parallel {
    19  #        $f > $pout[w] 2> $perr[w]
    20  #        file:close $pout[w]
    21  #        file:close $perr[w]
    22  #      } {
    23  #        set out = (slurp < $pout[r])
    24  #        file:close $pout[r]
    25  #      } {
    26  #        set err = (slurp < $perr[r])
    27  #        file:close $perr[r]
    28  #      }
    29  #      put $out $err
    30  #    }
    31  # ~> capture { echo stdout-test; echo stderr-test >&2 }
    32  # ▶ "stdout-test\n"
    33  # ▶ "stderr-test\n"
    34  # ```
    35  #
    36  # This command is intended for doing a fixed number of heterogeneous things in
    37  # parallel. If you need homogeneous parallel processing of possibly unbound data,
    38  # use `peach` instead.
    39  #
    40  # See also [`peach`]().
    41  fn run-parallel {|@callable| }
    42  
    43  # Calls `$f` on each [value input](#value-inputs).
    44  #
    45  # An exception raised from [`break`]() is caught by `each`, and will cause it to
    46  # terminate early.
    47  #
    48  # An exception raised from [`continue`]() is swallowed and can be used to
    49  # terminate a single iteration early.
    50  #
    51  # Examples:
    52  #
    53  # ```elvish-transcript
    54  # ~> range 5 8 | each {|x| * $x $x }
    55  # ▶ (num 25)
    56  # ▶ (num 36)
    57  # ▶ (num 49)
    58  # ~> each {|x| put $x[..3] } [lorem ipsum]
    59  # ▶ lor
    60  # ▶ ips
    61  # ```
    62  #
    63  # See also [`peach`]().
    64  #
    65  # Etymology: Various languages, as `for each`. Happens to have the same name as
    66  # the iteration construct of
    67  # [Factor](http://docs.factorcode.org/content/word-each,sequences.html).
    68  fn each {|f inputs?| }
    69  
    70  # Calls `$f` for each [value input](#value-inputs), possibly in parallel.
    71  #
    72  # Like `each`, an exception raised from [`break`]() will cause `peach` to
    73  # terminate early. However due to the parallel nature of `peach`, the exact time
    74  # of termination is non-deterministic, and termination is not guaranteed.
    75  #
    76  # An exception raised from [`continue`]() is swallowed and can be used to
    77  # terminate a single iteration early.
    78  #
    79  # The `&num-workers` option restricts the number of functions that may run in
    80  # parallel, and must be either an exact positive or `+inf`. A value of `+inf`
    81  # (the default) means no restriction. Note that `peach &num-workers=1` is
    82  # equivalent to `each`.
    83  #
    84  # Example (your output will differ):
    85  #
    86  # ```elvish-transcript
    87  # //skip-test
    88  # ~> range 1 10 | peach {|x| + $x 10 }
    89  # ▶ (num 12)
    90  # ▶ (num 13)
    91  # ▶ (num 11)
    92  # ▶ (num 16)
    93  # ▶ (num 18)
    94  # ▶ (num 14)
    95  # ▶ (num 17)
    96  # ▶ (num 15)
    97  # ▶ (num 19)
    98  # ~> range 1 101 |
    99  #    peach {|x| if (== 50 $x) { break } else { put $x } } |
   100  #    + (all) # 1+...+49 = 1225; 1+...+100 = 5050
   101  # ▶ (num 1328)
   102  # ```
   103  #
   104  # This command is intended for homogeneous processing of possibly unbound data. If
   105  # you need to do a fixed number of heterogeneous things in parallel, use
   106  # `run-parallel`.
   107  #
   108  # See also [`each`]() and [`run-parallel`]().
   109  fn peach {|&num-workers=(num +inf) f inputs?| }
   110  
   111  # Throws an exception; `$v` may be any type. If `$v` is already an exception,
   112  # `fail` rethrows it.
   113  #
   114  # ```elvish-transcript
   115  # ~> fail bad
   116  # Exception: bad
   117  #   [tty]:1:1-8: fail bad
   118  # ~> put ?(fail bad)
   119  # ▶ [^exception &reason=[^fail-error &content=bad &type=fail] &stack-trace=<...>]
   120  # ~> fn f { fail bad }
   121  # ~> fail ?(f)
   122  # Exception: bad
   123  #   [tty]:1:8-16: fn f { fail bad }
   124  #   [tty]:1:8-8: fail ?(f)
   125  # ```
   126  fn fail {|v| }
   127  
   128  # Raises the special "return" exception. When raised inside a named function
   129  # (defined by the [`fn` keyword](language.html#fn)) it is captured by the
   130  # function and causes the function to terminate. It is not captured by an
   131  # ordinary anonymous function.
   132  #
   133  # Because `return` raises an exception it can be caught by a
   134  # [`try`](language.html#try) block. If not caught, either implicitly by a
   135  # named function or explicitly, it causes a failure like any other uncaught
   136  # exception.
   137  #
   138  # See the discussion about [flow commands and
   139  # exceptions](language.html#exception-and-flow-commands)
   140  #
   141  # **Note**: If you want to shadow the builtin `return` function with a local
   142  # wrapper, do not define it with `fn` as `fn` swallows the special exception
   143  # raised by return. Consider this example:
   144  #
   145  # ```elvish-transcript
   146  # ~> use builtin
   147  # ~> fn return { put return; builtin:return }
   148  # ~> fn test-return { put before; return; put after }
   149  # ~> test-return
   150  # ▶ before
   151  # ▶ return
   152  # ▶ after
   153  # ```
   154  #
   155  # Instead, shadow the function by directly assigning to `return~`:
   156  #
   157  # ```elvish-transcript
   158  # ~> use builtin
   159  # ~> var return~ = { put return; builtin:return }
   160  # ~> fn test-return { put before; return; put after }
   161  # ~> test-return
   162  # ▶ before
   163  # ▶ return
   164  # ```
   165  fn return { }
   166  
   167  # Raises the special "break" exception. When raised inside a loop it is
   168  # captured and causes the loop to terminate.
   169  #
   170  # Because `break` raises an exception it can be caught by a
   171  # [`try`](language.html#try) block. If not caught, either implicitly by a loop
   172  # or explicitly, it causes a failure like any other uncaught exception.
   173  #
   174  # See the discussion about [flow commands and exceptions](language.html#exception-and-flow-commands)
   175  #
   176  # **Note**: You can create a `break` function and it will shadow the builtin
   177  # command. If you do so you should explicitly invoke the builtin. For example:
   178  #
   179  # ```elvish-transcript
   180  # ~> use builtin
   181  # ~> fn break { put 'break'; builtin:break; put 'should not appear' }
   182  # ~> for x [a b c] { put $x; break; put 'unexpected' }
   183  # ▶ a
   184  # ▶ break
   185  # ```
   186  fn break { }
   187  
   188  # Raises the special "continue" exception. When raised inside a loop it is
   189  # captured and causes the loop to begin its next iteration.
   190  #
   191  # Because `continue` raises an exception it can be caught by a
   192  # [`try`](language.html#try) block. If not caught, either implicitly by a loop
   193  # or explicitly, it causes a failure like any other uncaught exception.
   194  #
   195  # See the discussion about [flow commands and exceptions](language.html#exception-and-flow-commands)
   196  #
   197  # **Note**: You can create a `continue` function and it will shadow the builtin
   198  # command. If you do so you should explicitly invoke the builtin. For example:
   199  #
   200  # ```elvish-transcript
   201  # ~> use builtin
   202  # ~> fn continue { put 'continue'; builtin:continue; put 'should not appear' }
   203  # ~> for x [a b c] { put $x; continue; put 'unexpected' }
   204  # ▶ a
   205  # ▶ continue
   206  # ▶ b
   207  # ▶ continue
   208  # ▶ c
   209  # ▶ continue
   210  # ```
   211  fn continue { }
   212  
   213  # Schedules a function to be called when execution reaches the end of the
   214  # current closure. The function is called with no arguments or options, and any
   215  # exception it throws gets propagated.
   216  #
   217  # Examples:
   218  #
   219  # ```elvish-transcript
   220  # ~> { defer { put foo }; put bar }
   221  # ▶ bar
   222  # ▶ foo
   223  # ~> defer { put foo }
   224  # Exception: defer must be called from within a closure
   225  #   [tty]:1:1-17: defer { put foo }
   226  # ```
   227  fn defer {|fn| }