היום למדתי להיזהר מהפונקציה contains בקלוז'ר
האתגר הכי גדול עבורי עם קלוז'ר הוא חוסר העקביות של השפה, או שאולי יש לה איזשהו הגיון פנימי שאני לא מבין. הקיטור היום הוא על הפונקציות contains?
ו keys
.
הפונקציה keys
בקלוז'ר מקבלת מפה ומחזירה את המפתחות שלה. זה קל:
user=> (keys {:a 10 :b 20 })
(:a :b)
ברור שאי אפשר להשתמש ב keys על וקטור, כי אין לו מפתחות. קלוז'ר היא הרי לא JavaScript והיא לא חושבת שמפתחות של מערך זה האינדקסים שלו. זה מה שקורה אם מנסים:
user=> (keys ["a" "b" "c"])
Error printing return value (ClassCastException) at clojure.lang.APersistentMap$KeySeq/first (APersistentMap.java:168).
class java.lang.String cannot be cast to class java.util.Map$Entry (java.lang.String and java.util.Map$Entry are in module java.base of loader 'bootstrap')
בהתבסס על ההגיון הזה הלכתי לשחק עם הפונקציה contains?
בעבודה על מפה, הפונקציה contains?
בודקת אם ערך מסוים הוא מפתח במפה. עד פה הכל גם הגיוני:
user=> (contains? {:a 10 :b 20} :a)
true
בגלל ש keys לא עובדת על מערכים, חשבתי שגם contains?
לא אמורה לעבוד על מערכים, וקצת הופתעתי לגלות שהיא דווקא עובדת ואפילו לפעמים צודקת:
user=> (contains? [1 2 3] 2)
true
אבל זה היה רק מוקש. למעשה contains?
על מערכים בקלוז'ר בודקת אם הפרמטר שהיא קיבלה הוא אינדקס במערך - ולא ערך. הדוגמה הקודמת עבדה רק במקרה. הנה כמה דוגמאות יותר טובות:
user=> (contains? [1 2 3] 0)
true
user=> (contains? [1 2 3] 3)
false
user=> (contains? ['a' 'b' 'c'] 0)
true
user=> (contains? ['a' 'b' 'c'] 'a')
false
user=> (contains? ['a' 'b' 'c'] 9)
false
ונשארתי עם השאלה - אם האינדקסים של מערך הם המפתחות שלו, למה keys
לא מחזירה את רשימת האינדקסים? ואם הם לא מפתחות, למה contains?
בודקת אם ערך שהיא קיבלה הוא אינדקס חוקי במערך?