Как я могу имитировать макросы в JavaScript?

Я знаю, что JavaScript не поддерживает макросы (в стиле Lisp), но мне было интересно, есть ли у кого-нибудь решение для имитации макросов? Я погуглил, и одно из решений предложило использовать eval(), но, как он сказал, это будет довольно дорого.

Они не должны быть очень причудливыми. Я просто хочу делать с ними простые вещи. И это не должно сильно усложнять отладку :)


person Anders Rune Jensen    schedule 11.10.2008    source источник


Ответы (8)


Вы можете использовать parenscript. Это даст вам макросы для Javascript.

person Luís Oliveira    schedule 11.10.2008
comment
-1 Хотя в 2008 году с паренскриптом было все в порядке, сейчас вы действительно должны использовать ClojureScript. - person Cesar Canassa; 15.12.2011
comment
Разные решения... Parenscript — довольно тонкий слой, в отличие от ClojureScript. - person Luís Oliveira; 19.12.2011
comment
Не только разные решения, но и разные языки - person ; 07.04.2012
comment
@CesarCanassa parenscript — это библиотека Common Lisp, которая работает с большинством (возможно, со всеми) основными реализациями (я пробовал это сам). Clojurescript предназначен для более узкого рынка и подходит для другой аудитории. - person Luka Ramishvili; 15.05.2012

Библиотека Mozilla (называемая SweetJS) предназначена для имитации макросов в JavaScript. Например, вы можете использовать SweetJS, чтобы заменить ключевое слово function на def.

person Anderson Green    schedule 05.01.2013

Теперь также можно использовать ClojureScript для компиляции clojure в javascript и получения таким образом макросов. Примечание. ClojureScript использует Google Closure.

person Anders Rune Jensen    schedule 21.07.2011

Я написал эмулятор gameboy на javascript и имитирую макросы для эмуляции процессора следующим образом:

код макроса (функция возвращает строку с кодом макроса):

function CPU_CP_A(R,C) { // this function simulates the CP instruction, 
  return ''+             // sets CPU flags and stores in CCC the number
  'FZ=(RA=='+R+');'+     // of cpu cycles needed
  'FN=1;'+
  'FC=RA<'+R+';'+
  'FH=(RA&0x0F)<('+R+'&0x0F);'+
  'ICC='+C+';';
}

Использование «макроса», поэтому код генерируется «на лету», и нам не нужно делать вызовы функций или писать много повторяющегося кода для каждой инструкции...

OP[0xB8]=new Function(CPU_CP_A('RB',4)); // CP B
OP[0xB9]=new Function(CPU_CP_A('RC',4)); // CP C
OP[0xBA]=new Function(CPU_CP_A('RD',4)); // CP D
OP[0xBB]=new Function(CPU_CP_A('RE',4)); // CP E
OP[0xBC]=new Function('T1=HL>>8;'+CPU_CP_A('T1',4)); // CP H
OP[0xBD]=new Function('T1=HL&0xFF;'+CPU_CP_A('T1',4)); // CP L
OP[0xBE]=new Function('T1=MEM[HL];'+CPU_CP_A('T1',8)); // CP (HL)
OP[0xBF]=new Function(CPU_CP_A('RA',4)); // CP A

Теперь мы можем выполнить эмулированный код следующим образом:

OP[MEM[PC]](); // MEM is an array of bytes and PC the program counter

Надеюсь, поможет...

person Community    schedule 07.09.2009
comment
new Function(string) является контекстом eval() и поэтому имеет те же характеристики производительности, что и eval(). - person Havvy; 11.01.2014
comment
Я не думаю, что это правда. Это может быть eval, но eval происходит только один раз. Как только это функция, она должна выполняться любое количество раз с нормальной скоростью функции. - person Blake McBride; 03.06.2016
comment
IIRC, раньше объекты Function не оптимизировались большинством движков JS, в отличие от обычного кода JavaScript. Однако это было много лет назад, когда я читал это, поэтому мне интересно, насколько хорошо средний JS-движок поддерживает их сейчас. Особенно со всеми усилиями, направленными на оптимизацию закрытия. - person Job; 28.01.2019

LispyScript — это новейший язык, который компилируется в Javascript и поддерживает макросы. Он имеет синтаксис дерева, подобный Lisp, но также поддерживает ту же семантику Javascript. Отказ от ответственности: я являюсь автором LispyScript.

person Santosh    schedule 06.08.2012
comment
Является ли LispyScript гомоиконичным языком (как Scheme и Common Lisp)? - person Anderson Green; 11.01.2013
comment
Связан ли LispyScript с ParenScript каким-либо образом? На мой взгляд, они очень похожи, так как оба являются диалектами Лиспа, которые компилируются в JavaScript. common-lisp.net/project/parenscript - person Anderson Green; 25.01.2013
comment
@AndersonGreen Я думал, что Сантош утверждает, что LispyScript похож на шепелявость, но не на диалект шепелявости. - person emory; 16.10.2015
comment
Больше не поддерживается? - person Kevin Beal; 11.01.2019
comment
LispyScript больше не поддерживается и не должен использоваться. - person Gene Z. Ragan; 08.08.2020

Проверьте процессор Linux/Unix/GNU M4. Это универсальный и мощный макропроцессор для любого языка. Он особенно ориентирован на языки в стиле Алгол, частью которых является JavaScript.

person Blake McBride    schedule 09.05.2020

Javascript интерпретируется. Eval не дороже, чем что-либо еще в Javascript.

person James Curran    schedule 11.10.2008
comment
Неправильно! Джеймс, прочитайте этот вопрос: stackoverflow.com/questions/86513/ и подтвердите свое мнение, прежде чем делать вводящие в заблуждение заявления. Строка, переданная в eval, должна анализироваться/интерпретироваться каждый раз, когда вызывается eval! - person Ash; 11.10.2008
comment
Да, строка, переданная eval, должна анализироваться каждый раз, когда вызывается eval, но так же должна анализироваться и любая другая строка javascript. так работают интерпретаторы. Что касается ответа, на который вы ссылаетесь, он никогда не упоминает скорость, просто его намного легче читать, а также он менее потенциально глючит. - person James Curran; 11.10.2008
comment
Я соглашусь, что это, возможно, имело место с Javascript в браузерах, скажем, около 2000 года, но сегодня к простому коду Javascript (т.е. не-eval'd) применяются серьезные оптимизации, и это будет только продолжаться. Код в строке на любом языке также не может быть оптимизирован. - person Ash; 11.10.2008
comment
Эш, мне кажется, что Джеймс пытается донести мысль о том, что для единовременной сделки eval работает так же быстро, как буквальный JavaScript, потому что в любом случае интерпретатор делает одно и то же — берет строку и выполнение этого. Как вы думаете, что такое буквальный JavaScript? Это строка в файле HTML. - person Jason Bunting; 11.10.2008

person    schedule
comment
Неплохая идея, но, к сожалению, решение добавляет слишком много определений функций eval и 2x. +1 за попытку. - person Anders Rune Jensen; 27.10.2009
comment
Макросы раскрываются во время COMPILE, поэтому нам нужно добавить стадию компиляции в JavaScript или забыть о макросах. Мы можем скомпилировать JavaScript только вызовом функции eval(), так что eval() нам все равно понадобится. - person Volodymyr M. Lisivka; 06.11.2009
comment
макросы являются синтаксическим сахаром для более компактного и выразительного кода. Теоретически они не увеличивают тип вещей, которые вы можете делать или нет. Они расходуются один раз во время компиляции, что сводит затраты времени выполнения к нулю. Пример здесь терпит неудачу: eval будет вызываться каждый раз, а код будет более подробным и менее разборчивым, чем если бы кто-то напрямую написал эквивалентный javascript. Чтобы макросы были полезными, вы должны иметь возможность использовать их с таким синтаксисом, как «если» ('false','alert(OK)'); - person Nicolas Bousquet; 22.07.2011
comment
@NicolasBousquet Макросы дают вам возможность манипулировать кодом до его выполнения (и до его компиляции, время расширения макроса). Без макросов этого не сделать. - person Luka Ramishvili; 15.05.2012
comment
В конце концов, код, сгенерированный макросами, так же мощен, как и код, написанный вручную, но любой полный по Тьюрингу язык даст вам это. Важно то, что они увеличивают возможности вы. - person Luka Ramishvili; 15.05.2012