The Memristor

Mike's Notes

Pipi 11 (2029-) will take a deep dive into hybrid analogue-digital computing. These include;

  • Reservoir computing
  • Memristors
This article by Brian Hayes is an excellent introduction to memristors.
Memristor kits are available from Knowm.

Conceptual symmetries of resistor, capacitor, inductor, and memristor - Wikipedia

Resources

References

  • Reference

Repository

  • Home > Ajabbi Research > Library >
  • Home > Handbook > 

Last Updated

05/04/2026

The Memristor

By: Brian Hayes
American Scientist: 03/2011

Brian Hayes is a former editor and columnist for American Scientist. His most recent book is Foolproof, and Other Mathematical Meditations (MIT Press, 2017).

The first new passive circuit element since the 1830s might transform computer hardware

When Bell Telephone Laboratories announced the invention of the transistor in 1948, the press release boasted that “more than a hundred of them can easily be held in the palm of the hand.” Today, you can hold more than 100 billion transistors in your hand. What’s more, those transistors cost less than a dollar per billion, making them the cheapest and most abundant manufactured commodity in human history. Semiconductor fabrication lines churn out far more transistors than the world’s farmers grow grains of wheat or rice.

In this thriving transistor monoculture, can a new circuit element find a place to take root and grow? That’s the question posed by the memristor, a device first discussed theoretically 40 years ago and finally implemented in hardware in 2008. The name is a contraction of “memory resistor,” which offers a good clue to how it works.

Memristor enthusiasts hope the device will bring a new wave of innovation in electronics, packing even more bits into smaller volumes. Memristors would not totally supplant transistors but would supplement them in computer memories and logic circuits, and might also bring some form of analog information processing back into the world of computing. Farther out on the horizon is a vision of “neuromorphic” computers, modeled on animal nervous systems, where the memristor would play the role of the synapse.

Whether the memristor will ultimately fulfill all these hopes remains to be seen. The history of invention is littered with promising novelties that failed to dislodge an incumbent technology. On the other hand, there is now widespread agreement that some fundamental shift in circuit design will be needed if computer hardware is to remain a growth industry. The memristor looks like a strong candidate.

Titania

The device that has sparked all the recent excitement over memristors was created in 2008 by R. Stanley Williams and several colleagues at Hewlett-Packard Laboratories. The Williams memristor consists of two metal electrodes separated by a thin film of titanium dioxide, or TiO2. This substance, also known as titania, is familiar to artists as a white pigment and to beachgoers as an ingredient of sunscreen.

The memristor is a new building block for electrical circuits, an addition to the family of “passive” devices that also includes the resistor, the capacitor and the inductor. A version of the memristor invented at Hewlett-Packard in 2008 has a layer of insulating titanium dioxide, TiO2, sandwiched between two platinum (Pt) electrodes. Part of the TiO2 layer is “doped”: It has oxygen vacancies (orange disks) that act as positive ions and liberate electrons (purple dots) that can carry an electric current. The overall resistance of the device depends on the position of the boundary between the doped and the undoped regions; moreover, this boundary can be moved by an applied electric field. The diagrams above show several possible states of the memristor. Proceeding upward from the middle of the sequence, a forward bias voltage expands the doped region and thereby lowers the resistance; proceeding downward from the middle, a reverse bias voltage leaves most of the layer undoped, raising the resistance.

Illustration by Brian Hayes.

In its natural form titania is an electrical insulator, presenting very high resistance to the flow of electric current. In the memristor, part of the titania layer retains this natural insulating character, but the rest is altered during deposition by restricting the amount of oxygen available. The resulting oxygen vacancies in the crystal lattice reduce the resistance of the material by supplying mobile electrons that can carry a current. The oxygen-starved layer is said to be “doped.” (This term usually refers to added impurity atoms, but the effect of the oxygen deficiency is the same.)

An electric current passing through the memristor has to cross both the doped and the undoped regions, and so the total resistance is the sum of contributions from the two layers. The total depends on the relative thickness of the layers, or in other words on the position of the boundary between them. What gives the memristor its special traits is that this boundary can move.

Consider what happens inside the titania film when a voltage is applied to the terminals of the memristor, so that a current flows through it. The current is carried by conduction electrons—mostly electrons liberated by the oxygen vacancies. Electrons have a negative charge, and so they are repelled by the negative terminal and attracted to the positive one. In the background, meanwhile, another process is going on. The oxygen vacancies also have an electric charge; they act as positive ions, which drift toward the negative electrode. Movement of the vacancies requires physical rearrangement of the crystal lattice, and so it is much slower than the flow of electrons.

The relatively slow drift of the oxygen vacancies makes no significant contribution to the electric current flowing through the memristor, but by shifting the boundary line between doped and undoped layers, it alters the overall resistance of the device. Depending on the polarity of the applied voltage, the resistance can either increase (if the doped region is squeezed into a narrower layer) or decrease (if the doped region expands to include more of the total thickness). When the external voltage is removed, the boundary line stays put in its new position.

It is the migrating boundary between doped and undoped regions that gives the memristor its memory. And it’s not hard to see how this property can be put to work for information storage. One simple scheme defines a low-resistance state as a binary 0 and high-resistance state as a binary 1. To write a bit into the memory cell, apply a strong voltage pulse of the appropriate polarity, thereby setting the resistance either high or low. To read the stored state of the cell, use a lower voltage or a briefer pulse, which can measure the resistance without appreciably altering it.

A notable advantage of the memristor is that it can be made very small. As a matter of fact, it must be small, at least along one dimension—the thickness of the TiO2 film. The ratio of maximum to minimum resistance varies inversely as the square of this thickness. In practical devices the film might be as thin as 10 nanometers, which is just 25 or 30 atomic diameters.

It’s also notable that the memristor offers nonvolatile storage: The device retains its memory even when the power is turned off.

Lost and Found

There is a long tradition of explaining electric circuits by hydraulic analogies. Thus a conductor is compared to a pipe; electric current is analogous to the flow of water through the pipe; and voltage is like the pressure difference that drives the flow. In this imaginary world of electrical plumbing, a resistor is a small orifice that restricts the flow of water through a pipe. Similarly, a diode (or rectifier) might be likened to a one-way check valve, with a flap that the water pushes open when flowing in the right direction; pressure in the opposite direction closes the flap, which prevents any flow.

What is the hydraulic equivalent of a memristor? The closest analogy I can think of is a sand filter, an item of apparatus used in water-purification plants. As contaminated water flows through a bed of sand and gravel, sediment gradually clogs the pores of the filter and thereby increases resistance. Reversing the flow flushes out the sediment and reduces resistance. Note that this behavior differs from that of a check valve. Although in both cases the direction of flow is what controls the state of the device, at any given instant the resistance of the sand filter is the same in both directions. The memristor, too, is symmetric in this sense.

Plumbing analogies offer intuition about how a component works, but engineers need more—they need a predictive mathematical theory. The memristor has such a theory. It was formulated by Leon O. Chua of the University of California, Berkeley, in the early 1970s—when he had no physical device to which the theory applied. Chua’s 1971 paper on the subject was titled “Memristor—the missing circuit element.” Williams and his colleagues titled their 2008 announcement “The missing memristor found.”

Chua’s theory has nothing to say about oxygen vacancies or other details of materials and structures. It is framed in terms of the basic equations of electric circuits. Those equations link four quantities: voltage (v), current (i), charge (q) and magnetic flux (φ). Each equation establishes a relation between two of these variables. For example, the best-known equation is Ohm’s Law, v=Ri, which says that voltage is proportional to current, with the constant of proportionality given by the resistance R. If a current of i amperes is flowing through a resistance of R ohms, then the voltage measured across the resistance will be v volts. A graph of current versus voltage for an ideal resistor is a straight line whose slope is R.

Equations of circuit theory led to a prediction of the memristor almost 40 years before the device was discovered. The equations state relations among four variables: charge (q), current (i), voltage (v) and magnetic flux (phi). Taking these variables in pairs, there are six possible combinations, but only five equations were known. Leon O. Chua of the University of California, Berkeley, showed that the missing sixth equation, which links q and phi, defines the property he named memristance. In this matrix each equation appears in two forms, one the inverse of the other. Four paired equations (colored squares) are associated with basic circuit elements: resistance, capacitance, inductance and memristance. The remaining equations (gray squares) define charge as the time integral of current and voltage as the time derivative of flux.

Illustration by Brian Hayes.

Equations of the same form but with different pairs of variables describe two more basic electrical properties, capacitance and inductance. And two more equations define current and voltage in terms of charge and flux. That makes a total of five equations, which bring together various pairings of the four variables v, i, q and φ. Chua observed that four things taken two at a time yield six possible combinations, and so a sixth equation could be formulated. The missing equation would connect charge q and magnetic flux φ and would describe a new circuit element, joining the resistor, the capacitor and the inductor. Those three devices had all been known since the 1830s, so the new element would be a very late and unexpected addition to the family. Chua named it the memristor.

No law of physics demanded that such a device exist, but no law forbade it either; the existing theory of circuits with resistance, capacitance and inductance could be augmented in a straightforward way to include memristance as well. Chua argued for the plausibility of the memristor on grounds of symmetry and completeness, suggesting an analogy with Dmitri Mendeleev’s construction of the periodic table. Nature is not required to fill every square of this table, but a blank spot is certainly a good place to look for a new chemical element—or a new circuit element.

What would a device linking charge and flux look like? Framing the question in this way may be part of the reason it took so long to identify a physical memristor. The variables q and φ invite visions of electric and magnetic fields interacting in some conspicuous way. But the memristor invented at Hewlett-Packard has no obvious connection with magnetic phenomena. Instead it works as a special kind of variable resistor. How can this device be described in terms of q and φ?

Chua’s answer is that q and φ are more important as mathematical variables than as physical quantities. The charge q is the time integral of an electric current: The current is a rate of flow—the number of electrons per second passing some point in the circuit—whereas the charge is the total number of electrons passing that point. A similar relation defines voltage in terms of magnetic flux. By making use of these definitions, we can describe the action of the memristor in terms of voltage and current instead of charge and flux.

The simplest form of the memristor equation is just a variant of Ohm’s Law: v=M(q)i. Where Ohm’s Law has a constant, R, representing resistance, the memristor equation has a function, M(q). M is not a constant; instead it varies as a function of the quantity of charge that has passed through the device. This functional dependence allows memristance to be controlled in ways that ordinary resistance cannot. (Nevertheless, memristance is expressed in the same unit of measure as resistance, namely the ohm.)

Long before Williams announced the TiO2 memristor, there were reports of “anomalous” resistance effects that can now be understood in terms of memristance. Chua has compiled a list of examples going back to 1976, and Williams himself had been exploring such phenomena since 1997. What changed in 2008 was the recognition that Chua’s memristor theory could be applied to these devices. The connection between theory and experiment is more than a formality; it allows memristors to be modeled in circuit-simulation software, an essential in the design of large-scale systems.

Hysteresis and Memory

The resistor, the capacitor, the inductor and the memristor are all described as “passive” circuit elements, to distinguish them from “active” devices such as transistors, which can amplify signals and inject power into circuits. But the memristor differs from the other passive components in a crucial way: It is necessarily a nonlinear device. In an ideal resistor, as mentioned above, the relation between current and voltage is one of simple proportionality, and so the graph of this relation is a straight line of slope R. The equivalent graph for an ideal memristor is not a line but a curve, where the slope varies from place to place.


Plotting the relation of current to voltage highlights the difference between a resistor (above) and a memristor (see next illustration). In these graphs, voltage and current are each plotted separately as a function of time, and then combined in a current-voltage curve that shows the evolving state of the system. (The separate voltage and current graphs are turned 90 degrees to each other so that their axes match those of the current-voltage graph.) The input voltage is a sine wave. For an ideal resistor, current is proportional to voltage, and so the current is also sinusoidal. The current-voltage curve is a straight line whose slope is the resistance, a constant.

Illustration by Brian Hayes.

In the TiO2 memristor it’s easy to see where the nonlinearity comes from. Suppose the device is connected to a source of constant voltage. As current passes through the memristor in the “forward” direction—enlarging the conductive, doped, layer—the memristance decreases; this allows more current to pass, which further reduces the memristance, and so on. Reversing the polarity of the voltage source leads to the opposite kind of feedback loop, where increasing memristance causes still further increases.

The memristor current-voltage curve takes the form of a “pinched hysteresis loop.” Because of the shifting boundary between doped and undoped regions, memristance is not a constant. Current initially grows slower than voltage, then speeds up and continues increasing even after voltage has reached its peak. The loop closes again at the origin: Whenever the voltage is zero, so is the current. The colored dots are meant to help in tracing the trajectory of the system along the current-voltage curve. They identify five corresponding points in the first half-cycle of the sine wave; the sequence progresses from yellow through orange to red.

Illustration by Brian Hayes.

The nature of the nonlinearity can be seen clearly by tracing the response of the device to a sinusoidal signal—a smoothly alternating voltage. The plot starts at zero volts and zero amperes. As the voltage steadily increases, so does the current, at an accelerating rate reflecting the nonlinear memristance. Then, after the voltage reaches its maximum and starts to fall again, the current continues to rise briefly because the resistance of the TiO2 film is still diminishing. When the current finally does retreat, the descending branch of the curve does not retrace the path of the ascending branch. Instead it forms a loop, called a hysteresis loop (a term borrowed from the study of magnetic systems). Specifically, the memristor’s curve is a “pinched” hysteresis loop, because the two branches cross at the origin. It’s a characteristic of the memristor that whenever the voltage is zero, so is the current, and vice versa. This fact implies that the memristor stores no energy, not even briefly. (The same is true of resistors, but not of capacitors or inductors.)

Hysteresis creates a fundamental distinction between resistors and memristors. In a resistor, current is a simple, single-valued function of voltage; the same voltage always elicits the same current. The hysteresis curve of a memristor driven by a sinusoidal input signal implies that the same voltage can yield two different currents. More generally, when we consider inputs other than simple sine waves, a given voltage can correspond to many different values of current. What value is observed depends on the internal state of the memristor, which in turn depends on its history. This is just another way of saying that the memristor retains a memory of its own past.

Switching in Time

The transistor is a three-terminal device, with three connections to the rest of the circuit. It acts as a switch or amplifier, with a voltage applied to one terminal controlling a current flowing between the other two terminals. No such design is possible with memristors, which have just two terminals. But memristors can nonetheless be used to build both memory and digital logic. The key is to exploit the memristor’s built-in sense of history: A signal applied at one instant can affect another signal that later travels the same path. The first signal exerts this control by setting the internal state of the memristor to either high or low resistance.

The favored layout for memristor memory is a crossbar structure, where perpendicular rows and columns of fine metal conductors are separated by a thin, partially doped layer of TiO2. In this way a memristor is formed at every point where a column crosses a row. Each bit in the memory is individually addressable by selecting the correct combination of column and row conductors. A signal pulse applied to these conductors can write information by setting the resistive state of the TiO2 junction. A later pulse on the same pair of conductors reads the recorded information by measuring the resistance.

A near-term role for memristor crossbar arrays might be as a competitor for “flash” memory, the nonvolatile storage technology used in cell phones, cameras and many other devices. Each cell in a flash memory is a single transistor, modified for long-term storage of electric charge. The memristor structure is simpler and requires only two connections, so it might be made smaller than the flash-memory transistor. Thus there’s the possibility of higher density and lower cost.

Building logic circuits out of memristors would be a somewhat greater departure from current practice. In the early years of solid-state electronics, a technology called resistor-transistor logic had a brief vogue; the idea was to minimize the number of expensive transistors and maximize the number of cheap resistors. But with the coming of integrated circuits the economic incentives changed. With potential advantages in size and power consumption, memristors might shift the balance back toward a technology that combines active and passive devices. Williams and his colleagues have demonstrated a set of memristor logic gates that are computationally complete—they can implement any Boolean logic function.

Active components such as transistors would still be needed even if most information processing were done by memristors. The reason is that signals are reduced in amplitude by every passive circuit element, and at some point they must be restored to full strength. This requires a transistor or some other active device. Methods of fabricating hybrid circuits that combine transistors and memristors on the same substrate are an active area of investigation.

In binary digital circuits, memristors would operate as switches, toggling between maximum and minimum resistance. In this mode, the state of a memristor encodes one bit of information. If several intermediate resistances could be distinguished reliably, then the information density could be raised to two or three bits per device. The writing and reading processes would have to be calibrated to resolve four or eight levels of resistance. (Some flash memory chips already achieve this.) The end point of this evolution is to let the resistance vary continuously, and operate the memristor as an analog device.

One intriguing way to exploit analog memristors would be to build a machine modeled on the nervous system. In biological neural networks, each nerve cell communicates with other cells through thousands of synapses; adjustments to the strength of the synaptic connections is thought to be one mechanism of learning. In an artificial neural network, synapses must be small, simple structures if they are to be provided in realistic numbers. The memristor meets those requirements. Moreover, its native mode of operation—changing its resistance in response to the currents that flow through it—suggests a direct way of modelling the adjustment of synaptic strength.

Empire Building

Will the memristor turn out to be a transformative technology, the key to putting hundreds of trillions of devices in the palm of your hand? Or will we be asking, a few years from now, “Whatever happened to the memristor?”

The empire of the transistor has fended off many other rivals and would-be invaders. A memory technology based on magnetic “bubbles” floating on a garnet crystal once held great promise, but you can read about it now on the website of the Vintage Technology Association. The charge-coupled device, or CCD, was another candidate for main memory and mass storage; it failed to gain a foothold in that role, although it did find another niche, as the image sensor of digital cameras. And there were wilder flights of fancy, such as superconducting computers and photonic data processing.

This roster of defeated challengers might lead one to conclude that no innovation has a chance of displacing an entrenched technology. However, the transistor itself offers the obvious refutation. At its debut in 1948 it had to compete with the vacuum tube, which had dominated the electronics industry for 30 years. Although the transistor took more than a decade to establish itself, in the end the vacuum tube became a quaint collector’s item.

Today the TiO2 memristor is just one of many contending new technologies. Considering only the realm of switched-resistance memory elements, there are several other candidates, including devices based on phase changes, on magnetic fields and on electron spin. (Chua argues that all these devices should be classified as memristors.) To evaluate the long-term prospects of such technologies, one would have to go beyond basic principles of operation to questions of reliability, longevity, uniformity, cost of manufacturing and dozens of other details.

In a telephone conversation I asked Williams why he believes the memristor will be the technology that prevails. He offered several substantive arguments, but he also added, candidly: “It’s the one I’m working on. I have to believe in it.” In a sense this is the strongest endorsement anyone can give. As a bystander, I have the luxury of waiting on the sidelines to see how the contest comes out. But someone has to make choices, take risks and commit resources, or nothing new will ever be created.

©Brian Hayes

Bibliography

  • Borghetti, Julien, Gregory S. Snider, Philip J. Kuekes, J. Joshua Yang, Duncan R. Stewart and R. Stanley Williams. 2010. ‘Memristive’ switches enable ‘stateful’ logic operations via material implication. Nature 464:873–876.
  • Chua, Leon O. 1971. Memristor—the missing circuit element. IEEE Transactions on Circuit Theory 18:507–519.
  • Chua, Leon O., and Sung Mo Kang. 1976. Memristive devices and systems. Proceedings of the IEEE 64(2):209–223.
  • Chua, Leon. 2011. Resistance switching memories are memristors. Applied Physics A 102(4) (In press).
  • Joglekar, Yogesh N., and Stephen J. Wolf. 2009. The elusive memristor: properties of basic electrical circuits. European Journal of Physics 30:661–675.
  • Keyes, Robert W. 2009. The long-lived transistor. American Scientist 97:134–141.
  • Li, Hai, and Yiran Chen. 2010. Emerging non-volatile memory technologies. In Proceedings of the 53rd Midwest Symposium on Circuits and Systems. doi:10.1109/MWSCAS.2010.5548590.
  • Rose, Garrett S. 2010. Overview: Memristive devices, circuits and systems. In Proceedings of 2010 IEEE International Symposium on Circuits and Systems (ISCAS 2010), pp. 1955–1958.
  • Strukov, Dmitri B., Gregory S. Snider, Duncan R. Stewart and R. Stanley Williams. 2008. The missing memristor found. Nature 453:80–83.
  • Strukov, D. B., D. R. Stewart, J. Borghetti, X. Li, M. Pickett, G. Medeiros Ribeiro, W. Robinett, G. Snider, J. P. Strachan, W. Wu, Q. Xia, J. Joshua Yang and R. S. Williams. 2010. Hybrid CMOS/memristor circuits. In Proceedings of 2010 IEEE International Symposium on Circuits and Systems (ISCAS 2010), pp. 1967–1970.
  • Versace, Massimiliano, and Ben Chandler. 2010. The brain of a new machine. IEEE Spectrum 47(12):30–37.
  • Williams, R. Stanley. 2008. How we found the missing memristor. IEEE Spectrum 45(12):28–35.

Pipi autonomous Read-Eval-Print-Loop (REPL)

Mike's Notes

Deployment roadmap

Later in the year, Pipi will be able to deploy infrastructure on any platform using Infrastructure as Code (IaC).

Options on how to do this include;

  • CL (Command Line)
  • REPL (Read-Eval-Print-Loop)
  • API

Implementing a REPL (Read-Eval-Print-Loop) programmatically in CFML

I asked Google Search AI Mode (powered by Google Gemini) how to use CFML to write and read REPL.

The Google output has been reformatted but not edited, and the code needs to be tested. The questions were turned into headings. There is a lot of duplication.

I find that carefully using Gemini to write CFML code and then checking everything is making me more productive.

There is now enough here to set up REPL.

Once this automation is complete, productivity will increase by at least x10.

Resources

References

  • Reference

Repository

  • Home > Ajabbi Research > Library >
  • Home > Handbook > 

Last Updated

04/04/2026

Pipi autonomous Read-Eval-Print-Loop (REPL)

By: Mike Peters and Gemini
On a Sandy Beach: 04/04/2026

Mike is the inventor and architect of Pipi and the founder of Ajabbi.

Gemini is still cool.

A Read-Eval-Print-Loop (REPL) is an interactive computer programming environment that accepts single-user input, executes it, and returns the result immediately. It is also known as an interactive toplevel or language shell. [1, 2, 3] 

The Four Steps of the Loop

The name describes the precise cycle the environment follows: [4, 5] 

  • Read: The system accepts a line of input (usually a single expression or command) from the user.
  • Eval: It parses and evaluates the input code to determine its value or effect.
  • Print: The resulting value or output is displayed back to the user on the screen.
  • Loop: The process repeats, returning to the prompt to wait for the next input. [1, 5, 6, 7, 8, 9, 10] 

Why Developers Use REPLs

REPLs are highly valued for their tight feedback loop, which allows for: [6, 7, 11] 

  • Interactive Prototyping: Quickly testing small snippets of code without creating and saving files.
  • Debugging: Investigating the state of a program and testing potential fixes in real-time.
  • Learning: Experimenting with new language features or libraries with instant results.
  • Calculations: Using the environment as a high-powered calculator for mathematical expressions. [1, 12, 13, 14, 15, 16, 17] 

Common Examples

Most modern programming languages provide a built-in REPL or have popular third-party versions: [1, 18] 

References

Implementing REPL programmatically in CFML

Implementing a REPL (Read-Eval-Print-Loop) programmatically in CFML involves creating a loop that captures user input, evaluates it as live code, and returns the result. [1, 2, 3] 

While Adobe ColdFusion (2018+) and CommandBox include built-in REPLs for terminal use, you can build your own programmatic version using the following core functions: [2, 4]

1. The Evaluation Engine

The most critical part of a REPL is the Eval step. CFML provides two primary ways to execute strings as code:

  • Evaluate(): Best for executing single expressions and returning a value.
  • Render(): (Lucee specific) Similar to Evaluate, but specifically designed to execute CFML tag or script code and return the generated output as a string. [5, 6] 

2. Building a Basic Web-Based REPL

A programmatic REPL usually consists of a simple loop (often via a form submission) that maintains state.

// 1. READ: Get input from a form or API
inputCode = form.myScript ?: "";
if (len(trim(inputCode))) {
    try {
        // 2. EVAL: Execute the code
        // Note: Evaluate() is powerful but dangerous with untrusted input
        result = evaluate(inputCode);
        
        // 3. PRINT: Output the result
        writeOutput("Result: " & result);
    } catch (any e) {
        writeOutput("Error: " & e.message);
    }
}
// 4. LOOP: Handled by the user submitting the form again

3. Advanced Implementation Details

To create a more robust "shell-like" experience:

  • Persistent State: To keep variables alive across multiple inputs, store a "context" structure in a persistent scope like Session or Application.
  • Capturing Console Output: If the code uses writeOutput(), you may need to use cfsavecontent to capture that output before it hits the main buffer.
  • Safety: Never expose a REPL to public users. It allows for arbitrary code execution, which can delete files or access sensitive server data.
  • Multi-line Support: For more complex scripts, you may need to detect if a block (like an if statement or function) is complete before evaluating, similar to how [CommandBox's REPLParser](https://community.ortussolutions.com/t/replparser-multiline-support/9559) works. [6, 7, 8] 

Summary of Tools

Feature [2, 3] Function/Tool Platform
Expression Eval Evaluate(string) Adobe & Lucee
Full Code Execution Render(string) Lucee Only
Terminal REPL cf.bat / cf.sh Adobe (2018+)
CLI REPL box repl CommandBox

References

Using workflows written in CFML to write and read REPL

To build a workflow in CFML that programmatically reads from and writes to a REPL, you need to treat the REPL as an external process. This is most effectively done using CommandBox, which provides a robust CLI and REPL environment for CFML. [1, 2] 

1. Using CommandBox via cfexecute

The standard way to interact with a REPL from a running CFML workflow (like a background task or a web request) is to use <cfexecute> or the execute() function to call the [CommandBox binary](https://modern-cfml.ortusbooks.com/intro/instructions-and-interpreters).

  • Writing to REPL: You can pass CFML code directly to the CommandBox repl command using the --code flag or by piping input.
  • Reading from REPL: The output of the command is captured in a variable for your workflow to process. [3, 4, 5] 

Example: Running a Snippet and Capturing the Result

// Define the CFML code you want the REPL to evaluate
replInput = "x = 10; y = 20; writeOutput(x + y);";
// Execute CommandBox REPL with the code
execute(
    name = "box", 
    arguments = "repl --code=""#replInput#""", 
    variable = "replOutput", 
    timeout = 10
);
// Read the result back into your workflow
writeOutput("The REPL returned: " & replOutput);

2. Interactive Workflows with Piping

If your workflow needs to chain multiple operations, you can use the cfml command in CommandBox. This allows you to [pipe data](https://commandbox.ortusbooks.com/usage/execution/cfml-functions) between CFML functions as if they were terminal commands.

  • Workflow logic: #listGetAt www.foo.com 2 . | #ucase | #reverse
  • Result: The REPL processes each step and passes the "Read" result of one to the "Eval" of the next. [6, 7] 

3. Asynchronous "Daemon" REPL

For a long-running workflow that needs to keep a REPL "warm" (to avoid startup overhead), consider using an Event Gateway or a persistent background thread. [8] 

  1. Start a process: Use java.lang.ProcessBuilder via CFML to open a persistent connection to the CommandBox shell.
  2. Write to Stream: Send commands to the process's OutputStream.
  3. Read from Stream: Use a separate CFML thread to constantly poll the InputStream for the REPL's response. [9, 10] 

4. Safety and Best Practices

  • Sanitisation: If the input for your REPL comes from an external source, treat it as unsafe. Programmatic REPLs can execute fileDelete() or access system environment variables.
  • Timeouts: Always set a timeout in your execute calls to prevent a "loop" in the REPL from hanging your entire server.
  • Context: Remember that code executed in a separate REPL process does not share the same variable scope (like Session or Request) as your main workflow unless you explicitly pass those values in. [11] 

References

Pass complex data (like a Struct) between your workflow and a CommandBox REPL

To pass complex data, such as a Struct or Array, between a CFML workflow and a REPL, the most reliable method is to use JSON serialisation. Since the REPL and your main application run in separate memory spaces, JSON acts as a universal bridge for data exchange.

1. Passing a Struct into the REPL (Write)

When calling the REPL, convert your CFML Struct into a JSON string and inject it into the command as a literal. CommandBox’s REPL is smart enough to interpret a JSON string as a native Struct if it's the first input to certain functions or assigned directly. [1, 2] 

// Your complex workflow data
userData = {
    "id": 123,
    "roles": ["admin", "editor"],
    "settings": { "theme": "dark" }
};
// Serialize to JSON (use single quotes for the shell command)
jsonInput = serializeJSON(userData);
// Build the REPL command
// Note: We assign the JSON string directly to a variable inside the REPL
replCommand = "data = #jsonInput#; writeOutput(data.roles[1]);";
execute(
    name = "box",
    arguments = "repl --code=""#replCommand#""",
    variable = "replResponse"
);
writeOutput("REPL processed role: " & replResponse); // "admin"

2. Getting a Struct back from the REPL (Read)

To read complex data back into your workflow, have the REPL print the result as JSON. You then use deserializeJSON() in your main workflow to turn that string back into a live CFML Struct. [3] 

// REPL code that performs logic and returns a new struct
replCode = "result = { 'status': 'success', 'timestamp': now() }; writeOutput(serializeJSON(result));";
execute(
    name = "box",
    arguments = "repl --code=""#replCode#""",
    variable = "rawJsonResponse"
);
// Read the complex data back into your workflow
if (isJSON(rawJsonResponse)) {
    finalData = deserializeJSON(rawJsonResponse);
    writeOutput("Status received: " & finalData.status);
}

Key Considerations for Data Integrity

  • Key Casing: Adobe ColdFusion typically converts struct keys to UPPERCASE during serialisation unless you quote the keys (e.g., {"name": "value"}).
  • Shell Escaping: Be careful with double quotes inside your JSON. When building the arguments string for execute(), ensure you escape quotes correctly so the shell doesn't break the command.
  • Performance: If you are passing very large datasets (multi-MB structs), the overhead of serialisation and shell execution will increase. For high-frequency workflows, consider writing the data to a temporary JSON file and having the REPL read that file instead of passing it as a command-line argument. [4, 5, 6, 7] 

Using temporary files to handle larger datasets between your workflow and the REPL

To handle larger datasets between your CFML workflow and a REPL, using temporary files is the most reliable method. This avoids shell character limits and prevents memory issues. [1] 

1. The Workflow: Writing to a Temp File

First, your main application serialises the data into a JSON file. Use getTempFile() to ensure a unique filename that won't collide with other processes. [2, 3] 

// 1. Prepare your large dataset
complexData = {
    "users": queryToArray( myLargeUserQuery ), // Assume 10k rows
    "metadata": { "source": "workflow_alpha", "processed": now() }
};
// 2. Create a unique temp file
tempFilePath = getTempFile( getTempDirectory(), "repl_data" );
// 3. WRITE: Save the JSON to the file
fileWrite( tempFilePath, serializeJSON( complexData ) );

2. The REPL: Reading the File

When you execute the REPL, pass the file path as a variable. The REPL code will then read the file from disk and deserialise it back into a native CFML object. [4, 5] 

// 4. Build the REPL script to READ the file
replCode = "
    data = deserializeJSON( fileRead('#tempFilePath#') );
    // Perform complex logic on the data
    resultCount = data.users.len();
    writeOutput( resultCount );
";
// 5. EXECUTE: Call CommandBox REPL
execute(
    name = "box",
    arguments = "repl --code=""#replCode#""",
    variable = "replOutput"
);

3. Cleaning Up

Because these files are stored in the system's temporary directory, they will eventually be cleared, but it is best practice to delete them manually once your workflow is finished to save disk space. [1, 6] 

// 6. Cleanup after reading the result
if ( fileExists( tempFilePath ) ) {
    fileDelete( tempFilePath );
}
writeOutput( "REPL processed #replOutput# records." );

Why use files instead of variables?

  • Memory Efficiency: Large strings in shell commands can lead to "Out of Memory" (OOM) errors or exceed operating system command-line length limits.
  • Data Integrity: Files eliminate the need for complex shell quoting and escaping of special characters in your JSON.
  • Persistent Context: If the REPL crashes, the data remains safely on disk for debugging or a retry attempt. [1, 7] 

References

CommandBox Task Runners to make these multi-step REPL workflows even cleaner

While a REPL is great for ad-hoc snippets, CommandBox Task Runners provide a more structured way to handle multi-step workflows. A Task Runner is a CFML component (.cfc) that runs directly from the command line, allowing you to pass complex arguments naturally and use built-in helpers for file and shell interaction. [1, 2, 3, 4]

1. Create the Task Runner (MyTask.cfc) [5]

Instead of cramming logic into a string for the REPL, you write a standard CFML function. You can create one by running task create --open in [CommandBox](https://commandbox.ortusbooks.com/task-runners). [2, 3, 6] 

/**
 * MyTask.cfc
 * Automates a workflow with complex data
 */
component {
    
    function run( string inputPath ) {
        // 1. READ: Load the large dataset from the file
        var data = deserializeJSON( fileRead( arguments.inputPath ) );
        
        print.greenLine( "Processing #data.users.len()# users..." );

        // 2. EVAL: Perform your workflow logic
        var result = {
            "processedCount": data.users.len(),
            "timestamp": now(),
            "status": "complete"
        };

        // 3. PRINT: Return the result as JSON for the calling workflow
        print.text( serializeJSON( result ) );
    }
}

2. Execute the Task from your Workflow [5]

In your main application, you call the task just like you did with the REPL, but it’s much cleaner because the logic is encapsulated in its own file. [7, 8] 


// Path to your Task Runner CFC
taskPath = expandPath( "./MyTask.cfc" );
tempDataFile = getTempFile( getTempDirectory(), "data" );

// Prepare and write data
fileWrite( tempDataFile, serializeJSON( myLargeStruct ) );

// Execute the task via CommandBox
execute(
    name = "box",
    arguments = "task run taskFile=#taskPath# inputPath=#tempDataFile#",
    variable = "rawResult"
);

// Process the structured return
workflowResult = deserializeJSON( rawResult );
writeOutput( "Workflow finished at: #workflowResult.timestamp#" );

Why Task Runners are better for workflows:

  • Portability: Tasks are self-contained in a CFC and can be dropped into any folder without being a full module.
  • Built-in Helpers: You get access to the print helper for formatted console output and filesystemUtil for easy path resolution.
  • Named Parameters: Unlike the REPL, tasks support [named parameters](https://commandbox.ortusbooks.com/task-runners/running-other-tasks), making it easy to pass file paths, IDs, or configuration flags.
  • Readability: Your code is written in a standard IDE with syntax highlighting and error checking rather than as a string inside an execute() call. [1, 3, 9, 10, 11] 

References

Scheduling these tasks to run automatically at specific intervals

To schedule CommandBox Task Runners at specific intervals, you have three primary approaches depending on whether you want to use the operating system, a background process (daemon), or the ColdFusion engine itself. [1] 

1. The Daemon Approach (Self-Scheduling)

For workflows that need to run continuously in the background without external dependencies, you can write your task as a daemon. This involves a while(true) loop and a sleep() command within the CFC. [2, 3] 

/**
 * ScheduledTask.cfc
 * Run: box task run taskFile=ScheduledTask.cfc
 */
component {
    function run() {
        try {
            while( true ) {
                print.blueLine( "Running workflow at #now()#..." );
                
                // INSERT YOUR WORKFLOW LOGIC HERE
                
                // Sleep for 5 minutes (300,000 milliseconds)
                sleep( 300000 );
            }
        } catch( any e ) {
            print.redLine( "Task interrupted: #e.message#" );
        }
    }
}

2. OS-Level Scheduling (Cron / Task Scheduler)

This is the most "production-ready" method for strictly timed intervals (e.g., every day at 2 AM). You simply tell your OS to execute the CommandBox binary and your specific task file. [3, 4, 5, 6] 

  • Linux (Crontab): Add a line to your crontab using crontab -e:
    0 2 * * * /usr/local/bin/box task run /path/to/MyTask.cfc
  • Windows (Task Scheduler): Create a new task that runs the box.exe program with the arguments task run taskFile=C:\path\to\MyTask.cfc. [7, 8, 9] 

3. CFML Engine Scheduling (cfschedule) [10] 

If you want to manage the schedule from within your web application's admin interface or code, you can use the native <cfschedule> tag or cfschedule() function to call the CommandBox CLI. [10, 11] 

cfschedule(
    action    = "update",
    task      = "HourlyWorkflow",
    operation = "HTTPRequest",
    url       = "http://localhost/run_my_task.cfm", // A script that runs the task
    interval  = "3600" // Every hour
);

Note: Your run_my_task.cfm file would then contain the execute() call to trigger the CommandBox task.

4. Advanced: ColdBox Scheduled Tasks

If you are using the [ColdBox Framework](https://coldbox.ortusbooks.com/digging-deeper/scheduled-tasks), you can use the built-in Async Scheduler to define tasks with a fluent, human-readable API. [1, 9, 12] 

// inside your Scheduler.cfc
task( "CleanTempFiles" )
    .call( function(){
        // CommandBox execution logic here
    } )
    .every( 1, "hours" )
    .delay( 5, "minutes" );

References

The i18n Issue

Mike's Notes

This is a copy of the March issue of Ajabbi Research.

It is about the history of the effort to make Pipi available in any language, localisation, or script requested by users (i18n).

Ajabbi Research is published on SubStack on the first Friday of each month, and subscriptions are free.

Each issue is a broad historical overview of a research topic, serving as an index to dozens of previously posted related articles. There are now over 650 articles/posts.

This copy of the issue will be updated with additional information as it becomes available. Check the Last Updated date given below.

Eventually, each issue will be reused on the separate Ajabbi Research website as an introduction to a research area comprising multiple research projects.

Resources

References

  • SIL.
  • Unicode

Repository

  • Home > Ajabbi Research > Library >
  • Home > Handbook > 

Last Updated

03/04/2026

The i18n Issue

By: Mike Peters
Ajabbi Research: 6/03/2026

Mike is the inventor and architect of Pipi and the founder of Ajabbi.

This is the story of the effort to make Pipi available in any human language and script. The steps taken have been part of Pipi's development since 2005, spanning 5 versions.

The NZERN Pipi 2003-2005 Development Plan started it all.

Pipi 4 (2005-2008)

The story starts with Pipi 4. It was a big, successful system that supported community-driven Ecological Restoration in NZ. Here is a history of that Pipi version.

Initially, the large websites that Pipi generated were in English only.  Then, as botanical and zoological information was added, Latin, English, and Maori names were used. Eventually, provision for Chinese was planned to support the Chinese community-led conservation programmes. There were no separate language data structures in the 850-table Pipi 4 database; instead, some entities had additional columns for each language.

English

  • The 25,000 pages of websites that Pipi generated were initially in English.

Latin

  • Scientific names used in biological data were written in Latin.

Maori

  • Over time, it was realised that support for the Maori Language, Te Reo Maori, was required. To start, bilingual volunteers provided lists of words for regional areas, towns, etc.

Chinese

  • There was an Auckland-based Chinese Community-driven initiative to reach older residents who didn't speak English about conservation.

    Pipi 6 (2017-2019)

    When Pipi was rebuilt from memory, based on the limited experience with Pipi 4, foundational work was done to prepare Pipi for better multilingual support. This would require extra databases.

    Metadata using international codes was added to every database table to enable future language usage. The codes used were ISO 639-3, Country, Unicode, and CLDR/LDML

    ISO 639-3

    ISO 639 gives comprehensive provisions for the identification and assignment of language identifiers to individual languages, and for the creation of new language code elements or for the modification of existing ones (Terms of Reference of the ISO639/MA). - ISO 639-3

    *** 

    It defines three-letter codes for identifying languages. The standard was published by the International Organisation for Standardisation (ISO) on 1 February 2007. As of 2023, this edition of the standard has been officially withdrawn and replaced by ISO 639:2023.

    ISO 639-3 extends the ISO 639-2 alpha-3 codes with an aim to cover all known natural languages. The extended language coverage was based primarily on the language codes used in the Ethnologue (volumes 10–14) published by SIL International, which is now the registration authority for ISO 639-3.[2] It provides an enumeration of languages as complete as possible, including living and extinct, ancient and constructed, major and minor, written and unwritten. However, it does not include reconstructed languages such as Proto-Indo-European.

    ISO 639-3 is intended for use as metadata codes in a wide range of applications. It is widely used in computer and information systems, such as the Internet, in which many languages need to be supported. In archives and other information storage, it is used in cataloging systems, indicating what language a resource is in or about. The codes are also frequently used in the linguistic literature and elsewhere to compensate for the fact that language names may be obscure or ambiguous. Wikipedia

    Examples

    • Eng (English
    • Fra (French)

    ISO_3166-1_alpha-3

    ISO 3166-1 alpha-3 codes are three-letter country codes defined in ISO 3166-1, part of the ISO 3166 standard published by the International Organization for Standardization (ISO), to represent countries, dependent territories, and special areas of geographical interest. They allow a better visual association between the codes and the country names than the two-letter alpha-2 codes (the third set of codes is numeric and hence offers no visual association). They were first included as part of the ISO 3166 standard in its first edition in 1974. - Wikipedia

     Examples

    • ABW  (Aruba)
    • AFG  (Afghanistan)
    • AGO  (Angola)

    Unicode

    Unicode (also known as The Unicode Standard and TUS) is a character encoding standard maintained by the Unicode Consortium designed to support the use of text in all of the world's writing systems that can be digitized. Version 17.0[A] defines 159,801 characters and 172 scripts used in various ordinary, literary, academic and technical contexts. - Wikipedia

    Examples

    • Latn (Latin)
    • Lina (Linear B)
    • Hebr (Hebrew)

    CLDR/LDML

    The Common Locale Data Repository (CLDR) is a project of the Unicode Consortium to provide locale data in XML format for use in computer applications. CLDR contains locale-specific information that an operating system will typically provide to applications. CLDR is written in the Locale Data Markup Language (LDML). - Wikipedia

    Example

     <?xml version="1.0" encoding="UTF-8" ?>
    <ldml>
      
        <version number="1.1">ldml version 1.1</version>
        <generation date="2024-03-06"/>
        <language type="en"/>
        <territory type="US"/>
      
      <!-- other locale data sections follow -->
    </ldml>

    Localisation (L10N)

    Language localisation (or language localisation) is the process of adapting a product's translation to a specific country or region. It is the second phase of a larger process of product translation and cultural adaptation (for specific countries, regions, cultures or groups) to account for differences in distinct markets, a process known as internationalisation and localisation. - Wikipedia

    ***

    Pipi internally automatically stores and uses 3-letter language codes, 4-letter Unicode and 3-letter country codes to define Locales.

    Examples

    • eng-Latn-NZD (New Zealand English)
    • eng-Latn-USA (United States English)

    Customers can configure the options for their own websites.

    Examples

    • en-NZ
    • en-uk

    More information

    Pipi 7 (2020)

    Small, simple, static HTML mockups of websites were created to test how different languages could be used. Experiments with HTML and CSS were conducted to display text on a website in Left-to-Right (LTR) and Right-to-Left (RTL) word order.

    Pipi 8 (2021-2022)

    System-wide i18n and L10N namespaces were implemented throughout Pipi to enable reliable automation and rapid scaling across multiple languages.

    Pipi 9 (2023-2026)

    Joining up all the built systems to self-generate documentation and a front-end User Interface (UI).

    Experiments were conducted to determine how to integrate i18n support with Pipi's other features. It was confirmed that the Pipi core is written in British Standard English and checked by Grammarly.

    A source-target data model structure was created to store i18n scripts. It was greatly influenced by the system used by Wikipedia (MediaWiki) and OpenOffice.

    Experiments were done using 23 languages and writing scripts to test the CMS Engine (cms), data storage, UI layout, etc.

    String Translation

    Community translation will require a dedicated workspace.

    Account Settings

    Each Pipi is built in 1 language and script. Each account can have many languages. An account has many deployments, each in only one language. A deployment can have many workspaces.

    Localisation

    API Endpoints

    All API connections include a choice of API version and language/script.

    Scripts

    Noto from Google was chosen as the default font for Ajabbi due to the number of scripts it supports.

    KeyMan

    SIL provides an open-source KeyMan that enables keyboards for 2500 different languages to be added to websites. Pipi will use a Keyboard Engine (kyb) to provide this integration. This will be built as part of Pipi 10.

    Url Naming Pattern

    Many experiments were conducted to determine a URL structure that could accommodate websites in many languages. Wikipedia was the main influence.

    Examples

    • eng.example.com
    • example.com/eng/
    • en-uk.example.com
    • example.com/en-nz/

    Documentation

    Documentation and Learning material will need to be provided in many languages. The data models are ready for this. As the British English documentation is completed, it could be auto-translated into US English using Grammarly and into the 9 world languages using Google Translate. It would then need to be checked by volunteer users. This is speculative and will require trial and error to confirm.

    Language Prioritisation

    English > 9 world languages > 7000 local languages + localisation.

    Priority will be given to English, which will then serve as the source for translation into 9 world languages.

    • Arabic
    • Bhasa Indonesian
    • Chinese
    • French
    • German
    • Japanese
    • Hindi
    • Portugese
    • Russian
    • Spanish

    Carefully edited material in those languages can then be translated into any of the other 7,000 languages by volunteers in response to user requests.

      Model-driven UI

      The User Interface Description Language (UIDL) was an EU-funded project that was abandoned in 2010 after 10 years of excellent work. It was to enable accessibility on different screens and devices. The research results were reverse-engineered to build a User Interface Engine (usi) that would run in reverse to generate accessibility solutions for Pipi. The CSS Engine (css) replaced some redundant components of the UIDL project. Additional engines for localisation and personalisation were created.


      Pipi CMS Engine (cms)

      For a first teaching customer, a decision was made early on to autogenerate a separate website for each language (English, Māori, NZ Sign Language, and AAC picture language). This was the simplest solution for the CMS and the users.

      Creating UI for each natural language, including sign languages (i18n), requires user requests and volunteer testers.

      Sign Language

      The scheme was dreamed up to embed NZ Relay Video Interpreting on any webpage and in user workspaces. This is an ongoing experiment, driven by deaf people.

      Picture Language

      Professor Stephen Hawking used AAC via a computer-generated voice. There are many forms of AAC, including picture language. Providing this as a UI is being explored, with other AAC to follow. Important for the millions of people with Cerebral Palsy and Motor Neurone Disease.

      Invented Languages

      This system will be able to provide support for Klingon, Elvish, and other invented languages from books and movies, upon request and with volunteers prepared to do the work. This could be useful for fan communities.

      Dead Languages

      This system will be able to provide support for long-dead languages often studied by linguists and historians, such as Ancient Egyptian, Sumerian, Sanskrit, and Ancient Greek, upon request, with volunteers prepared to do the work. This could be useful for museums and faith communities.

      Workspace personalisation

      The workspace settings will eventually offer complete personalisation of the UI in other languages. This will use a personalisation form in account settings.

      Future Ajabbi Foundation Sponsorship

      Once Ajabbi has established ongoing sponsorship for Ortus for providing open-source BoxLang, the Ajabbi Foundation will generously sponsor open-source SIL KeyMan on an ongoing basis.

      Whats next

      Pipi 9 is available only in English. However, users can request any other language through their profile. Pipi 10 (2027-) will feature those multiple languages.

      The most useful and inspiring resource has been SIL Global.

      Dedication

      Every child has the right to be educated in the language of their people and of their birth. This is dedicated to those working tirelessly to record, strengthen or revive human languages.