Dynamic Hyperlambda slots
This tutorial covers the following parts of Magic and Hyperlambda.
- How to create reusable Hyperlambda slots or “functions”
- How to pass arguments to dynamically created Hyperlambda slots
- How to make sure your slots are re-created when your server restarts
- How to modify your dynamically created Hyperlambda slots
A dynamic Hyperlambda slot is the equivalent of what you would refer to as a “function” in another programming language, since it allows you to declare a dynamic lambda object that you can pass in arguments to, return arguments from, and treat the same way you would typically treat a function in a more traditional programming language. Consider the following code.
slots.create:foo.bar config.get:"magic:databases:default" return:x:-
The above create a “dynamic slot” for you that you can invoke using the following.
Assuming you’re using MySQL as your default database provider, the above will return the following.
A dynamic slot can contain any amount of Hyperlambda you wish, allowing you to encapsulate your logic into a single point, from where you can reuse it later as you see fit. Below is an example of a slightly more useful slot, returning all roles that exists in your installation.
slots.create:foo.bar.get-roles data.connect:[generic|magic] data.read table:roles columns name as:. return:x:@data.read/*/*
If you invoke the above slot using the following Hyperlambda …
… you will have something resembling the following returned to you.
signal .:admin .:blocked .:chat-admin .:guest .:moderator .:reset-password .:root .:translator .:unconfirmed
You can pass in arguments to your slots by adding these up as children nodes to your invocations, which will result in these arguments being available for you to reference inside of your slots. Below is an example.
slots.create:hello-world strings.concat .:"Hello " get-value:x:@.arguments/*/name return:x:- signal:hello-world name:Thomas Hansen
Molding your Hyperlambda
The following slots exists in Hyperlambda allowing you to create, signal/invoke, and administrate your dynamic slots.
- [signal] - Invokes an already existing dynamic slot slot
- [slots.create] - Creates a new dynamic slot
- [slots.delete] - Deletes an existing dynamic slot
- [slots.exists] - Returns true if the specified dynamic slot already exists
- [slots.get] - Returns the lambda object associated with a slot
- [slots.vocabulary] - Returns all dynamic slots to caller, similar to [vocabulary], except will only return dynamic slots.
All in all, the above slots allows you to administrate your existing slots any ways you see fit. As an interesting exercise try to invoke the following Hyperlambda, assuming you executed the first Hyperlambda in this tutorial.
The above of course will return the following.
slots.get:foo.bar config.get:"magic:databases:default" return:x:-
This is an extremely useful feature of Hyperlambda, since the returned lambda object is semantically returned to the caller, allowing you to modify existing slots semantically, to inject, remove, or modify any parts of the lambda object they are executing once invoked. To understand the idea, imagine the following code.
slots.create:foo.bar config.get:"magic:databases:default" return:x:- slots.get:foo.bar insert-before:x:-/0 . log.info:[foo.bar] was invoked add:x:+ get-nodes:x:@slots.get/* slots.create:foo.bar slots.get:foo.bar
The last invocation to [slots.get] returns the following.
slots.get:foo.bar log.info:[foo.bar] was invoked config.get:"magic:databases:default" return:x:-
In the above snippet we semantically retrieved a dynamic slot, for then to inject new slot invocations into it, and saving our updated slot afterwards. This allows you to look at code as a dynamic living thing, possible to modify over time according to your needs. Arguably allowing you to from within your production environment literally semantically ‘patch’ your existing code. Hence your code is no longer a “static” thing once deployed, but a living and changeable thing you can “mold” and change as you see fit. In a way this allows you to treat your Hyperlambda code the same way you treat your relational database system, by providing you with CRUD capabilities on your codebase, allowing you to change it over time, almost the same way you’d change data in your database. This is only possible because of Hyperlambda’s extreme meta data capabilities, implying it is super-structured in its format, allowing you to semantically traverse it the same way you would semantically traverse an XML document, and/or a JSON object.
One example of this feature is to combine this with cryptographic lambda invocations, to patch and administrate a multitude of servers dynamically, giving you orchestration capabilities on your servers from a single point, to administer a heterogenous environment consisting of a multitude of servers.
Persisting dynamic slots
When you create a dynamic slot, it only exists in memory. If for some reasons your web server falls down, your slot will cease to exist. To create a dynamic slot that is always re-created as your web server starts, and/or your module is installed, you’ll have to put your [slots.create] invocations into a file inside your module’s “magic.startup” folder. For instance, if your module is called “foo”, and your slot is called [foo.bar], the full name of this file would typically be “/modules/foo/magic.startup/foo.bar.hl”. All Hyperlambda files existing within your module’s “magic.startup” folder will be automatically executed as the system restarts, and/or is installed. Files within a “magic.startup” folder inside of your module’s main folder cannot be executed as endpoints, but will only be executed as the module is installed, and/or the server restarts.
Namespacing your slots
Notice, when you invoke [slots.create] any existing slots with the same name will simply be overwritten. This is intentional, since it creates a simple “polymorphistic” behaviour. However, this implies you need to carefully namespace your slots. Our advice is to use the name of your company, then the name of your application/module, for then to add something describing what your slot actually does. An example of this can be found below.
This prevents one module from accidentally interferring with objects in another module, by creating a unique namespace internally within your server, and/or also globally to some extent. This makes your code more maintainable and interoperable in the long run.
- Continue with Hyperlambda tasks and scheduled tasks