lazy-seq
lazy-seq copied to clipboard
How about adding `reduce` `->vec` and `transpose` function?
Firstly thank you for maintaining such a useful lib in fennel. Most my problems is about there are lots of construct function for seq, but merely destruct one. And adding functions below would be very helpful, IMO.
reduce : forall a. forall b. (b -> a -> b) -> b -> Seq a -> b
->vec : forall a. Seq a -> List a
->string: forall a. Seq String -> String
->string = reduce (..) ""
transpose : forall a. Seq (Seq a) -> Seq (Seq a)
You can destructure a sequence with Fennel's destructuring, since sequences can be indexed, and also define a __fennelrest
metamethod to avoid realizing the tail. Like so:
(let [[a b c & rest] (range)]
(print a b c rest))
;; 0 1 2 lazy cons: 0x559c54c0f770
I'm not very good at reading Haskellish type descriptions, but I'll try to answer all these:
-
reduce
isn't needed as there's alreadyaccumulate
in Fennel, and sequences support iterators, so you can do:(local nums (range 10)) (accumulate [res 0 _ x (pairs (range 10))] (+ res x)) ;=> 45
-
->vec
is currently implemented in tests but only for the comparison purposes, as not all Lua's allow comparing objects with different__eq
methods. However, such a simple implementation will not work for broader cases, because, unlike tables, sequences can containnil
s, which when put into a table result in holes. The library provides apack
function, that takes a sequence and packs it into a table with size indication, much liketable.pack
.(local s (cons :a (cons nil (cons :c (list))))) s ;=> @seq(:a nil :c) (pack s) ;=> {1 :a 3 :c :n 3} (table.pack :a nil :c) ;=> {1 "a" 3 "c" :n 3}
-
As for
->string
this is handled byfennel.view
module:(local fennel (require :fennel)) (fennel.view (list 1 2 3)) ;=> "@seq(1 2 3)"
This is a general mechanism with additional control options, that works for all data structures that implement the
__fennelview
metamethod, so a separate->string
is not needed. Lua'stostring
also works on sequences, but it returns a more Lua-like"lazy cons: 0x682687623"
thing. -
For
transpose
there's alreadymap
andunpack
:(map list (unpack (list (list 1 2 3) (list 4 5 6)))) ;=> @seq(@seq(1 4) @seq(2 5) @seq(3 6)) (map list (unpack [[1 2 3] [4 5 6]])) ;=> @seq(@seq(1 4) @seq(2 5) @seq(3 6)) ;; and back (map list (unpack (map list (unpack (list (list 1 2 3) (list 4 5 6)))))) ;=> @seq(@seq(1 2 3) @seq(4 5 6))
unpack
here serves the same purpose asapply
in other lisps.
Hope this answers your questions!
Additionally, I'm going to use this library in cljlib (eventually) to provide all seq
related features via functions from this library. Cljlib has a more broader scope and thus includes some of the functions you've mentioned. For this library the main focus is providing lazy sequences and the most essential operations on them. All things you've described aren't specific to sequences and not necessary lazy, so I'd move them to cljlib
or left for user to implement. Granted Fennel already provides everything you need! :smiley:
Thanks for your detailed explanation and patience to understand my wierd expression.
Your answer solve my problem using this lib. And I will try cljlib later.
Retrospectively, the reason why I struggle to find a lib, is that I want to do everything, especially array like data structure processing, in a functional programming style. In fp world, everything should be combinable. icollect
and accumulate
work, but cannot combine directly like map, filter, reduce, fold. What I want feels like that, I was a chief and asked for cooking chicken, all I need to do is sealing chicken into a magical black box, and flipping and shaking the box in a specific manner, and finally when open the box, chicken dish is done.
Thanks again for solving my problem.
Cheers
------- Original Message ------- On Saturday, May 7th, 2022 at 12:25 AM, Andrey Listopadov @.***> wrote:
Additionally, I'm going to use this library in cljlib (eventually) to provide all
seq
related features via functions from this library. Cljlib has a more broader scope and thus includes some of the functions you've mentioned. For this library the main focus is providing lazy sequences and the most essential operations on them. All things you've described aren't specific to sequences and not necessary lazy, so I'd move them tocljlib
or left for user to implement. Granted Fennel already provides everything you need! 😃— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you authored the thread.Message ID: @.***>
yes, accumulate
is a bit hard to compose with the rest of the library, as it's not a function you could thread to or compose with comp. Adding reduce can be done, I just need to think of a proper way to do so, like supporting early termination with reduced
@para100 I've added reduce
and reduced
in d902303
Now you can do (reduce #(.. $1 $2) [1 2 3])
and other stuff you would normally need accumulate
to. I think that all other cases are now well covered and don't require to be added to the library