views:

1000

answers:

7

I know that JavaScript doesn't support macros (Lisp-style ones) but I was wondering if anyone had a solution to maybe simulate macros? I Googled it, and one of the solutions suggested using eval(), but as he said, would be quite costly.

They don't really have to be very fancy. I just want to do simple stuff with them. And it shouldn't make debugging significantly harder :)

A: 

Heh, that is a clever solution. I guess I could roll some Emacs lisp code to do this. Not a bad suggestion, but it only covers one part of the equation: entering the stuff. Maintaining it code "generated" is at least as important.

Anders Rune Jensen
A: 

Javascript is interpreted. Eval isn't any more costly that anything else in Javascript.

James Curran
Wrong! James, please read up on this question:http://stackoverflow.com/questions/86513/why-is-using-javascript-eval-function-a-bad-idea#87260 and validate your opinions before making misleading statements. The string passed to an eval must be parsed/interpreted every time the eval is called!
Ash
Yes, the string passed to eval must parsed every time eval is called -- but so must every other line of javascript. that's how interpreters works. As for the answer you linked to, he never mentions speed, just "much easier to read as well as less potentially buggy"
James Curran
I'll grant that this possibly may have been the case with Javascript in browsers say around 2000, but today there are serious optimisations being applied to plain Javascript code (ie non-eval'd) and this will only continue. Code in a string in any language cannot be optimised anywhere near as well.
Ash
Ash, the point James is trying to make, I believe, is that for a one time deal, eval works as quickly as literal JavaScript because *either way* the interpreter is doing the same thing - taking a string and executing it. What do you think literal JavaScript is? It is a string in an HTML file.
Jason Bunting
A: 

As much as it might be considered overhead by some, the best approach is to use functions, shorthand and ternary conditions as a replacement for macros. Most of the JavaScript libraries do that these days. For example:

1.)

var a, b;
if ( !a ) {
    a = b;
}

// shorthand approach:

var a, b;
a = a || b;

2.)

var a, b, c;
if ( true ) {
    a = b;
} else {
    a = c;
}

// shorthand approach:

var a, b, c;
a = ( true ) ? b : c;

3.)

var a, b, c, d;
b = a;
c = b;
d = c;

// shorthand approach:

var a, b, c, d;
d = c = b = a;

Several methods in jQuery are all essentially macros, although you have to define them as functions first, since the browser does not automatically interpret them. For example, some of the more popular of these are each(), next() and filter().

hal10001
These are more idioms rather then macros (as idioms, they are good). A macro is a transformation that happens as part of the code parsing, not by hand.
Jonathan Arkell
- how can i cross this river stranger?- if you cross that forest you get to a nice inn.
Attila Lendvai
+8  A: 

You could use parenscript. That'll give you macros for Javascript.

Luís Oliveira
A: 

I've written a gameboy emulator in javascript and I simulate macros for cpu emulation this way:

macro code (the function returns a string with the macro code):

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

Using the "macro", so the code is generated "on the fly" and we don't need to make function calls to it or write lots of repeated code for each istruction...

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

Now we can execute emulated code like this:

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

Hope it helps...

A: 

what about using iMacros for Firefox?

w35l3y
this is about programming macros, not user macros to make firefox do repetitive tasks.
Anders Rune Jensen
Ok. this was not clear in the question. I thought you wanted macro for debugging.
w35l3y
A: 
function unless(condition,body) {
    return 'if(! '+condition.toSource()+'() ) {' + body.toSource()+'(); }';
}


eval(unless( function() {
    return false;
  }, function() {
    alert("OK");
}));
Volodymyr M. Lisivka
Not a bad idea, but sadly the solution adds a eval and 2x function definitions too much. +1 for trying though.
Anders Rune Jensen
Macroses are expanded at COMPILE time, so we need to add compilation stage to JavaScript or forget about macroses. We can compile JavaScript by call to eval() function only, so we need eval() anyway.
Volodymyr M. Lisivka