The Equivalence of Code and Data

Why does PicoLisp make so much fuss about that equivalence of code and data? Answer: Because it is such a powerful abstraction instrument! It supports the "locality principle of structure, content and behavior".

Let me try to explain this using a GUI example, though the same principle also applies to most other libraries and applications. Take a simple GUI page:

   (action
      (html 0 "Increment" "lib.css" NIL
         (form NIL
            (gui '(+Var +NumField) '*Num 9)
            (gui '(+JS +Button) "+" '(inc '*Num)) ) ) )

This page shows two components, a numeric input field and a button labeled "+". You can either enter a value into that field, or increment its value with the button.

The page has a structure, namely a HTML body containing a form, which in turn contains the two components. It has content, the numeric value shown in the field. And it has behavior, as the numeric field handles string conversion and error checking, and the button increments the number.

Note that a fourth attribute of the page, the layout and style, is not discussed here. It is maintained separately in the CSS file.

The three attributes structure, content and behavior, however, cannot be separated. This may be contrary to some schools of thought, which advocate a separation of structure and content, and behavior anyway. But obviously the HTML structure also holds content like the "Increment" page title or the "+" button label. And this content might also be subject to behavior, for example the button label may change dynamically:

   (gui '(+JS +Button)
      (if *VerboseDisplay "Increment" "+")
      '(inc '*Num) )

Or the button may prompt a confirmation dialog to the user:

   (gui '(+JS +Button) "+"
      '(ask "Increment value?"
         (inc '*Num) ) )

The equivalence of code and data makes the development of functions like html, form, gui or ask particularly simple. The list

   (ask "Increment value?" (inc '*Num))

is data for the gui function. gui constructs a component of the class +Button, and simply stows away that list into the new component. Later, when the button is pressed, it is executed. It is just that simple.

gui itself doesn't understand anything about buttons and what they do with these arguments. It is all data. From the view of the button, however, that list is a piece of code, to be executed when the button is pressed.

Later, when ask is executed, the situation is similar. A dialog is shown which displays the question "Increment value?", and a "Yes" and a "No" button. The "Yes" button receives the expression (inc '*Num), to increment the number when pressed.

The example can be modified, to operate on database entities instead. Instead of connecting the numeric field to a variable (with the +Var prefix class), we connect it to the count property of the database object, and instead of incrementing the variable, the button increments that object's count attribute:

   (gui '(+E/R +NumField) '(count : home obj) 9)
   (gui '(+JS +Button) "+" '(inc!> (: home obj) 'count))

No need to write some separate database "select" or "update" functionality! It is all in a single place.

This shows how easily any kind of application logic can be implemented using this style. In a typical application hundreds or thousands of such components are put together, so it is essential that this can be done with as little noise and redundancy as possible.

This becomes especially evident if you compare this style with the GUI and application strategies of other languages, for example in the RosettaCode tasks GUI component interaction and GUI enabling/disabling of controls.

In other environments, you usually end up defining constants, components and functions in separate locations. This is the opposite of what PicoLisp advocates, the "locality principle of structure, content and behavior".

http://picolisp.com/wiki/?equivalencecodedata

01apr16    erik
Revision History