6 ms·
Roy — small functional language that compiles to JavaScript
- archivator 15y agoThis looks great! It has all the essentials and compiles to readable JavaScript, should be a real productivity booster. Looking at the JavaScript, though, all those anonymous functions can't be very fast.. I wonder if the compiler could try to defunctionalize the output..
- hammerdr 15y agoThe only gratuitous functions I saw were the "case" statement and the "with" statement. The with statement can really only be implemented with that function (though there is something to be said of only defining it once instead of n times). The "case" statement may be gratuitous but it feels like the compiler has a reason for wrapping it in a leakless function wrapper.
- pufuwozu 15y agoFor "match", it needs to be an expression for some things so that means wrapping it in a function and returning the result. In the future I'm going to do some optimisation to see if the expression is the last in a function and remove the wrapper. For example: return (function() { if(b instanceof True) { return ifTrue; } else if(b instanceof False) { return ifFalse; } })(); Can just become: if(b instanceof True) { return ifTrue; } else if(b instanceof False) { return ifFalse; } The output of `with` is pretty gross. Definitely want to hear ideas on how to clean it up :)
- jawher 15y agoCan't you take te same approach ClojureScript took, i.e. to generate a straitforward translation to JavaScript, and then let Google's closure compiler take care of the optimizing thing ? For instance, for this Roy generated JS: var True = function(){}; var False = function(){}; var getBool = function(b, ifTrue, ifFalse) { return (function() { if(b instanceof True) { return ifTrue; } else if(b instanceof False) { return ifFalse; } })(); } The Closure compiler generates: var True = function() { }, False = function() { }, getBool = function(b, c, d) { var a; b instanceof True ? a = c : b instanceof False && (a = d); return a };
- pufuwozu 15y agoRoy has the same goal as CoffeeScript - create output that would be similar to how a JS dev would write it. If you use Roy but then decide you don't like it, just take the output and keep going. I could rely on Closure for optimal performance but what I really want is optimal readability.
- epidemian 15y agoIt looks very nice! I'm digging the simple Haskell-ish syntax. The example on Types is not compiling as it is. The last line should be something like: console.log (getName {firstName: "John", lastName: "Doe"})
- meric 15y agoI do like Haskell syntax, but only because it allows partial application of functions. No partial application allowed here, so what is the point? =\ let add a b = a + b let add2 = add 2 Does not work. let fact a = if a == 0 then 1 else (fact (a-1)) * a Does not support recursion like this either. The "functional" description brought my expectations too high I think. It compiles to very lean Javascript though, so that's a big plus.
- archivator 15y agoCurrying is a nice-to-have but definitely not a requirement for a usable functional language. It might be possible to add it to Roy by abusing JavaScript dictionaries and identifying functions that are partially applied but I'm not convinced it's worth the effort.
- amalcon 15y agoCurrying is very easy to implement in terms of lexical closures.
- masklinn 15y agoSure, but that can get costly fast (at runtime) when the language implementations are not highly optimized for funcalling and recursion (javascript VMs tends not to be), so ideally you'd only use partial application in the underlying (compiler result) code when that's needed rather than have all functions be curried.
- paulmillr 15y agoIt's an early version. Maybe, currying would be added in one of upcoming releases.
- jaipilot747 15y agoThe roy code looks very clean and readable, but what will the js output be like for larger projects, I wonder.
- joebo 15y agoThe tracing monad is fascinating. What would be a practical application of it? I've been studying monads through Learn You a Haskell for Great Good but haven't been able to put them into context (other than isolating side effects and enforcing order of execution). https://github.com/pufuwozu/roy/blob/master/test/trace_monad.roy https://github.com/pufuwozu/roy/blob/master/test/trace_monad... let traceMonad = { return: fn x = console.log "Return:" x x bind: fn x f = console.log "Binding:" x f x } console.log (do traceMonad bind w = 1 let x = 2 bind y = 3 bind z = 4 return w + x + y + z )
- Peaker 15y agoThat's actually not a Monad :-) To be a monad, return must be a left and right identity: x >>= return = x return x >>= f = f x By having return do things other than wrapping the value, the monad laws are broken. Similarly, bind cannot have such effects, it would break its associativity.
- joebo 15y agoThe option monad example might be closer. I'm having trouble figuring out how to get the value out of it though data Option a = Some a | None let optionMonad = { return: fn x = Some x bind: fn x f = match x case (Some a) = f a case None = None } let m = (do optionMonad bind x = Some 1 let y = 2 bind z = Some 3 return x + y + z ) match m case (Some x) = console.log x shows an error Error: Type error: Native is not Option 'dwk
- pufuwozu 15y agoBug in the type system. Fixed. Roy could be cached so you might need to force a refresh.
- embwbam 15y agoKnow what would be awesome? If you could use the monad syntax to clean up async, cb-passing code. I've been learning a lot of Haskell lately too, and I like to think of the monads as returning a set of instructions with side effects to be executed in order. I think this example is kind of trivial. I'd love to see one that does something more than simple addition (IO!)
- g3orge 15y agoI think this has the same disadvantage with coffeescript. The web is full with javascript and there isn't an easy way to swap between the languages. Also it's a pain to debug.
- embwbam 15y agoPersonally, I'd much prefer to have my compiled JavaScript have the same line numbers as the source. I think readability of the compiled js is great and all, but correct line numbers would be awesome OTOH, string typing will greatly reduce your errors.
- mhd 15y agoLet's hope that Mozilla's SourceMap[1] gets finished then. Should alleviate most of the debugging problems. [1]: https://wiki.mozilla.org/DevTools/Features/SourceMap https://wiki.mozilla.org/DevTools/Features/SourceMap
- bergie 15y agojs2coffee helps there. I've gotten into the habit of converting old JS code with it as a first step of refactoring when I need to take over some old codebase.
- Miky 15y agoIt makes me sad that having monad sugar is now just a given feature for a functional language. Especially when that language has unrestricted side effects and the example code using the monad syntax uses those side effects, completely obviating the need for, and in fact rendering useless, monads as used in the example. This is cargo cult programming at its worst. Including monad sugar because it's the thing to do, without even understanding what monads are or why they're useful. This is quite clear from the "tracing monad" example code. This "tracing monad" is like the Writer monad, stripped of all utility and sense. What drove you to unleash this horror on the programming masses, Moggi? Why have you cursed us so?
- pufuwozu 15y agoThe example sucks but is very simple. I didn't add monadic sugar just to be part of the "cargo cult". I added it because I'm eventually going to use it to implement an automatic continuation-passing transform. I've done a similar thing before with ClojureScript's macros: http://brianmckenna.org/blog/cps_transform_js http://brianmckenna.org/blog/cps_transform_js
- Miky 15y agoMonadic sugar is probably not the way to go for implementing an automatic continuation-passing transform. Why not just do macros?
- pufuwozu 15y agoMonads suit the problem nicely and it's been done in quite a few languages already: http://lambda-the-ultimate.org/node/4117 http://lambda-the-ultimate.org/node/4117 http://ocaml.janestreet.com/?q=node/100 http://ocaml.janestreet.com/?q=node/100 http://en.wikibooks.org/wiki/F_Sharp_Programming/Async_Workflows http://en.wikibooks.org/wiki/F_Sharp_Programming/Async_Workf... This is something that JavaScript desperately needs. Macros aren't so nice for this stuff in non-homoiconic languages.
- Miky 15y ago
- prpatel 15y agoInteresting language. Feels a bit like Coffeescript with lesser use of symbols and (possibly less) syntaxic sugar. Going to play with it a bit more...
- tjholowaychuk 15y agoor... coffeescript looks like other languages that already exist.. and this one just happens to have significant whitespace as well :p
- skrebbel 15y agoI don't understand the monad because I'm too stupid, but I really really like Roy nevertheless. I've really missed static typing on Javascript and Coffeescript; little typos are so hard to find! Structured typing really sounds like the way to go for putting type checking into Javascript, and I like how, just like Coffeescript, Roy tastes a lot like Javascript otherwise - avoiding all kinds of leaky abstractions you get with less JS-like languages. Plus, it has a sexy syntax. I'd like to try this out in a real project. Is that being done already?
- cheald 15y agoThis may just be my ignorance talking, but isn't a functional language that doesn't implement tail call optimization a Bad Idea?
- false 15y agohttp://roy.brianmckenna.org/bundled-roy.js http://roy.brianmckenna.org/bundled-roy.js There are some characters that shouldn't be there in the middle of the file, thus demo is broken.