From 49d59ddc16a588115e02303fd325e46d6c1c87ac Mon Sep 17 00:00:00 2001 From: Eduardo Julian Date: Tue, 3 Jul 2018 22:30:49 -0400 Subject: - Re-named "stream" to "sequence". - Updated copyright dates for lux-mode. --- lux-mode/lux-mode.el | 4 +- stdlib/source/lux/data/coll/sequence.lux | 146 ++++++++++++++++++++++++++++ stdlib/source/lux/data/coll/stream.lux | 146 ---------------------------- stdlib/test/test/lux/data/coll/sequence.lux | 101 +++++++++++++++++++ stdlib/test/test/lux/data/coll/stream.lux | 101 ------------------- 5 files changed, 249 insertions(+), 249 deletions(-) create mode 100644 stdlib/source/lux/data/coll/sequence.lux delete mode 100644 stdlib/source/lux/data/coll/stream.lux create mode 100644 stdlib/test/test/lux/data/coll/sequence.lux delete mode 100644 stdlib/test/test/lux/data/coll/stream.lux diff --git a/lux-mode/lux-mode.el b/lux-mode/lux-mode.el index dc780b364..5beb7f91c 100644 --- a/lux-mode/lux-mode.el +++ b/lux-mode/lux-mode.el @@ -1,6 +1,6 @@ ;;; lux-mode.el --- Major mode for Lux code -*- lexical-binding: t; -*- -;; Copyright © 2014-2017 Eduardo Julian +;; Copyright © 2014-2018 Eduardo Julian ;; ;; Authors: Eduardo Julian ;; URL: https://github.com/LuxLang/lux/tree/master/lux-mode @@ -233,7 +233,7 @@ Called by `imenu--generic-function'." "list" "list&" "io" "row" "tree" "get@" "set@" "update@" "|>" "|>>" "<|" "<<|" "_$" "$_" "~" "~+" "~!" "~'" "::" ":::" "|" "&" "->" "All" "Ex" "Rec" "primitive" "$" "type" - "^" "^or" "^slots" "^multi" "^@" "^template" "^open" "^|>" "^code" "^stream&" "^regex" + "^" "^or" "^slots" "^multi" "^@" "^template" "^open" "^|>" "^code" "^sequence&" "^regex" "bin" "oct" "hex" "pre" "post" "sig" "struct" "derive" diff --git a/stdlib/source/lux/data/coll/sequence.lux b/stdlib/source/lux/data/coll/sequence.lux new file mode 100644 index 000000000..b8908403b --- /dev/null +++ b/stdlib/source/lux/data/coll/sequence.lux @@ -0,0 +1,146 @@ +(.module: + lux + (lux (control functor + monad + comonad + [continuation #+ pending Cont] + ["p" parser]) + [macro #+ with-gensyms] + (macro [code] + ["s" syntax #+ syntax: Syntax]) + (data (coll [list "List/" Monad]) + bool))) + +## [Types] +(type: #export (Sequence a) + {#.doc "An infinite sequence of values."} + (Cont [a (Sequence a)])) + +## [Utils] +(def: (cycle' x xs init full) + (All [a] + (-> a (List a) a (List a) (Sequence a))) + (case xs + #.Nil (pending [x (cycle' init full init full)]) + (#.Cons x' xs') (pending [x (cycle' x' xs' init full)]))) + +## [Functions] +(def: #export (iterate f x) + {#.doc "Create a sequence by applying a function to a value, and to its result, on and on..."} + (All [a] + (-> (-> a a) a (Sequence a))) + (pending [x (iterate f (f x))])) + +(def: #export (repeat x) + {#.doc "Repeat a value forever."} + (All [a] + (-> a (Sequence a))) + (pending [x (repeat x)])) + +(def: #export (cycle xs) + {#.doc "Go over the elements of a list forever. + + The list should not be empty."} + (All [a] + (-> (List a) (Maybe (Sequence a)))) + (case xs + #.Nil #.None + (#.Cons x xs') (#.Some (cycle' x xs' x xs')))) + +(do-template [ ] + [(def: #export ( s) + (All [a] (-> (Sequence a) )) + (let [[h t] (continuation.run s)] + ))] + + [head a h] + [tail (Sequence a) t]) + +(def: #export (nth idx s) + (All [a] (-> Nat (Sequence a) a)) + (let [[h t] (continuation.run s)] + (if (n/> +0 idx) + (nth (dec idx) t) + h))) + +(do-template [ ] + [(def: #export ( pred xs) + (All [a] + (-> (Sequence a) (List a))) + (let [[x xs'] (continuation.run xs)] + (if + (list& x ( xs')) + (list)))) + + (def: #export ( pred xs) + (All [a] + (-> (Sequence a) (Sequence a))) + (let [[x xs'] (continuation.run xs)] + (if + ( xs') + xs))) + + (def: #export ( pred xs) + (All [a] + (-> (Sequence a) [(List a) (Sequence a)])) + (let [[x xs'] (continuation.run xs)] + (if + (let [[tail next] ( xs')] + [(#.Cons [x tail]) next]) + [(list) xs])))] + + [take-while drop-while split-while (-> a Bool) (pred x) pred] + [take drop split Nat (n/> +0 pred) (dec pred)] + ) + +(def: #export (unfold step init) + {#.doc "A stateful way of infinitely calculating the values of a sequence."} + (All [a b] + (-> (-> a [a b]) a (Sequence b))) + (let [[next x] (step init)] + (pending [x (unfold step next)]))) + +(def: #export (filter p xs) + (All [a] (-> (-> a Bool) (Sequence a) (Sequence a))) + (let [[x xs'] (continuation.run xs)] + (if (p x) + (pending [x (filter p xs')]) + (filter p xs')))) + +(def: #export (partition p xs) + {#.doc "Split a sequence in two based on a predicate. + + The left side contains all entries for which the predicate is true. + + The right side contains all entries for which the predicate is false."} + (All [a] (-> (-> a Bool) (Sequence a) [(Sequence a) (Sequence a)])) + [(filter p xs) (filter (complement p) xs)]) + +## [Structures] +(struct: #export _ (Functor Sequence) + (def: (map f fa) + (let [[h t] (continuation.run fa)] + (pending [(f h) (map f t)])))) + +(struct: #export _ (CoMonad Sequence) + (def: functor Functor) + (def: unwrap head) + (def: (split wa) + (let [[head tail] (continuation.run wa)] + (pending [wa (split tail)])))) + +## [Pattern-matching] +(syntax: #export (^sequence& {patterns (s.form (p.many s.any))} + body + {branches (p.some s.any)}) + {#.doc (doc "Allows destructuring of sequences in pattern-matching expressions." + "Caveat emptor: Only use it for destructuring, and not for testing values within the sequences." + (let [(^sequence& x y z _tail) (some-sequence-func 1 2 3)] + (func x y z)))} + (with-gensyms [g!sequence] + (let [body+ (` (let [(~+ (List/join (List/map (function (_ pattern) + (list (` [(~ pattern) (~ g!sequence)]) + (` ((~! continuation.run) (~ g!sequence))))) + patterns)))] + (~ body)))] + (wrap (list& g!sequence body+ branches))))) diff --git a/stdlib/source/lux/data/coll/stream.lux b/stdlib/source/lux/data/coll/stream.lux deleted file mode 100644 index 305a5da4e..000000000 --- a/stdlib/source/lux/data/coll/stream.lux +++ /dev/null @@ -1,146 +0,0 @@ -(.module: - lux - (lux (control functor - monad - comonad - [continuation #+ pending Cont] - ["p" parser]) - [macro #+ with-gensyms] - (macro [code] - ["s" syntax #+ syntax: Syntax]) - (data (coll [list "List/" Monad]) - bool))) - -## [Types] -(type: #export (Stream a) - {#.doc "An infinite stream of values."} - (Cont [a (Stream a)])) - -## [Utils] -(def: (cycle' x xs init full) - (All [a] - (-> a (List a) a (List a) (Stream a))) - (case xs - #.Nil (pending [x (cycle' init full init full)]) - (#.Cons x' xs') (pending [x (cycle' x' xs' init full)]))) - -## [Functions] -(def: #export (iterate f x) - {#.doc "Create a stream by applying a function to a value, and to its result, on and on..."} - (All [a] - (-> (-> a a) a (Stream a))) - (pending [x (iterate f (f x))])) - -(def: #export (repeat x) - {#.doc "Repeat a value forever."} - (All [a] - (-> a (Stream a))) - (pending [x (repeat x)])) - -(def: #export (cycle xs) - {#.doc "Go over the elements of a list forever. - - The list should not be empty."} - (All [a] - (-> (List a) (Maybe (Stream a)))) - (case xs - #.Nil #.None - (#.Cons x xs') (#.Some (cycle' x xs' x xs')))) - -(do-template [ ] - [(def: #export ( s) - (All [a] (-> (Stream a) )) - (let [[h t] (continuation.run s)] - ))] - - [head a h] - [tail (Stream a) t]) - -(def: #export (nth idx s) - (All [a] (-> Nat (Stream a) a)) - (let [[h t] (continuation.run s)] - (if (n/> +0 idx) - (nth (dec idx) t) - h))) - -(do-template [ ] - [(def: #export ( pred xs) - (All [a] - (-> (Stream a) (List a))) - (let [[x xs'] (continuation.run xs)] - (if - (list& x ( xs')) - (list)))) - - (def: #export ( pred xs) - (All [a] - (-> (Stream a) (Stream a))) - (let [[x xs'] (continuation.run xs)] - (if - ( xs') - xs))) - - (def: #export ( pred xs) - (All [a] - (-> (Stream a) [(List a) (Stream a)])) - (let [[x xs'] (continuation.run xs)] - (if - (let [[tail next] ( xs')] - [(#.Cons [x tail]) next]) - [(list) xs])))] - - [take-while drop-while split-while (-> a Bool) (pred x) pred] - [take drop split Nat (n/> +0 pred) (dec pred)] - ) - -(def: #export (unfold step init) - {#.doc "A stateful way of infinitely calculating the values of a stream."} - (All [a b] - (-> (-> a [a b]) a (Stream b))) - (let [[next x] (step init)] - (pending [x (unfold step next)]))) - -(def: #export (filter p xs) - (All [a] (-> (-> a Bool) (Stream a) (Stream a))) - (let [[x xs'] (continuation.run xs)] - (if (p x) - (pending [x (filter p xs')]) - (filter p xs')))) - -(def: #export (partition p xs) - {#.doc "Split a stream in two based on a predicate. - - The left side contains all entries for which the predicate is true. - - The right side contains all entries for which the predicate is false."} - (All [a] (-> (-> a Bool) (Stream a) [(Stream a) (Stream a)])) - [(filter p xs) (filter (complement p) xs)]) - -## [Structures] -(struct: #export _ (Functor Stream) - (def: (map f fa) - (let [[h t] (continuation.run fa)] - (pending [(f h) (map f t)])))) - -(struct: #export _ (CoMonad Stream) - (def: functor Functor) - (def: unwrap head) - (def: (split wa) - (let [[head tail] (continuation.run wa)] - (pending [wa (split tail)])))) - -## [Pattern-matching] -(syntax: #export (^stream& {patterns (s.form (p.many s.any))} - body - {branches (p.some s.any)}) - {#.doc (doc "Allows destructuring of streams in pattern-matching expressions." - "Caveat emptor: Only use it for destructuring, and not for testing values within the streams." - (let [(^stream& x y z _tail) (some-stream-func 1 2 3)] - (func x y z)))} - (with-gensyms [g!stream] - (let [body+ (` (let [(~+ (List/join (List/map (function (_ pattern) - (list (` [(~ pattern) (~ g!stream)]) - (` ((~! continuation.run) (~ g!stream))))) - patterns)))] - (~ body)))] - (wrap (list& g!stream body+ branches))))) diff --git a/stdlib/test/test/lux/data/coll/sequence.lux b/stdlib/test/test/lux/data/coll/sequence.lux new file mode 100644 index 000000000..44eea350b --- /dev/null +++ b/stdlib/test/test/lux/data/coll/sequence.lux @@ -0,0 +1,101 @@ +(.module: + lux + (lux [io] + (control [monad #+ do Monad] + comonad) + (data [maybe] + [text "Text/" Monoid] + text/format + (coll [list] + ["&" sequence]) + [number "Nat/" Codec]) + ["r" math/random]) + lux/test) + +(context: "Sequences" + (<| (times +100) + (do @ + [size (|> r.nat (:: @ map (|>> (n/% +100) (n/max +2)))) + offset (|> r.nat (:: @ map (n/% +100))) + factor (|> r.nat (:: @ map (|>> (n/% +100) (n/max +2)))) + elem r.nat + cycle-seed (r.list size r.nat) + cycle-sample-idx (|> r.nat (:: @ map (n/% +1000))) + #let [(^open "List/") (list.Eq number.Eq) + sample0 (&.iterate inc +0) + sample1 (&.iterate inc offset)]] + ($_ seq + (test "Can move along a sequence and take slices off it." + (and (and (List/= (list.n/range +0 (dec size)) + (&.take size sample0)) + (List/= (list.n/range offset (dec (n/+ offset size))) + (&.take size (&.drop offset sample0))) + (let [[drops takes] (&.split size sample0)] + (and (List/= (list.n/range +0 (dec size)) + drops) + (List/= (list.n/range size (dec (n/* +2 size))) + (&.take size takes))))) + (and (List/= (list.n/range +0 (dec size)) + (&.take-while (n/< size) sample0)) + (List/= (list.n/range offset (dec (n/+ offset size))) + (&.take-while (n/< (n/+ offset size)) + (&.drop-while (n/< offset) sample0))) + (let [[drops takes] (&.split-while (n/< size) sample0)] + (and (List/= (list.n/range +0 (dec size)) + drops) + (List/= (list.n/range size (dec (n/* +2 size))) + (&.take-while (n/< (n/* +2 size)) takes))))) + )) + + (test "Can repeat any element and infinite number of times." + (n/= elem (&.nth offset (&.repeat elem)))) + + (test "Can obtain the head & tail of a sequence." + (and (n/= offset (&.head sample1)) + (List/= (list.n/range (inc offset) (n/+ offset size)) + (&.take size (&.tail sample1))))) + + (test "Can filter sequences." + (and (n/= (n/* +2 offset) + (&.nth offset + (&.filter n/even? sample0))) + (let [[evens odds] (&.partition n/even? (&.iterate inc +0))] + (and (n/= (n/* +2 offset) + (&.nth offset evens)) + (n/= (inc (n/* +2 offset)) + (&.nth offset odds)))))) + + (test "Functor goes over 'all' elements in a sequence." + (let [(^open "&/") &.Functor + there (&/map (n/* factor) sample0) + back-again (&/map (n// factor) there)] + (and (not (List/= (&.take size sample0) + (&.take size there))) + (List/= (&.take size sample0) + (&.take size back-again))))) + + (test "CoMonad produces a value for every element in a sequence." + (let [(^open "&/") &.Functor] + (List/= (&.take size (&/map (n/* factor) sample1)) + (&.take size + (be &.CoMonad + [inputs sample1] + (n/* factor (&.head inputs))))))) + + (test "'unfold' generalizes 'iterate'." + (let [(^open "&/") &.Functor + (^open "List/") (list.Eq text.Eq)] + (List/= (&.take size + (&/map Nat/encode (&.iterate inc offset))) + (&.take size + (&.unfold (function (_ n) [(inc n) (Nat/encode n)]) + offset))))) + + (test "Can cycle over the same elements as an infinite sequence." + (|> (&.cycle cycle-seed) + maybe.assume + (&.nth cycle-sample-idx) + (n/= (|> cycle-seed + (list.nth (n/% size cycle-sample-idx)) + maybe.assume)))) + )))) diff --git a/stdlib/test/test/lux/data/coll/stream.lux b/stdlib/test/test/lux/data/coll/stream.lux deleted file mode 100644 index 9431e2a46..000000000 --- a/stdlib/test/test/lux/data/coll/stream.lux +++ /dev/null @@ -1,101 +0,0 @@ -(.module: - lux - (lux [io] - (control [monad #+ do Monad] - comonad) - (data [maybe] - [text "Text/" Monoid] - text/format - (coll [list] - ["&" stream]) - [number "Nat/" Codec]) - ["r" math/random]) - lux/test) - -(context: "Streams" - (<| (times +100) - (do @ - [size (|> r.nat (:: @ map (|>> (n/% +100) (n/max +2)))) - offset (|> r.nat (:: @ map (n/% +100))) - factor (|> r.nat (:: @ map (|>> (n/% +100) (n/max +2)))) - elem r.nat - cycle-seed (r.list size r.nat) - cycle-sample-idx (|> r.nat (:: @ map (n/% +1000))) - #let [(^open "List/") (list.Eq number.Eq) - sample0 (&.iterate inc +0) - sample1 (&.iterate inc offset)]] - ($_ seq - (test "Can move along a stream and take slices off it." - (and (and (List/= (list.n/range +0 (dec size)) - (&.take size sample0)) - (List/= (list.n/range offset (dec (n/+ offset size))) - (&.take size (&.drop offset sample0))) - (let [[drops takes] (&.split size sample0)] - (and (List/= (list.n/range +0 (dec size)) - drops) - (List/= (list.n/range size (dec (n/* +2 size))) - (&.take size takes))))) - (and (List/= (list.n/range +0 (dec size)) - (&.take-while (n/< size) sample0)) - (List/= (list.n/range offset (dec (n/+ offset size))) - (&.take-while (n/< (n/+ offset size)) - (&.drop-while (n/< offset) sample0))) - (let [[drops takes] (&.split-while (n/< size) sample0)] - (and (List/= (list.n/range +0 (dec size)) - drops) - (List/= (list.n/range size (dec (n/* +2 size))) - (&.take-while (n/< (n/* +2 size)) takes))))) - )) - - (test "Can repeat any element and infinite number of times." - (n/= elem (&.nth offset (&.repeat elem)))) - - (test "Can obtain the head & tail of a stream." - (and (n/= offset (&.head sample1)) - (List/= (list.n/range (inc offset) (n/+ offset size)) - (&.take size (&.tail sample1))))) - - (test "Can filter streams." - (and (n/= (n/* +2 offset) - (&.nth offset - (&.filter n/even? sample0))) - (let [[evens odds] (&.partition n/even? (&.iterate inc +0))] - (and (n/= (n/* +2 offset) - (&.nth offset evens)) - (n/= (inc (n/* +2 offset)) - (&.nth offset odds)))))) - - (test "Functor goes over 'all' elements in a stream." - (let [(^open "&/") &.Functor - there (&/map (n/* factor) sample0) - back-again (&/map (n// factor) there)] - (and (not (List/= (&.take size sample0) - (&.take size there))) - (List/= (&.take size sample0) - (&.take size back-again))))) - - (test "CoMonad produces a value for every element in a stream." - (let [(^open "&/") &.Functor] - (List/= (&.take size (&/map (n/* factor) sample1)) - (&.take size - (be &.CoMonad - [inputs sample1] - (n/* factor (&.head inputs))))))) - - (test "'unfold' generalizes 'iterate'." - (let [(^open "&/") &.Functor - (^open "List/") (list.Eq text.Eq)] - (List/= (&.take size - (&/map Nat/encode (&.iterate inc offset))) - (&.take size - (&.unfold (function (_ n) [(inc n) (Nat/encode n)]) - offset))))) - - (test "Can cycle over the same elements as an infinite stream." - (|> (&.cycle cycle-seed) - maybe.assume - (&.nth cycle-sample-idx) - (n/= (|> cycle-seed - (list.nth (n/% size cycle-sample-idx)) - maybe.assume)))) - )))) -- cgit v1.2.3