# --------------------------------------------------------------------------- # # LazySequence Class # --------------------------------------------------------------------------- # # - An Lazy Immutable Sequence class # --------------------------------------------------------------------------- # ^LazySequence := ^Class.new({}); ^LazySequence.set_name('LazySequence'); ^LazySequence.set_version('0.0.1'); ^LazySequence.set_authority('url:pugscode.org'); ^LazySequence.set_roles([ ^Seq ]); ^LazySequence.set_superclasses([ ^Object ]); ^LazySequence.add_attribute('$!current', nil); ^LazySequence.add_attribute('&generator', nil); ^LazySequence.add_method('BUILD', -> %params { # cache the current (head) element # at instance creation time :) self`set_attr('$!current', self`get_attr('&generator')`()); }); # --------------------------------------------------------------------------- # # Methods dependent upon the repr type ^LazySequence.add_method('head', -> { self`get_attr('$!current') }); ^LazySequence.add_method('tail', -> { # create a new instance, which then forces the # current element to be generated (see BUILD above) $?CLASS.new({ '&generator' => self`get_attr('&generator') }); }); # these two need to be re-implemented to return LazySequences ^LazySequence.add_method('apply', -> &code { &old_generator := self`get_attr('&generator'); $?CLASS.new({ '&generator' => -> { &code`(&old_generator`()) } }); }); ^LazySequence.add_method('filter', -> &code { &old_generator := self`get_attr('&generator'); $?CLASS.new({ '&generator' => -> { &redo := &?SUB; my $value = &old_generator`(); &code`($value)`as_bit()`if_else( -> { $value }, -> { &redo`() } ); } }); }); # NOTE: # ideally this would not need to be re-implemented # here just so that I could return a non-lazy Sequence # but I see no other way currently. ^LazySequence.add_method('reverse', -> { -> $list, @acc { &redo := &?SUB; $list.is_empty()`if_else( -> { ^Sequence.new(@acc) }, # << Must return a regular Sequcene type -> { &redo`($list.tail(), [ $list.head() ]`concat(@acc)) } ); }`(self.tail(), [ self.head() ]); });