another false example above fixed: user=> (into '(1) '(2 3))
(3 2 1) On Fri, Jul 20, 2018 at 9:13 AM Christian Seberino <cseber...@gmail.com> wrote: > 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. > -- 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.