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:
-
reduceisn't needed as there's alreadyaccumulatein Fennel, and sequences support iterators, so you can do:(local nums (range 10)) (accumulate [res 0 _ x (pairs (range 10))] (+ res x)) ;=> 45 -
->vecis currently implemented in tests but only for the comparison purposes, as not all Lua's allow comparing objects with different__eqmethods. However, such a simple implementation will not work for broader cases, because, unlike tables, sequences can containnils, which when put into a table result in holes. The library provides apackfunction, 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
->stringthis is handled byfennel.viewmodule:(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
__fennelviewmetamethod, so a separate->stringis not needed. Lua'stostringalso works on sequences, but it returns a more Lua-like"lazy cons: 0x682687623"thing. -
For
transposethere's alreadymapandunpack:(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))unpackhere serves the same purpose asapplyin 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
seqrelated 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 tocljlibor 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