מצאו את ההבדלים

שני קטעי הקוד האלה ברובי מדפיסים את אותו ערך ונראים מאוד דומה:

require 'set'

s = Set.new([10, 20, 30])
t = Set.new([30, 40])
puts (s | t).inspect
puts s.merge(t).inspect

בשני המקרים תוצאת ההדפסה היא:

#<Set: {10, 20, 30, 40}>

אבל מתחת לפני השטח קורה דבר אחרי לגמרי. בהדפסה הראשונה אנחנו מחברים את שתי הקבוצות ויוצרים מהן קבוצה חדשה, אליה מעתיקים את כל האיברים משתי הקבוצות. בפעולה השניה אנחנו מעתיקים את האיברים מקבוצה t לקבוצה s, בלי לגעת באיברים שהיו קודם ב s.

תוצאה אחת של ההבדל היא שאחרי סיום הפעולה הראשונה הקבוצות s ו t לא ישתנו, ואילו הפעולה השניה כן משנה את s. תוצאה שניה ויותר מעניינת היא ביצועים- כש s גדולה מאוד העתקה של כל האיברים תיקח המון זמן.

עם הזמן אנחנו לומדים להתעצבן פחות מההבדלים האלה ואפילו שמחים שיש אפשרויות שונות להגיע לתוצאה. בהמשך אנחנו גם לומדים להסתכל על דוגמת קוד ולשאול: איך זה עובד? יש פה העתקה? מה יקרה עם הערכים? מה יכול להשתבש?

עכשיו אתם ועדיין ברובי- מה ההבדל בין ארבעת אלה? מה יכול להשתבש? ואיך?

arr = [10, 20, 30]

arr.inject(0) { |acc, val| acc + val }
arr.inject { |acc, val| acc + val }
arr.inject do |acc, val| acc + val; end
arr.inject(0) do |acc, val| acc + val; end