מה map מחזירה
עוד דרך להסתכל על ההבדל בין תכנות מונחה עצמים לתכנות פונקציונאלי היא להסתכל על פונקציות וערכי ההחזר שלהן. ניקח את הפונקציה map לדוגמה ונשווה -
סקאלה, שהיא שפה מונחית עצמים, תגדיר לכל Collection פונקציית map שונה שמחזירה Collection חדש מאותו הסוג. בגלל זה כשאני מריץ map על קבוצה אני מקבל חזרה קבוצה:
scala> Set(1, 2, 3).map(_ * 2)
val res1: Set[Int] = Set(2, 4, 6)
scala> List(1, 2, 3).map(_ * 2)
val res4: List[Int] = List(2, 4, 6)
קלוז'ר לעומתה שמה את הדגש על הפונקציה ולכן הפעלה של map על כל דבר מחזירה תמיד LazySeq:
user=> (type (map (partial * 2) #{1 2 3}))
clojure.lang.LazySeq
user=> (type (map (partial * 2) [1 2 3]))
clojure.lang.LazySeq
ו JavaScript מסכימה להגדיר map רק על רשימה ולכן:
new Set([1, 2, 3]).map(i => i * 2)
TypeError: new Set([1, 2, 3]).map is not a function. (In 'new Set([1, 2, 3]).map(i => i * 2)', 'new Set([1, 2, 3]).map' is undefined)
מה עדיף? לא נעים להגיד אבל אני מצליח לטעות בכל השפות. הדבר החשוב הוא תמיד לזכור באיזה שפה אנחנו ומה המאפיינים של אותה שפה. אפילו (ואולי במיוחד) כשלפונקציות יש את אותו שם.
נ.ב. ומה מחזיר הקוד הבא ברובי? נסו לבדוק ותראו אם הבנתם למה:
3.1.1 :002 > [1, 2, 3].map { _ * 2 }