Source File
builtin_fn_flow.go
Belonging Package
src.elv.sh/pkg/eval
package evalimport ()// Flow control.// TODO(xiaq): Document "multi-error".func () {addBuiltinFns(map[string]interface{}{"run-parallel": runParallel,// Exception and control"fail": fail,"multi-error": multiErrorFn,"return": returnFn,"break": breakFn,"continue": continueFn,// Iterations."each": each,"peach": peach,})}//elvdoc:fn run-parallel//// ```elvish// run-parallel $callable ...// ```//// Run several callables in parallel, and wait for all of them to finish.//// If one or more callables throw exceptions, the other callables continue running,// and a composite exception is thrown when all callables finish execution.//// The behavior of `run-parallel` is consistent with the behavior of pipelines,// except that it does not perform any redirections.//// Here is an example that lets you pipe the stdout and stderr of a command to two// different commands://// ```elvish// pout = (pipe)// perr = (pipe)// run-parallel {// foo > $pout 2> $perr// pwclose $pout// pwclose $perr// } {// bar < $pout// prclose $pout// } {// bar2 < $perr// prclose $perr// }// ```//// This command is intended for doing a fixed number of heterogeneous things in// parallel. If you need homogeneous parallel processing of possibly unbound data,// use `peach` instead.//// @cf peachfunc ( *Frame, ...Callable) error {var sync.WaitGroup.Add(len()):= make([]Exception, len())for , := range {go func( *Frame, Callable, *Exception) {:= .Call(, NoArgs, NoOpts)if != nil {* = .(Exception)}.Done()}(.fork("[run-parallel function]"), , &[])}.Wait()return MakePipelineError()}//elvdoc:fn each//// ```elvish// each $f $input-list?// ```//// Call `$f` on all inputs. Examples://// ```elvish-transcript// ~> range 5 8 | each [x]{ ^ $x 2 }// ▶ 25// ▶ 36// ▶ 49// ~> each [x]{ put $x[:3] } [lorem ipsum]// ▶ lor// ▶ ips// ```//// @cf peach//// Etymology: Various languages, as `for each`. Happens to have the same name as// the iteration construct of// [Factor](http://docs.factorcode.org/content/word-each,sequences.html).func ( *Frame, Callable, Inputs) error {:= falsevar error(func( interface{}) {if {return}:= .fork("closure of each"):= .Call(, []interface{}{}, NoOpts).Close()if != nil {switch Reason() {case nil, Continue:// nopcase Break:= truedefault:= true=}}})return}//elvdoc:fn peach//// ```elvish// peach $f $input-list?// ```//// Call `$f` on all inputs, possibly in parallel.//// Example (your output will differ)://// ```elvish-transcript// ~> range 1 7 | peach [x]{ + $x 10 }// ▶ 12// ▶ 11// ▶ 13// ▶ 16// ▶ 15// ▶ 14// ```//// This command is intended for homogeneous processing of possibly unbound data. If// you need to do a fixed number of heterogeneous things in parallel, use// `run-parallel`.//// @cf each run-parallelfunc ( *Frame, Callable, Inputs) error {var sync.WaitGroup:= falsevar error(func( interface{}) {if || != nil {return}.Add(1)go func() {:= .fork("closure of peach").ports[0] = DummyInputPort:= .Call(, []interface{}{}, NoOpts).Close()if != nil {switch Reason() {case nil, Continue:// nopcase Break:= truedefault:= true= diag.Errors(, )}}.Done()}()}).Wait()return}// FailError is an error returned by the "fail" command.type FailError struct{ Content interface{} }// Error returns the string representation of the cause.func ( FailError) () string { return vals.ToString(.Content) }// Fields returns a structmap for accessing fields from Elvish.func ( FailError) () vals.StructMap { return failFields{} }type failFields struct{ e FailError }func (failFields) () {}func ( failFields) () string { return "fail" }func ( failFields) () interface{} { return .e.Content }//elvdoc:fn fail//// ```elvish// fail $v// ```//// Throws an exception; `$v` may be any type. If `$v` is already an exception,// `fail` rethrows it.//// ```elvish-transcript// ~> fail bad// Exception: bad// [tty 9], line 1: fail bad// ~> put ?(fail bad)// ▶ ?(fail bad)// ~> fn f { fail bad }// ~> fail ?(f)// Exception: bad// Traceback:// [tty 7], line 1:// fn f { fail bad }// [tty 8], line 1:// fail ?(f)// ```func ( interface{}) error {if , := .(error); {// MAYBE TODO: if v is an exception, attach a "rethrown" stack trace,// like Javareturn}return FailError{}}func ( ...Exception) error {return PipelineError{}}//elvdoc:fn return//// Raises the special "return" exception. When raised inside a named function// (defined by the [`fn` keyword](../language.html#function-definition-fn)) it// is captured by the function and causes the function to terminate. It is not// captured by an anonymous function (aka [lambda](../language.html#lambda)).//// Because `return` raises an exception it can be caught by a// [`try`](language.html#exception-control-try) block. If not caught, either// implicitly by a named function or explicitly, it causes a failure like any// other uncaught exception.//// See the discussion about [flow commands and// exceptions](language.html#exception-and-flow-commands)//// **Note**: If you want to shadow the builtin `return` function with a local// wrapper, do not define it with `fn` as `fn` swallows the special exception// raised by return. Consider this example://// ```elvish-transcript// ~> use builtin// ~> fn return { put return; builtin:return }// ~> fn test-return { put before; return; put after }// ~> test-return// ▶ before// ▶ return// ▶ after// ```//// Instead, shadow the function by directly assigning to `return~`://// ```elvish-transcript// ~> use builtin// ~> var return~ = { put return; builtin:return }// ~> fn test-return { put before; return; put after }// ~> test-return// ▶ before// ▶ return// ```func () error {return Return}//elvdoc:fn break//// Raises the special "break" exception. When raised inside a loop it is// captured and causes the loop to terminate.//// Because `break` raises an exception it can be caught by a// [`try`](language.html#exception-control-try) block. If not caught, either// implicitly by a loop or explicitly, it causes a failure like any other// uncaught exception.//// See the discussion about [flow commands and exceptions](language.html#exception-and-flow-commands)//// **Note**: You can create a `break` function and it will shadow the builtin// command. If you do so you should explicitly invoke the builtin. For example://// ```elvish-transcript// ~> use builtin// ~> fn break []{ put 'break'; builtin:break; put 'should not appear' }// ~> for x [a b c] { put $x; break; put 'unexpected' }// ▶ a// ▶ break// ```func () error {return Break}//elvdoc:fn continue//// Raises the special "continue" exception. When raised inside a loop it is// captured and causes the loop to begin its next iteration.//// Because `continue` raises an exception it can be caught by a// [`try`](language.html#exception-control-try) block. If not caught, either// implicitly by a loop or explicitly, it causes a failure like any other// uncaught exception.//// See the discussion about [flow commands and exceptions](language.html#exception-and-flow-commands)//// **Note**: You can create a `continue` function and it will shadow the builtin// command. If you do so you should explicitly invoke the builtin. For example://// ```elvish-transcript// ~> use builtin// ~> fn continue []{ put 'continue'; builtin:continue; put 'should not appear' }// ~> for x [a b c] { put $x; continue; put 'unexpected' }// ▶ a// ▶ continue// ▶ b// ▶ continue// ▶ c// ▶ continue// ```func () error {return Continue}
The pages are generated with Golds v0.2.8-preview. (GOOS=darwin GOARCH=arm64)