Git Product home page Git Product logo

lispyscript's People

Contributors

balajirrao avatar darrencruse avatar gozala avatar santoshrajan avatar tehshrike avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lispyscript's Issues

Long whitespace indentation on "Try It!"

After fiddling around with the code, the output looks like:

// Generated by LispyScript v0.2.5
                                                                                                        var x = 10;
                                                                                                        var y = 10;
                                                                                                        console.log((x + y));
                                                                                                        x = (x + y);
                                                                                                        var a = function() {
                                                                                                        };

Strange macro behavior

I'm trying to make a simple macro to save myself some typing:

(macro onload (body...)
  ($ (function ()
       ~@body...
       null)))

(onload
  (alert (+ 1 2))
  (alert (+ 2 3)))

($ (function ()
     (alert (+ 1 2))
     (alert (+ 2 3))
     null))

I expect the onload form to expand into something like the last form there, and then get compiled. But when I compile this I get the following javascript:

// Generated by LispyScript v0.2.9
$(function() {
    alert;
    (1 + 2);
    return null;
});
$(function() {
    alert((1 + 2));
    alert((2 + 3));
    return null;
});

I have no idea what the heck is happening here since Lispyscript macros are a templating language instead of real Lisp macros (and aren't really documented (I think the ~@ char splices?)). Is this a bug or am I doing something wrong?

npm release needed!

The version of lispyscript on npm is two years old. Is all of the development in this repository since then that unstable? When can it be released to npm?

Which version are most users currently using? The one in this repository, or the one on npm?

Does anyone know what all has changed between the last npm release and the current repository state?

How to create more complicated macros?

Right now it seems like macro is just kind of a templating engine instead of a full, Lispy macro implementation. For example, what if I wanted a macro that would let me insert some logging between each line of a function? Ideally I'd do something like this (in pseudocode):

(macro traced-function (args rest...)
  (var logs (map (function (n) `(console.log ~n))
                 (range (length rest...))))
  (var interleaved-lines (interleave logs rest...))
  `(function ~args ~@interleaved-lines))


(traced-function (foo)
  (var foo 5)
  (var bar 10)
  (+ foo bar))

Which would macroexpand to:

(function (foo)
  (console.log 1)
  (var foo 5)
  (console.log 2)
  (var bar 10)
  (console.log 3)
  (+ foo bar))

Is this simply not going to happen, and that's what "LispyScript is not a dialect of Lisp. There is no list processing in LispyScript." means? I haven't looked at the implementation, so I don't know how homoiconic LispyScript is...

$.map is not a function in browser

Using the browser-bundle.js generated by lispy -b and the following directory structure:

├── browser-bundle.js
├── index.html
├── serve.js
├── serve.ls
└── square.ls

Where index.html and square.ls are the same as http://lispyscript.com/docs/#browserrunning, and serve.js looks like:

#!/usr/bin/env js
// Generated by LispyScript v1.0.0
var http = require('http');
var url = require('url');
var fs = require('fs');
var path = require('path');
var port = (process.argv[2] || 1337);
var baseDir = __dirname;
(http.createServer(function(request,response) {
    return (function() {
    try {
        var reqUrl = url.parse(request.url);
        var fsPath = [baseDir,path.normalize(reqUrl.pathname)].join('');
        response.writeHead(200,{"Content-Type": "text/html"});
        var fStream = fs.createReadStream(fsPath);
        fStream.pipe(response);
        return fStream.on('error',function(err) {
            response.writeHead(404);
            return response.end();
        });

    } catch (e) {
    return (function(err) {
        response.writeHead(500);
        response.end();
        return console.log(e.stack);
    })(e);
    }
    })();
})).listen(port);
console.log("listening on port",port);

Running ./serve.js will print listening on port 1337, but the loaded page http://localhost:1337/index.html will log an error:

Uncaught TypeError: $.map is not a function
  (anonymous function) @ browser-bundle.js:4040
  (anonymous function) @ browser-bundle.js:40

Any pointers? Am I missing something?

publish to npm

please publish this to npm so one can install / start using easily:

npm install -g lispy

How to define an asynchronous callback?

I'm not clear on how to define asynchronous callbacks. I tried the function (gotData) below but that doesn't work (never gets invoked).

(d3.csv CSV gotData)

(var gotData
  (function (err data)
    (if err
      (throw err)
      (console.log data))))

Thanks in advance.

coffee like try lispyscript

While I really like the idea of lispy script, but having to requiring node + npm + lispyscript just to give it a try sets a high price I think. Having coffeescript like try lispy-script would probably get a lot more people interested in giving it a try.

Unexpected token (

$ lispy
lispy> LispyScript REPL v0.2.1
lispy> (function (x) (* x x))
[SyntaxError: Unexpected token (]
lispy> 

member access

Can we have '-' to represent '.' ? As in, (this-member-property) == this.member.property ?
Or that is , this['member']['property'] for symbols of any kind ? Thank you!

clojurescript compatible JS APIs

It would be very nice if lispyscript had API compatible with clojurescript:

;; Method call 
(.open window "http://github.com")

;; Property access
(.-location window)

;; Property setting
(set! (.-location js/window) (+ (.-location js/window) "#foo"))

How to chain methods of a object

Can somebody how to produce the following code:

http.createServer(app).listen(app.get('port'), function(){
  console.log("Express server listening on port " + app.get('port'));
});

How to chain the 'listen' method after the http object ?

Use `;` for comment instead of `#`

All the lispy languages I know use ; character for comments. It seems that it would be much better idea to stick to the same character as all the tools build around lispy languages will be able to handle it properly.

String interpolation

Would it be possible to implement string interpolation using a macro? I tried my hand at adding it to ls.js, but that got hairy pretty fast.

Variadic functions

=, !=, !, >, <, <=, >=, +, -, *, /, %, &&, || should take a variable number of arguments, like in Clojure. For example,

(+ 3 4 5)
(= 1 1 2)

enhance "lispy --run" to run .ls files requiring other .ls files (and not leave .js files) ?

For server side lispyscript files I've just been compiling them all to javascript with the lispy command and running the result directly with node given the main .ls file's output .js file.

But I noticed the "lispy -r"/"lispy --run" option, as well as the src/require.ls file in the lispyscript code which appears to install a require extension so that "require" in node can require .ls files directly (with them being compiled to javascript in memory and run without creating a .js file).

But when I tried it on this simple example it doesn't work:

file 1: "subtract.ls":

(set module.exports (function (x y)
    (- x y)))

file 2: "square.ls":

(var sub (require "./subtract.ls"))
    (console.log (sub 13 5))

i.e. I get this error:

$ lispy -r square.ls
~/testdir/subtract.ls:1
(function (exports, require, module, __filename, __dirname) { (set module.expo
^^^^^^
SyntaxError: Unexpected identifier

Note the "(set module.expo" is the original lispyscript trying to be executed by node without ever being translated to javascript.

What I think I see looking at the code is that square.ls is being written to a square.js file (just like you'd compiled using the lispy command) and then that is being run with node, but without that .ls "require extension" plugged into node. That's why lispy -r appears to work for simple examples but breaks if you try and require .ls lispyscript files from within those files.

So I think there's a bug where that src/require.ls file was never required in the actual node process that runs the program with "lispy -r"?

For a little test I created my own little "require.js" file like this:

var fs = require("fs"),
    path = require("path"),
    ls = require("lispyscript");
require.extensions[".ls"] = function(module,filename) {
    var code = fs.readFileSync(filename,"utf8");
    return module._compile(ls._compile(code,path.relative(process.cwd(),filename)),filename);
};

And then this does work:
node -e "require('./require.js');require('square.ls')"

i.e. the .ls code is run and the require from square to subtract works and it completes with no .js files left over on the file system.

Not that I think this is the best or only way to work with lispy (I notice the other issue here about having a "watch dir" option to automatically create js files from .ls files as they're modified I agree that's probably a more useful thing overall).

But I think this other way is useful too - and I think it makes "lispy --run" more useful and understandable. (basically: "lispy --run" is the command you use instead of node if you want to write and use your .ls files as if that's all there is!).

My biggest doubt: to implement the above I probably wouldn't have thought to even spawn a child node process I would have just installed the ".ls" require extension and then run their main.ls file in the very same node process that's running the "lispy" command.

But is there a reason the child process was spawned for the current "lispy -r" that I'm not understanding?

Also if "lispy -r" were changed so it no longer created the .js file as a side effect - would anybody care? I assume nobody depends on that - that's what plain "lispy" is there for right...

fn and obj aliases

Can you please add "fn" as an alias for "function", and "obj" as an alias for "object"

Splats...

Can you please add splats, like in CoffeeScript.

add a macro to ease the use node.js callbacks?

Was just playing with a little example of walking file directories asyncronously with node.js and it struck me lispyscript might be well positioned to simplify/hide/eliminate the use of callbacks...

I actually tried it out with a little macro and was delighted with how easy lispyscript made it (i'd been playing with generators recently and this was remarkably simple by comparison!!).

Here's my original function in lispyscript using callbacks:

(var fs (require 'fs'))

(function walk (rootDir)
  (fs.readdir rootDir (function (err files)
    (each files (function (file)
      (do
        (var filePath (str rootDir '/' file))
        (fs.stat filePath (function (err stats)
          (if (stats.isDirectory)
            (do
              (console.log 'directory:' filePath)
              (walk filePath))
            (console.log filePath))))))))))

(walk '.')

Here's the same code with a little "await" macro (which I show further down):

(var fs (require 'fs'))

(function walk (rootDir)
  (await files (fs.readdir rootDir)
    (each files (function (file)
      (var filePath (str rootDir '/' file))
      (await stats (fs.stat filePath)
        (if (stats.isDirectory)
          (do
            (console.log 'directory:' filePath)
              (walk filePath))
          (console.log filePath)))))))

(walk '.')

And here's the little "await" macro:

(macro await (result asynccall rest...)
  (~@asynccall (function (err ~result)
    ~rest...)))

As I mentioned above - I was delighted the above macro was so short and actually worked perfectly on the first try!!

I was trying to think if the same macro could work with both callback taking functions and promise-returning functions without the programmer having to use a different macro.

I couldn't think of any way - please others comment if somebody sees a way.

As it is I could easily see their being an "awaitp" for "await promise" as a sister to the above?

Also I obviously have ignored errors in the above I need to correct that. I thought I would have the macro include code to throw the received "err" parameter if it gets one.

    edit:  I had a feeling I was going to look like an idiot for writing the above...
I know exception handling is broken with async callbacks but I keep having 
selective memory wanting it not to be true...  I guess the "handle the err yourself" 
option below should really should be the only option where node callbacks are used(?)  
But something nicer could/should be done where promises or generators are involved.  
Nice article about such things fwiw:  
    https://strongloop.com/strongblog/comparing-node-js-promises-trycatch-zone-js-angular/

But maybe there should be a way to handle the err parameter yourself if you want to... The ideal syntax to me would look like destructuring assignment:

So this if you want to handle the err yourself:

  (await (err files) (fs.readdir rootDir) 

This if you want it to throw if there's an error:

  (await files (fs.readdir rootDir) 

Would that be doable I wonder?

(still learning the finer points of macros - seems to me the above implies in my macro I need some logic distinguishing what form I've gotten as the first "result" argument to the macro. I don't know how to do that ATM).

Destructuring

Can you please add destructuring similar to Clojure/CoffeeScript/LiveScript.

Uninstalling

Hello... how can I uninstall lispyscript? I used "npm link" as suggested but now "npm unlink" complains there is no uninstall installed in node_modules...

try catch form is buggy

try special form is pretty strange it expects function form but does not accepts non-inline functions.

js loops (for, while)

Lispyscript almost lets me write straight s-expression flavored JS, but it doesn't allow direct access to js loops for and while. This is perhaps a non-goal, but my use-case requires that I save on the runtime size and performance with direct loops. For now, I'm making do with the following macros, which compile to much larger forms than needed.

(macro forloop (i start n rest...)
  (loop (i) (~start)
    (if (< i ~n)
      (do
        ~rest...
        (recur (+ i 1)))
      null)))

(macro while (condition rest...)
  (loop () ()
    (if ~condition
      (do
        ~rest...
        (recur))
      null)))

set and get

i've come across a bug in lispyscript with get and set.

the code

(var a {})
(set "obj" a {})
(set  "test " (get "obj" a) 1)

does not produce the expected behaviour. i'd expected something like this

var a = {};
a["obj"] ={};
a["obj"]["test"] = 1;

further more i've seen that it is possible to make a javascript object like this:

{"test":1}

but it is not possible to set function with this:

{"test": (function (x) (* x x))}

but thats not a huge issue since one could use the set function.

lispyscript's ".ls" file extension overlaps with livescript

this is admittedly a low priority thing (I don't know there's anything to be done about it).

but I just wanted to create this issue as a note of this overlap in the use of ".ls" with "livescript" (another compile to javascript language) as can be seen here: http://livescript.net/#usage

I ran into the issue when working on an atom editor preview for lispyscript - the editor kept thinking my file was livescript not lispyscript.

To avoid the conflict in my experimental lispyscript branch (now renamed to "sugarlisp" after discussing with Santosh to avoid confusion with the new Lispyscript 2 effort), I'm supporting both the ".ls" extension for backward compatibility and an alternative (tbd) extension as well.

I just noticed the Lispyscript 2 project is already using ".ls2" so they've avoided the issue anyway:
https://github.com/geekskool/lispyscript2/tree/master/lispytest

Feel free to close this issue if desired - I'd just meant some time back to record the issue and never did.

I guess it's really only a problem in Lispyscript 1 if others want such an atom preview for Lispyscript 1 - in which case adding support for an alternative to the ".ls" file extension might be worthwhile.

add a lispy option for tracing?

Some of the quirks I saw when I tried source maps got me thinking...

What about an option for the lispy command to generate the code in a "trace" mode?

Such that when you run it outputs a trace of the program run?

Where (ideally) this might show the lispy source (and maybe the lispy source line numbers and javascript line numbers? since maybe that's not too hard since the sourcemap support in theory has that available already?)

Not that I've given it much thought - maybe less ambitious but still helpful is just a little api for log statements that are only included in the generated code if you've compiled with this special "debug"/"trace" option enabled?

To be a more concrete - I was thinking about this in the context of the "await" macro I just posted about in issue #56.

What if the macros had some optional trace statements that normally expand to nothing/no-ops but expand to console.log statements - output in the generated code - when the lispy compiler got this "trace" mode option:

So e.g.:

(macro await (result asynccall rest...)
  (trace "await for" ^result "from" ^asynccall)
    (~@asynccall (function (err ~result)
       (trace "got" ^result "from" ^asynccall ":" ~result)
       ~rest...)))

The above is just to illustrate the idea it doesn't actually work of course.

In particular in the above I've used a hypothetical e.g. "^result" to indicate "I want the macro argument as a quoted string" (which is what is needed for a console.log statement).

As opposed to the normal "~result" to get the macro argument unquoted as needed for actual generated code.

is there already a way to do domething similar I wonder?

I can see where the above might be questioned as too simple, but if it were also supported through the "keyword" handling in the "lib/ls.js" file...

And maybe even allowed for a few different tracing "levels".

I could see this being very helpful when developing real programs, esp. where complex control flow and asyncrony is involved.

Strange REPL behavior

I installed LispyScript 0.3.6 with Node v0.10.24, launched the REPL and tried this :

lispy> (+ 1 2)
3

lispy> (+ 1 2 3)
[Error: Syntax Error
Line no 1]

lispy> (+ 1 2)
[SyntaxError: Illegal return statement]

:-|

Feature request: quote syntax.

Hi
Can you add quote syntax to expand s-expression to data?

Now I'm trying to use lispyscript with gulp.
Gulp have api like this.

    gulp.task("taskname", function() { doSometing(); })

I'd like to use this api like this using macro.

    (deftask taskname
        (doSomething))

But I can't found the way to convert taskname to "taskname" in macro.

I propose more general solution that implement quote.

I want to use quote syntax like this:

   (quote taskname)

Expand to js like

   "taskname"

Then I can define macro like:

(macro (name rest...)
  (gulp.task (quote ~name) (function () ~rest...)))

Allowing a wider range of characters for identifiers

For example the minus sign, which is a commonly used separator in lisp like languages.
It is not a supported character for identifiers in Javascript, so there should be no conflict. ? and > could be considered, too.

  • a-b could be converted to a_b
  • a->b to a_to_b
  • ? could add a "p" suffix for "predicate". a? would become a_p.
  • ! could add a "x" suffix. something like set! would become set_x

There could also be a generic way to convert characters not supported by javascript. For example by using ".charCodeAt()" unicode values. "a?" could be converted to "a_u63".
It wouldn't really matter how long the variables are if the files get minified.

undefined is not a function

lispy uses undefined in place of no operation everywhere.
When this is fine in Node, it will produce "undefined is not a function" in browser js console.

Could you use something else that won't produce browser warnings?

ReferenceError: define is not defined

I try to require the "lispyscript" module, it throws an error:

> require('lispyscript')
ReferenceError: define is not defined
    at Object.<anonymous> (/home/me/myapp/node_modules/lispyscript/lib/ls.js:8:1)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at repl:1:2
    at REPLServer.self.eval (repl.js:110:21)
    at Interface.<anonymous> (repl.js:239:12)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.