Collection.java

/**
* Copyright 2010,2021 Nikolas S Boyd.
Permission is granted to copy this work provided this copyright statement is retained in all copies.

*/
package Hoot.Collections;

import Hoot.Runtime.Functions.*;
import Hoot.Runtime.Faces.*;
import Hoot.Runtime.Values.*;
import Hoot.Runtime.Blocks.*;
import Smalltalk.Core.*;
import Smalltalk.Blocks.*;
import Smalltalk.Magnitudes.*;
import Hoot.Behaviors.*;
import Hoot.Behaviors.Nil;
import Hoot.Behaviors.Object;
import Hoot.Behaviors.True;
import Hoot.Behaviors.False;
import Hoot.Behaviors.Boolean;
import Hoot.Magnitudes.*;
import Hoot.Magnitudes.Integer;
import Hoot.Magnitudes.Character;
import Hoot.Magnitudes.Float;
import Hoot.Magnitudes.Double;
import Hoot.Magnitudes.Integer;
import Hoot.Magnitudes.FastInteger;
import static Hoot.Magnitudes.SmallInteger.*;
import Smalltalk.Magnitudes.Ordinal;
import Smalltalk.Collections.*;
import Smalltalk.Core.Subject;
import Smalltalk.Core.Classified;
import java.util.List;

public abstract class Collection<ElementType extends Object> extends Object implements CollectedVariably<ElementType>
{

  public static Metaclass type() { return (Metaclass)Metaclass.$class; }
  @Override public Metaclass $class() { return (Metaclass)Metaclass.$class; }
  public static class Metaclass extends Object.Metaclass implements CollectedVariably.Metatype
  {
    static final Collection.Metaclass $class = new Collection.Metaclass();
    public Metaclass() {
      this(Collection.Metaclass.class);
    }

    public Metaclass(java.lang.Class aClass) {
      super(aClass);
    }

    @Override public java.lang.Class outerClass() { return Collection.class; }


    /**
     * @return 
     */
    @Override public   Collection $new()
    {
      java.lang.String exitID = "CollectionMetatype>>$new";
      Frame f0 = new Frame(exitID);
      return f0.evaluate(() -> {
      return (Collection)f0.exit(exitID, this.$new(SmallInteger.from(10)));
      });
    }

    /**
     * @return 
     */
    @Override public   Collection $new(final Ordinal capacity)
    {
      java.lang.String exitID = "CollectionMetatype>>$new";
      Frame f0 = new Frame(exitID);
      return f0.evaluate(() -> {
      return (Collection)f0.exit(exitID, new OrderedCollection(capacity));
      });
    }

    /**
     * @return 
     */
    public  <ElementType extends Subject> CollectedVariably<ElementType> with(final ElementType a)
    {
      java.lang.String exitID = "CollectionMetatype>>with";
      Frame f0 = new Frame(exitID);
      return f0.evaluate(() -> {
      return (CollectedVariably<ElementType>)f0.exit(exitID, (fp) -> {
      Collection prime = (Collection)this.$new();
      prime.add(((Object)a)); 

      return prime.yourself();
      });
      });
    }

    /**
     * @return 
     */
    public  <ElementType extends Subject> CollectedVariably<ElementType> with_with(final ElementType a, final ElementType b)
    {
      java.lang.String exitID = "CollectionMetatype>>with_with";
      Frame f0 = new Frame(exitID);
      return f0.evaluate(() -> {
      return (CollectedVariably<ElementType>)f0.exit(exitID, (fp) -> {
      Collection prime = (Collection)this.$new();
      prime.add(((Object)a)); 
      prime.add(((Object)b)); 

      return prime.yourself();
      });
      });
    }

    /**
     * @return 
     */
    public  <ElementType extends Subject> CollectedVariably<ElementType> with_with_with(final ElementType a, final ElementType b, final ElementType c)
    {
      java.lang.String exitID = "CollectionMetatype>>with_with_with";
      Frame f0 = new Frame(exitID);
      return f0.evaluate(() -> {
      return (CollectedVariably<ElementType>)f0.exit(exitID, (fp) -> {
      Collection prime = (Collection)this.$new();
      prime.add(((Object)a)); 
      prime.add(((Object)b)); 
      prime.add(((Object)c)); 

      return prime.yourself();
      });
      });
    }

    /**
     * @return 
     */
    public  <ElementType extends Subject> CollectedVariably<ElementType> with_with_with_with(final ElementType a, final ElementType b, final ElementType c, final ElementType d)
    {
      java.lang.String exitID = "CollectionMetatype>>with_with_with_with";
      Frame f0 = new Frame(exitID);
      return f0.evaluate(() -> {
      return (CollectedVariably<ElementType>)f0.exit(exitID, (fp) -> {
      Collection prime = (Collection)this.$new();
      prime.add(((Object)a)); 
      prime.add(((Object)b)); 
      prime.add(((Object)c)); 
      prime.add(((Object)d)); 

      return prime.yourself();
      });
      });
    }

    /**
     * @return 
     */
    public  <ElementType extends Subject> CollectedVariably<ElementType> withAll(final CollectedReadably<ElementType> elements)
    {
      java.lang.String exitID = "CollectionMetatype>>withAll";
      Frame f0 = new Frame(exitID);
      return f0.evaluate(() -> {
      return (CollectedVariably<ElementType>)f0.exit(exitID, (fp) -> {
      Collection prime = (Collection)this.$new();
      prime.addAll(elements); 

      return prime.yourself();
      });
      });
    }
  }


    protected Classified elementType = Object.type();
    public Classified elementType() { return this.elementType; }
    public Object getElementType() { return (Object)this.elementType; }

    public Collection elementType(Classified value) { this.elementType = value; return this; }
    public void setElementType(Object value) { this.elementType = (Classified)value; }

  ;

  /**
   * @return 
   */
  public   Collection rehash()
  {
    java.lang.String exitID = "Collection>>rehash";
    Frame f0 = new Frame(exitID);
    return (Collection)this;
  }

  /**
   * @return 
   */
  public   Integer capacity()
  {
    java.lang.String exitID = "Collection>>capacity";
    Frame f0 = new Frame(exitID);
    return (Integer)this.size();
  }

  /**
   * @return 
   */
  public   int primitiveSize()
  {
    java.lang.String exitID = "Collection>>primitiveSize";
    Frame f0 = new Frame(exitID);
    return (int)this.size().primitiveInteger();
  }

  /**
   * @return 
   */
  public   Integer size()
  {
    java.lang.String exitID = "Collection>>size";
    Frame f0 = new Frame(exitID);
    FastInteger tally = Zero.asFastInteger();
    this.$do(Closure.with(f2 -> {
      Hoot.Behaviors.Object element = f2.getValue(0).value();
      tally.add(Unity);
    }, "element"));
    return (Integer)tally;
  }

  /**
   * @return 
   */
  public   Integer occurrencesOf(final Subject candidate)
  {
    java.lang.String exitID = "Collection>>occurrencesOf";
    Frame f0 = new Frame(exitID);
    FastInteger tally = Zero.asFastInteger();
    this.$do(Closure.with(f2 -> {
      Hoot.Behaviors.Object element = f2.getValue(0).value();
      return (candidate.equals(element)).ifTrue(Closure.with(f3 -> {
      tally.add(Unity);
    }, ""));
    }, "element"));
    return (Integer)tally;
  }

  /**
   * @return 
   */
  @Override public   java.lang.String toString()
  {
    java.lang.String exitID = "Collection>>toString";
    Frame f0 = new Frame(exitID);
    return (java.lang.String)this.printString().primitiveString();
  }

  /**
   * @return 
   */
  @Override public   String printString()
  {
    java.lang.String exitID = "Collection>>printString";
    Frame f0 = new Frame(exitID);
    return (String)String.from(this.asList().toString());
  }

  /**
   * @return 
   */
  public   List<ElementType> asList()
  {
    java.lang.String exitID = "Collection>>asList";
    Frame f0 = new Frame(exitID);
    return (List<ElementType>)this.asOrderedCollection().asList();
  }

  /**
   * @return 
   */
  public   CollectedArray<ElementType> asArray()
  {
    java.lang.String exitID = "Collection>>asArray";
    Frame f0 = new Frame(exitID);
    Array result = Array.type().$new(this.size());

    FastInteger index = SmallInteger.from(1).asFastInteger();
    this.$do(Closure.with(f2 -> {
      Hoot.Behaviors.Object element = f2.getValue(0).value();
      result.at_put(index, element);
    index.add(SmallInteger.from(1));
    }, "element"));
    return (CollectedArray<ElementType>)result;
  }

  /**
   * @return 
   */
  public   CollectedBaggage<ElementType> asBag()
  {
    java.lang.String exitID = "Collection>>asBag";
    Frame f0 = new Frame(exitID);
    {
    Bag prime = (Bag)Bag.type().$new(this.size());
    prime.addAll(this); 

    return prime.yourself();
    }
  }

  /**
   * @return 
   */
  public   CollectedOrdinally<ElementType> asOrderedCollection()
  {
    java.lang.String exitID = "Collection>>asOrderedCollection";
    Frame f0 = new Frame(exitID);
    OrderedCollection result = OrderedCollection.type().$new(this.size());
    this.$do(Closure.with(f2 -> {
      Hoot.Behaviors.Object element = f2.getValue(0).value();
      return result.addLast(element);
    }, "element"));
    return (CollectedOrdinally<ElementType>)result;
  }

  /**
   * @return 
   */
  public   CollectedDistinctly<ElementType> asSet()
  {
    java.lang.String exitID = "Collection>>asSet";
    Frame f0 = new Frame(exitID);
    {
    Set prime = (Set)Set.type().$new(this.size());
    prime.addAll(this); 

    return prime.yourself();
    }
  }

  /**
   * @return 
   */
  public   CollectedSortably<ElementType> sorted()
  {
    java.lang.String exitID = "Collection>>sorted";
    Frame f0 = new Frame(exitID);
    return (CollectedSortably<ElementType>)this.asSortedCollection();
  }

  /**
   * @return 
   */
  public   CollectedSortably<ElementType> asSortedCollection()
  {
    java.lang.String exitID = "Collection>>asSortedCollection";
    Frame f0 = new Frame(exitID);
    {
    SortedCollection prime = (SortedCollection)SortedCollection.type().$new(this.size());
    prime.addAll(this); 

    return prime.reSort();
    }
  }

  /**
   * @return 
   */
  public   CollectedSortably<ElementType> asSortedCollection(final DyadicPredicate sortBlock)
  {
    java.lang.String exitID = "Collection>>asSortedCollection";
    Frame f0 = new Frame(exitID);
    {
    SortedCollection prime = (SortedCollection)SortedCollection.type().$new(this.size());
    prime.sortBlock(sortBlock); 
    prime.addAll(this); 

    return prime.reSort();
    }
  }

  /**
   * @return 
   */
  @Override public   Collection $do(final MonadicValuable aBlock)
  {
    java.lang.String exitID = "Collection>>$do";
    Frame f0 = new Frame(exitID);
    return (Collection)this;
  }

  /**
   * @return 
   */
  public   Collection reverseDo(final MonadicValuable aBlock)
  {
    java.lang.String exitID = "Collection>>reverseDo";
    Frame f0 = new Frame(exitID);
    return (Collection)this;
  }

  /**
   * @return 
   */
  public  <CollectionType extends Collected> CollectionType collect(final MonadicValuable transformBlock)
  {
    java.lang.String exitID = "Collection>>collect";
    Frame f0 = new Frame(exitID);
    CollectedVariably result = this.species().$new();
    this.$do(Closure.with(f2 -> {
      ElementType element = f2.getValue(0).value();
      return result.add(transformBlock.value(element));
    }, "element"));
    return (CollectionType)((CollectionType)result);
  }

  /**
   * @return 
   */
  public   ElementType detect(final MonadicPredicate testBlock)
  {
    java.lang.String exitID = "Collection>>detect";
    Frame f0 = new Frame(exitID);
    return (ElementType)this.detect_ifNone(testBlock, Predicate.with(f2 -> {
      this.elementNotFound();
    return Nil.literal();
    }, ""));
  }

  /**
   * @return 
   */
  public   ElementType detect_ifNone(final MonadicPredicate testBlock, final NiladicValuable missingBlock)
  {
    java.lang.String exitID = "Collection>>detect_ifNone";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    this.$do(Closure.with(f2 -> {
      ElementType element = f2.getValue(0).value();
      return (ElementType)f0.exit(exitID, testBlock.value(element).ifTrue(Closure.with(f3 -> {
      return (ElementType)f0.exit(exitID, element);
    }, "")));
    }, "element"));
    return (ElementType)f0.exit(exitID, missingBlock.value());
    });
  }

  /**
   * @return 
   */
  public   Collection do_separatedBy(final MonadicValuable aBlock, final NiladicValuable betweenBlock)
  {
    java.lang.String exitID = "Collection>>do_separatedBy";
    Frame f0 = new Frame(exitID);
    Boolean betweenElements = False.literal() ; f0.bind("betweenElements", betweenElements);
    this.$do(Closure.with(f2 -> {
      ElementType element = f2.getValue(0).value();
      f0.getValue("betweenElements", Boolean.class).ifTrue(Closure.with(f3 -> {
      betweenBlock.value();
    }, ""));
    aBlock.value(element);
    ; f0.bind("betweenElements", f0.getValue("betweenElements", Boolean.class).not());
    }, "element"));
    return (Collection)this;
  }

  /**
   * @return 
   */
  public  <ResultType extends Subject> ResultType inject_into(final ResultType value, final DyadicValuable binaryBlock)
  {
    java.lang.String exitID = "Collection>>inject_into";
    Frame f0 = new Frame(exitID);
    Subject result = value ; f0.bind("result", result);
    this.$do(Closure.with(f2 -> {
      ElementType element = f2.getValue(0).value();
      ; f0.bind("result", binaryBlock.value_value(f0.getValue("result", Subject.class), element));
    }, "element"));
    return (ResultType)((ResultType)f0.getValue("result", Subject.class));
  }

  /**
   * @return 
   */
  public  <CollectionType extends Collected> CollectionType reject(final MonadicPredicate testBlock)
  {
    java.lang.String exitID = "Collection>>reject";
    Frame f0 = new Frame(exitID);
    CollectedVariably result = this.species().$new();
    this.$do(Closure.with(f2 -> {
      ElementType element = f2.getValue(0).value();
      return testBlock.value(element).ifFalse(Closure.with(f3 -> {
      return result.add(element);
    }, ""));
    }, "element"));
    return (CollectionType)((CollectionType)result);
  }

  /**
   * @return 
   */
  public  <CollectionType extends Collected> CollectionType select(final MonadicPredicate testBlock)
  {
    java.lang.String exitID = "Collection>>select";
    Frame f0 = new Frame(exitID);
    CollectedVariably result = this.species().$new();
    this.$do(Closure.with(f2 -> {
      ElementType element = f2.getValue(0).value();
      return testBlock.value(element).ifTrue(Closure.with(f3 -> {
      return result.add(element);
    }, ""));
    }, "element"));
    return (CollectionType)((CollectionType)result);
  }

  /**
   * @return 
   */
  public   Collection indexError()
  {
    java.lang.String exitID = "Collection>>indexError";
    Frame f0 = new Frame(exitID);
    this.error(String.from("Improper index for this collection"));
    return (Collection)this;
  }

  /**
   * @return 
   */
  public   Collection indexRangeError()
  {
    java.lang.String exitID = "Collection>>indexRangeError";
    Frame f0 = new Frame(exitID);
    this.error(String.from("Supplied index is out of bounds"));
    return (Collection)this;
  }

  /**
   * @return 
   */
  public   Collection indexError_limit(final Ordinal index, final Ordinal limit)
  {
    java.lang.String exitID = "Collection>>indexError_limit";
    Frame f0 = new Frame(exitID);
    this.error(index.printString().append(String.from(" exceeds ")).append(limit.printString()));
    return (Collection)this;
  }

  /**
   * @return 
   */
  public   Collection elementNotFound()
  {
    java.lang.String exitID = "Collection>>elementNotFound";
    Frame f0 = new Frame(exitID);
    this.error(String.from("Desired collection element not found"));
    return (Collection)this;
  }

  /**
   * @return 
   */
  public   Collection elementClassError()
  {
    java.lang.String exitID = "Collection>>elementClassError";
    Frame f0 = new Frame(exitID);
    this.error(String.from("Collection does not hold supplied kind of element"));
    return (Collection)this;
  }

  /**
   * @return 
   */
  public   Collection immutabilityError()
  {
    java.lang.String exitID = "Collection>>immutabilityError";
    Frame f0 = new Frame(exitID);
    this.error(String.from("Collection contents cannot be changed"));
    return (Collection)this;
  }

  /**
   * @return 
   */
  public   Collection compatibilityError()
  {
    java.lang.String exitID = "Collection>>compatibilityError";
    Frame f0 = new Frame(exitID);
    this.error(String.from("Collections are not comparable"));
    return (Collection)this;
  }

  /**
   * @return 
   */
  public   Collection emptyCollectionError()
  {
    java.lang.String exitID = "Collection>>emptyCollectionError";
    Frame f0 = new Frame(exitID);
    this.error(String.from("This collection is empty"));
    return (Collection)this;
  }

  /**
   * @return 
   */
  @Override public   Boolean isCollection()
  {
    java.lang.String exitID = "Collection>>isCollection";
    Frame f0 = new Frame(exitID);
    return (Boolean)True.literal();
  }

  /**
   * @return 
   */
  @Override public   Boolean equals(final Subject candidate)
  {
    java.lang.String exitID = "Collection>>equals";
    Frame f0 = new Frame(exitID);
    return (Boolean)((Object)candidate).isCollection().and(Predicate.with(f2 -> {
      return (this.equals(((Collected)candidate)));
    }, ""));
  }

  /**
   * @return 
   */
  public   Boolean equals(final Collected<ElementType> aCollection)
  {
    java.lang.String exitID = "Collection>>equals";
    Frame f0 = new Frame(exitID);
    return (Boolean)False.literal();
  }

  /**
   * @return 
   */
  public   Boolean allSatisfy(final MonadicPredicate testBlock)
  {
    java.lang.String exitID = "Collection>>allSatisfy";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    this.$do(Closure.with(f2 -> {
      Hoot.Behaviors.Object element = f2.getValue(0).value();
      return (Boolean)f0.exit(exitID, testBlock.value(element).ifFalse(Closure.with(f3 -> {
      return (Boolean)f0.exit(exitID, False.literal());
    }, "")));
    }, "element"));
    return (Boolean)f0.exit(exitID, True.literal());
    });
  }

  /**
   * @return 
   */
  public   Boolean anySatisfy(final MonadicPredicate testBlock)
  {
    java.lang.String exitID = "Collection>>anySatisfy";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    this.$do(Closure.with(f2 -> {
      Hoot.Behaviors.Object element = f2.getValue(0).value();
      return (Boolean)f0.exit(exitID, testBlock.value(element).ifTrue(Closure.with(f3 -> {
      return (Boolean)f0.exit(exitID, True.literal());
    }, "")));
    }, "element"));
    return (Boolean)f0.exit(exitID, False.literal());
    });
  }

  /**
   * @return 
   */
  public   Boolean contains(final MonadicPredicate testBlock)
  {
    java.lang.String exitID = "Collection>>contains";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    this.detect_ifNone(testBlock, Predicate.with(f2 -> {
      return (Boolean)f0.exit(exitID, False.literal());
    }, ""));
    return (Boolean)f0.exit(exitID, True.literal());
    });
  }

  /**
   * @return 
   */
  public   Boolean includes(final Subject anObject)
  {
    java.lang.String exitID = "Collection>>includes";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    this.$do(Closure.with(f2 -> {
      Hoot.Behaviors.Object element = f2.getValue(0).value();
      return (Boolean)f0.exit(exitID, (element.equals(anObject)).ifTrue(Closure.with(f3 -> {
      return (Boolean)f0.exit(exitID, True.literal());
    }, "")));
    }, "element"));
    return (Boolean)f0.exit(exitID, False.literal());
    });
  }

  /**
   * @return 
   */
  public   Boolean _isEmpty()
  {
    java.lang.String exitID = "Collection>>_isEmpty";
    Frame f0 = new Frame(exitID);
    return (Boolean)(SmallInteger.from(0).equals(this.size()));
  }

  /**
   * @return 
   */
  public   Boolean notEmpty()
  {
    java.lang.String exitID = "Collection>>notEmpty";
    Frame f0 = new Frame(exitID);
    return (Boolean)(SmallInteger.from(0).lessThan(this.size()));
  }

  /**
   * @return 
   */
  public   Collection emptyCheck()
  {
    java.lang.String exitID = "Collection>>emptyCheck";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    this._isEmpty().ifTrue(Closure.with(f2 -> {
      return (Collection)f0.exit(exitID, this.emptyCollectionError());
    }, ""));
    return (Collection)this;
    });
  }

  /**
   * @return 
   */
  public   int checkRange(final Ordinal index)
  {
    java.lang.String exitID = "Collection>>checkRange";
    Frame f0 = new Frame(exitID);
    return (int)this.checkIndex(index);
  }

  /**
   * @return 
   */
  public   int checkGrows(final Ordinal index)
  {
    java.lang.String exitID = "Collection>>checkGrows";
    Frame f0 = new Frame(exitID);
    int i = (((Integer)index).primitiveInteger() - 1);
    if ((i < 0)) {
      this.indexError_limit(index, Unity);
      return Negativity.primitiveInteger();
    };
    return (int)i;
  }

  /**
   * @return 
   */
  public   int checkIndex(final Ordinal index)
  {
    java.lang.String exitID = "Collection>>checkIndex";
    Frame f0 = new Frame(exitID);
    int i = (((Integer)index).primitiveInteger() - 1);
    if ((i < 0)) {
      this.indexError_limit(index, Unity);
      return Negativity.primitiveInteger();
    };
    if (!((i < this.primitiveSize()))) {
      this.indexError_limit(index, this.size());
      return Negativity.primitiveInteger();
    };
    return (int)i;
  }

  /**
   * @return 
   */
  public   int checkIndex_ifAbsent(final Ordinal index, final NiladicValuable aBlock)
  {
    java.lang.String exitID = "Collection>>checkIndex_ifAbsent";
    Frame f0 = new Frame(exitID);
    int i = (((Integer)index).primitiveInteger() - 1);
    if ((i < 0)) {
      aBlock.value();
      return Negativity.primitiveInteger();
    };
    if (!((i < this.primitiveSize()))) {
      aBlock.value();
      return Negativity.primitiveInteger();
    };
    return (int)i;
  }

  /**
   * @return 
   */
  public   Collection registerType(final Object element)
  {
    java.lang.String exitID = "Collection>>registerType";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    Object.isNull(element).ifTrue(Closure.with(f2 -> {
      return (Collection)f0.exit(exitID, this);
    }, ""));

     elementType = element.species();
    return (Collection)this;
    });
  }

  /**
   * @return 
   */
  public   Boolean collectsElements(final Object element)
  {
    java.lang.String exitID = "Collection>>collectsElements";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    Object.isNull(element).ifTrue(Closure.with(f2 -> {
      return (Boolean)f0.exit(exitID, False.literal());
    }, ""));
    return (Boolean)f0.exit(exitID, Boolean.from(element.species().inheritsFrom(this.elementType())));
    });
  }

  /**
   * @return 
   */
  public   Integer findFirst(final MonadicPredicate testBlock)
  {
    java.lang.String exitID = "Collection>>findFirst";
    Frame f0 = new Frame(exitID);
    return (Integer)this.findFirst_ifAbsent(testBlock, Closure.with(f2 -> {
      return SmallInteger.from(0);
    }, ""));
  }

  /**
   * @return 
   */
  public   Integer findLast(final MonadicPredicate testBlock)
  {
    java.lang.String exitID = "Collection>>findLast";
    Frame f0 = new Frame(exitID);
    return (Integer)this.findLast_ifAbsent(testBlock, Closure.with(f2 -> {
      return SmallInteger.from(0);
    }, ""));
  }

  /**
   * @return 
   */
  public   Integer findFirst_ifAbsent(final MonadicPredicate testBlock, final NiladicValuable exceptionBlock)
  {
    java.lang.String exitID = "Collection>>findFirst_ifAbsent";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    FastInteger index = SmallInteger.from(1).asFastInteger();
    this.$do(Closure.with(f2 -> {
      ElementType element = f2.getValue(0).value();
      testBlock.value(element).ifTrue(Closure.with(f3 -> {
      return (Integer)f0.exit(exitID, index);
    }, ""));
    index.add(SmallInteger.from(1));
    }, "element"));
    return (Integer)f0.exit(exitID, exceptionBlock.value());
    });
  }

  /**
   * @return 
   */
  public   Integer findLast_ifAbsent(final MonadicPredicate testBlock, final NiladicValuable exceptionBlock)
  {
    java.lang.String exitID = "Collection>>findLast_ifAbsent";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    FastInteger index = this.size().asSmallInteger().asFastInteger();
    this.reverseDo(Closure.with(f2 -> {
      ElementType element = f2.getValue(0).value();
      testBlock.value(element).ifTrue(Closure.with(f3 -> {
      return (Integer)f0.exit(exitID, index);
    }, ""));
    index.subtract(SmallInteger.from(1));
    }, "element"));
    return (Integer)f0.exit(exitID, exceptionBlock.value());
    });
  }

  /**
   * @return 
   */
  public   OrderedCollection<String> printElements()
  {
    java.lang.String exitID = "Collection>>printElements";
    Frame f0 = new Frame(exitID);
    return (OrderedCollection<String>)this.collect(Closure.with(f2 -> {
      Hoot.Behaviors.Object element = f2.getValue(0).value();
      return element.printLine();
    }, "element"));
  }
}