Skip to content

remolueoend/js-lisp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

LISPY-JS

Fun-project for playing around with Lisp-alike array-based Javascript expressions.

The idea is to express a whole program using only javascript arrays, and - where necessary - arrow functions.

The core of this project is a function called evalExp<R>(Expression): R located at ./core.js, accepting an array-based expression and returning the resolved value.

This project might help me to understand the advantages of Lisp-related languages, especially in context of meta-programming.

Check out ./index.js for some basic examples.

Other things to try

Let's assume we want to define a function which accepts a list of numeric values and returns their sum. To solve this recursively, we could just add the head of the list to the result of the recursive call for the tail of the same list. If the list is empty, we return 0:

const sumList = [deffun, 1, list => [
    ifOrElse,
    [empty, list],
    0,
    [add, [car, list], [sumList, [cdr, list]]]
]]

ifOrElse is defined as:

const ifOrElse = [deffun, 3, (cond, ifVal, elseVal) => [
    or, [and, cond, ifVal], elseVal // let's just ignore all flaws of these simple comparisons
]

Our sumList function won't work. Instead it fails with RangeError: Maximum call stack size exceeded. This happens because when evaluating the resulting expression of sumList, ifVal and elseVal are always evaluated regardless of the condition, leaving us with an indefinitely recurring function. To avoid this error, we have to provide separate arrow functions for ifVal and elseVal to delay the evaluation:

const sumList = [deffun, 1, list => [
    ifOrElse,
    [empty, list],
    () => 0,
    () => [add, [car, list], [sumList, [cdr, list]]]
]]

What if the evaluation routine (evalExp) could instead automate this transformation? Because our expressions are nothing else than plain Javascript arrays, this should be fairly easy:

const transformIfOrElse = [deffun, 1, ([fn, cond, ifVal, elseVal]) => [
    fn, cond, () => ifVal, () => elseVal
]]

➡ We need some kind of function decorators on expressions allowing us to declare transformations applied before evaluation .

About

kind-of-LISP-expression interpreter in Javascript

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published