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.

Reply via email to