

Fargo: new Scheme-like language working in Node.js/browser - sphynx
http://fargo.jcoglan.com/

======
turbolent
I've been working on Ralph for a while now:
<https://github.com/turbolent/ralph>

It compiles a major subset of Apple's Dylan
([http://lispm.dyndns.org/documentation/prefix-
dylan/book.anno...](http://lispm.dyndns.org/documentation/prefix-
dylan/book.annotated/annotated-manual.html)) to JavaScript, both for use on a
CommonJS implementation and in the browser. A bootstrapping compiler is
implemented in JS, but the same compiler is also available in Ralph itself and
features define-macro (Cl-like). The whole runtime is defined in Ralph as well
and provides a single-inheritance object system (including next-method):
[https://github.com/turbolent/ralph/blob/master/src/runtime/c...](https://github.com/turbolent/ralph/blob/master/src/runtime/core.ralph)

Almost all of the features are shown in
[https://github.com/turbolent/ralph/blob/master/src/tests/run...](https://github.com/turbolent/ralph/blob/master/src/tests/runtime-
tests.ralph) and I'm using it a project now. To build HTML5 apps, there's a
small toolbox: <https://github.com/turbolent/toolbox>

Maybe it's useful to someone else. Cheers

~~~
mikelevins
I notice that it doesn't support multiple inheritance or multimethods; out of
curiosity, is that because of a principled objection to them, or more because
it wouldn't be convenient to implement them?

~~~
turbolent
At the beginning I tried implementing various object systems. The first one
was indeed multiple inheritance with multimethods, based on C3 linearization
(<http://en.wikipedia.org/wiki/C3_linearization>) and didn't use the prototype
chain, but wasn't finished. The second one was similar to Clojure's protocols
(define-protocol, extend-protocol, ...), but wasn't very handy.

The current one is single-inheritance, because it uses the prototype chain.
It's a compromise between speed and usefulness. I'd prefer having multimethods
(and maybe also multiple inheritance), but speed is a bit more important, as
JavaScript is already quite slow.

So far I'm quite pleased with the single-inheritance and single dispatch
solution, which basically works like that: <https://gist.github.com/866506>

------
icey

      > (+ 1 1 1 1)
      => 2
    
      > (* 3 4 5 6)
      => 12
    

Does it only consider the first and second items in a list?

~~~
ionfish
So it would seem:

[https://github.com/jcoglan/fargo/blob/master/source/fargo/li...](https://github.com/jcoglan/fargo/blob/master/source/fargo/lib/primitives.js#L124-132)

~~~
icey
Man, I forget how nice it is to be able to look into the source of stuff.

Other than being obviously new, this is pretty cool.

Edit: Would there be a better way to fix it than to add functions like this?

    
    
      function adder() {
        var args = Array.prototype.slice.call(arguments);
        return args.reduce(function(a, b){return a + b})
      }
    
      function subtractor() {
        var args = Array.prototype.slice.call(arguments);
        return args.reduce(function(a, b){return a - b})
      }
    
      function multiplier() {
        var args = Array.prototype.slice.call(arguments);
        return args.reduce(function(a, b){return a * b})
      }
    
      function divider() {
        var args = Array.prototype.slice.call(arguments);
        return args.reduce(function(a, b){return a / b})
      }
    

(I haven't really put too much thought into this, but would love to hear of
stronger approaches or obvious bad ideas in this one)

~~~
ionfish
In principle that is a nice way to do it, and given that reduce is implemented
natively on some platforms it might even be sufficiently performant, but to be
honest I'd probably just write them as loops mutating a local variable. A
language runtime is one of the places where a little bit of readability can be
sacrificed for performance (although of course, one should measure it to make
sure the gains are worth the cost).

Someone has actually already submitted a pull request doing just this:

<https://github.com/jcoglan/fargo/pull/3>

------
edw
Well, TCO seems to work:

    
    
        (define (count x)
          (let loop ((x x) (sum 0))
            (if (zero ? x)
              sum
              (loop  (- x 1) (+ sum x)))))
        
        (count 100000) ; ==> 5000050000 (doesn't blow up)
    

I'm very tempted to help out however I can. I've been dreaming of using Scheme
instead of JS in a Node.js setting.

------
judofyr
The more interesting feature of Fargo is coroutines (which can make async
programming easier): <https://github.com/jcoglan/fargo>

------
DTrejo
Also, SibilantJS (which seems more mature at the moment, as `npm install
sibilant` works, but `npm install fargo` does not):

<http://sibilantjs.info/#welcome>

~~~
jcoglan
With regard to maturity, Fargo is one week into development. I'm not even sure
if its just a quick hack to show off an idea or if it will become a production
language. Certainly I have a lot to learn about compilers and VMs before that
happens.

~~~
DTrejo
Hey, didn't mean to be mean, my apologies. I love to see people experimenting
with new things. I may play around with it tonight :)

~~~
jcoglan
Oh, no offense taken. Thanks for pointing out other lisps, I should check them
out for alternative ideas.

------
nkassis
I'm a newb or something but :

(cdr ()) makes it explode. What's nil? null nil don't exist

I do really like this. I was hoping for something like this where it would
allow me to write lisp instead of javascript.

~~~
dfox
well, (cdr ()) is an error in standard Scheme, as empty list is not pair.

~~~
jcoglan
I'll fix this so that invalid expressions are reported and car and cdr of ()
are errors.

------
pflanze
Any reason why not to implement call/cc and then write fibers in terms of
call/cc? The implementation may not actually be any different from what it is.
(I've not studied the code enough to understand how it implements fibers,
although I got the impression that it handles call frames explicitely
(source/fargo/runtime/stack{,less}.js).)

~~~
jcoglan
I was going to do call/cc but fibers are cheaper. The implementation is very
similar, but because fibers can only be resumed once from the last yield you
don't need to copy the stack when yielding and resuming.

They also require the user to explicitly start a fiber. This means when you're
not in a fiber you can use a faster stackless engine because you don't need to
track the state of the current continuation.

~~~
pflanze
> explicitly start a fiber

Fair point.

BTW what's interesting about yield based versus lazy evaluation (functional
stream) based sequence generation? Advantages of the latter are that they can
easily be understood as sequences and thus further processed by lazy versions
of the known sequence processing functions (map etc.), also they can be re-
read multiple times, which you just made impossible for yield by not basing it
on call/cc :).

~~~
jcoglan
I've been thinking about this. I might try out making all the primitive
functions understand promises. So not lazy evaluation per se, but having the
core library transparently deal with asynchronous values. Maybe monads would
help but that really requires a decent type system.

------
shiven
Isn't Shen a very similar idea? Bringing functional programming to Javascript.

It is expected to be released very soon for Javascript (and Scheme).

[1]: <http://news.ycombinator.com/item?id=1921347>

[2]:
[https://groups.google.com/group/qilang/msg/bd474d815479b50a?...](https://groups.google.com/group/qilang/msg/bd474d815479b50a?hl=en)

------
LeonidasXIV
Hmm, I actually hoped for Clojure on Node.js (don't get me wrong, Scheme is
beautiful and this seems to be quite a capable implementation but Clojure is
way more practical) but hmm, I hope this gets popular.

~~~
pjscott
Clojure is a big language, and pretty deeply tied to the JVM; I'm not sure how
you'd put it on V8. Scheme is pretty practical, though, once you get used to
it.

~~~
swannodette
The first version of Clojure was a Common Lisp compiler that compiled Clojure
down to JS to be run on Rhino. There's interest in the Clojure community to
have a Clojure "Light" that runs on V8 or SpiderMonkey.

~~~
nkassis
I'd like to see it run in a browser also, that would be awesome.

------
d0m
Is there a similar version (something like Heist) but for Python?

------
caioariede
The double quotes does not work on MacOSX/Chrome?

