Updated 2014-06-07 17:14:09 by dkf

GN This is a simple study for a chan command as suggested in TIP 208 by using XOTcl. The following commands are implemented
    chan blocked     ; # fblocked
    chan close       ; # close
    chan fconfigure  ; # fconfigure
    chan open        ; # open
    chan puts        ; # puts

We define here a Class chan, which is used to provide an ensemble-like interface as well as an object oriented interface (creating instances). We use here xotcl's forwarding mechanism. The same could be achieved via renaming or by implementing the methods in C.
  Class chan 
  chan proc unknown {m args} {
    chan puts "unknown chan method '$m $args' called
            defined: [lsort [my info commands]]"
  }
  chan forward blocked    ::fblocked
  chan forward close      ::close
  chan forward fconfigure ::fconfigure
  chan forward open       ::open
  chan forward puts       ::puts 

Now we can use the chan command:
  set c [chan open /tmp/junk w]
  chan puts -nonewline $c "hello"
  chan puts $c " world"
  chan close $c
  chan xxx

In order to define an OO interface for streams, we can extend the definitions:
  # allow configuration of a stream name
  chan parameter stream

  # redefine "new" such it creates and
  # opens a stream and creates as well an instance
  chan proc new args { 
    set stream [eval chan open $args]
    my create $stream -stream $stream  ;# create object
  }
  # close stream and destroy object
  chan instproc destroy {} {
    chan close [my stream]
    next
  }
  # handle other subcommands (methods) via unknown
  chan instproc unknown {m args} {
    set valid [lsort [chan info instcommands]]
    stderr puts "unknown chan method '$m' $args called; 
              defined methods: $valid"
  }
  # define forwarders to the chan ensemble
  chan instforward puts ::chan puts {%@-1 %my stream}
  chan instforward blocked ::chan fblocked {%my stream}
  chan instforward fconfigure ::chan fconfigure {%my stream} 

  # create standard streams
  chan create stdout -stream stdout
  chan create stderr -stream stderr

Now we can use the chan OO interface:
  set c [chan new /tmp/junk w]
  $c puts -nonewline "hello"
  $c puts -nonewline " world"
  $c puts ""
  $c xxx
  stderr puts "currently open streams: [chan info instances]"
  $c destroy
  stderr puts "currently open streams: [chan info instances]"

A reflection interface an be established

  • on the object level (per stream) via a mixin class, or
  • on the class level (for all streams) via a instmixin class,
  • as well as a mixin on the chan command...
  Class StreamReflect
  foreach m {puts blocked fconfigure} {
    StreamReflect instproc $m args {
      puts stderr "  before [self proc] $args"
      set r [next]
      puts stderr "  after [self proc] returning <$r>"  
      return $r
    }
  } 

  puts ===== 
  chan instmixin StreamReflect
  set c [chan new /tmp/junk w]
  $c puts "hello"
  stderr puts "currently open streams: [chan info instances]"
  $c destroy
  puts ===== 

  chan mixin StreamReflect
  set c [chan open /tmp/junk w]
  chan puts $c "hello"
  chan close $c
  puts =====