DEV Community 👩‍💻👨‍💻

Cover image for Pruning your Hyperlambda tree
Thomas Hansen
Thomas Hansen

Posted on

Pruning your Hyperlambda tree

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
Enter fullscreen mode Exit fullscreen mode

Executing the above in your Evaluator results in the following.

.destination
   foo:bar
add:x:@.destination
Enter fullscreen mode Exit fullscreen mode

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/*
Enter fullscreen mode Exit fullscreen mode

If you execute the above Hyperlambda in the evaluator, its result will resemble the following.

Adding nodes from one node collection to another

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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.

Creating 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".

New file dialog in Hyper IDE

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:-/*
Enter fullscreen mode Exit fullscreen mode

Below is a screenshot of how it should look like as you save your file.

Saving a file in Hyper IDE

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.

Invoking your HTTP endpoint

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:..
Enter fullscreen mode Exit fullscreen mode

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
        },
Enter fullscreen mode Exit fullscreen mode

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

The space time continuum of showing your tongue

Top comments (2)

Collapse
jeremyf profile image
Jeremy Friesen

I am reading the syntax of these Hyperlamba structures and can't help but see Lisp. I'm wondering a bit about the parser.

Collapse
polterguy profile image
Thomas Hansen Author

Hyperlambda is heavily influenced and inspired by Lisp, but it is not Lisp for the record. But, I'll take that as a compliment :)

🌚 Friends don't let friends browse without dark mode.

Sorry, it's true.