Sequoia

Sequoia seq library
Login

A library for lazy sequences heavily inspired by clojure seq's and stdlib

Goals

Design

A seq is a command which:

This makes a coroutine a very natural choice to implement a sequence. They can be used to wrap other Tcl iterators such as an TclOO based ones to allow cleanup after the last successful call for a next element. Because the command is expanded, subcommands such as {cmd next} are also good choices to implement a seq.

The general pattern with coroutines as also used in the standard library is:

  proc seqtypeimpl {arg1 .....} {
    # init based on arg1 ......

    # return the name
    yield [info coroutine]
    
    # yield elements
    yield [list $elem true]

    # cleanup
    return {{} false}
  }

  proc seqtype {arg1 .....} {
    return [::seq::createcoro seqtypeimpl arg1 .....]
  }


  # loop over a seq
  while {[lassign [{*}$seq] val]} { # do something with $val }


It's good practice to use [::seq::seqname] to create a proc name for the seq to be created. This also allows easy monitoring of leaked seqs.

Function calls

Whenever a command accepts a function, either a prefix command or a lambda can be passed The difference can be indicated by the first character. Lambdas will start with &. For example:

  set l {&x {puts $x}}
Defines a one argument lambda. If a prefix command is passed the command will be expanded and the arguments appended.

Standard Library

first seq

Return the first element from seq.

seqname

Helper to create a unique seq command name. The commands names are created in the ::seq::seqs namespace.

createcoro cmd args

Helper to create a seq command with coroutine backed by impl. Pass {*}$args to the coroutine command. Uses [seqname] to generate the seq command name

listseq list

Create a sequence from a list.

lineseq chan

Create a sequence of lines retrieved with [gets] from chan.

do f seq

Execute the one argument function f for every seq element

map f seq

return a new seq with f applied to every element of seq.

take count seq

take the first count elements from seq and return them as a list

takeseq count seq

take the first count elements from seq and return them as a new seq

dup count seq

duplicate the first count elements and return the new seq

iterate f x

create an infinite sequence of {x [f x] [f [f x]] ....}

iterate-until pred f x

create an sequence of {x [f x] [f [f x]] ....} stop when pred becomes true the element where pred is true is not included in the sequence

range start end

create a sequence with items start to end (inclusive)

into type arg seq

realize the seq into an eager tcl string.

cons item seq

prepend item to the seq and return the new seq

peek seq

get the first element of seq without removing it NB: this obviously will realize the first element

drop seq

drop the first element of seq.

filter pred seq

Return a new seq with all elements from seq for which the predicate pred is true. pred is handled as decribed in the Function Calls section.

reduce start f seq

Reduce the seq with f on start