Стендап Сьогодні 📢 Канал в Telegram @stendap_sogodni

21.10.2022

🚂🚅🪆 Чому в Ruby метапрограмування — це норма, а в JavaScript його не роблять, віддаючи перевагу функціональній композиції? Ну, може, тому, що JavaScript - справжня функціональна мова, а Ruby - зовсім ні.

От вам треба зробити обгортку для якоїсь логіки. В Ruby, напевно, будете створювати методи через class_eval, який викликає інший метод, названий за деякою договореністю. На цьому побудований весь фреймворк Ruby on Rails.

А в JavaScript замість того можна просто передати в обгортку внутрішню функцію, а результат зберегти у константу, та вживати як будь-яку іншу звичайну функцію. Наприклад, так працює React, Redux, Reselect, та весь сучасний ідіоматичний JavaScript.

Тому вийду і скажу: метапрограмування в Ruby - це милиця, яка існує тому, що передача функції як значення в Ruby - надто повільна операція. Щоб не бути голослівним, побудував бенчмарк, що порівнює різні способи викликати шматок коду на Ruby.

Що виявляється: найшвидше працюють саме названі методи, тобто створені напряму в класі командою def, або через class_eval. На цілих 75% повільніше працює Proc - найближче, що є в Ruby до справжніх функцій. А виклик методу командою send аж в 3 рази повільніше. Гірше над усе робити посилання на метод командою method, яка практично не зустрічається на практиці.

До того ж схоже на те, що кожний вкладений виклик накладає таку саму ціну, тобто в Ruby краще обходитись найпростішою абстракцією.

Тепер, порівняємо з аналогічним бенчмарком для JS. По-перше, в JavaScript варіантів побудови та виклику набагато менше. Функція — це значення, та й годі. Роби з нею, що хочеш.

По-друге, цікаво, що в Google Chrome та в Safari вкладені функції не впливають на швидкість виконання. Як я розумію, це завдяки потужному механізму оптимізації JIT.

Для мене можливість функціонального програмування робить JS набагато привабливішою та елегантнішою мовою, ніж Ruby.