% crochet

/// Converts a [type:linked-stream] to a [type:list]. Assumes that the [type:linked-stream]
/// is finite, as otherwise the conversion will never finish.
command linked-stream-empty as list = [];
command linked-stream-cons as list = (self rest as list) prepend: self first;

test "linked-stream as list" do
  assert ((#stream from: [1, 2, 3]) as list) === [1, 2, 3];
  assert (new linked-stream-cons(1, lazy linked-stream-empty) as list) === [1];
  assert (new linked-stream-cons(1, lazy new linked-stream-cons(2, lazy linked-stream-empty)) as list) === [1, 2];
end

// -- List conversions
/// Converts a [type:list] to a [type:stream].
command list as stream do
  let Go = { I in
    condition
      when I <= self count => new linked-stream-cons(self at: I, lazy Go(I + 1));
      otherwise => linked-stream-empty;
    end
  };
  Go(1);
test
  assert (([] as stream) as list) === [];
  assert (([1, 2, 3] as stream) as list) === [1, 2, 3];
end

/// Converts a [type:list] to a [type:set].
command list as set = #set from: self;

/// Converts a [type:list] to a [type:map]
command list as map = #map from: list;
