Vvvv Spreads

v1.0.1

Helps write code using vvvv gamma's Spread<T> immutable collection type and SpreadBuilder<T>. Use when working with Spreads, SpreadBuilder, collections, arra...

0· 289·1 current·1 all-time
byTebjan Halm@tebjan

Install

OpenClaw Prompt Flow

Install with OpenClaw

Best for remote or guided setup. Copy the exact prompt, then paste it into OpenClaw for tebjan/vvvv-spreads.

Previewing Install & Setup.
Prompt PreviewInstall & Setup
Install the skill "Vvvv Spreads" (tebjan/vvvv-spreads) from ClawHub.
Skill page: https://clawhub.ai/tebjan/vvvv-spreads
Keep the work scoped to this skill only.
After install, inspect the skill metadata and help me finish setup.
Use only the metadata you can verify from ClawHub; do not invent missing requirements.
Ask before making any broader environment changes.

Command Line

CLI Commands

Use the direct CLI path if you want to install manually and keep every step visible.

OpenClaw CLI

Canonical install target

openclaw skills install tebjan/vvvv-spreads

ClawHub CLI

Package manager switcher

npx clawhub@latest install vvvv-spreads
Security Scan
VirusTotalVirusTotal
Benign
View report →
OpenClawOpenClaw
Benign
high confidence
Purpose & Capability
Name, description, and included files are consistent: the skill provides guidance and code snippets for vvvv gamma's Spread<T> and SpreadBuilder<T>. It does not request extra binaries, credentials, or unrelated capabilities. Minor metadata mismatch: SKILL.md lists version "1.1" while registry metadata shows 1.0.1 (likely bookkeeping, not a security issue).
Instruction Scope
SKILL.md contains only documentation and C# example code for Spread usage and performance tips. It instructs agents to apply the skill whenever collection-processing C# code appears (including generic terms like 'list' or 'array'), which broadens when the skill might be triggered but stays within the coding-assistant domain. There are no instructions to read files, access environment variables, or contact external endpoints.
Install Mechanism
No install spec and no code files beyond examples and documentation. This is low risk because nothing is downloaded or written to disk by the skill itself.
Credentials
The skill declares no required environment variables, credentials, or config paths. SKILL.md does not reference any secrets or external service tokens.
Persistence & Privilege
Flags are defaults (always: false, user-invocable: true, disable-model-invocation: false). Autonomous invocation is permitted by default on the platform; combined with this skill's narrow scope and lack of sensitive access, that is acceptable. If you prefer the agent not to trigger it automatically when mentioning generic collection terms, consider disabling autonomous invocation or only invoking the skill explicitly.
Assessment
This is an instruction-only helper with code examples for vvvv gamma Spread<T>. It asks for no credentials and installs nothing, so there is no direct exfiltration or install risk. Things to consider before enabling: (1) the skill may trigger automatically when you or your agent mention lists/arrays unless you restrict autonomous invocation — disable autonomous use if you want manual control; (2) verify the patterns and edge cases against your vvvv gamma version and build/test generated code in a safe environment; (3) note the minor version mismatch between the registry (1.0.1) and SKILL.md (1.1) — this is likely cosmetic but worth confirming if provenance/version tracking matters to you; and (4) the content is licensed CC-BY-SA-4.0, so reuse of examples should follow that license.

Like a lobster shell, security has layers — review code before you run it.

latestvk97e3f457xx47xktgv8r5tzs2s82bfm3
289downloads
0stars
2versions
Updated 1mo ago
v1.0.1
MIT-0

vvvv Spreads

What Are Spreads

Spread<T> is vvvv's immutable collection type, conceptually similar to ImmutableArray<T>. It is the primary way to pass collections between nodes.

Key properties:

  • Immutable — never modify in place, always create new spreads
  • Value semantics — two spreads with same elements are considered equal
  • Cyclic indexing — in visual patches, indexing wraps around (not in C# API)
  • Never null — use Spread<T>.Empty instead of null

Creating Spreads

SpreadBuilder (Primary Method)

var builder = new SpreadBuilder<float>(expectedCount);
for (int i = 0; i < count; i++)
    builder.Add(ComputeValue(i));
Spread<float> result = builder.ToSpread();

From Existing Data

// From array (extension method)
Spread<int> fromArray = new int[] { 1, 2, 3 }.ToSpread();

// From array (static factory)
Spread<Waypoint> fromResult = Spread.Create(resultArray);

// Empty spread (NEVER use null)
Spread<float> empty = Spread<float>.Empty;

// Single element
var single = new SpreadBuilder<float>(1);
single.Add(42f);
Spread<float> one = single.ToSpread();

Accessing Elements

// Always check Count before indexing
if (spread.Count > 0)
{
    float first = spread[0];
    float last = spread[spread.Count - 1];
}

// Iterate (preferred — no allocation)
foreach (var item in spread)
    Process(item);

// Index access in loop
for (int i = 0; i < spread.Count; i++)
    Process(spread[i]);

Common Patterns in C#

Map (Transform Each Element)

public static Spread<float> Scale(Spread<float> input, float factor = 1f)
{
    var builder = new SpreadBuilder<float>(input.Count);
    foreach (var value in input)
        builder.Add(value * factor);
    return builder.ToSpread();
}

Filter

public static Spread<float> FilterAbove(Spread<float> input, float threshold = 0.5f)
{
    var builder = new SpreadBuilder<float>();
    foreach (var value in input)
    {
        if (value > threshold)
            builder.Add(value);
    }
    return builder.ToSpread();
}

Zip (Process Two Spreads Together)

public static Spread<float> Add(Spread<float> a, Spread<float> b)
{
    int count = Math.Max(a.Count, b.Count);
    var builder = new SpreadBuilder<float>(count);
    for (int i = 0; i < count; i++)
    {
        float va = a.Count > 0 ? a[i % a.Count] : 0f;
        float vb = b.Count > 0 ? b[i % b.Count] : 0f;
        builder.Add(va + vb);
    }
    return builder.ToSpread();
}

Accumulate (Running Total)

public static Spread<float> RunningSum(Spread<float> input)
{
    var builder = new SpreadBuilder<float>(input.Count);
    float sum = 0f;
    foreach (var value in input)
    {
        sum += value;
        builder.Add(sum);
    }
    return builder.ToSpread();
}

ReadOnlySpan as High-Performance Alternative

For hot-path output (e.g., per-frame simulation data), ReadOnlySpan<T> avoids allocation entirely:

[ProcessNode]
public class ParticleSimulator
{
    private ParticleState[] _states;

    public ReadOnlySpan<ParticleState> Update(SimulationConfig config, float deltaTime)
    {
        // Simulate into pre-allocated array — zero allocation
        Simulate(_states, config, deltaTime);
        return _states.AsSpan();
    }
}

Use Spread<T> for infrequent config inputs; use ReadOnlySpan<T> for high-frequency frame data.

Performance Rules

  • Pre-allocate builder: new SpreadBuilder<T>(expectedCount) when count is known
  • No LINQ in hot paths: .Where(), .Select(), .ToList() create hidden allocations
  • Cache spreads: If output doesn't change, return the cached spread reference
  • Avoid repeated .ToSpread(): Build once, output the result
  • For large spreads: Consider Span<T> internally, convert to Spread at the API boundary
  • Spread change detection: Since Spreads are immutable, reference equality (!= or ReferenceEquals) is sufficient — if the reference changed, the content changed

Spreads in ProcessNodes

[ProcessNode]
public class SpreadProcessor
{
    private Spread<float> _lastInput = Spread<float>.Empty;
    private Spread<float> _cachedOutput = Spread<float>.Empty;

    public void Update(
        out Spread<float> output,
        Spread<float> input = default)
    {
        input ??= Spread<float>.Empty;

        if (!ReferenceEquals(input, _lastInput))
        {
            var builder = new SpreadBuilder<float>(input.Count);
            foreach (var v in input)
                builder.Add(v * 2f);
            _cachedOutput = builder.ToSpread();
            _lastInput = input;
        }

        output = _cachedOutput;
    }
}

For more code examples, see examples.md.

Comments

Loading comments...