Ткання байтового коду проти макросів Lisp


11

Я читав про бібліотеки, які люди писали для таких мов, як Java та C #, які використовують байтове плетіння коду, щоб виконувати такі дії, як перехоплення функцій викликів, вставлення коду журналу тощо. Я також читав макроси Lisp / Clojure у намагання краще зрозуміти, як їх використовувати. Чим більше я читаю про макроси, тим більше здається, що вони забезпечують такий же функціонал, як і бібліотеки байтового плетіння коду. Під функціоналом я маю на увазі можливість маніпулювати кодом під час компіляції.

Прикладами бібліотек, які я розглядав, були AspectJ, PostSharp та Cecil.

Чи є щось, що можна зробити з одним, а не з іншим? Вони насправді вирішують одні і ті ж проблеми чи я порівнюю яблука та апельсини?


2
Плетіння коду байтів - це вирішення проблем, коли вам потрібна динамічна мова, але вони застрягли зі статично набраною мовою
Кевін Клайн

2
@kevincline Ви серйозно намагаєтеся розпочати цю стару боротьбу?
Джонатан Хенсон

Відповіді:


10

Ткання байтового коду та макроси - це дві різні речі.

Переплетення байтового коду - це спосіб перехоплення функціональних викликів, завдяки чому ви можете ввести якийсь функціонал (як правило, наскрізний занепокоєння, наприклад, ведення журналу) у виклик функції, до або після виконання функції. Переплетення байтового коду здійснюється на рівні байтового коду, а це означає, що воно відбувається після компіляції. Сама функція не впливає. Це одна з методик, яку використовує орієнтоване на аспекти програмування .

Макроси - це спосіб розширити синтаксис мови. У своєму найпростішому вигляді макрос - це просто спосіб записувати натискання клавіш, а потім відтворювати їх за допомогою гарячої клавіші. Мовні макроси працюють аналогічно; ключове слово або інша конструкція синтаксису замінює якесь розширення макросу. Це, звичайно, спрощено; кращий приклад макроса, специфічного для Lisp, можна знайти тут .


+1 за те, що вони зазначили, що це ключовий спосіб впровадження АОП.
Джонатан Хенсон

А транзакції ... не будемо забувати транзакції.
Джонатан Хенсон

3
Макроси LISP - це не що інше, як "спосіб записувати натискання клавіш".
кевін клайн

1
Добре, що у відповіді ІМО відсутні деякі фундаментальні поняття, такі можуть бути: AST, рефлексія, метациркулярність.
AndreasScheinert

2
@AndreasScheinert: ОП не запитувала жодної з цих речей. Це не дисертація; це лише відповідь на питання ОП.
Роберт Харві

5

Хоча вони можуть використовуватися для того ж самого кінця, макроси LISP сильно відрізняються від плагінів байтового кодування для Java. Макроси LISP розширюють синтаксис LISP на рівні вихідного коду LISP. Оскільки макроси LISP записуються на тому ж рівні, що й інший код LISP, вони є загальноприйнятою мовною ознакою.

Плагіни для байтового кодування Java працюють на рівні JVM. Хоча багато Java-програмісти можуть використовувати плагіни для переплетення байт-кодів, написані іншими, дуже небагато Java-програмістів пишуть власні плагіни байтового кодування.

Деяка робота, виконана плагінами компілятора Java, дуже легко виконується в динамічних мовах. Перехоплення функціонального виклику особливо просте.


Я розумію технічні відмінності між ними. Я намагався розглянути питання з точки зору високого рівня. Чи можуть обидва інструменти маніпулювати кодом для досягнення однакових цілей? Чи є якісь проблеми, які макроси не можуть вирішити, що маніпуляція байт-кодом може (розумним та економічно ефективним способом)? Це більше, за що я йшов.
mortalapeman

@mortalapeman: можливі маніпуляції в Java та C # через модифікацію байт-коду, все можна проводити безпосередньо такими мовами, як Lisp, Ruby, Python, Lua, Javascript ... Імовірно, можливо зробити все, що може зробити макрос LISP через байт -кодування маніпуляцією, але на практиці цього не відбувається.
Кевін Клайн

4

Макроси Lisp працюють на рівні вихідного коду. Якщо обгорнути якийсь макрос навколо шматка коду, ви можете зробити багато речей. Включаючи розбір вихідного коду, вставлення коду, код перезапису тощо.

Якщо ви хочете змінити функціональні виклики, Lisp зазвичай використовує два механізми:

  • символи пізнього зв’язування. Ви можете змінити функцію, пов'язану з символом. Кожна функція виклику, яка проходить через символ, потім використовує нову функцію.

  • Реалізації Lisp іноді надають функцію під назвою "порада". Це дозволяє виконувати код до, після або навколо дзвінків. Наприклад, у LispWorks: Поради .

Таким чином, ви можете перехоплювати дзвінки без маніпуляції кодом низького рівня.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.