santoshrajan / lispyscript

A javascript with Lispy syntax and macros
MIT License
572 stars 57 forks source link

Added a compile() function to use lispyscript as a library. #38

Closed robbrit closed 11 years ago

robbrit commented 11 years ago

I added a compile function so that LispyScript can be used as a library to process LispyScript strings within a larger Node.js project. There are some examples of usage in the comments for the function.

Let me know if there should be any tweaks made.

robbrit commented 11 years ago

Hmm, still a bit clunky. I'll work on the interface a bit and re-send the pull request.

santoshrajan commented 11 years ago

I am not clear exactly what this pull request is doing. You can use the JavaScript 'Function' class if you want to wrap compiled code in a function. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function

robbrit commented 11 years ago

This allows you to write code like this:

var ls = require("lispyscript");
var func = ls.compile('(* a b)', ["a", "b"]);
console.log(func(2, 3));  // outputs 6

This is useful for when you want to embed the LispyScript interpreter within a larger Node.js application where you have the benefits of using a Lisp but you're not able to write the entire code-base in it.

The equivalent using Function does not work due to the way LispyScript compiles simple s-expressions:

var ls = require("lispyscript");
var func = new Function("a", "b", ls._compile('(* a b)', ""));
//  function body is `(a * b)`, not `return (a * b)`
console.log(func(2, 3)); // outputs undefined
santoshrajan commented 11 years ago

Got you. However I was considering something more compatible with node's module system. So that you could do something like

var foo = require_ls("bar.ls")

bar.ls

(set module.exports (function (a b) (+ a b)))
robbrit commented 11 years ago

That would be really good too, CoffeeScript currently allows that and it is extremely useful.

However it doesn't solve my current problem: the reason I did my pull request is so that I could use LispyScript for genetic programming - you have many randomly generated strings of Lisp that you execute and modify over and over again. It doesn't fit into Node's module system since the strings are not static, they are executed a few times and then most likely discarded to make room for other strings. I originally tried my own little Lisp interpreter, however LispyScript turned out to be roughly 100x more performant.

santoshrajan commented 11 years ago

By the way if you wrap the expressions in a function you will get the return statement.

function createFunctionStr(args, expressions) {
    return "(function " + args + " " + expressions + ")"
}
ls._compile(createFunctionStr("(a b)", "(+ a b)"))

Does that help for the moment?

robbrit commented 11 years ago

I did try something like that, might have been a little different from what you posted. There was an issue with it being a bit slower (about 3x slower) than the version I eventually pushed, but I can give it another shot.

santoshrajan commented 11 years ago

You can now load lispyscript modules in javascript. Pushed changes to github. Use github version till i release 0.3.3.

require("lispyscript/lib/node")
require("./mylsmodule")

Would writing a macro in a ls module solve your problem?

robbrit commented 11 years ago

I'm not writing any LispyScript modules. The genetic programming system generates hundreds of Lisp s-expressions that evolve over the lifetime of the program, they are never actually saved to a file or anything. Instead they are run through the LispyScript compiler to convert them to a Javascript function so that they can be executed from the larger Node.js program.

The function that I wrote in my PR is exactly what I need to accomplish this. If you don't want to merge it in don't worry about it, I'll just use my fork of LispyScript to get it done.