proc pipedata {data args} {
    #puts stderr "'$args'"
    set r $data
    for {set i 0} {$i < [llength $args]} {incr i} {
        set e [lindex $args $i]
        if {[catch {llength $e} seglen]} {
                #not a list - assume script and run anyway
                set r [apply [list {data} $e] $r]
        } else {
            if {[llength $e] == 1} {
                if {$e eq {>}} {
                    #output to calling context. only pipedata return value and '> varname' should affect caller.
                    incr i
                    uplevel 1 [list set [lindex $args $i] $r]
                } elseif {$e in {% pipematch ispipematch}} {
                    incr i
                    set e2 [lindex $args $i]
                    #set body [list $e {*}$e2] 
                    #append body { $data}
                    
                    set body [list $e {*}$e2] 
                    append body { {*}$data}
                    
                    
                    set applylist [list {data}  $body]
                    #puts stderr $applylist
                    set r [apply $applylist $r]
                } elseif {$e in [list pipeswitch pipeswitchc]} {
                    #pipeswitch takes a script not a list.
                    incr i
                    set e2 [lindex $args $i]
                    set body [list $e $e2]
                    #pipeswitch takes 'args' - so expand $data when in pipedata context 
                    append body { {*}$data}
                    #use applylist instead of uplevel when in pipedata context!
                    #can use either switchdata/data but not vars in calling context of 'pipedata' command.
                    #this is consistent with pipeswitch running in a % / .= pipeline which can only access vars in immediate calling context.
                    set applylist [list {data} $body]
                    #puts stderr $applylist
                    set r [apply $applylist $r]
                } else {
                    #puts "other single arg: [list $e $r]"
                    append e { $data}
                    set r [apply [list {data} $e] $r]
                }
            } else {
                set r [apply [list {data} $e] $r]
            }
        }
    }
    return $r
}

set s "    supercalifragilistichespiralitoso    "
pipedata  $s  {string trim $data} {split $data {}} {lsort -unique $data} {join $data {}} > s \
        {string length $data} > l
puts $s
puts $l

#test running of patternmatching pipelines within pipe*
set x [list a b blah etc]
puts "-1"
pipedata $x {,'a'@0/0= |@0> {puts $data; set data} <| $data} {val $data}

puts "-2"
pipedata $x {,'a'@0/0= |@0> {
            puts $data
            set data
        } <| $data} {val $data}
        
pipeset pipe1 ,'a'@0/0= |/0-1> {puts $data; set data} |> string toupper <|
puts "-3"
pipedata $x pipematch $pipe1