Since we've now established that Hyperlambda is a unique meta programming language, with the capacity to dynamically construct graph objects, a natural question becomes; "How do we modify these graph objects?" The answer to that question is almost as easy to understand as CRUD itself, because at Hyperlambda's core exists a handful of slots capable of modifying your execution trees. The main ones are as follows.
- [set-value] - Changes a node's value
- [set-name] - Changes a node's name
- [add] - Adds nodes to another node's children collection
- [insert-before] - Inserts nodes before some specified node
- [insert-after] - Insert nodes after some specified node
- [remove-nodes] - Removes the specified node(s)
The above list of slots allows you to orthogonally modify your tree structures anyways you see fit. Below is an example of using the [add] slot with a static source.
.destination
add:x:@.destination
.
foo:bar
Executing the above in your Evaluator results in the following.
.destination
foo:bar
add:x:@.destination
All of the above slots can also be combined. The above example for instance adds a list of statically declared nodes into the [.destination] node. Sometimes you want to add nodes from one node-set to another, at which point you can combine the [add] node with the [get-nodes] slot, such as illustrated below.
.src
foo1:bar1
foo2:bar2
foo3:bar3
.destination
add:x:@.destination
get-nodes:x:@.src/*
If you execute the above Hyperlambda in the evaluator, its result will resemble the following.
Such simple trickery as illustrated above, allows you to have complete control over the way you create and modify your lambda objects. The [set-name] and [set-value] slots works in a similar fashion, either taking a statically declared value, or some other nested slot retrieving the source. Below is an example.
.dest1
.dest2
.src1:foo
set-value:x:@.dest1
.:value
set-name:x:@.dest2
get-value:x:@.src1
After executing the above in your Magic Evaluator component, you'll be given the following result.
.dest1:value
foo
.src1:foo
set-value:x:@.dest1
.:value
set-name:x:@.dest2
get-value:foo
Lambda transformations
As you've probably realised by now, executing a lambda object typically transforms that lambda object into something else. Hence, the same lambda object cannot be executed twice and expecting the same result. Magic of course automatically takes care of this for you, by giving you a "fresh copy" of your original Hyperlambda file as you invoke it, for then to discard the lambda object after execution. However, this has huge advantages when it comes to dynamically generating code.
This is what allows you to start out with something, and end up with something else, a requirement for dynamically generating code of course. Hence, everything is literally about "transformations" at Magic's core.
Fundamentally, this model of thinking about code is actually much easier to understand for the human mind, since it's much closer to the way any computer process works, in that it takes input, acts upon the input, and produces a result. So even though your brain probably has suffered severe damage du to too much OOP, this is a much more natural process of thinking about computing for most.
Database fun
Assuming you've already installed the Chinook database, let's create a new file in Hyper IDE, and name our file "foo.get.hl" and put that file into our "chinook" folder. Below is a screenshot of how to create a new file in Hyper IDE.
Make sure you have selected your "chinook" folder before you click the "New file" button. This will bring up a modal dialog resembling the following. Make sure you name your file "foo.get.hl".
This will create a new HTTP GET endpoint for you, where you can put any Hyperlambda you wish. Copy and paste the following Hyperlambda into the file, and click the "Active file/Save" action menu button afterwards.
sqlite.connect:chinook
sqlite.select:@"select ar.Name, count(*) as count
from Album al, Artist ar where al.ArtistId = ar.ArtistId
group by al.ArtistId
order by count desc
limit 5"
return:x:-/*
Below is a screenshot of how it should look like as you save your file.
Notice, you can also use the keyboard shortcut ALT+S on Windows or OPTION+S on Mac to save your active files faster.
If you click the action menu called "Active file/Invoke..." you can now immediately invoke your HTTP endpoint. This should look like the following.
Notice how the [return] keyword simply returns a list of nodes. You could replace the code with the code below, which would give you a "weird result".
sqlite.connect:chinook
sqlite.select:@"select ar.Name, count(*) as count
from Album al, Artist ar where al.ArtistId = ar.ArtistId
group by al.ArtistId
order by count desc
limit 5"
return-nodes:x:..
The above of course returns your entire lambda object as JSON back to your client, which is only possible because fundamentally in Magic there is no difference between code and data. Below is parts of the result invoking the above would result in.
[
{
"sqlite.connect": {
"sqlite.select": [
{
"Name": "Iron Maiden",
"count": 21
},
The Hyperlambda space time continuum
In a way, this is the computing equivalent of the space time continuum, where there is no difference between space and time, the same way Hyperlambda doesn't discriminate between code and data.
In Hyperlambda code IS data and vice versa
Initially this is super weird if you've created software in a traditional programming language, but after a while it becomes easily understood, and frees your mind in ways difficult to understand initially. And most importantly of course ...
It allows the machine to create the code
Top comments (2)
Hyperlambda is heavily influenced and inspired by Lisp, but it is not Lisp for the record. But, I'll take that as a compliment :)