Sheerpower Logo

String Views (Zero-Copy Slices)


String Views -- Zero-Copy, Live Slices of Strings

The VIEW statement creates a dynamic, zero-copy reference into a string. Unlike MID$() or BETWEEN$(), which return static copies, a VIEW binds directly to the original source variable.

Lazy updating and caching: Views update dynamically. When the source variable is assigned a new value, a view does not immediately recalculate its start or end positions. Instead, these are evaluated the next time the view is referenced (a lazy update).

To avoid unnecessary work, a view also caches its resolved slice. If the source has not changed since the last evaluation, the cached start/end positions of the view are reused and no recalculation occurs. This keeps repeated references fast and allocation-free.

These rules apply to any change in the source. For example, if the source is set to the null string, then on the next reference every view derived from it will also evaluate as a null string.

Views can be created using fixed positions and lengths, or using start and end delimiters. All views support write-through changes to the underlying string.


VIEW a Given Position and Length

The VIEW statement creates a live, dynamic slice of a string variable. Unlike MID$(), which returns a copy, a VIEW does not duplicate data — it binds the view variable directly to the source string.

A view automatically tracks the current value of the source variable. It updates instantly when characters change, or when the entire source variable is reassigned to a new string.

Syntax

VIEW view_var$ INTO source_var$ position numeric_expr1, length numeric_expr2

All four parameters are required:

  • view_var$ — the view variable
  • source_var$ — the source string
  • position — starting position (1-based, like MID$).
  • length — number of characters in the view
Note:
  • A view is read-only except when using overlay operations (LSET, OVERLAY(), etc.), which write directly into the underlying source string.
  • If the starting position is beyond the end of the source, the view evaluates as an empty string.
  • A negative starting position counts backward from the end of the source.
  • If the view's requested length extends past the end of the source, it is automatically truncated to the remaining characters.

Example

phone$ = "8085551212" // Create a view into the first 3 characters VIEW area$ INTO phone$: position 1, length 3 print area$ // Output: 808 // Create a view into the last 3 characters VIEW area$ INTO phone$: position -3, length 3 print area$ // Output: 212 // Modify the source string phone$ = "7022229999" // area$ updates automatically print area$ // Output: 702 // Overwriting a view updates the source lset area$ = "abc" print phone$ // Output: abc2229999 phone$ = "" print area$ // Output: (empty string), since phone$ now has zero length.

The VIEW…MATCH Option

The MATCH option extends the fixed-position VIEW syntax so that the source string is treated as a contiguous array of fixed-width segments. Instead of selecting a single absolute start position, you define:

  • Base Position — where the first segment begins,
  • Record Length — the width of every segment, and
  • Index — which segment (occurrence) you want to view.

This is ideal for processing flat-file segments, binary headers, fixed-layout structures, or tightly packed lists of codes—without doing your own loop arithmetic.

Syntax for the MATCH Option

VIEW view_var$ INTO source_var$, POSITION base, LENGTH size, MATCH index
  • base: The starting position of the first segment (typically 1).
  • size: The fixed width of each segment.
  • index: The segment number to view (1-based).

Multiple Views Inside a CLUSTER

You can also store multiple views inside a CLUSTER, turning a single string into a lightweight, structured record that automatically tracks the source variable. Note: A CLUSTER is a named collection of variables.

cluster parts: area$, exch$ view parts->area$ into phone$ position 1, length 3 view parts->exch$ into phone$ position 5, length 3 phone$ = "702-997-1212" print cluster parts // Outputs: 702, 997 phone$ = "213-555-1212" print cluster parts // Outputs: 213, 555

Key Differences Between MID$() and VIEW

Feature MID$() VIEW
Mechanism Creates a new string (copy) Creates a reference (pointer)
Memory Allocates new memory Points to the existing memory of the source
Behavior Static snapshot Dynamic: updates when the source variable changes
Use Case When you want a fixed value When you want to track changes

VIEW Between -- Using Delimiters (Dynamic BETWEEN)

The extended VIEW syntax allows you to create a dynamic slice of a string variable using start and end delimiters, just like BETWEEN$() — except the result is a live view instead of a copied string.

This makes it the dynamic counterpart to BETWEEN$(), just as the original VIEW ... position/length is the dynamic counterpart to MID$().

Syntax

VIEW view_var$ INTO base_var$ BETWEEN start_delim$, end_delim$

How it works:

  • The statement searches base_var$ for start_delim$ and end_delim$.
  • If start_delim$ is empty, the beginning of base_var$ is assumed.
  • If end_delim$ is empty, the end of base_var$ is assumed.
  • Instead of returning a copied substring, the view variable points directly into the section of base_var$ between the two delimiters.
  • If the delimiters are not found, the view becomes an empty string.
Note:
  • This form of VIEW creates a read-only view except for overlay operations (LSET, OVERLAY()), which modify the corresponding characters in base_var$.

    It also treats delimited regions of a string as live fields. Whenever the base string changes, the view re-locates its delimited region the next time the view variable is referenced (or becomes an empty string if the delimiters are not present). Because the view points directly into the base string, overlaying the view updates the underlying text without copying or rebuilding the string.
  • If base_var$ is reassigned to a new value, the view will re-evaluate its delimiters the next time the view variable is referenced. This ensures the view always corresponds to the current value of base_var$.
  • If the characters in base_var$ shift — for example, due to editing, concatenation, or overlay operations — the view will locate the delimiters again when the view is next used. This guarantees the view reflects the correct, live region of the modified string.
  • The view statement is executable, so any of its expression arguments can be changed at runtime. When evaluated, it updates the corresponding view_var$ when the variable is next referenced.

VIEW_Between Options

  • MATCH — By default, the search uses the first occurrence of the start delimiter paired with the next occurrence of the end delimiter. With MATCH, the engine instead returns the Nth such matching pair.
  • NOTRIM — By default, the substring between the delimiters is trimmed of leading and trailing spaces before it is returned or exposed via the view. Use NOTRIM to preserve the exact characters between the delimiters, including any surrounding whitespace.
  • BALANCED — By default, the search uses the first occurrence of the start delimiter and the very next occurrence of the end delimiter. With BALANCED, the engine instead finds the outer delimited region: starting at the first start delimiter and locating the matching closing delimiter that encloses the full region, including any nested or inner delimiters.

VIEW Example

data$ = "phone=(702) 555-1212 age=42" VIEW area$ INTO data$ BETWEEN "(", ")" VIEW age$ INTO data$ BETWEEN "age=", "" print area$ // Output: 702 print age$ // Output: 42 // Replace the entire base string data$ = "My new phone number is (858) 555-1212" // The view updates automatically print area$ // Output: 858 print age$ // Output: (empty string) // Overlay through the view modifies the source lset area$ = "211" print data$ // Output: My new phone number is (211) 555-1212 // Using MATCH to get a specific occurrence data$ = "phone=(702) 555-(1212) age=42" VIEW area2$ INTO data$ BETWEEN "(", ")" MATCH 2 print area2$ // Output: 1212 data$ = "phone=555-1212 age=42" // Missing parens print area2$ // Output: (empty string) // All VIEW parameters accept runtime expressions list$ = "[apple][banana][cherry]" for occurrence = 1 to 10 VIEW item$ INTO list$ BETWEEN "[", "]" MATCH occurrence if item$ = "" then exit for // No more items print item$ next occurrence // Output (one per line): // apple // banana // cherry // Automatic zero-copy parsing into cluster fields upon reference cluster info: name$, age$, weight$ view info->name$ into data$ between "name=" , ";" view info->age$ into data$ between "age=" , ";" view info->weight$ into data$ between "weight=", ";" data$ = 'name=Fred; age=45; weight=160;' print cluster info // outputs all field values in the cluster called info. data$ = 'weight=120; age=25; name=Sally; ' print cluster info // outputs: // "Fred","45","160" // "Sally","25","120"

Example: Using NOTRIM to Preserve Whitespace

// Base string with padded value data$ = "value=[ 123 ] status=ok" // Default: trims spaces between delimiters VIEW num$ INTO data$ BETWEEN "[", "]" // NOTRIM: keeps the exact characters between delimiters VIEW num_raw$ INTO data$ BETWEEN "[", "]" NOTRIM print "[" + num$ + "]" // Output: [123] print "[" + num_raw$ + "]" // Output: [ 123 ]

Example: Using BALANCED for Outer Delimited Region

data$ = "outer[start [inner] tail] end" // Without BALANCED: first "[" to first "]" after it VIEW inner$ INTO data$ BETWEEN "[", "]" // With BALANCED: first "[" to its matching outer "]" VIEW outer$ INTO data$ BETWEEN "[", "]" BALANCED print inner$ // Output: start [inner print outer$ // Output: start [inner] tail

Behavior Summary

Feature BETWEEN$() VIEW ... BETWEEN
Mechanism Returns a copy Creates a live view
Updates with base changes? No Yes, automatically
Memory Allocates new string No allocation; points to base
Write-through No Yes, using OVERLAY/LSET
Hide Description

    

       


      

Enter or modify the code below, and then click on RUN

Looking for the full power of Sheerpower?
Check out the Sheerpower website. Free to download. Free to use.