Active Variables in Common Lisp

A feature I lifted from ksh93, I thought I would share with LTU. Active variables in Common Lisp; variables with callbacks on reading and writing. Possibly a useful feature that I rarely see in modern programming languages.

github/cl-active-variables

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

C# supports these

Properties in C# are referenced using the syntax of class or instance variables, but are implemented by a get and an optional set method which can take arbitrary action.

Why make activation

Why make activation optional? In all examples that come to my mind, the callbacks are used to enforce invariants on the value being stored and accessed; making it easy to bypass those callbacks -- especially when the short default, the path of least effort, is to bypass -- kinds of defeat the purpose.

Rarely realy?

What's the difference between this and replacing a variable with get/set accessor functions (available in most modern OO languages) and adding a callback to these functions?

Accessors not really the same thing...

The orginal poster is referring to variables not slots (members).

CLOS indeed gives the equivalent of accessors, it is even called an accessor. It is also allowed for a slot to have more than one accessor, reader and/or writer.

Reflection

This sounds reminiscent of the procedural representation of environments used in reflective Lisps.

Variable traces in Tcl/Tk

Sounds like variable traces in Tcl. Used extensively in Tk.

Dart supports this

Dart, like C#, Ruby, et. al., has getters and setters. It also has top-level members: stuff defined outside of any class. You can combine these and define getters and setters at the top level. For instance, here's a getter:

get d6() {
  return (Math.random() * 6.0).floor();
}

main() {
  print('You rolled ' + d6);
}

and here's a setter:

set thunk(value) {
  print('You set ' + value);
}

main() {
  thunk = 3;
}

It ends up being handy for "singleton-like" variables that look just like top-level objects but can do some logic when evaluated like lazy initialization or caching.

OO languages do it for

OO languages do it for object slots but not references.

I found having this to mix particularly well with FRP ("cells"). The read aspect is the linguistic basis of MzTake, a scriptable debugger :)

In Bling, you can create a

In Bling, you can create a dependency property and then "Bind" to it. So something like:

var dp = IntBl.New();
dp.Bind = Time.Sin;

or even assign its value discretely:

dp.Value = 42;

I've found C#'s accessor syntax to be pretty powerful, although sometimes I really want to overload assignment (=), or perhaps C# could have some overloadable assigners like := or ::=.

Access Oriented

Access oriented programming was mentioned a while back, which describes systematic use of active variables. Here is a paper describing access oriented and the language Loops.

I think such systems won't be easy to reason about, at least not with an imperative paradigm. Too much depends on order for activations, which isn't explicit in the program. Activations aren't idempotent, and even `get` accessors might be effectful, so it becomes more difficult to reason about the program. Stability and reentrant concurrency can also become problems.

Lenses

A powerful technique is to treat all variables as lenses, a construct for bi-directional programming (cf. Boomerang project) via mutable views.

There are languages that ease support for this, i.e. treating public attribute X as a pair of methods (GetX, SetX) which can be overloaded.