adds lots of helpful methods that can be done on enumerable methods. based on the 'each' method being available on the self.

Mimics
Inactive cells
Active cells
Specs
Inactive cells (details)
kind = "Mixins Enumerable"
Active cells (details)
all?(...)

takes zero, one or two arguments. if zero arguments, returns false if any of the elements yielded by each is false, otherwise true. if one argument, expects it to be a message chain. if that message chain, when applied to the current element returns a false value, the method returns false. finally, if two arguments are given, the first argument is an unevaluated name and the second is a code element. these will together be turned into a lexical block and tested against the values in this element. if it returns false for any element, this method returns false, otherwise true.

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      0), 
    
    
    
    
    self each(n, 
      x = cell(:n) 
      unless(cell(:x), 
        return(false))) 
    true, 
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    
    
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      unless(cell(:x), 
        return(false))) 
    true, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    
    
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      unless(cell(:x), 
        return(false))) 
    true, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
any?(...)

takes zero, one or two arguments. if zero arguments, returns true if any of the elements yielded by each is true, otherwise false. if one argument, expects it to be a message chain. if that message chain, when applied to the current element returns a true value, the method returns true. finally, if two arguments are given, the first argument is an unevaluated name and the second is a code element. these will together be turned into a lexical block and tested against the values in this element. if it returns true for any element, this method returns true, otherwise false.

macro(
  argCount = call arguments length 
  if(
    argCount ==(
      0), 
    
    
    
    
    self each(n, 
      x = cell(:n) 
      if(cell(:x), 
        return(true))) 
    false, 
    if(
      argCount ==(
        1), 
      
      theCode = call arguments [](
          0) 
      
      
      
      self each(n, 
        x = theCode evaluateOn(call ground, cell(:n)) 
        if(cell(:x), 
          return(true))) 
      false, 
      if(
        argCount ==(
          2), 
        
        argName = call arguments [](
            0) 
        theCode = call arguments [](
            1) 
        
        
        
        destructor = Destructor from(argName) 
        lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
        self each(n, 
          x = lexicalCode call(*(destructor unpack(cell(:n)))) 
          if(cell(:x), 
            return(true))) 
        false, 
        error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)))) 
  )
asList()

will return a list created from calling each on the receiver until everything has been yielded. if a more efficient version is possible of this, the object should implement it, since other Enumerable methods will use this for some operations. note that asList is not required to return a new list

method(
  result = list 
  self each(n, result <<(cell(:n))) 
  result)
asTuple()

will return a tuple created from calling each on the receiver until everything has been yielded.

method(
  tuple(*(asList)))
collect(...)

nil

macro(
  argCount = call arguments length 
  if(
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    result = list 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      result <<(cell(:x))) 
    result, 
    if(
      argCount ==(
        2), 
      
      argName = call arguments [](
          0) 
      theCode = call arguments [](
          1) 
      
      result = list 
      destructor = Destructor from(argName) 
      lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
      self each(n, 
        x = lexicalCode call(*(destructor unpack(cell(:n)))) 
        result <<(cell(:x))) 
      result, 
      error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext))) 
  )
collect:dict(...)

nil

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    result = dict 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      if(cell(:x) kind ==("Pair"), 
        result [](x key) = x value, 
        result [](cell(:x)) = nil)) 
    result, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    result = dict 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      if(cell(:x) kind ==("Pair"), 
        result [](x key) = x value, 
        result [](cell(:x)) = nil)) 
    result, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
collect:list(...)

nil

macro(
  argCount = call arguments length 
  if(
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    result = list 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      result <<(cell(:x))) 
    result, 
    if(
      argCount ==(
        2), 
      
      argName = call arguments [](
          0) 
      theCode = call arguments [](
          1) 
      
      result = list 
      destructor = Destructor from(argName) 
      lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
      self each(n, 
        x = lexicalCode call(*(destructor unpack(cell(:n)))) 
        result <<(cell(:x))) 
      result, 
      error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext))) 
  )
collect:set(...)

nil

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    result = set 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      result <<(cell(:x))) 
    result, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    result = set 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      result <<(cell(:x))) 
    result, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
collectFn(+blocks)

nil

method(+blocks, 
  result = list 
  self each(n, 
    current = cell(:n) 
    blocks each(b, current = cell(:b) call(cell(:current))) 
    result <<(current)) 
  result)
collectFn:dict(+blocks)

nil

method(+blocks, 
  result = dict 
  self each(n, 
    current = cell(:n) 
    blocks each(b, current = cell(:b) call(cell(:current))) 
    if(cell(:current) mimics?(Pair), 
      result [](current key) = current value, 
      result [](cell(:current)) = nil) 
    ) 
  result)
collectFn:set(+blocks)

nil

method(+blocks, 
  result = set 
  self each(n, 
    current = cell(:n) 
    blocks each(b, current = cell(:b) call(cell(:current))) 
    result <<(current)) 
  result)
count(...)

takes zero, one or two arguments. if zero arguments, returns the number of elements in the collection. if one argument, expects it to be a message chain. if that message chain, that will be used as a predicate. returns the number of elements where the predicate returns true. finally, if two arguments are given, the first argument is an unevaluated name and the second is a code element. these will together be turned into a lexical block and used as a predicate, and the result will be the number of elements matching the predicate.

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      0), 
    
    
    result = 0 
    argLength = call arguments length 
    self each(n, 
      x = cell(:n) 
      if(cell(:x) ||(argLength ==(0)), 
        ++(result))) 
    result, 
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    result = 0 
    argLength = call arguments length 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      if(cell(:x) ||(argLength ==(0)), 
        ++(result))) 
    result, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    result = 0 
    argLength = call arguments length 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      if(cell(:x) ||(argLength ==(0)), 
        ++(result))) 
    result, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
cycle(...)

takes one or two arguments and cycles over the elements of this collection. the cycling will be done by calling each once and collecting the result, and then using this to continue cycling. if one argument is given, it should be a message chain to apply. if two arguments are given, they will be turned into a lexical block and applied. if the collection is empty, returns nil.

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    internal = list 
    self each(n, 
      internal <<(cell(:n)) 
      theCode evaluateOn(call ground, cell(:n))) 
    if(internal empty?, return(nil)) 
    loop(internal each(x, theCode evaluateOn(call ground, cell(:x)))), 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    internal = list 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      internal <<(cell(:n)) 
      lexicalCode call(*(destructor unpack(cell(:n))))) 
    if(internal empty?, return(nil)) 
    loop(internal each(x, lexicalCode call(*(destructor unpack(cell(:x)))))), 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
detect(...)

nil

macro(
  argCount = call arguments length 
  if(
    argCount ==(
      0), 
    
    
    
    
    self each(n, 
      x = cell(:n) 
      if(cell(:x), 
        return(cell(:n)))) 
    nil, 
    if(
      argCount ==(
        1), 
      
      theCode = call arguments [](
          0) 
      
      
      
      self each(n, 
        x = theCode evaluateOn(call ground, cell(:n)) 
        if(cell(:x), 
          return(cell(:n)))) 
      nil, 
      if(
        argCount ==(
          2), 
        
        argName = call arguments [](
            0) 
        theCode = call arguments [](
            1) 
        
        
        
        destructor = Destructor from(argName) 
        lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
        self each(n, 
          x = lexicalCode call(*(destructor unpack(cell(:n)))) 
          if(cell(:x), 
            return(cell(:n)))) 
        nil, 
        error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)))) 
  )
drop(howMany)

takes one argument and returns a list of all the elements in this object except for how many that should be avoided.

method(howMany, 
  result = list 
  currentCount = howMany 
  self each(n, 
    if(currentCount >(0), 
      --(currentCount), 
      result <<(cell(:n)))) 
  result)
drop:dict(howMany)

takes one argument and returns a dict of all the elements in this object except for how many that should be avoided.

method(howMany, 
  result = dict 
  currentCount = howMany 
  self each(n, 
    if(currentCount >(0), 
      --(currentCount), 
      if(cell(:n) mimics?(Pair), 
        result [](n key) = n value, 
        result [](cell(:n)) = nil))) 
  result)
drop:set(howMany)

takes one argument and returns a set of all the elements in this object except for how many that should be avoided.

method(howMany, 
  result = set 
  currentCount = howMany 
  self each(n, 
    if(currentCount >(0), 
      --(currentCount), 
      result <<(cell(:n)))) 
  result)
dropWhile(...)

takes zero, one or two arguments. it will evaluate a predicate once for each element, and avoid all the elements until the predicate returns false for the first time, then it will start collecting data. if zero arguments, the predicate is the element itself. if one argument, expects it to be a message chain to apply as a predicate. if two arguments are given, the first argument is an unevaluated name and the second is a code element. these will together be turned into a lexical block and used as the predicate.

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      0), 
    
    
    result = list 
    collecting = false 
    self each(n, 
      x = cell(:n) 
      if(collecting, 
        result <<(cell(:n)), 
        unless(cell(:x), 
          collecting = true 
          result <<(cell(:n))))) 
    result, 
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    result = list 
    collecting = false 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      if(collecting, 
        result <<(cell(:n)), 
        unless(cell(:x), 
          collecting = true 
          result <<(cell(:n))))) 
    result, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    result = list 
    collecting = false 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      if(collecting, 
        result <<(cell(:n)), 
        unless(cell(:x), 
          collecting = true 
          result <<(cell(:n))))) 
    result, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
dropWhile:dict(...)

takes zero, one or two arguments. it will evaluate a predicate once for each element, and avoid all the elements until the predicate returns false for the first time, then it will start collecting data. if zero arguments, the predicate is the element itself. if one argument, expects it to be a message chain to apply as a predicate. if two arguments are given, the first argument is an unevaluated name and the second is a code element. these will together be turned into a lexical block and used as the predicate.

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      0), 
    
    
    result = dict 
    collecting = false 
    self each(n, 
      x = cell(:n) 
      if(collecting, 
        if(cell(:n) mimics?(Pair), 
          result [](n key) = n value, 
          result [](cell(:n)) = nil), 
        unless(cell(:x), 
          collecting = true 
          if(cell(:n) mimics?(Pair), 
            result [](n key) = n value, 
            result [](cell(:n)) = nil)))) 
    result, 
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    result = dict 
    collecting = false 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      if(collecting, 
        if(cell(:n) mimics?(Pair), 
          result [](n key) = n value, 
          result [](cell(:n)) = nil), 
        unless(cell(:x), 
          collecting = true 
          if(cell(:n) mimics?(Pair), 
            result [](n key) = n value, 
            result [](cell(:n)) = nil)))) 
    result, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    result = dict 
    collecting = false 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      if(collecting, 
        if(cell(:n) mimics?(Pair), 
          result [](n key) = n value, 
          result [](cell(:n)) = nil), 
        unless(cell(:x), 
          collecting = true 
          if(cell(:n) mimics?(Pair), 
            result [](n key) = n value, 
            result [](cell(:n)) = nil)))) 
    result, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
dropWhile:set(...)

takes zero, one or two arguments. it will evaluate a predicate once for each element, and avoid all the elements until the predicate returns false for the first time, then it will start collecting data. if zero arguments, the predicate is the element itself. if one argument, expects it to be a message chain to apply as a predicate. if two arguments are given, the first argument is an unevaluated name and the second is a code element. these will together be turned into a lexical block and used as the predicate.

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      0), 
    
    
    result = set 
    collecting = false 
    self each(n, 
      x = cell(:n) 
      if(collecting, 
        result <<(cell(:n)), 
        unless(cell(:x), 
          collecting = true 
          result <<(cell(:n))))) 
    result, 
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    result = set 
    collecting = false 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      if(collecting, 
        result <<(cell(:n)), 
        unless(cell(:x), 
          collecting = true 
          result <<(cell(:n))))) 
    result, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    result = set 
    collecting = false 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      if(collecting, 
        result <<(cell(:n)), 
        unless(cell(:x), 
          collecting = true 
          result <<(cell(:n))))) 
    result, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
eachCons(...)

takes one, two or three arguments. if one argument, assumes this to be a message chain and the cons length to be two. if two arguments, expects the first to be the cons length and the second to be the message chain. if three, expects the first to be the cons length, the second to be a variable name and the third to be a message chain. will yield lists of length consLength counting from the beginning of the enumerable

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      1), 
    
    code = call arguments [](
        0) 
    
    consLength = 2 
    ary = list 
    
    self each(n, 
      if(ary length ==(consLength), 
        ary shift!) 
      ary push!(n) 
      if(ary length ==(consLength), 
        code evaluateOn(call ground, ary mimic)) 
      ) 
    self 
    , 
    argCount ==(
      2), 
    
    consLength = call argAt(
        0) 
    code = call arguments [](
        1) 
    
    ary = list 
    
    self each(n, 
      if(ary length ==(consLength), 
        ary shift!) 
      ary push!(n) 
      if(ary length ==(consLength), 
        code evaluateOn(call ground, ary mimic)) 
      ) 
    self 
    , 
    argCount ==(
      3), 
    
    consLength = call argAt(
        0) 
    argName = call arguments [](
        1) 
    code = call arguments [](
        2) 
    
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(code)), call ground) 
    ary = list 
    
    self each(n, 
      if(ary length ==(consLength), 
        ary shift!) 
      ary push!(n) 
      if(ary length ==(consLength), 
        lexicalCode call(*(destructor unpack(ary mimic)))) 
      ) 
    self 
    , 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
eachSlice(...)

takes one, two or three arguments. if one argument, assumes this to be a message chain and the slice length to be two. if two arguments, expects the first to be the slice length and the second to be the message chain. if three, expects the first to be the slice length, the second to be a variable name and the third to be a message chain. will yield lists of length sliceLength counting from the beginning of the enumerable

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      1), 
    
    code = call arguments [](
        0) 
    
    sliceLength = 2 
    ary = list 
    
    self each(n, 
      ary push!(n) 
      if(ary length ==(sliceLength), 
        code evaluateOn(call ground, ary) 
        ary = list) 
      ) 
    if(ary length >(0), code evaluateOn(call ground, ary)) 
    self 
    , 
    argCount ==(
      2), 
    
    sliceLength = call argAt(
        0) 
    code = call arguments [](
        1) 
    
    ary = list 
    
    self each(n, 
      ary push!(n) 
      if(ary length ==(sliceLength), 
        code evaluateOn(call ground, ary) 
        ary = list) 
      ) 
    if(ary length >(0), code evaluateOn(call ground, ary)) 
    self 
    , 
    argCount ==(
      3), 
    
    sliceLength = call argAt(
        0) 
    argName = call arguments [](
        1) 
    code = call arguments [](
        2) 
    
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(code)), call ground) 
    ary = list 
    
    self each(n, 
      ary push!(n) 
      if(ary length ==(sliceLength), 
        lexicalCode call(*(destructor unpack(ary))) 
        ary = list) 
      ) 
    if(ary length >(0), lexicalCode call(*(destructor unpack(ary)))) 
    self 
    , 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
filter(...)

nil

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      0), 
    
    
    result = list 
    self each(n, 
      x = cell(:n) 
      if(cell(:x), 
        result <<(cell(:n)))) 
    result, 
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    result = list 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      if(cell(:x), 
        result <<(cell(:n)))) 
    result, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    result = list 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      if(cell(:x), 
        result <<(cell(:n)))) 
    result, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
filter:dict(...)

nil

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      0), 
    
    
    result = dict 
    self each(n, 
      x = cell(:n) 
      if(cell(:x), 
        if(cell(:n) mimics?(Pair), 
          result [](n key) = n value, 
          result [](cell(:n)) = nil))) 
    result, 
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    result = dict 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      if(cell(:x), 
        if(cell(:n) mimics?(Pair), 
          result [](n key) = n value, 
          result [](cell(:n)) = nil))) 
    result, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    result = dict 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      if(cell(:x), 
        if(cell(:n) mimics?(Pair), 
          result [](n key) = n value, 
          result [](cell(:n)) = nil))) 
    result, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
filter:set(...)

nil

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      0), 
    
    
    result = set 
    self each(n, 
      x = cell(:n) 
      if(cell(:x), 
        result <<(cell(:n)))) 
    result, 
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    result = set 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      if(cell(:x), 
        result <<(cell(:n)))) 
    result, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    result = set 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      if(cell(:x), 
        result <<(cell(:n)))) 
    result, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
find(...)

takes zero, one or two arguments. if zero arguments, returns the first element that is true, otherwise nil. if one argument, expects it to be a message chain. if that message chain, when applied to the current element returns a true value, the corresponding element is returned. finally, if two arguments are given, the first argument is an unevaluated name and the second is a code element. these will together be turned into a lexical block and tested against the values in this element. if it returns true for any element, the element will be retuend, otherwise nil.

macro(
  argCount = call arguments length 
  if(
    argCount ==(
      0), 
    
    
    
    
    self each(n, 
      x = cell(:n) 
      if(cell(:x), 
        return(cell(:n)))) 
    nil, 
    if(
      argCount ==(
        1), 
      
      theCode = call arguments [](
          0) 
      
      
      
      self each(n, 
        x = theCode evaluateOn(call ground, cell(:n)) 
        if(cell(:x), 
          return(cell(:n)))) 
      nil, 
      if(
        argCount ==(
          2), 
        
        argName = call arguments [](
            0) 
        theCode = call arguments [](
            1) 
        
        
        
        destructor = Destructor from(argName) 
        lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
        self each(n, 
          x = lexicalCode call(*(destructor unpack(cell(:n)))) 
          if(cell(:x), 
            return(cell(:n)))) 
        nil, 
        error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)))) 
  )
findAll(...)

nil

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      0), 
    
    
    result = list 
    self each(n, 
      x = cell(:n) 
      if(cell(:x), 
        result <<(cell(:n)))) 
    result, 
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    result = list 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      if(cell(:x), 
        result <<(cell(:n)))) 
    result, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    result = list 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      if(cell(:x), 
        result <<(cell(:n)))) 
    result, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
findAll:dict(...)

nil

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      0), 
    
    
    result = dict 
    self each(n, 
      x = cell(:n) 
      if(cell(:x), 
        if(cell(:n) mimics?(Pair), 
          result [](n key) = n value, 
          result [](cell(:n)) = nil))) 
    result, 
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    result = dict 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      if(cell(:x), 
        if(cell(:n) mimics?(Pair), 
          result [](n key) = n value, 
          result [](cell(:n)) = nil))) 
    result, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    result = dict 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      if(cell(:x), 
        if(cell(:n) mimics?(Pair), 
          result [](n key) = n value, 
          result [](cell(:n)) = nil))) 
    result, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
findAll:set(...)

nil

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      0), 
    
    
    result = set 
    self each(n, 
      x = cell(:n) 
      if(cell(:x), 
        result <<(cell(:n)))) 
    result, 
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    result = set 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      if(cell(:x), 
        result <<(cell(:n)))) 
    result, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    result = set 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      if(cell(:x), 
        result <<(cell(:n)))) 
    result, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
findIndex(...)

takes zero, one or two arguments. if zero arguments, returns the index of the first element that is true, otherwise nil. if one argument, expects it to be a message chain. if that message chain, when applied to the current element returns a true value, the corresponding element index is returned. finally, if two arguments are given, the first argument is an unevaluated name and the second is a code element. these will together be turned into a lexical block and tested against the values in this element. if it returns true for any element, the element index will be returned, otherwise nil.

macro(
  argCount = call arguments length 
  if(
    argCount ==(
      0), 
    
    
    self each(ix, n, if(cell(:n), return(ix))) 
    nil, 
    if(
      argCount ==(
        1), 
      
      theCode = call arguments [](
          0) 
      
      self each(ix, n, if(theCode evaluateOn(call ground, cell(:n)), return(ix))) 
      nil, 
      if(
        argCount ==(
          2), 
        
        argName = call arguments [](
            0) 
        theCode = call arguments [](
            1) 
        
        destructor = Destructor from(argName) 
        lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
        self each(ix, n, if(lexicalCode call(*(destructor unpack(cell(:n)))), return(ix))) 
        nil, 
        error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)))) 
  )
first(howMany nil)

takes one optional argument. if no argument is given, first will return the first element in the collection, or nil if no such element exists. if an argument is given, it should be a number describing how many elements to get. the return value will be a list in that case

method(howMany nil, 
  if(howMany, 
    result = list 
    self each(n, 
      if(howMany ==(0), return(result)) 
      --(howMany) 
      result <<(cell(:n))) 
    return(result), 
    self each(n, return(cell(:n))) 
    return(nil)))
first:dict(howMany)

takes one argument. the argument should be a number describing how many elements to get. the return value will be a dict

method(howMany, 
  result = dict 
  self each(n, 
    if(howMany ==(0), return(result)) 
    --(howMany) 
    if(cell(:n) mimics?(Pair), 
      result [](n key) = n value, 
      result [](cell(:n)) = nil)) 
  return(result))
first:set(howMany)

takes one argument. the argument should be a number describing how many elements to get. the return value will be a set

method(howMany, 
  result = set 
  self each(n, 
    if(howMany ==(0), return(result)) 
    --(howMany) 
    result <<(cell(:n))) 
  return(result))
flatMap(...)

expects to get the same kind of arguments as map, and that each map operation returns a list. these lists will then be folded into a single list.

macro(
  call resendToMethod("map") fold(+))
flatMap:dict(...)

expects to get the same kind of arguments as map:dict, and that each map operation returns a dict for key. these dicts will then be folded into a single dict.

macro(
  call resendToMethod("map:dict") fold({}, sum, arg, 
    arg key each(val, 
      sum [](val key) = val value) 
    sum) 
  )
flatMap:list(...)

nil

macro(
  call resendToMethod("map") fold(+))
flatMap:set(...)

expects to get the same kind of arguments as map:set, and that each map operation returns a set. these sets will then be folded into a single set.

macro(
  call resendToMethod("map:set") fold(+))
fold(...)

nil

macro(
  argCount = call arguments length 
  if(
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    theCode = theCode deepCopy 
    elementName = genSym 
    theCode last <<(message(elementName)) 
    sum = nil 
    self each(i, n, 
      if(i ==(0), 
        sum = cell(:n), 
        call ground cell(elementName) = cell(:n) 
        sum = theCode evaluateOn(call ground, cell(:sum)))) 
    return(cell(:sum)), 
    if(
      argCount ==(
        2), 
      
      argName = call arguments [](
          0) 
      theCode = call arguments [](
          1) 
      
      elementName = argName name 
      sum = nil 
      self each(i, n, 
        if(i ==(0), 
          sum = cell(:n), 
          call ground cell(elementName) = cell(:n) 
          sum = theCode evaluateOn(call ground, cell(:sum)))) 
      return(cell(:sum)), 
      if(
        argCount ==(
          3), 
        
        sumArgName = call arguments [](
            0) 
        argName = call arguments [](
            1) 
        theCode = call arguments [](
            2) 
        
        destructor = Destructor from(argName) 
        lexicalCode = LexicalBlock createFrom(list(sumArgName) +(destructor argNames) +(list(theCode)), call ground) 
        sum = nil 
        self each(i, n, 
          if(i ==(0), 
            sum = cell(:n), 
            sum = lexicalCode call(cell(:sum), *(destructor unpack(cell(:n)))))) 
        return(cell(:sum)), 
        if(
          argCount ==(
            4), 
          
          sum = call argAt(
              0) 
          sumArgName = call arguments [](
              1) 
          argName = call arguments [](
              2) 
          theCode = call arguments [](
              3) 
          
          destructor = Destructor from(argName) 
          lexicalCode = LexicalBlock createFrom(list(sumArgName) +(destructor argNames) +(list(theCode)), call ground) 
          self each(n, 
            sum = lexicalCode call(cell(:sum), *(destructor unpack(cell(:n))))) 
          return(cell(:sum)), 
          error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext))))) 
  )
grep(...)

takes one, two or three arguments. grep will first find any elements in the collection matching the first argument with '==='. if two or three arguments are given, these will be used to transform the matching object and then add the transformed version instead of the original element to the result list. the two argument version expects the second argument to be a message chain, and the three argument version expects it to be something that can be turned into a lexical block

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      1), 
    
    matchingAgainst = call argAt(
        0) 
    
    result = list 
    self each(n, 
      if(matchingAgainst ===(cell(:n)), 
        result <<(cell(:n)))) 
    result, 
    argCount ==(
      2), 
    
    matchingAgainst = call argAt(
        0) 
    theCode = call arguments [](
        1) 
    
    result = list 
    self each(n, 
      if(matchingAgainst ===(cell(:n)), 
        result <<(theCode evaluateOn(call ground, cell(:n))))) 
    result, 
    argCount ==(
      3), 
    
    matchingAgainst = call argAt(
        0) 
    argName = call arguments [](
        1) 
    theCode = call arguments [](
        2) 
    
    destructor = Destructor from(argName) 
    result = list 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      if(matchingAgainst ===(cell(:n)), 
        result <<(lexicalCode call(*(destructor unpack(cell(:n))))))) 
    result, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
grep:set(...)

takes one, two or three arguments. grep will first find any elements in the collection matching the first argument with '==='. if two or three arguments are given, these will be used to transform the matching object and then add the transformed version instead of the original element to the result set. the two argument version expects the second argument to be a message chain, and the three argument version expects it to be something that can be turned into a lexical block

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      1), 
    
    matchingAgainst = call argAt(
        0) 
    
    result = set 
    self each(n, 
      if(matchingAgainst ===(cell(:n)), 
        result <<(cell(:n)))) 
    result, 
    argCount ==(
      2), 
    
    matchingAgainst = call argAt(
        0) 
    theCode = call arguments [](
        1) 
    
    result = set 
    self each(n, 
      if(matchingAgainst ===(cell(:n)), 
        result <<(theCode evaluateOn(call ground, cell(:n))))) 
    result, 
    argCount ==(
      3), 
    
    matchingAgainst = call argAt(
        0) 
    argName = call arguments [](
        1) 
    theCode = call arguments [](
        2) 
    
    destructor = Destructor from(argName) 
    result = set 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      if(matchingAgainst ===(cell(:n)), 
        result <<(lexicalCode call(*(destructor unpack(cell(:n))))))) 
    result, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
group()

returns a dict where all the keys are distinct elements in the enumerable, and each value is a list of all the values that are equivalent

method(
  groupBy)
groupBy(...)

takes zero, one or two arguments. it will evaluate all the elements in the enumerable and return a dictionary where the keys will be the result of evaluating the arguments and the value will be a list of all the original values that match that key.

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      0), 
    
    
    result = dict 
    self each(n, 
      x = cell(:n) 
      if(result key?(cell(:x)), 
        result [](cell(:x)) <<(cell(:n)), 
        result [](cell(:x)) = list(cell(:n)))) 
    result, 
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    result = dict 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      if(result key?(cell(:x)), 
        result [](cell(:x)) <<(cell(:n)), 
        result [](cell(:x)) = list(cell(:n)))) 
    result, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    result = dict 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      if(result key?(cell(:x)), 
        result [](cell(:x)) <<(cell(:n)), 
        result [](cell(:x)) = list(cell(:n)))) 
    result, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
include?(toFind)

takes one argument and returns true if this element is in the collection. comparisons is done with ==.

method(toFind, 
  self each(n, 
    if(toFind ==(cell(:n)), 
      return(true))) 
  return(false))
inject(...)

takes one, two, three or four arguments. all versions need an initial sum, code to execute, a place to put the current sum in the code, and a place to stick the current element of the enumerable. if one argument, it has to be a message chain. this message chain will be applied on the current sum. the element will be appended to the argument list of the last message send in the chain. the initial sum is the first element, and the code will be executed once less than the size of the enumerable due to this. if two arguments given, the first argument is the name of the variable to put the current element in, and the message will still be sent to the sum - and the initial sum works the same way as for one argument. when three arguments are given, the whole thing will be turned into a lexical closure, where the first argument is the name of the sum variable, the second argument is the name of the element variable, and the last argument is the code. when given four arguments, the only difference is that the first argument will be evaluated as the initial sum.

macro(
  argCount = call arguments length 
  if(
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    theCode = theCode deepCopy 
    elementName = genSym 
    theCode last <<(message(elementName)) 
    sum = nil 
    self each(i, n, 
      if(i ==(0), 
        sum = cell(:n), 
        call ground cell(elementName) = cell(:n) 
        sum = theCode evaluateOn(call ground, cell(:sum)))) 
    return(cell(:sum)), 
    if(
      argCount ==(
        2), 
      
      argName = call arguments [](
          0) 
      theCode = call arguments [](
          1) 
      
      elementName = argName name 
      sum = nil 
      self each(i, n, 
        if(i ==(0), 
          sum = cell(:n), 
          call ground cell(elementName) = cell(:n) 
          sum = theCode evaluateOn(call ground, cell(:sum)))) 
      return(cell(:sum)), 
      if(
        argCount ==(
          3), 
        
        sumArgName = call arguments [](
            0) 
        argName = call arguments [](
            1) 
        theCode = call arguments [](
            2) 
        
        destructor = Destructor from(argName) 
        lexicalCode = LexicalBlock createFrom(list(sumArgName) +(destructor argNames) +(list(theCode)), call ground) 
        sum = nil 
        self each(i, n, 
          if(i ==(0), 
            sum = cell(:n), 
            sum = lexicalCode call(cell(:sum), *(destructor unpack(cell(:n)))))) 
        return(cell(:sum)), 
        if(
          argCount ==(
            4), 
          
          sum = call argAt(
              0) 
          sumArgName = call arguments [](
              1) 
          argName = call arguments [](
              2) 
          theCode = call arguments [](
              3) 
          
          destructor = Destructor from(argName) 
          lexicalCode = LexicalBlock createFrom(list(sumArgName) +(destructor argNames) +(list(theCode)), call ground) 
          self each(n, 
            sum = lexicalCode call(cell(:sum), *(destructor unpack(cell(:n))))) 
          return(cell(:sum)), 
          error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext))))) 
  )
join(separator "")

returns a string created by converting each element of the array to text, separated by an optional separator

method(separator "", 
  result = "" 
  self each(index, n, 
    +=(result, (n asText)) 
    if(index <(count -(1)), +=(result, separator))) 
  result)
map(...)

takes one or two arguments. if one argument is given, it will be evaluated as a message chain on each element in the enumerable, and then the result will be collected in a new List. if two arguments are given, the first one should be an unevaluated argument name, which will be bound inside the scope of executing the second piece of code. it's important to notice that the one argument form will establish no context, while the two argument form establishes a new lexical closure.

macro(
  argCount = call arguments length 
  if(
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    result = list 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      result <<(cell(:x))) 
    result, 
    if(
      argCount ==(
        2), 
      
      argName = call arguments [](
          0) 
      theCode = call arguments [](
          1) 
      
      result = list 
      destructor = Destructor from(argName) 
      lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
      self each(n, 
        x = lexicalCode call(*(destructor unpack(cell(:n)))) 
        result <<(cell(:x))) 
      result, 
      error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext))) 
  )
map:dict(...)

takes one or two arguments. if one argument is given, it will be evaluated as a message chain on each element in the enumerable, and then the result will be collected in a new Dict. if the message chain returns a pair, that pair will be used as key and value. if it's something else, that value will be the key, and the value for it will be nil. if two arguments are given, the first one should be an unevaluated argument name, which will be bound inside the scope of executing the second piece of code. it's important to notice that the one argument form will establish no context, while the two argument form establishes a new lexical closure.

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    result = dict 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      if(cell(:x) kind ==("Pair"), 
        result [](x key) = x value, 
        result [](cell(:x)) = nil)) 
    result, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    result = dict 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      if(cell(:x) kind ==("Pair"), 
        result [](x key) = x value, 
        result [](cell(:x)) = nil)) 
    result, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
map:list(...)

nil

macro(
  argCount = call arguments length 
  if(
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    result = list 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      result <<(cell(:x))) 
    result, 
    if(
      argCount ==(
        2), 
      
      argName = call arguments [](
          0) 
      theCode = call arguments [](
          1) 
      
      result = list 
      destructor = Destructor from(argName) 
      lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
      self each(n, 
        x = lexicalCode call(*(destructor unpack(cell(:n)))) 
        result <<(cell(:x))) 
      result, 
      error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext))) 
  )
map:set(...)

takes one or two arguments. if one argument is given, it will be evaluated as a message chain on each element in the enumerable, and then the result will be collected in a new Set. if two arguments are given, the first one should be an unevaluated argument name, which will be bound inside the scope of executing the second piece of code. it's important to notice that the one argument form will establish no context, while the two argument form establishes a new lexical closure.

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    result = set 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      result <<(cell(:x))) 
    result, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    result = set 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      result <<(cell(:x))) 
    result, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
mapFn(+blocks)

takes zero or more arguments that evaluates to lexical blocks. these blocks should all take one argument. these blocks will be chained together and applied on each element in the receiver. the final result will be collected into a list. the evaluation happens left-to-right, meaning the first method invoked will be the first argument.

method(+blocks, 
  result = list 
  self each(n, 
    current = cell(:n) 
    blocks each(b, current = cell(:b) call(cell(:current))) 
    result <<(current)) 
  result)
mapFn:dict(+blocks)

takes zero or more arguments that evaluates to lexical blocks. these blocks should all take one argument. these blocks will be chained together and applied on each element in the receiver. the final result will be collected into a dict. the evaluation happens left-to-right, meaning the first method invoked will be the first argument.

method(+blocks, 
  result = dict 
  self each(n, 
    current = cell(:n) 
    blocks each(b, current = cell(:b) call(cell(:current))) 
    if(cell(:current) mimics?(Pair), 
      result [](current key) = current value, 
      result [](cell(:current)) = nil) 
    ) 
  result)
mapFn:set(+blocks)

takes zero or more arguments that evaluates to lexical blocks. these blocks should all take one argument. these blocks will be chained together and applied on each element in the receiver. the final result will be collected into a set. the evaluation happens left-to-right, meaning the first method invoked will be the first argument.

method(+blocks, 
  result = set 
  self each(n, 
    current = cell(:n) 
    blocks each(b, current = cell(:b) call(cell(:current))) 
    result <<(current)) 
  result)
max(...)

takes zero, one or two arguments. if zero arguments, returns the maximum elemnt ackording to the <=> ordering. if one argument, expects it to be a message chain. if that message chain, that will be used as a transform to create the element to compare with. finally, if two arguments are given, the first argument is an unevaluated name and the second is a code element. these will together be turned into a lexical block and used as the transformer for comparison. the result will always be an element from the collection, or nil if the collection is empty.

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      0), 
    
    
    theMax = nil 
    theMaxVal = nil 
    self each(n, 
      x = cell(:n) 
      if(theMax nil?, 
        theMax = cell(:n) 
        theMaxVal = cell(:x), 
        if(theMaxVal <(cell(:x)), 
          theMax = cell(:n) 
          theMaxVal = cell(:x)))) 
    theMax, 
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    theMax = nil 
    theMaxVal = nil 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      if(theMax nil?, 
        theMax = cell(:n) 
        theMaxVal = cell(:x), 
        if(theMaxVal <(cell(:x)), 
          theMax = cell(:n) 
          theMaxVal = cell(:x)))) 
    theMax, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    theMax = nil 
    theMaxVal = nil 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      if(theMax nil?, 
        theMax = cell(:n) 
        theMaxVal = cell(:x), 
        if(theMaxVal <(cell(:x)), 
          theMax = cell(:n) 
          theMaxVal = cell(:x)))) 
    theMax, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
member?(toFind)

nil

method(toFind, 
  self each(n, 
    if(toFind ==(cell(:n)), 
      return(true))) 
  return(false))
min(...)

takes zero, one or two arguments. if zero arguments, returns the minimum elemnt ackording to the <=> ordering. if one argument, expects it to be a message chain. if that message chain, that will be used as a transform to create the element to compare with. finally, if two arguments are given, the first argument is an unevaluated name and the second is a code element. these will together be turned into a lexical block and used as the transformer for comparison. the result will always be an element from the collection, or nil if the collection is empty.

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      0), 
    
    
    theMin = nil 
    theMinVal = nil 
    self each(n, 
      x = cell(:n) 
      if(theMin nil?, 
        theMin = cell(:n) 
        theMinVal = cell(:x), 
        if(theMinVal >(cell(:x)), 
          theMin = cell(:n) 
          theMinVal = cell(:x)))) 
    theMin, 
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    theMin = nil 
    theMinVal = nil 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      if(theMin nil?, 
        theMin = cell(:n) 
        theMinVal = cell(:x), 
        if(theMinVal >(cell(:x)), 
          theMin = cell(:n) 
          theMinVal = cell(:x)))) 
    theMin, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    theMin = nil 
    theMinVal = nil 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      if(theMin nil?, 
        theMin = cell(:n) 
        theMinVal = cell(:x), 
        if(theMinVal >(cell(:x)), 
          theMin = cell(:n) 
          theMinVal = cell(:x)))) 
    theMin, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
none?(...)

takes zero, one or two arguments. if zero arguments, returns false if any of the elements yielded by each is true, otherwise true. if one argument, expects it to be a message chain. if that message chain, when applied to the current element returns a true value, the method returns false. finally, if two arguments are given, the first argument is an unevaluated name and the second is a code element. these will together be turned into a lexical block and tested against the values in this element. if it returns true for any element, this method returns false, otherwise true.

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      0), 
    
    
    
    
    self each(n, 
      x = cell(:n) 
      if(cell(:x), 
        return(false))) 
    true, 
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    
    
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      if(cell(:x), 
        return(false))) 
    true, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    
    
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      if(cell(:x), 
        return(false))) 
    true, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
one?(...)

takes zero, one or two arguments. if zero arguments, returns true if exactly one of the elements is true, otherwise false. if one argument, expects it to be a message chain that will be used as a predicate. if that predicate returns true for exactly one element, returns true, otherwise false. finally, if two arguments are given, the first argument is an unevaluated name and the second is a code element. these will together be turned into a lexical block and tested against the values in this element. if it returns true for exactly one element, returns true, otherwise false

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      0), 
    
    
    result = false 
    self each(n, 
      x = cell(:n) 
      if(cell(:x), 
        if(result, 
          return(false), 
          result = true))) 
    result, 
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    result = false 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      if(cell(:x), 
        if(result, 
          return(false), 
          result = true))) 
    result, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    result = false 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      if(cell(:x), 
        if(result, 
          return(false), 
          result = true))) 
    result, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
partition(...)

takes zero, one or two arguments. if zero arguments, will return a list containing two list, where the first list contains all true values, and the second all the false values. if one argument is given, it will be used as a predicate message chain, and the return lists will be based on the result of this predicate. finally, if three arguments are given, they will be turned into a lexical block and used as a predicate to determine the result value.

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      0), 
    
    
    resultTrue = list 
    resultFalse = list 
    self each(n, 
      x = cell(:n) 
      if(cell(:x), resultTrue, resultFalse) <<(cell(:n))) 
    list(resultTrue, resultFalse), 
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    resultTrue = list 
    resultFalse = list 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      if(cell(:x), resultTrue, resultFalse) <<(cell(:n))) 
    list(resultTrue, resultFalse), 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    resultTrue = list 
    resultFalse = list 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      if(cell(:x), resultTrue, resultFalse) <<(cell(:n))) 
    list(resultTrue, resultFalse), 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
partition:dict(...)

takes zero, one or two arguments. if zero arguments, will return a list containing two dicts, where the first dict contains all true values, and the second all the false values. if one argument is given, it will be used as a predicate message chain, and the return dicts will be based on the result of this predicate. finally, if three arguments are given, they will be turned into a lexical block and used as a predicate to determine the result value.

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      0), 
    
    
    resultTrue = dict 
    resultFalse = dict 
    self each(n, 
      x = cell(:n) 
      place = if(cell(:x), resultTrue, resultFalse) 
      if(cell(:n) mimics?(Pair), 
        place [](n key) = n value, 
        place [](cell(:n)) = nil)) 
    list(resultTrue, resultFalse), 
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    resultTrue = dict 
    resultFalse = dict 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      place = if(cell(:x), resultTrue, resultFalse) 
      if(cell(:n) mimics?(Pair), 
        place [](n key) = n value, 
        place [](cell(:n)) = nil)) 
    list(resultTrue, resultFalse), 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    resultTrue = dict 
    resultFalse = dict 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      place = if(cell(:x), resultTrue, resultFalse) 
      if(cell(:n) mimics?(Pair), 
        place [](n key) = n value, 
        place [](cell(:n)) = nil)) 
    list(resultTrue, resultFalse), 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
partition:set(...)

takes zero, one or two arguments. if zero arguments, will return a list containing two sets, where the first set contains all true values, and the second all the false values. if one argument is given, it will be used as a predicate message chain, and the return sets will be based on the result of this predicate. finally, if three arguments are given, they will be turned into a lexical block and used as a predicate to determine the result value.

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      0), 
    
    
    resultTrue = set 
    resultFalse = set 
    self each(n, 
      x = cell(:n) 
      if(cell(:x), resultTrue, resultFalse) <<(cell(:n))) 
    list(resultTrue, resultFalse), 
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    resultTrue = set 
    resultFalse = set 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      if(cell(:x), resultTrue, resultFalse) <<(cell(:n))) 
    list(resultTrue, resultFalse), 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    resultTrue = set 
    resultFalse = set 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      if(cell(:x), resultTrue, resultFalse) <<(cell(:n))) 
    list(resultTrue, resultFalse), 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
reduce(...)

nil

macro(
  argCount = call arguments length 
  if(
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    theCode = theCode deepCopy 
    elementName = genSym 
    theCode last <<(message(elementName)) 
    sum = nil 
    self each(i, n, 
      if(i ==(0), 
        sum = cell(:n), 
        call ground cell(elementName) = cell(:n) 
        sum = theCode evaluateOn(call ground, cell(:sum)))) 
    return(cell(:sum)), 
    if(
      argCount ==(
        2), 
      
      argName = call arguments [](
          0) 
      theCode = call arguments [](
          1) 
      
      elementName = argName name 
      sum = nil 
      self each(i, n, 
        if(i ==(0), 
          sum = cell(:n), 
          call ground cell(elementName) = cell(:n) 
          sum = theCode evaluateOn(call ground, cell(:sum)))) 
      return(cell(:sum)), 
      if(
        argCount ==(
          3), 
        
        sumArgName = call arguments [](
            0) 
        argName = call arguments [](
            1) 
        theCode = call arguments [](
            2) 
        
        destructor = Destructor from(argName) 
        lexicalCode = LexicalBlock createFrom(list(sumArgName) +(destructor argNames) +(list(theCode)), call ground) 
        sum = nil 
        self each(i, n, 
          if(i ==(0), 
            sum = cell(:n), 
            sum = lexicalCode call(cell(:sum), *(destructor unpack(cell(:n)))))) 
        return(cell(:sum)), 
        if(
          argCount ==(
            4), 
          
          sum = call argAt(
              0) 
          sumArgName = call arguments [](
              1) 
          argName = call arguments [](
              2) 
          theCode = call arguments [](
              3) 
          
          destructor = Destructor from(argName) 
          lexicalCode = LexicalBlock createFrom(list(sumArgName) +(destructor argNames) +(list(theCode)), call ground) 
          self each(n, 
            sum = lexicalCode call(cell(:sum), *(destructor unpack(cell(:n))))) 
          return(cell(:sum)), 
          error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext))))) 
  )
reject(...)

takes one or two arguments. if one argument is given, it will be applied as a message chain as a predicate. those elements that doesn't the predicate will be returned. if two arguments are given, they will be turned into a lexical block and used as a predicate to choose the elements that doesn't match.

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      0), 
    
    
    result = list 
    self each(n, 
      x = cell(:n) 
      unless(cell(:x), 
        result <<(cell(:n)))) 
    result, 
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    result = list 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      unless(cell(:x), 
        result <<(cell(:n)))) 
    result, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    result = list 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      unless(cell(:x), 
        result <<(cell(:n)))) 
    result, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
reject:dict(...)

takes one or two arguments. if one argument is given, it will be applied as a message chain as a predicate. those elements that doesn't the predicate will be returned. if two arguments are given, they will be turned into a lexical block and used as a predicate to choose the elements that doesn't match.

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      0), 
    
    
    result = dict 
    self each(n, 
      x = cell(:n) 
      unless(cell(:x), 
        if(cell(:n) mimics?(Pair), 
          result [](n key) = n value, 
          result [](cell(:n)) = nil))) 
    result, 
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    result = dict 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      unless(cell(:x), 
        if(cell(:n) mimics?(Pair), 
          result [](n key) = n value, 
          result [](cell(:n)) = nil))) 
    result, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    result = dict 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      unless(cell(:x), 
        if(cell(:n) mimics?(Pair), 
          result [](n key) = n value, 
          result [](cell(:n)) = nil))) 
    result, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
reject:set(...)

takes one or two arguments. if one argument is given, it will be applied as a message chain as a predicate. those elements that doesn't the predicate will be returned. if two arguments are given, they will be turned into a lexical block and used as a predicate to choose the elements that doesn't match.

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      0), 
    
    
    result = set 
    self each(n, 
      x = cell(:n) 
      unless(cell(:x), 
        result <<(cell(:n)))) 
    result, 
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    result = set 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      unless(cell(:x), 
        result <<(cell(:n)))) 
    result, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    result = set 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      unless(cell(:x), 
        result <<(cell(:n)))) 
    result, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
select(...)

takes zero, one or two arguments. if zero arguments, will return a list with all the values that are true in the original collection. if one argument is given, it will be applied as a message chain, that should be a predicate. those elements that match the predicate will be returned. if two arguments are given, they will be turned into a lexical block and used as a predicate to choose elements.

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      0), 
    
    
    result = list 
    self each(n, 
      x = cell(:n) 
      if(cell(:x), 
        result <<(cell(:n)))) 
    result, 
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    result = list 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      if(cell(:x), 
        result <<(cell(:n)))) 
    result, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    result = list 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      if(cell(:x), 
        result <<(cell(:n)))) 
    result, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
select:dict(...)

takes zero, one or two arguments. if zero arguments, will return a dict with all the values that are true in the original collection. if one argument is given, it will be applied as a message chain, that should be a predicate. those elements that match the predicate will be returned. if two arguments are given, they will be turned into a lexical block and used as a predicate to choose elements.

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      0), 
    
    
    result = dict 
    self each(n, 
      x = cell(:n) 
      if(cell(:x), 
        if(cell(:n) mimics?(Pair), 
          result [](n key) = n value, 
          result [](cell(:n)) = nil))) 
    result, 
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    result = dict 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      if(cell(:x), 
        if(cell(:n) mimics?(Pair), 
          result [](n key) = n value, 
          result [](cell(:n)) = nil))) 
    result, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    result = dict 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      if(cell(:x), 
        if(cell(:n) mimics?(Pair), 
          result [](n key) = n value, 
          result [](cell(:n)) = nil))) 
    result, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
select:set(...)

takes zero, one or two arguments. if zero arguments, will return a set with all the values that are true in the original collection. if one argument is given, it will be applied as a message chain, that should be a predicate. those elements that match the predicate will be returned. if two arguments are given, they will be turned into a lexical block and used as a predicate to choose elements.

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      0), 
    
    
    result = set 
    self each(n, 
      x = cell(:n) 
      if(cell(:x), 
        result <<(cell(:n)))) 
    result, 
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    result = set 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      if(cell(:x), 
        result <<(cell(:n)))) 
    result, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    result = set 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      if(cell(:x), 
        result <<(cell(:n)))) 
    result, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
some(...)

takes zero, one or two arguments. if zero arguments, returns the first element that is true, otherwise false. if one argument, expects it to be a message chain. if that message chain, when applied to the current element returns a true value, that value is return. finally, if two arguments are given, the first argument is an unevaluated name and the second is a code element. these will together be turned into a lexical block and tested against the values in this element. if it returns true for any element, that value will be returned, otherwise false.

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      0), 
    
    
    
    
    self each(n, 
      x = cell(:n) 
      if(cell(:x), 
        return(it))) 
    false, 
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    
    
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      if(cell(:x), 
        return(it))) 
    false, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    
    
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      if(cell(:x), 
        return(it))) 
    false, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
sort()

will return a sorted list of all the entries of this enumerable object

method(
  self asList sort)
sortBy(...)

takes one or two arguments that are used to transform the objects into something that can be sorted, then sorts based on that. if one argument, that argument is handled as a message chain, and if two arguments it will be turned into a lexical block and used.

macro(
  argCount = call arguments length 
  if(
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    map(x, list(theCode evaluateOn(call ground, cell(:x)), cell(:x))) sort map(second), 
    if(
      argCount ==(
        2), 
      
      argName = call arguments [](
          0) 
      theCode = call arguments [](
          1) 
      
      destructor = Destructor from(argName) 
      lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
      map(x, list(lexicalCode call(*(destructor unpack(cell(:x)))), cell(:x))) sort map(second), 
      error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext))) 
  )
sum()

returns an object created by summing all objects in the enumerable using the + operator. the default value for an empty enumerable will be nil.

method(
  inject(+))
take(howMany)

takes one argument and returns a list with as many elements from the collection, or all elements if the requested number is larger than the size.

method(howMany, 
  self first(howMany))
take:dict(howMany)

takes one argument and returns a dict with as many elements from the collection, or all elements if the requested number is larger than the size.

method(howMany, 
  self first:dict(howMany))
take:set(howMany)

takes one argument and returns a set with as many elements from the collection, or all elements if the requested number is larger than the size.

method(howMany, 
  self first:set(howMany))
takeWhile(...)

takes zero, one or two arguments. it will evaluate a predicate once for each element, and collect all the elements until the predicate returns false for the first time. at that point the collected list will be returned. if zero arguments, the predicate is the element itself. if one argument, expects it to be a message chain to apply as a predicate. if two arguments are given, the first argument is an unevaluated name and the second is a code element. these will together be turned into a lexical block and used as the predicate.

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      0), 
    
    
    result = list 
    self each(n, 
      x = cell(:n) 
      if(cell(:x), 
        result <<(cell(:n)), 
        return(result))) 
    result, 
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    result = list 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      if(cell(:x), 
        result <<(cell(:n)), 
        return(result))) 
    result, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    result = list 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      if(cell(:x), 
        result <<(cell(:n)), 
        return(result))) 
    result, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
takeWhile:dict(...)

takes zero, one or two arguments. it will evaluate a predicate once for each element, and collect all the elements until the predicate returns false for the first time. at that point the collected dict will be returned. if zero arguments, the predicate is the element itself. if one argument, expects it to be a message chain to apply as a predicate. if two arguments are given, the first argument is an unevaluated name and the second is a code element. these will together be turned into a lexical block and used as the predicate.

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      0), 
    
    
    result = dict 
    self each(n, 
      x = cell(:n) 
      if(cell(:x), 
        if(cell(:n) mimics?(Pair), 
          result [](n key) = n value, 
          result [](cell(:n)) = nil), 
        return(result))) 
    result, 
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    result = dict 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      if(cell(:x), 
        if(cell(:n) mimics?(Pair), 
          result [](n key) = n value, 
          result [](cell(:n)) = nil), 
        return(result))) 
    result, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    result = dict 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      if(cell(:x), 
        if(cell(:n) mimics?(Pair), 
          result [](n key) = n value, 
          result [](cell(:n)) = nil), 
        return(result))) 
    result, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
takeWhile:set(...)

takes zero, one or two arguments. it will evaluate a predicate once for each element, and collect all the elements until the predicate returns false for the first time. at that point the collected set will be returned. if zero arguments, the predicate is the element itself. if one argument, expects it to be a message chain to apply as a predicate. if two arguments are given, the first argument is an unevaluated name and the second is a code element. these will together be turned into a lexical block and used as the predicate.

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      0), 
    
    
    result = set 
    self each(n, 
      x = cell(:n) 
      if(cell(:x), 
        result <<(cell(:n)), 
        return(result))) 
    result, 
    argCount ==(
      1), 
    
    theCode = call arguments [](
        0) 
    
    result = set 
    self each(n, 
      x = theCode evaluateOn(call ground, cell(:n)) 
      if(cell(:x), 
        result <<(cell(:n)), 
        return(result))) 
    result, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    theCode = call arguments [](
        1) 
    
    result = set 
    destructor = Destructor from(argName) 
    lexicalCode = LexicalBlock createFrom(destructor argNames +(list(theCode)), call ground) 
    self each(n, 
      x = lexicalCode call(*(destructor unpack(cell(:n)))) 
      if(cell(:x), 
        result <<(cell(:n)), 
        return(result))) 
    result, 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
zip(+listsAndFns)

takes zero or more arguments, where all arguments should be a list, except that the last might also be a lexical block. zip will create a list of lists, where each internal list is a combination of the current element, and the corresponding elements from all the lists. if the lists are shorter than this collection, nils will be supplied. if a lexical block is provided, it will be called with each list created, and if that's the case nil will be returned from zip

method(+listsAndFns, 
  theFn = listsAndFns last 
  if(cell(:theFn) &&((cell(:theFn) mimics?(LexicalBlock))), 
    listsAndFns = listsAndFns [](0 ..(0 -(2))) 
    listsAndFns map!(x, 
      if(x mimics?(Sequence), 
        x, 
        x seq)) 
    self each(n, 
      internal = list(cell(:n)) 
      listsAndFns each(n2, 
        val = if(n2 next?, n2 next, nil) 
        internal <<(cell(:val))) 
      cell(:theFn) call(internal)) 
    nil, 
    listsAndFns map!(x, 
      if(x mimics?(Sequence), 
        x, 
        x seq)) 
    result = list 
    self each(n, 
      internal = list(cell(:n)) 
      listsAndFns each(n2, 
        val = if(n2 next?, n2 next, nil) 
        internal <<(cell(:val))) 
      result <<(internal)) 
    result))
zip:set(+lists)

takes zero or more arguments, where all arguments should be lists or sequences. zip:set will create a list of set, where each internal set is a combination of the current element, and the corresponding elements from all the lists. if the lists are shorter than this collection, nils will be supplied.

method(+lists, 
  lists map!(x, 
    if(x mimics?(Sequence), 
      x, 
      x seq)) 
  result = list 
  self each(n, 
    internal = set(cell(:n)) 
    lists each(n2, 
      val = if(n2 next?, n2 next, nil) 
      internal <<(cell(:val))) 
    result <<(internal)) 
  result)