Module: System::Collections::StreamLambdas

Extended by:
StreamLambdas
Included in:
StreamLambdas, F
Defined in:
lib/raskell/f.rb

Instance Method Summary collapse

Instance Method Details

#appendObject



651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
# File 'lib/raskell/f.rb', line 651

def append
  @@append||= ->(left_stream) {
    ->(right_stream) {
      left_next_fn = ->(stream) {
        next_el = stream.next_item
        if next_el == [:done]
          [:skip, right_stream]
        elsif next_el.first == :skip
          [:skip, Stream.new(left_next_fn, next_el.last)]
        elsif next_el.first == :yield
          [next_el.first, next_el[1], Stream.new(left_next_fn, next_el.last)]
        else
          raise "#{next_el.inspect} is not a valid stream state!"
        end
      }
      
      Stream.new(left_next_fn, left_stream)
    } * to_stream
    
  } * to_stream
end

#cartesian_productObject



886
887
888
889
890
891
892
# File 'lib/raskell/f.rb', line 886

def cartesian_product
  @@cartesian_product||= ->(xs) {
    ->(ys) {
        flatmap.(->(x) { map.(->(y) { [x,y] }, ys) }, xs)
      } * to_stream
  } * to_stream
end

#concatObject



673
674
675
# File 'lib/raskell/f.rb', line 673

def concat
  @@concat||= flatmap.(to_stream)
end

#consObject



573
574
575
576
577
578
579
# File 'lib/raskell/f.rb', line 573

def cons
 @@cons||= ->(el) { 
    ->(stream) {
      Stream.new(->(x) { [:yield, el, stream] } , Nothing) 
    } * to_stream
  }
end

#contains?Boolean

Returns:



837
838
839
# File 'lib/raskell/f.rb', line 837

def contains?
  @@contains_p||= ->(el) { F.not * F.equal.(Nothing) * find_where.(equals.(el)) }
end

#contains_slice?Boolean

Returns:



845
846
847
# File 'lib/raskell/f.rb', line 845

def contains_slice?
  @@contains_slice_p||= ->(slice) { any?.(starts_with.(slice)) * tails }
end

#continuous_subsequencesObject



919
920
921
# File 'lib/raskell/f.rb', line 919

def continuous_subsequences
  @@continuous_subsequences||= filter.(F.not * empty?) * flatmap.(prefixes) * suffixes
end

#differenceObject



877
878
879
880
881
882
883
884
# File 'lib/raskell/f.rb', line 877

def difference
  @@difference||= ->(xs) {
    ->(ys) {
        to_remove = to_set.(ys)
        filter.(->(x) { !ys.include?(x)}) << xs
      } * to_stream
  } * to_stream
end

#does_not_contain?Boolean

Returns:



841
842
843
# File 'lib/raskell/f.rb', line 841

def does_not_contain?
  @@does_not_contain_p||= ->(el) { F.equal.(Nothing) * find_where.(equals.(el)) }
end

#emptyObject



562
563
564
# File 'lib/raskell/f.rb', line 562

def empty
  @@empty||= Stream.new(->(x) { [:done] }, Nothing)
end

#empty?Boolean

Returns:



554
555
556
# File 'lib/raskell/f.rb', line 554

def empty?
  @@empty_p||= F.equal.(empty)
end

#enconcatObject



677
678
679
# File 'lib/raskell/f.rb', line 677

def enconcat
  @@enconcat||= ->(left_stream, el) { append.(left_stream.to_stream) * cons.(el) * to_stream }
end

#ends_with?Boolean

Returns:



829
830
831
# File 'lib/raskell/f.rb', line 829

def ends_with?
  @@ends_with||= ->(slice) { F.equal.(slice) * drop_except.(length.(slice)) }
end

#finalObject



699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
# File 'lib/raskell/f.rb', line 699

def final
  @@final||= -> (stream) { 
    next_fn = ->(state) {
      prev_step = state.first
      strm = state.last
      raise("Must have at least one item inside of the stream!") if prev_step == [:done]
      next_item = strm.next_item
      if prev_step.first == :skip
        [:skip, Stream.new(next_fn, [next_item, next_item.last])]
      elsif next_item == [:done]
        [:yield, prev_step[1], empty]
      elsif next_item.first == :yield
        [:skip, Stream.new(next_fn, [next_item, next_item.last])]
      elsif next_item.first == :skip
        [:skip, Stream.new(next_fn, [prev_step, next_item.last])]
      else
        raise "#{next_item} is a malformed stream result"
      end
    }
    next_item = stream.next_item
    Stream.new(next_fn, [next_item, next_item.last])
  } * to_stream
end

#firstObject



582
583
584
585
586
587
588
589
590
# File 'lib/raskell/f.rb', line 582

def first
  @@first||= -> (stream) { ## should offer an equivalent that returns a stream with a single element
    next_item = stream.next_item
    while next_item.first == :skip
      next_item = next_item.last.next_item
    end
    next_item.first == :yield ? next_item[1] : Nothing
  } * to_stream
end

#first_index_ofObject



857
858
859
# File 'lib/raskell/f.rb', line 857

def first_index_of
  @@first_index_of||= ->(x) { first_index_where.( F.equal.(x) ) }
end

#groupObject



936
937
938
# File 'lib/raskell/f.rb', line 936

def group 
  @@group||= ->(xs) { group_by.(id) }
end

#headObject



813
814
815
# File 'lib/raskell/f.rb', line 813

def head
  @@head||= first
end

#initObject



628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
# File 'lib/raskell/f.rb', line 628

def init
  @@init||= ->(stream) { 
    next_fn = ->(state) {
      strm = state.last
      next_item = strm.next_item
      if next_item == [:done] && state.first == Nothing
        raise "init requires a stream length of at least 1"
      elsif next_item == [:done]
        [:done]
      elsif next_item.first == :skip 
        [:skip, Stream.new(next_fn, [state.first, next_item.last])]
      elsif next_item.first == :yield && state.first == Nothing
        [:skip, Stream.new(next_fn, [next_item[1], next_item.last])]
      elsif next_item.first == :yield
        [:yield, state.first, Stream.new(next_fn, [next_item[1], next_item.last])]
      else
        raise "#{next_item} is a malformed stream response"
      end
    }
    Stream.new(next_fn, [Nothing, stream])
  } * to_stream
end

#initialObject



681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
# File 'lib/raskell/f.rb', line 681

def initial
  @@initial||= ->(stream) {
    next_fn = ->(strm) {
      next_item = strm.next_item
      if next_item.first == :done
        raise "Must have at least one item inside of the stream!"
      elsif next_item.first == :yield
        [:yield, next_item[1], empty]
      elsif next_item.first == :skip
        [:skip, next_item.last]
      else
        raise("#{next_item} is a malformed stream response!")
      end
    }
    Stream.new(next_fn, stream)
    }
end

#initsObject



817
818
819
# File 'lib/raskell/f.rb', line 817

def inits
  @@inits||= prefixes
end

#intercalateObject

you can undo this with % n, where n is the number of streams



733
734
735
# File 'lib/raskell/f.rb', line 733

def intercalate
  @@intercalate||= ->(xs, xss) { concat.intersperse.(xs, xss) }
end

#interleaveObject



729
730
731
# File 'lib/raskell/f.rb', line 729

def interleave
  @@interleave||= ->(xs, *ys) { ys.length > 0 ? (concat * zip).(*([xs]+ys)) : ->(zs, *ys) { concat << zip.(*([xs,zs]+ys)) } }
end

#intersectObject



869
870
871
872
873
874
875
# File 'lib/raskell/f.rb', line 869

def intersect
  @@intersect||= ->(xs) {
    ->(ys) {
        to_stream << (to_set.(xs) & to_set.(ys))
      } * to_stream
  } * to_stream
end

#intersperseObject



833
834
835
# File 'lib/raskell/f.rb', line 833

def intersperse
  @@intersperse||= ->(x, xs) { rest * flatmap.(->(y) { [x, y].to_stream }) << xs.to_stream }
end

#lastObject

stream functions



761
762
763
# File 'lib/raskell/f.rb', line 761

def last
  @@last||= first * final
end

#last_index_ofObject



853
854
855
# File 'lib/raskell/f.rb', line 853

def last_index_of
  @@last_index_of||= ->(x) { last_index_where.(F.equal.(x)) }
end

#lengthObject



777
778
779
# File 'lib/raskell/f.rb', line 777

def length
  @@length||= foldl.(inc, 0)
end

#length_at_leastObject



781
782
783
# File 'lib/raskell/f.rb', line 781

def length_at_least
  @@length_at_least||= ->(n) { ->(x) { x != Nothing } * find_where.(equals.(n)) * scanl.(inc, 0) }
end

#null?Boolean

Returns:



558
559
560
# File 'lib/raskell/f.rb', line 558

def null?
  @@null_p||= F.equal.(empty)
end

#partition_atObject



849
850
851
# File 'lib/raskell/f.rb', line 849

def partition_at
  @@partition_at||= ->(n) { take.(n) + drop.(n) }
end

#prefixObject



805
806
807
# File 'lib/raskell/f.rb', line 805

def prefix
  @@prefix||= init
end

#prefixesObject



756
757
758
# File 'lib/raskell/f.rb', line 756

def prefixes
  @@prefixes||= foldr.(->(el, acc) { cons.(empty, map.(cons.(el), acc)) }, wrap.(empty))
end

#quicksortObject

continuous subsequences is useful for exact inside sequence matching a la find in sublime



924
925
926
927
928
929
930
931
932
933
934
# File 'lib/raskell/f.rb', line 924

def quicksort
   ->(xs) {
     if empty?.(xs)
       empty
     else
       pivot = head.(xs)
       partitions = (F.map.(self.quicksort) * partition_by.(F.is_lte.(pivot)) << tail.(xs)).to_a
       append.(partitions[0],cons.(pivot, partitions[1]))
     end
   } * to_stream ### if only this wasn't infinitely recursing...
end

#replaceObject



785
786
787
# File 'lib/raskell/f.rb', line 785

def replace
  @@replace||= ->(to_replace, to_replace_with) {map.(->(x) { x == to_replace ? to_replace_with : x })}
end

#restObject



592
593
594
595
596
597
# File 'lib/raskell/f.rb', line 592

def rest
  @@rest||= -> (stream) { 
    next_item = stream.next_item
    next_item == [:done] ? Nothing : next_item.last
  } * to_stream
end

#reverseObject



773
774
775
# File 'lib/raskell/f.rb', line 773

def reverse
  @@reverse||= foldl.(->(acc, el) { cons.(el, acc) }, []) ## or foldr.(->(el,acc) { snoc.(acc, el) }
end

#rotateObject



724
725
726
# File 'lib/raskell/f.rb', line 724

def rotate
  @@rotate||= ->(s) { append.(tail.(s), initial.(s)) }
end

#snocObject



599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
# File 'lib/raskell/f.rb', line 599

def snoc
  @@snoc||= ->(el) {
    
     ->(stream) { 
      # next_fn = step.(->(stream) {
      #     next_item = stream.next_item
      #     next_item == [:done] ? wrap.(el) : next_item.last
      #   },
      #   ->(stream) {
      #     next_item = stream.next_item
      #     next_item.first == :skip ? Nothing : next_item[1]
      # })
      next_fn = ->(s) {
        next_item = s.next_item
        if next_item == [:done]
          [:skip, wrap.(el)]
        elsif next_item.first == :skip
          [:skip, Stream.new(next_fn, next_item.last)]
        elsif next_item.first == :yield
          [:yield, next_item[1], Stream.new(next_fn, next_item.last)]
        else 
          raise "#{next_item} is a malformed stream result"
        end
      }
      Stream.new(next_fn, stream)
    } * to_stream
  }
end

#starts_with?Boolean

Returns:



825
826
827
# File 'lib/raskell/f.rb', line 825

def starts_with?
  @@starts_with||= ->(prefix, stream) { F.ands << zip_with.(equals, prefix, stream) }
end

#subsequencesObject



906
907
908
909
910
# File 'lib/raskell/f.rb', line 906

def subsequences
  @@subsequences||= ->() { ## Using the applicative instance for <**>, which is ^ in Raskell
    subs = ->(ys) { ys == empty ? wrap.(empty) : subs.(rest.(ys)) ^ [F.id, F.cons.(first.(ys))].to_stream }
  }.() #wrap.(empty)
end

#suffixObject



809
810
811
# File 'lib/raskell/f.rb', line 809

def suffix
  @@suffix||= rest
end

#suffixesObject



737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
# File 'lib/raskell/f.rb', line 737

def suffixes
  @@suffixes||= ->(stream) {
    next_fn = ->(strm) {
      next_item = strm.next_item
      if next_item.first == :done
        [:yield, strm, empty]
      elsif next_item.first == :yield
        [:yield, strm, Stream.new(next_fn, next_item.last)]
      elsif next_item.first == :skip
        [:skip, Stream.new(next_fn, next_item.last)]
      else
        raise("#{next_item} is a malformed stream response!")
      end
    }
    Stream.new(next_fn, stream)
  } * to_stream
end

#tailObject



801
802
803
# File 'lib/raskell/f.rb', line 801

def tail
  @@tail||= rest
end

#tailsObject



821
822
823
# File 'lib/raskell/f.rb', line 821

def tails
  @@tails||= suffixes
end

#transposeObject



797
798
799
# File 'lib/raskell/f.rb', line 797

def transpose
  @@transpose||= ->(stream_of_streams) { zip.( *(stream_of_streams.to_stream) ) }
end

#unconsObject



765
766
767
# File 'lib/raskell/f.rb', line 765

def uncons
  @@uncons||= ->(s) { append(first.(l), wrap(rest.(l)))  } * to_stream
end

#unionObject



861
862
863
864
865
866
867
# File 'lib/raskell/f.rb', line 861

def union
  @@union||= ->(xs) {
    ->(ys) {
        to_stream * to_set << append.(xs, ys)
      } * to_stream
  } * to_stream
end

#unsnocObject



769
770
771
# File 'lib/raskell/f.rb', line 769

def unsnoc
  @@unsnoc||= ->(s) { append(wrap(init.(s)), last.(s)) } * to_stream
end

#unzipObject



894
895
896
897
898
# File 'lib/raskell/f.rb', line 894

def unzip
  @@unzip||= ->(xs) {
    map.(first) + map.(last) << xs
  } * to_stream
end

#windowObject



900
901
902
903
904
# File 'lib/raskell/f.rb', line 900

def window
  @@window||= ->(n) {
    map.(take.(n)) * suffixes
  }
end

#wrapObject



566
567
568
569
570
571
# File 'lib/raskell/f.rb', line 566

def wrap
  @@wrap||= ->(x) {
    next_fn = ->(bool) { bool ? [:yield, x, Stream.new(next_fn, false)] : [:done]}
    Stream.new(next_fn, true)
  }
end

#zipObject



789
790
791
# File 'lib/raskell/f.rb', line 789

def zip
  @@zip||= zip_with.(list)
end

#zip_with_indexObject



793
794
795
# File 'lib/raskell/f.rb', line 793

def zip_with_index
  @@zip_with_index||= F.zip_with.(F.list).(F.range.(0, F.infinity))
end