Wow thanks.  That was pretty thorough.

cs

On Friday, July 20, 2018 at 10:51:48 AM UTC-5, Gary Johnson wrote:
>
> Hi Christian,
>
> You are looking for "into", which is already part of the Clojure standard 
> library.
>
> Appending:
>
> (into '(1 2) '(3))         ;=>  (1 2 3)
> (into [1 2] [3])           ;=>  [1 2 3]
> (into {:a 1 :b 2} {:c 3})  ;=>  {:a 1, :b 2, :c 3}
> (into #{:a :b} #{:c})      ;=>  #{:c :b :a}
>
> Prepending:
>
> (into '(1) '(2 3))         ;=>  (1 2 3)
> (into [1] [2 3])           ;=>  [1 2 3]
> (into {:a 1} {:b 2 :c 3})  ;=>  {:a 1, :b 2, :c 3}
> (into #{:a} #{:b :c})      ;=>  #{:c :b :a}
>
> The "into" function pours the contents of the second collection into the 
> first collection, returning a collection of the same type as the first 
> argument.
>
> That being said, I agree with Alex and James in this rather lengthy 
> discussion. Clojure is unique among the Lisps in that it moved beyond 
> having linked lists as the only first class data structure.
>
> Prior to Clojure, if you worked in a Lisp like Scheme or Common Lisp, you 
> would design your program around the creation, traversal, and manipulation 
> of linked lists using higher order functions and explicit recursions. The 
> standard library in both languages is heavily focused on these list-related 
> operations. After developing the initial version of your program, if you 
> found that it was too slow or used too much memory, the accepted practice 
> was to profile your application to identify the functions that were getting 
> hammered the most and were using up the majority of your computing 
> resources. You would then often end up rewriting those function bodies in 
> an imperative fashion using loops and mutable data structures (i.e., arrays 
> and hashtables). The "wisdom" here was that this would enable you to "first 
> make it right, then make it fast". If even further performance was required 
> from your program, you might then rewrite part of your program in C, build 
> a foreign function interface (FFI) to link the C code into your Lisp 
> program, and go from there. These were the Bad Old Days of Lisp(TM).
>
> What was IMHO quite possibly Rich's greatest contribution in the design of 
> Clojure to the Lisp world was his decision to make additional data 
> structures first class citizens of the language. Most importantly, he did 
> so by creating Clojure's vectors, maps, and sets to be immutable, 
> persistent, performant, recursively constructed, and representable as data 
> literals. This was already a wonderful improvement over previous Lisps, but 
> it created a new problem: How could we enjoy the pure delight of 
> list-oriented programming that Lisp had always offered us now that the data 
> structure space had been fragmented? A famous quote from Alan Perlis is a 
> popular gem in the Lisp world, and it goes like so:
>
> "It is better to have 100 functions operate on one data structure than to 
> have 10 functions operate on 10 data structures."
>
> Every Lisp had always satisfied this by simply giving programmers only one 
> first class data structure to use: the linked list. As I already mentioned, 
> the bulk of its standard library would then be built around list 
> manipulation functions. Clojure needed a way to preserve this unified style 
> of programming while still providing a collection of performant data 
> structures for real-world programming. So how did Rich accomplish this?
>
> He created the "sequence abstraction". A sequence in Clojure serves a 
> similar role to the linked list of previous Lisps in that it unifies the 
> API for interacting with all of Clojure's first class data structures 
> (list, vector, map, set). By calling the function "seq" on any data 
> structure, you are given a list-like view of that collection that allows 
> you to traverse it from beginning to end one element at a time and to add 
> new elements to the beginning of it. These operations are called "first", 
> "rest", and "cons", and they behave precisely as you would expect them to 
> if you were calling them on a linked list.
>
> By using seq throughout the Clojure sequence library (i.e., the set of 
> standard library functions responsible for creating, traversing, 
> transforming, and manipulating sequences), Clojure is able to have single 
> implementations of all of the common Lispy higher order list transformation 
> functions. For example, we have "map", "filter", "reduce", "iterate", 
> "take", "drop", "repeat", "cycle", and so on. The amazing thing is that 
> these can all take any of Clojure's data structures as their inputs. So you 
> can call map on a list, vector, map, or set without having to change the 
> function signature. Without the sequence abstraction, we could need 
> multiple functions for every data structure we wanted to support (e.g., 
> map-list, map-vec, map-hash, map-set, filter-list, filter-vec, filter-hash, 
> filter-set). This is precisely the kind of combinatorial explosion of the 
> function space the Alan Perlis was warning us about. The tradeoff is that 
> each of these higher order functions will then return a new sequence as its 
> output. While this prints to the REPL like a list, please note that a 
> sequence is not a list (except when it is a sequence on a list ;-D ). It is 
> a list-like representation of the contents of any data structure. You can 
> check this by calling the "type" function on the output of either "seq" or 
> any higher order function (e.g., map, filter, reduce) that calls seq 
> internally.
>
> So when you are programming Clojure or teaching it to new programmers (as 
> I have done on numerous occasions), it really is important IMHO to take a 
> moment to appreciate the history that motivated Rich's design decisions 
> around data structures and the sequence abstraction and not to simply write 
> it off and treat Clojure as though it were Scheme or Common Lisp made to 
> run on the JVM.
>
> In Clojure, the choice of your data structures is central in the design of 
> your programs when it comes to performance. However, an equally important 
> part of program design is the conceptualization of much of your program as 
> a series of sequence transformations composed together so as to reach the 
> output you desire from the inputs you are given. To that end, if you wish 
> to equip new programmers with the skills to think like a Clojure 
> programmer, I would first teach them the four main data structures (list, 
> vector, map, set) and the functions to operate on each of them. Next, I 
> would teach them the sequence API and demonstrate how these four data 
> structures are represented as sequences. This enable everyone to reason in 
> a straightforward manner about all of the sequence functions going forward. 
> Then, I would teach them how to use higher order functions like map, 
> filter, reduce, and range to replace loops and mutation in their program 
> logic. After this, I would discuss recursion and function composition as 
> the fundamental components of flow control in a functional programming 
> language. Finally, I would spend some time going over dynamic vs lexical 
> scoping rules, shadowed bindings, namespaces, and the call stack.
>
> This should provide your students with most of the groundwork that they 
> need to get going with Clojure programming and to dig deeper into various 
> advanced topics like host interop, concurrency primitives, parallel 
> programming, spec, pure/impure functions, macros, and so on.
>
> One thing that I would definitely avoid in teaching a new language is to 
> alter the syntax of that language on day 1 and teach constructs that are 
> neither efficient nor particularly useful in practice. To that end, I would 
> advise you to use the "into" function that I demonstrated at the beginning 
> of this email if you wish to teach a unified API for appending and 
> prepending to each of Clojure's four main data structures while preserving 
> the types of the function's inputs.
>
> And with that, I'm going to head back to my day job. Good luck in learning 
> Clojure and teaching it to others, and don't hesitate to reach out with 
> questions to the Clojure mailing list. Most of the folks on here are 
> usually very friendly and intelligent, and I've always found that to be a 
> hallmark of this community.
>
> Happy hacking,
>   Gary
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to