Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Say out of date instead of trying to update


Clarify semicolon usage;

Show more examples of using the defined action in a rule
Info
titleTODO
Warning

This example is out of date (KRL no longer handles web page sources), but the principles are the same.

One of the keys to making use of an external API inside KRL is being able to define actions. As we've seen, using data from the API is a powerful way to harness the abilities of APIs inside a ruleset. What's more, actions like send_directive() and http:post() give us the ability to respond to those APIs for a true dialog.

The expression language documentation describes how functions are defined. Functions are great when you want to abstract the computation of a value, but they don't work for abstracting the computation of an action. KRL provides a parallel construction for defining actions called defaction.

Just as the function primitive in KRL defined an anonymous function that can be applied as part of an expression for creating a value, the defaction primitive defines an anonymous action that can be applied in an action context to take a user-defined action. Here's a simple example:

Code Block
languagejavascript
themeConfluence
languagejavascript
global {
  send_warning = defaction(msg) {
    notify("Warning!", msg)
      with sticky = true
  }
}

...

Later, the rule could use this action like so:

Code Block
languagejavascript
themeConfluencelanguagejavascript
if error_level > 12 && error_level < 15 then
  send_warning("Abnormal error levels")

...

As an example, suppose that in the previous example we want the send_warning() action to be sticky by default, but allow the developer to make it transitory when needed. We could add a parameter like so:

Code Block
languagejavascript
themeConfluencelanguagejavascript
global {
  send_warning = defaction(msg, transitory) {
    notify("Warning!", msg)
      with sticky = not transitory
  }
}

But this requires that the developer always supply the argument indicating whether to make the warning sticky or transitory. A better option is to use a configuration variable like so:

Code Block
languagejavascript
themeConfluence
languagejavascript
global {
  send_warning = defaction(msg) {
    configure using transitory = false
    notify("Warning!", msg)
      with sticky = not transitory
  }
}

The configure clause defines a variable and its default value. The value can be any KRL expression. Multiple name-value pairs can be given separated using the keyword and (the same syntax as optional action parameters):

Code Block
languagejavascript
themeConfluencelanguagejavascript
global {
  send_warning = defaction(msg) {
    configure using transitory = false
                and title = "Warning!"
    notify(title, msg)
      with sticky = not transitory
  }
}

When this action is applied the notification will be sticky by default and use the title "Warning" as before. However, the developer can call it with the optional parameter transitory to change that default behavior:

Code Block
languagejavascript
themeConfluence
languagejavascript
if error_level > 12 && error_level < 15 then
  send_warning("Abnormal error levels")
    with transitory = true

A defined action, like a function, can have declarations before the action to compute intermediate values:

Code Block
language
languagejavascript
themeConfluencejavascript
global {
  send_warning = defaction(msg) {
    configure using transitory = false
                and error_code = 0
    title = error_code < 5  => "Warning!"  |
            error_code < 10 => "Error!"    |
            error_code < 15 => "Critical!" |
                               "Danger!"
    notify(title, msg)
      with sticky = not transitory
  }
}

...

A defined action can use more than one action; compound actions can be used in a defined action as well. For example the following user defined action will place the notification box and append a warning banner to the <div/> element named warning_box on the page:

Code Block
languagejavascript
themeConfluencelanguagejavascript
global {
  send_warning = defaction(msg) {
    configure using transitory = false
                and error_code = 0
    title = error_code < 5  => "Warning!"  |
            error_code < 10 => "Error!"    |
            error_code < 15 => "Critical!" |
                               "Danger!"
    every {
      notify(title, msg)
        with sticky = not transitory;
      append("#warning_box", "A #{title} alert is active")
    }
  }
}

...