אחד ההבדלים שמתכנתים מאוד רגישים אליו בין שפות תכנות הוא היכולת לבצע בקלות פעולות מסוימות בשפה אחת, כאשר בשפה אחרת צריך לעבוד מאוד קשה בשביל לקבל את אותה התנהגות. כמה דוגמאות שקופצות לראש:
לכל פונקציה ב JavaScript יש מאפיין משם length שמחזיר כמה פרמטרים הפונקציה מצפה לקבל. ב Python קצת יותר קשה לגלות את זה אבל עדיין אפשרי עם חבילת inspect, ב Ruby יש לכל פונקציה מאפיין בשם arity שמחזיר את הערך וב Clojure אנחנו צריכים לקפוץ שמיניות באוויר בשביל למצוא אותו.
הפונקציה merge של Hash ממזגת בין שני מילונים ב Ruby ומאפשרת לנו בקלות להחליט מה לעשות עם ערכים מתנגשים. כך קוד רובי הבא יכול לשלב בקלות ערכים משני מילונים למילון שלישי:
a = { a: 10, c: 30 }
b = { a: 5, b: 20 }
res = a.merge(b) {|k, v1, v2| v1 + v2 }
# now res is: { a: 15, b: 20, c: 30 }
בפייתון קל מאוד לשלב שני מילונים שאין ביניהם ערכים מתנגשים עם כתיב שתי הכוכביות:
a = { 'a': 10, 'c': 30 }
b = { 'b': 20 }
res = dict(**a, **b)
# now res is: { 'a': 10, 'b': 20, 'c': 30 }
אבל זה לא מה שרצינו ובשביל לשלב את המילונים עם פונקציית חיבור שלנו נצטרך להתאמץ יותר ולכתוב לולאה מסודרת.
ויש עוד מאות כעסים קטנים כאלה בכל מעבר בין שפות, וזה בסדר. שווה לזכור שבכל מעבר כזה בין שפות מאוד קל למצוא חבילות שסוגרות את הפער. גם אם ל JavaScript אין את random.randint של פייתון, אנחנו עדיין יכולים לקבל פונקציונאליות זהה מ lodash; חבילת mergedict של פייתון מאפשרת לשלב בצורה אלגנטית בין מילונים ולקבוע מה לעשות עם ערכים מתנגשים בקלות ממש כמו ב Ruby.
ההבדלים האמיתיים בין שפות הם לא בפונקציה מסוימת שנמצאת או לא, אלא בגישה ובהשקפת עולם שונה: האם יש Type System? האם הוא מחייב? האם יש Class-ים? האם יש הגבלה על עומק הרקורסיה? איך בונים קוד מקבילי או מבוזר? האם זה מתקמפל? האם זה רץ על המכונה אליה אני מכוון?
(וכמובן חוץ מבחירת שפה ברוב הפרויקטים נצטרך לעשות בחירה הרבה יותר קשה ולבחור Framework. אבל זה כבר סיפור ליום אחר).