Каковы различия между mapcat в Clojure и flatMap в Scala с точки зрения того, над чем они работают?

Я понимаю, что эквивалент flatMap в Scala есть mapcat в Clojure.

У меня есть подозрение, что mapcat в clojure работает только с последовательностями, в отличие от flatMap в Scala, что является более гибким.

Мой вопрос: каковы различия между mapcat в clojure и flatMap в Scala с точки зрения того, над чем они работают?

Предположения:

  • Я понимаю, что Scala имеет богатую систему типов и clojure имеет необязательную типизацию - мне интересно узнать, является ли ограничение в параметрах, которые принимает mapcat, которые делают его только подмножеством flatMap функциональность.

Ответ 1

В стандартной библиотеке Scala: Responder, Future, Parser, ControlContext. Ни одна из них не является последовательностями или особенно подобна последовательности. Существует также небольшое изменение ParseResult.

Ответ 2

Я немного знаю о Scala, но мне кажется, что flatMap - это функция связывания Scala в монаде, а mapcat - возможная реализация функции bind для последовательности monad в Clojure. Поэтому они одинаковы для последовательностей.

Но Scala, например, имеет функцию flatMap для Futures: она берет будущее и функцию сопоставления и возвращает будущее, которое будет завершено после завершения ввода. Эта операция не кажется простым mapcat в Clojure. Это может быть реализовано таким образом вместо

(defn flat-map [f mv] (mapcat (fn [v] (future (f @v))) mv))

Итак, нет. Они не то же самое, ни с точки зрения того, что они действуют. В Scala flatMap - это общее имя для разных функций и, например, фьючерсы на флешки. Простой mapcat в Clojure не будет работать, потому что он не вернет будущее.

Ответ 3

Они кажутся очень похожими и, похоже, работают на одни и те же вещи. От взгляда на документацию и examples Я не вижу функциональной разницы.

mapcat работает над последовательностями, и почти каждый тип данных clojure может быть последовательностью. Если вы передадите то, что еще не от seq до mapcat, оно автоматически вызовет seq, поэтому на практике вы можете передать почти все значения clojure в mapcat. Если вы хотите итерации по дереву, вам нужно вызвать prewalk или postwalk, чтобы указать порядок обхода.