
Show HN: LJSON: JSON extended with pure functions - LightMachine
https://github.com/MaiaVictor/LJSON
======
archgrove
I think it's a lovely idea, with an interesting implementation.

Obligatory HN style comment: It might be wise to strengthen the description
from "pure" functions to "pure and terminating". I've not had time to form an
opinion on whether the restrictions are sufficient to ensure this
(JavaScript's evaluation rules are...complex). However, the informal
specification of this being a lambda calculus with multiple arguments isn't
strong enough - that would allow non-termination on load, which is not
something you really want in your data serialisation format.

~~~
LightMachine
There is no protection against non-termination. For example, an user could
give you this function:

    
    
        f = (function (x){ return x(x); })
    

Now, if you call `f(function(f){return function(x){ return f(f(x)) }})`, it'll
not halt. But there are good principled ways to work around that, such as
adding a type system like System F. That would discard 100% of the programs
that halt, at the cost of also losing some programs that do halt.

------
lambdapie
Fun project. From examining the source code, they are using the technique that
can be considered a kind of higher order abstract syntax (HOAS). In
particular, LJSON can be fooled by so called exotic terms. E.g.

    
    
      LJSON.stringify(function(v) { return v; })
    

evaluates to the string

    
    
      (function(v0){return v0})
    

While

    
    
      LJSON.stringify(function(v) { return v(null) } )
    

Evaluates to the string

    
    
      (function(v0){return "v0"})
    

In the latter case, v(null) was able to examine the variable that stringify
injects into the function. In this case, v(null) is the name of the injected
variable.

~~~
LightMachine
Very good catch. Any suggestion how I could improve the usage of null for
determining the end of a call list?

~~~
lambdapie
Actually there are other problems that are caused by the fact that you're not
really doing HOAS, but something even more difficult, namely trying to infer
the function by passing in values.

For example

    
    
      LJSON.stringify(function(v) { if (v == 0) { return "zero"; } else { return "one"; } })
    

Evaluates to the string

    
    
      (function(v0){return "one"})
    

The only way to avoid both these issues, is to inspect the code of a function
f using f.toString(). However you would need to consider the scope where f was
defined.

~~~
LightMachine
Ah, fair enough. The user should avoid using native JS constructs on the code
to be stringified, though - it is an interesting/useful side effect of the
method that you are able to, but ideally you would define your functions using
only the pure λ-calculus grammar.

Thanks for figuring that out!

------
vortico
Without being able to call pure functions within pure functions, what use is
this beyond the trivial simple examples? Couldn't it be possible to pass a
"this" argument as the current JSON node and have it traverse the tree or
something? For example:

    
    
      {
        "math": {
          "sin": function(x) {...}
        },
        "numerics": {
          "sin2": function(x) {
            return this.parent.math.sin(x)
          },
          "parent": [automatically inserted by parser]
        }
      }

~~~
LightMachine
There are many possibilities since you can pass any program/algorithm through
LJSON while still having a good level of safety. You could it, for example, to
allow your users to pick an AI strategy for their bots in a game, among
billion of other things. But there are many restrictions, so you can't just
write arbitrary JS functions. You have to design them much more carefully by
requesting the proper primitives, using the technique I explained with the
_hypothenuse_ example. Of cours, you could just request `window` as a
primitive and get everything, but yea...

------
statictype
Neat concept.

It reminds me of how JSON started - as just a string representation of a
javascript object and parsing JSON was as simple as evaling it.

Once it picked up steam, it got a formal definition and a parser.

If serializing pure functions ever takes off, it will have to follow the same
route - without using clever javascript tricks to make it work.

Still, very cool concept.

------
IgorPartola
This would be interesting, except JavaScript is a terrible language for this.
At the minimum I think you'd want all the arguments and return values to be
strictly typed. Otherwise you can't for example determine how much memory to
allocate for the returned value. The big strength of JSON is that the encoder
and decoder can be written by anyone in any language fairly easily. I've used
it in JS, Python, PHP, and C, and every time it's been super easy because the
format is so simple.

What would actually be cool is to add type hints to JSON. That way we could
conceivably add things like date types to it fairly easily.

------
TazeTSchnitzel
This is something I'd wanted to do, and I'm glad someone else had the same
idea. Lots of exciting possibilities.

Something important that needs doing is strictly defining the JavaScript
subset used. As simple as possible, ideally, in keeping with the JSON spirit.
This would mean you could then safely implement that subset in other
languages. Imagine serialising a PHP function into λJSON and running it from
JavaScript, or vice-versa!

------
SFjulie1
Neat idea, mutable in serialization format and functions...

We are a step close to the YAML fiasco that has crippled rails.

/me grabs popcorns, and will likely enjoy to watch the world burns.

~~~
LightMachine
Mutable what?

------
d0m
I definitely see some uses to it as a way to pass client code to the server
safely. What would stop the client from using global variable though?

~~~
ch
There are no free terms in any of these LJSON functions, since all the terms
are explicitly named in the arguments. Globals would presumably get shadowed
and so would not be captured.

