Commits

camlspotter committed 72da43c

split_at

Comments (0)

Files changed (3)

+open Base
 open Xlazy
 
 type 'a t = 'a desc lazy_t
 
 let between t1 t2 = List.rev (rev_between t1 t2)
 
+let split_at len t = 
+  let rec split rev_list len t = 
+    if len <= 0 then List.rev rev_list, t
+    else 
+      match t with
+      | lazy Null -> List.rev rev_list, null
+      | lazy (Cons (v, t)) -> split (v::rev_list) (len-1) t
+  in
+  split [] len t
+          
+(*
+let rec split_at' : int -> 'a t -> 'a t * 'a t = fun len t ->
+  let ztuple : ('a t * 'a t) Lazy.t = lazy (
+    if len <= 0 then null, t
+    else match t with
+    | lazy Null -> null, null
+    | lazy (Cons (v, t)) -> 
+        let pref, post = split_at' (len-1) t in
+        v^^pref, post
+  )
+  in
+  lazy(!!(fst !!ztuple)),
+  lazy(!!(snd !!ztuple))
+*)
+
+let rec split_at' : int -> 'a t -> 'a t * 'a t = fun len t ->
+  let ztuple : ('a t * 'a t) Lazy.t = lazy (
+    if len <= 0 then null, t
+    else match t with
+    | lazy Null -> null, null
+    | lazy (Cons (v, t)) -> 
+        let pref, post = split_at' (len-1) t in
+        v^^pref, post
+  )
+  in
+  lazy(!!(fst !!ztuple)),
+  lazy(!!(snd !!ztuple))
+
+let _test_split_at' () = 
+  let rec list = 
+    function 
+      | 0 -> null
+      | i -> lazy (print_int i; print_newline (); Cons (i, list (i-1)))
+  in
+  let my = split_at' 3 (list 10) in
+  print_endline "forcing fst";
+  ignore & Lazy.force (fst my);
+  print_endline "forcing snd";
+  ignore & Lazy.force (snd my);
+  ()
+  
 val iter : ('a -> unit) -> 'a t -> unit
 (** Iteration. Never terminates over inifinite streams. *)
 
-val fold_left : ('a Lazy.t -> 'b -> 'a Lazy.t) -> 'a Lazy.t-> 'b t -> 'a Lazy.t
+val fold_left : ('a Lazy.t -> 'b -> 'a Lazy.t) -> 'a Lazy.t -> 'b t -> 'a Lazy.t
 (** Folding left. Tail recursive. Lazy. *)
 
 val fold_left1 : ('a Lazy.t -> 'a Lazy.t -> 'a Lazy.t) -> 'a Lazy.t t -> 'a Lazy.t
 val intersparse : 'a -> 'a t -> 'a t
 (** Haskell's intersparse *)
 
+val split_at : int -> 'a t -> 'a list * 'a t
+(** Haskell's splitAt. Prefix is forced. *)
+
+val split_at' : int -> 'a t -> 'a t * 'a t
+(** Haskell's splitAt. Prefix is lazy. *)
+
 (** {6 Inpure hacks} *)
 
 val rev_between : 'a t -> 'a t -> 'a list
 let is_val = lazy_is_val
 
 let detuple xy = 
-  let map f = let lazy xy = xy in f xy in
-  lazy (map fst),
-  lazy (map snd)
+  map ~f:fst xy,
+  map ~f:snd xy