Clojure: how is the map different from comp?

map accepts a function and a list and applies this function to each element of the list. eg.

(map f [x1 x2 x3]) ;= [(f x1) (f x2) (f x3)] 

Mathematically, a list is a partial function of natural numbers β„•. If x: β„• β†’ X is a list and f: X β†’ Y is a function, then the map takes the pair (f, x) to the list f β—‹ x: β„• β†’ Y. Therefore, map and comp return the same value at least in the simple case.

However, when we use a map with more than one argument, something more complex happens. Consider an example:

 (map f [x1 x2 x3] [y1 y2 y3]) ;= [(f x1 y1) (f x2 y2) (f x3 y3)] 

Here we have two lists x: β„• β†’ X and y: β„• β†’ Y with the same domain and a function of type f: X β†’ (Y β†’ Z). To evaluate on a tuple (f, x, y), the map needs to do some more work behind the scenes.

First, the map builds a diagonal list of products diag (x, y): β„• β†’ X Γ— Y, which is determined by diag (x, y) (n) = (x (n), y (n)).

Secondly, the map expands the function curry -1 (f): X Γ— Y β†’ Z. Finally, the map compiles these operations to get curry -1 (f) β—‹ diag (x, y): β„• β†’ Z.

My question is: does this template generalize? Namely, suppose we have three lists x: β„• β†’ X, y: β„• β†’ Y and z: β„• β†’ Z and a function f: X β†’ (Y β†’ (Z β†’ W))). Does the map map the tuple (f, x, y, z) to the curry list -2 (f) β—‹ diag (x, y, z): β„• β†’ W?

+4
source share
3 answers

It seems that the title of the question has little to do with the question that is really asked in the body; I will try to solve both problems.

Clojure Party

As the examples show, such as (map inc [1 2 3]) and (comp inc [1 2 3]) - both of which, by the way, make sense in Clojure - the Clojure map and comp functions work very differently even in one case of sequence. map simply does not treat its sequence arguments as functions in the programmatic sense of called objects, while comp considers all its arguments in this way; map returns a composite datat while comp does not work; the value returned by comp can be called as a function, whereas map returns no values; and etc.

(Other functional languages ​​likewise have separate "maps" and "make up" functions of a higher order, in Haskell - map (and more general fmap ) and (.) .)

It is noteworthy that map does not actually enumerate the arguments in memory into its input function and does not apply any decryption / expansion of the conversion to the input function.

Math side

The template, of course, generalizes the penalty, although it is worth keeping in mind that some function of that, etc. - under the hood of the model, as it were - depends on the choice of the representation, which tends to be arbitrary, The final sequences can be perfectly represented as (complete) functions with finite ordinals as domains, or as Kuratovsky tuples, or the way you describe where you are don’t care about your lists, which are not necessarily β€œgapless”, etc. Depending on representative options, the concept of natural numbers cannot be included in the picture at all, objects representing lists may or may not look like functions, whose codename is a superset of a set of list entries, etc.

+6
source

I don't know if this helps, but:

  • Clojure does not have currying, like Haskell. It has a partial function app, but it's not the same as curry.
  • Clojure map is more like zipWith, zipWith3 etc. in Haskell
+3
source

Technically yes, a map can be considered as composite functions like this, although in practice it introduces some overhead that is not in comp.

map creates a lazy sequence that will calculate the sequence when the result is finally read. Thus, it returns a sequence not strictly the result expressed by your type expression. It also adds sequence overhead and reorders the order because it is lazy and broken.

+1
source

Source: https://habr.com/ru/post/1502662/


All Articles