2008-10-11 13 views
16

Ich weiß, dass JavaScript keine Makros unterstützt (Lisp-ähnliche), aber ich frage mich, ob jemand eine Lösung hat, um vielleicht Makros zu simulieren? Ich habe es gegoogelt, und eine der vorgeschlagenen Lösungen eval() vorgeschlagen, aber wie er sagte, wäre ziemlich teuer.Wie kann ich Makros in JavaScript simulieren?

Sie müssen nicht wirklich sehr extravagant sein. Ich möchte nur einfache Sachen mit ihnen machen. Und es sollte nicht wesentlich schwerer machen Debuggen :)

Antwort

-2

Javascript interpretiert wird. Eval ist nicht teurer als alles andere in Javascript.

+0

Falsch! James, bitte lesen Sie diese Frage: http: //stackoverflow.com/questions/86513/why-is-using-javascript-eval-function-a-bad-idea#87260 und validieren Sie Ihre Meinungen, bevor Sie irreführende Aussagen machen. Die an ein eval übergebene Zeichenfolge muss bei jedem Aufruf des evals geparst/interpretiert werden! – Ash

+0

Ja, die an eval übergebene Zeichenkette muss jedes Mal geparst werden, wenn eval aufgerufen wird - aber auch jede andere Zeile von javascript. so arbeiten Dolmetscher. Wie für die Antwort auf Sie verlinkt, hat er nie Geschwindigkeit erwähnt, nur –

+2

„viel einfacher als auch weniger potenziell Buggy zu lesen:“ Ich werde zugeben, dass dies möglicherweise mit Javascript der Fall gewesen sein mag in Browsern sagen um 2000, aber heute gibt Es werden ernsthafte Optimierungen auf den JavaScript-Code angewendet (dh nicht evaluiert) und dies wird nur fortgesetzt. Code in einer Zeichenfolge in einer beliebigen Sprache kann auch nicht annähernd optimiert werden. – Ash

22

könnten Sie parenscript verwenden. Das gibt Ihnen Makros für Javascript.

+0

-1 Während Parenscript in 2008 in Ordnung war, sollten Sie jetzt ClojureScript verwenden. –

+0

Verschiedene Lösungen ... Parenscript ist eine ziemlich dünne Schicht, anders als ClojureScript. –

+2

Nicht nur verschiedene Lösungen, auch andere Sprachen –

5

ich ein Gameboy-Emulator in JavaScript geschrieben habe und ich Makros für CPU-Emulation simulieren auf diese Weise:

Makrocode (die Funktion einen String mit dem Makrocode zurückgibt):

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+';'; 
} 

die Verwendung von „Makro“, so wird der Code generiert „on the fly“ und wir brauchen nicht zu Funktionsaufrufe zu machen oder für jede istruction viele wiederholten Code schreiben ...

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 

Jetzt w e kann emulierten Code wie folgt aus:

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

Hoffe, es hilft ...

+2

Ist der Quellcode des Emulators überall verfügbar? –

+1

'neue Funktion (String)' ist ein 'eval()' Kontext, und als solcher, hat die gleichen Leistungsmerkmale von 'eval()' – Havvy

+1

Ich glaube nicht, dass das wahr ist. Es kann ein Eval sein, aber das Eval tritt nur einmal auf. Sobald es eine Funktion ist, sollte es beliebig oft mit normaler Funktionsgeschwindigkeit ausgeführt werden. –

3
function unless(condition,body) { 
    return 'if(! '+condition.toSource()+'()) {' + body.toSource()+'(); }'; 
} 


eval(unless(function() { 
    return false; 
    }, function() { 
    alert("OK"); 
})); 
+0

Keine schlechte Idee, aber leider fügt die Lösung eine eval und 2x Funktionsdefinitionen zu viel hinzu. +1 für den Versuch, obwohl. –

+1

Macroses werden zu COMPILE-Zeit erweitert, also müssen wir das Kompilierungsstadium zu JavaScript hinzufügen oder Makros vergessen. Wir können JavaScript nur durch Aufruf der Funktion eval() kompilieren, also brauchen wir eval() trotzdem. –

+0

Makro sind Syntaxzucker für mehr Consise und expressiven Code. Sie erhöhen theoretisch nicht die Art von Dingen, die Sie tun können oder nicht. Sie werden einmal zur Kompilierzeit verbraucht, wodurch die Laufzeitkosten auf Null fallen. Beispiel hier scheitern: eval wird jedes Mal aufgerufen und der Code ist ausführlicher und weniger lisibel als wenn man direkt das entsprechende Javascript schreiben würde. Damit die Makros nützlich sind, sollten Sie sie mit einer Syntax wie unless verwenden können ('false', 'alert (' OK ')'); –

10

Man kann jetzt auch ClojureScript clojure Javascript zu kompilieren verwenden und Makros, die Quere kommen. Hinweis ClojureScript verwendet Google Closure.

5

LispyScript ist die neueste Sprache, die Javascript kompiliert, die Makros unterstützt. Es hat eine Lisp-ähnliche Baum-Syntax, behält aber auch die gleiche Javascript-Semantik bei. Haftungsausschluss: Ich bin der Autor von .

+0

Ist LispyScript eine homoonische Sprache (wie Scheme und Common Lisp)? –

+0

Ja LispyScript ist homoikonisch. Sehen Sie sich die Dokumentation hier an. http://lispyscript.com – Santosh

+0

Ist LispyScript in irgendeiner Weise mit ParenScript verwandt? Sie sehen mir sehr ähnlich, da sie beide Lisp-Dialekte sind, die zu JavaScript kompilieren. http://common-lisp.net/project/parenscript/ –

20

Eine Bibliothek von Mozilla (genannt SweetJS) ist so konzipiert, Makros in JavaScript zu simulieren. Beispielsweise können Sie SweetJS verwenden, um das Schlüsselwort function durch def zu ersetzen.

Verwandte Themen