github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/docs/parser/lambda.md (about)

     1  # `[{ Lambda }]`
     2  
     3  > Iterate through structured data
     4  
     5  ## Description
     6  
     7  Lambdas, in Murex, are a concise way of performing various actions against
     8  structured data. They're a convenience tool to range over arrays and objects,
     9  similar to `foreach` and `formap`.
    10  
    11  ### Etiquette
    12  
    13  The intention of lambdas isn't to be used liberally within shell scripts but
    14  rather than allow for more efficient one liners when performing quick, often
    15  one-off, tasks in the interactive terminal. The terse syntax for lambdas
    16  combined with it's adaptive functionality allow for flexibility when using,
    17  albeit at the potential cost of readability.
    18  
    19  For shell scripts where error handling, readability, and maintainability are a
    20  concern, more conventional iteration blocks like `foreach` and `formap` are
    21  recommended.
    22  
    23  The reason lambda variables (known as **meta values** are single characters
    24  also falls in line with this vision: they're terse to make one-liners
    25  convenient and to discourage shell script usage.
    26  
    27  ### Technical
    28  
    29  Code running inside a lambda inherit a special variable, named **meta values**,
    30  which hold the state for each iteration (see section below).
    31  
    32  Lambdas will adapt its return value depending on the nature of the code it's
    33  executing.
    34  
    35  #### Filter
    36  
    37  If your code returns a boolean data type, eg `[{$.v =~ "foobar"}]`, then the
    38  lambda will filter that list or map, only returning values that match `true`,
    39  discarding the others.
    40  
    41  #### Update
    42  
    43  If the **meta value** `v` (value) is updated then the lambda output reflects
    44  that change.
    45  
    46  The **meta value** `k` (key) works similarly for maps / objects too. However
    47  updating it in arrays and lists currently does nothing.
    48  
    49  This cannot be used in combination with **output**.
    50  
    51  #### Output
    52  
    53  If STDOUT isn't empty, then STDOUT is outputted rather than the object being
    54  filtered and/or updated.
    55  
    56  This usage most closely resembles `foreach` and `formap` except that the data
    57  type of STDOUT is not preserved.
    58  
    59  
    60  
    61  ## Examples
    62  
    63  #### Filter
    64  
    65  Filtering a map:
    66  
    67  ```
    68  » %{hello: world, foo: bar} -> [{$.v == "world"}]
    69  {
    70      "hello": "world"
    71  }
    72  ```
    73  
    74  Filtering an array:
    75  
    76  In this example we return the days of the week excluding todays day (in this
    77  example, today is Friday)
    78  
    79  ```
    80  » %[Monday..Sunday] -> [{$.v != datetime(--in {now} --out {py}%A)}]
    81  [
    82      "Monday",
    83      "Tuesday",
    84      "Wednesday",
    85      "Thursday",
    86      "Saturday",
    87      "Sunday"
    88  ]
    89  ```
    90  
    91  #### Update
    92  
    93  Updating a map:
    94  
    95  ```
    96  » %{hello: world, foo: bar} -> [{$.v == "world" -> if {$.v = "Earth"}}]
    97  {
    98      "foo": "bar",
    99      "hello": "Earth"
   100  }
   101  ```
   102  
   103  Updating an array:
   104  
   105  ```
   106  » %[monday..friday] -> [{$.v | tr [:lower:] [:upper:] | set $.v}]
   107  [
   108      "MONDAY",
   109      "TUESDAY",
   110      "WEDNESDAY",
   111      "THURSDAY",
   112      "FRIDAY"
   113  ]
   114  ```
   115  
   116  #### Output
   117  
   118  Output from a map:
   119  
   120  ```
   121  » %{hello: world, foo: bar} -> [{$.v == "world" && out "Key '$.k' contains '$.v'"}]
   122  Key 'hello' contains 'world'
   123  ```
   124  
   125  Output from an array:
   126  
   127  ```
   128  » %[Monday..Sunday] -> [{ $.v =~ "^S" && out "$.v is the weekend"}]
   129  Saturday is the weekend
   130  Sunday is the weekend
   131  ```
   132  
   133  #### Foreach
   134  
   135  Here we are using a lambda just as a terser way of writing a standard `foreach`
   136  loop:
   137  
   138  ```
   139  » %[Monday..Sunday] -> [{$.v =~ "^S" && $count+=1}]; echo "$count days being with an 'S'"
   140  Error in `expr` (0,22): [json marshaller] no data returned
   141  2 days being with an 'S'
   142  ```
   143  
   144  However this is a contrived example. The more idiomatic way to write the above
   145  would be (and notice it doesn't produce any empty array error too):
   146  
   147  ```
   148  » %[Monday..Sunday] -> foreach day { $day =~ "^S" && $count+=1}; echo "$count days being with an 'S'"
   149  2 days being with an 'S'
   150  ```
   151  
   152  ...or even just using `regexp`, since the check is just a simple regexp match:
   153  
   154  ```
   155  » %[Monday..Sunday] -> regexp m/^S/ -> count
   156  2
   157  ```
   158  
   159  ## Detail
   160  
   161  ### Meta values
   162  
   163  Meta values are a JSON object stored as the variable `$.`. The meta variable
   164  will get overwritten by any other block which invokes meta values. So if you
   165  wish to persist meta values across blocks you will need to reassign `$.`, eg
   166  
   167  ```
   168  %[1..3] -> foreach {
   169      meta_parent = $.
   170      %[7..9] -> foreach {
   171          out "$(meta_parent.i): $.i"
   172      }
   173  }
   174  ```
   175  
   176  The following meta values are defined:
   177  
   178  * `i`: iteration number (counts from one)
   179  * `k`: key name (for arrays / lists this will count from zero)
   180  * `v`: item value of map / object or array / list
   181  
   182  ## See Also
   183  
   184  * [`%[]` Create Array](../parser/create-array.md):
   185    Quickly generate arrays
   186  * [`%{}` Create Map](../parser/create-object.md):
   187    Quickly generate objects and maps
   188  * [`alter`](../commands/alter.md):
   189    Change a value within a structured data-type and pass that change along the pipeline without altering the original source input
   190  * [`datetime`](../commands/datetime.md):
   191    A date and/or time conversion tool (like `printf` but for date and time values)
   192  * [`foreach`](../commands/foreach.md):
   193    Iterate through an array
   194  * [`formap`](../commands/formap.md):
   195    Iterate through a map or other collection of data
   196  * [`regexp`](../commands/regexp.md):
   197    Regexp tools for arrays / lists of strings
   198  * [`while`](../commands/while.md):
   199    Loop until condition false
   200  
   201  <hr/>
   202  
   203  This document was generated from [gen/parser/lambda_doc.yaml](https://github.com/lmorg/murex/blob/master/gen/parser/lambda_doc.yaml).