Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add map and array support #1

Open
kirsle opened this issue Feb 1, 2015 · 0 comments
Open

Add map and array support #1

kirsle opened this issue Feb 1, 2015 · 0 comments

Comments

@kirsle
Copy link
Member

kirsle commented Feb 1, 2015

Add support for hash maps and arrays in RiveScript.

Maps

Maps would be global variables (like bot variables). Their purpose is to hold simple key/value style data to simplify the reply structure for holding knowledge (examples would be: capitals of the states, etc.)

Syntax example:

// Define a map name and add key/value pairs one at a time
! map capitals CA = Sacramento
! map capitals MI = Lansing

// Define a map, provide the mappings immediately
! map capitals =
^ CA = Sacramento
^ MI = Lansing

// This would also have worked, but isn't as readable and won't be
// the preferred syntax:
! map capitals = CA = Sacramento
^ MI = Lansing

// If you "re-define" a map using the above syntax (provide the mappings
// immediately) on a map that already exists, your new key/value pairs
// will be merged with the existing ones. So you can add key/value pairs
// in bulk multiple times throughout your code with no problems. Map keys
// are always unique, though, so if you use the same key twice the value
// will be overwritten.

// Example of maps in use:
+ what is the capital of _
* <exists capitals <uppercase>> == true => The capital of <uppercase> is:\s
  ^ <map capitals <uppercase>>.
- I don't know what the capital of <uppercase> is.

New tags added to support maps:

  • <exists MAP_NAME KEY_NAME> - returns "true" if KEY_NAME exists in MAP_NAME
  • <map MAP_NAME> - returns the full contents of the map, in JSON format (mostly useful for debugging)
  • <map MAP_NAME KEY_NAME> - get the value of that key, or undefined if it doesn't exist
  • <map MAP_NAME KEY_NAME=VALUE> - dynamically reassign the value of a key in the map (the key doesn't need to exist in advance).

User Maps?

Some syntax ideas to support maps as user variables.

+ i have a (@colors) *
- <set %colors:<star1>=<star2>>Okay.

+ do you know about my *
* <get %colors:<star>> != undefined => Yes, your\s
  ^ <star> was colored <get %colors:<star>> right?
- You didn't tell me what color it is.

Human> I have a blue car
Bot> Okay.
Human> Do you know about my car?
Bot> Yes, your car was colored blue right?

The existing <get> and <set> tags would be repurposed for map variables. A map variable always has its name prefixed with a % symbol (like in Perl). To refer to a specific key, use a colon symbol ":".

  • <get %name> - would dump the map as JSON, for debugging
  • <get %name:key> - get the named key from the map, or "undefined"
  • <set %name:key=value> - set a key
  • <set %name:key=undefined> - delete a key by setting it to undefined (consistent with all other variable-setting tags). Maybe add a <delete> tag instead that works on all variable types (user vars, anyway)?

Sets

Sets would be arrays for user variables, for holding a list of things in one variable.

Syntax examples:

+ i like the color *
- <add @color=<star>>I'll remember that you like <star>.

+ what colors do i like
- You like: <get @color>.
// would output e.g.: "You like: red, green, blue."

Existing variable-setting tags would be re-used, but array names are prefixed with an @ symbol.

Sets would work like the data type of the same name in Python: its contents would be de-duplicated. If you add the same item to the set twice, it only ends up going in one time.

Tags:

  • <get @name> - returns a comma separated list of values
  • <get @name:length> - get the number of elements in the set
  • <get @name[0]> - get an item from the list by index
  • <add @name=value> - add a value to the set
  • <delete @name=value> - remove a value from the set

Iteration?

Some ideas to support iterating over set elements without making the syntax too ugly?

+ what are my favorite colors
* <get @colors:length> >= 2 => They are:\s
  ^ {iter @colors[:-1]}<item>,{/iter} and <get @colors[-1]>.
* <get @colors:length> == 1 => There is only <get @colors[0]>.
- You didn't tell me any.

Human> What are my favorite colors?
(if they have 2 or more)
Bot> They are: red, blue, yellow, and green.
(if they have 1)
Bot> There is only red.
(if none)
Bot> You didn't tell me any.

Tags:

  • {iter LIST}...{/iter}
    • Creates an iterator over the list-like object, LIST. The code between the opening and closing tag will be run for each item in LIST, and the new <item> tag would hold the current item.
  • <item> - holds the current item in an iterator; only available inside an {iter}...{/iter} block.

Array index slices would work like in Python, so colors[:-1] meant "all colors except for the last one", example:

>>> colors = ["red", "blue", "yellow", "green"]
>>> colors[:-1]
['red', 'blue', 'yellow']
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant