Lazy Nodes Example

examples/Intermediate/LazyNodes/LazyNodes.ino
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/**
 * SPDX-FileCopyrightText: 2026 Maximiliano Ramirez <maximiliano.ramirezbravo@gmail.com>
 *
 * SPDX-License-Identifier: MIT
 */

/**
 * ReactiveESP32 Example Overview:
 * - This example demonstrates the use of lazy evaluation in Computed and Effect nodes.
 * - A Signal holds a numeric value that can be updated via Serial commands.
 * - A Computed node calculates double the signal's value, but only when accessed (lazy).
 * - An Effect node logs the computed value when it changes, also using lazy evaluation.
 *
 * - The Serial interface is used to interact with the program:
 *   - 'g': Get the current value of the signal and computed.
 *   - 'r': Manually run the effect to log the current computed value.
 *   - 's': Set the signal to a new value.
 *   - 'm': Mutate the signal value by adding 5.
 *
 * - Pressing '0' restarts the ESP32.
 */

#include <ReactiveESP32.h>
using namespace RxESP32;

/* ---------------------------------------------------------------------------------------------- */
// Define a simple signal
Signal<uint8_t> number(0);

// Define a computed doubles the signal value, but with lazy evaluation
Computed<uint16_t> doubled(
  []() {
    uint8_t value   = number.get();
    uint16_t result = value * 2;
    Serial.printf("\t[Computed] Recalculated: %u * 2 = %u\n", value, result);
    return result;
  },
  {.lazy = true}); // Enable lazy evaluation

// Define an effect to log when 'doubled' changes, but with lazy evaluation
Effect<> doubled_changed(
  []() {
    uint16_t value = doubled.get();
    Serial.printf("\t[Effect] 'doubled' value: %u\n", value);
    return nullptr; // No cleanup needed
  },
  {.lazy = true}); // Enable lazy evaluation

// Read Serial input and process commands
void serialRead();
/* ---------------------------------------------------------------------------------------------- */

void setup() {
  Serial.begin(115200);
  delay(1000);

  Serial.println("=================================");
  Serial.println("ReactiveESP32 - LazyNodes Example");
  Serial.println("=================================");

  // Start the ReactiveESP32 dispatcher
  if (!Dispatcher::start()) {
    Serial.println("Failed to start ReactiveESP32 Dispatcher!");
    while (true) {
      delay(1000);
    }
  }
}

void loop() { serialRead(); }

void serialRead() {
  if (!Serial.available()) return;

  char c = Serial.read();

  if (c == '\r') return;
  if (c == '\n') c = ' ';
  Serial.printf("> %c\n", c);

  switch (c) {
    case '0':
    {
      // Restart the ESP32
      ESP.restart();
    } break;

    case 'g':
    {
      // Get the current value of signal and computed
      Serial.println("Getting values...");

      // If computed is dirty, it will recompute on get()
      if (doubled.isDirty()) {
        Serial.println("\tComputed 'doubled' is dirty, will recompute on get()");
      } else {
        Serial.println("\tComputed 'doubled' is clean, using cached value");
      }

      uint8_t value_number   = number.get();
      uint16_t value_doubled = doubled.get();
      Serial.printf("Number - Doubled: %u - %u\n", value_number, value_doubled);
    } break;

    case 'r':
    {
      // Manually run the effect to log the current doubled value
      doubled_changed.run();
    } break;

    case 's':
    {
      // Set the signal to a new value using set()
      static uint8_t new_value = 1;

      if (!number.set(new_value)) {
        Serial.printf("Number unchanged: %u\n", new_value);
        break;
      }

      Serial.printf("Number set to: %u\n", new_value);
      new_value++;
    } break;

    case 'm':
    {
      // Mutate the signal value using mutate()
      number.mutate([](uint8_t& value) {
        value += 5;
        Serial.printf("Number mutated to: %u\n", value);
      });
    } break;
  }
}

See Also

  • Core - Core API Reference

  • Filters - Filters API Reference

  • Helpers - Helpers API Reference