Great news! I wanted to learn BEAM/OTP, but had tried
Erlang briefly years ago, and then went back to Common Lisp. Now I can try to learn BEAM/OTP in a syntax that is more appealing to me than Elixir's Ruby-like syntax. I like Elixir, and it is very popular, but true runtime macros are available in LFE 1.0. In addition, Robert Virding was one of the co-creators of Erlang, so his devotion to bringing the best Lisp he could to the BEAM platform within its confines, comes with some authority. The Google Group Lisp Flavoured Erlang is a very responsive community and resource for getting started. Congratulations LFE on your v1.0!
OT, but I also use Extempore - the music, graphics livecoding environment with a great language, xtlang that I believe was based upon S7 scheme and has an LLVM backend [1]. There are some s-expression to WebAssembly projects floating around too. All around good news for all the choices to work with up front no matter your preferences.
Elixir is really not similar to Ruby and the comparison wears thin. This is my opinion after having used Elixir daily for the last 1.5 years and Ruby for 10 years before that.
Elixir really is a brilliant language and José et al have made the developer experience second to none with hex, mix, the language guide and docs. Compare how you bring up a repl: Elixir, type iex; LFE, cd into LFE dir, type ./bin/lfe. (EDIT: this is incorrect, see child) Trivial example and something easily fixed if it bothers you, but it's emblematic of the attention to detail that has gone into devx. I am deeply in love with Elixir. That Robert co-authored Erlang should not mean giving Elixir any less consideration IMO.
That said I sincerely wish to congratulate Robert on this 1.0, I look forward to using LFE in anger for something very soon now it is 1.0 (and it will be easy to slip in an LFE module into one of my OTP apps). Exciting times for the Erlang ecosystem.
I didn't exactly write it that way; I specifically referred to syntax. I am aware of the good things in Elixir, since I started playing with it years ago. I gave up trying to figure out why something in life becomes more popular than another, and just go with what I judge is best for me, makes me happy and gets the job done. Pony seems to be chomping on the heels of Erlang/Elixir/LFE, but I will stay with LFE for now. Jose and team have done a great job putting together a great ecosystem. I just happen to prefer Lisp syntax over blocks with 'END's. It is purely subjective. I know many languages to a certain degree (J, Python, C, Scheme, some Prolog, APL), and I try and pick the one that is best for the job. I just find myself comfortable in Lisp or Scheme. I am trying to grok Idris and Haskell this year, but I am really into livecoding, and so I chose Extempore. Sonic Pi is great, and is based on Ruby. Again, just personal preference. I am just excited about LFE for my selfish reasons ;)
Sadly not a joke, just me not reading properly (scanning over on my phone but no excuse!). Thanks for correcting me, I deserve the down votes for that. I fully retract and make no claims as to the devx of LFE. My feelings on Elixir remain unchanged :)
WRT to macros how does LFE differ from Elixir? My understanding was that Elixir macros were incredibly powerful(hence most of the language constructs being built in them).
I feel that this LFE release further validates BEAM as a promising platform for future development of new programming languages. Also I look forward to reading SICP converted to LFE. Available chapters can be found here https://www.gitbook.com/book/lfe/sicp
Given you mentioned SICP... SICP is cool for its math and its puzzle-like problems, but I found http://scheme.com/tspl4/ a much better introduction to Scheme and more likely to help me solve problems with Scheme in the real world (i.e. a good reference book).
Main issue is that luerl does support metatables. That caveat was written ago and I can't remember what it was I didn't support then. But as I said now it works.
I do want to point out that LFE has been release ready and of production quality for a long time but I tend to suffer from a "Jag ska bara"* syndrome which has delayed things. :-)
What do you all think are the "good bits" of lisp that Clojure lacks?
Compared to common lisp off the top of my head (correct me if I am misrepresenting Clojure from memory): condition system, multiple return values and &key, CLOS with all that entails, and I seem to remember that clojure had some fiddly issues with macros and reader macros.
Not intended as a knock on Clojure, btw, but the JVM is somewhat limiting, in the same way you can't do a "proper" common lisp on the CLR.
Readable stack traces. Unfortunately, the JVM is the culprit here. I like Clojure's syntax, and some other bits, but if I were to chose a Lisp that runs under another system like Clojure, I'd choose Shen [1].
Shen is built on it's own simplified parent dialect that is easily implementable in pretty much any language. Once you implement that core, everything else comes along for free, in theory.
Map is a constructor in this case. You'll want lists:map/2 (fn comes first). I don't know LFE much so there may be sugar of sorts for this, perhaps a comprehension syntax.
One obvious example is that AFAIK the VM doesn't support functions with a variable number of arguments (foo/1 and foo/2 are two separate functions). This means that you can't have CL-style &rest or &key arguments.
This is a feature to me more like a limitation. I do not like optional arguments &rest style. In Erlang you need to have explicit number of arguments and need to explicitly implement them. I really like that. Keep in mind that default values are trivial to implement when the smaller arity function calls the higher arity one with added values. Or you can call in yourself to the higher arity function and specify the parameters yourself. In my opinion this is elegant and safe way of dealing with the problem.
In Erlang you need to have explicit number of arguments and need to explicitly implement them.
Or, you know, just use lists as parameters. That's the standard Erlang pattern for unknown parameters lengths (e.g. io:format("debug ~s because ~p~n", [SomeString, SomeType]))
Firstly, this still requires a mechanism which underlies the [ ... ] notation for evaluating a sequence of any number of expressions and constructing a list.
In Lisp dialects, that is done by a variadic function:
(list 1 2 3 4 ...)
Of course, if we don't need to indirect on this function, we could implement it as a macro (supposing further that we have variadic macros for compile time, but not variadic functions for run time).
The macro would turn (list 1 2 3) into the non-variadic calls (cons 1 (cons 2 (cons 3 nil))).
I imagine that's a conceptual facsimile of what Erlang's list constructor notation is doing.
Erlang has variadic features in its read syntax; without a doubt its BNF is chock full of "zero or more of ..." grammar productions. The function defining mechanism lets you define a function which has any number of arguments; just that number has to be fixed for that function. So the mechanism itself enjoys variadic application. Here it is asked to define a three-arg function, here a ten-arg, ...
We can simulate some aspects of variadic application with syntactic sugar, but not all. A Lisp function call which specifies five arguments can call a function which requires exactly five arguments, or a function which requires three arguments, followed by variadic ones.
For instance, if we have a callback registration interface that passes five arguments, the client can supply a fixed arity function, or a variadic one.
I suppose that if everything is static, that can still be worked out. The compiler sees that a variadic function with only two required args is passed as a callback that must be 5-ary, so it inserts a conversion shim: an anonymous function which takes exactly 5 parameters and applies them to the 3+rest function.
LFE macros can have variable number of arguments. The compiler does very little in helping with this as there are in principle no inter-module dependencies. This is a requirement of the dynamic code handling which allows you to reload any module at any time without any requirements on the contents. All checking is done at run-time. This is a basic property of the Erlang system and to make something which is fully compatible you have to follow this.
One way to have made LFE fully variadic in its functions would have been to have made each function only take one argument which is a list of the arguments in the call. This would have been easy to do but made it very difficult to interface LFE with the rest of the Erlang system in a clean way.
I think io:format has fixed number of arguments(2), the text that you use as a template and the second parameter is a list of things that you will be using in the template.
I feel like it's OK not having rest args if you leave them out in order to support currying, but leaving both out seems really weird for a language that's trying to be functional.
Leaving out rest args supports the syntactic sugar for currying, not currying itself. (Let's call that sugar OAIPA: omission of arguments is partial application.)
Even syntaxes which have OAIPA can (and do) still have optional parentheses to exactly delimit the arguments of a call, and that notation can clearly support variadic args.
Outside of explicit delimiting with parens, OAIPA can work on a variadic function up to its required arguments by considering it to be a function of exactly that number of arguments, and no more.
While &key is CL-specific (and if you don't have it, you can ad-hoc it if you have variable arguments) variadic functions are pretty important, and found broadly in Lisp dialects.
If you're on a VM or other target that doesn't do them natively, it's worth fighting tooth and nail to somehow get the functionality.
E.g. make an inefficient variadic type that at the VM level takes a single argument---a list or vector of the arguments. Or multiple types for different combinations of fixed arg arity plus variable list.
>E.g. make an inefficient variadic type that at the VM level takes a single argument---a list or vector of the arguments. Or multiple types for different combinations of fixed arg arity plus variable list.
This would hurt interop with Erlang, which seems to be a goal of LFE.
> One obvious example is that AFAIK the VM doesn't support functions with a variable number of arguments (foo/1 and foo/2 are two separate functions). This means that you can't have CL-style &rest or &key arguments.
But surely one could call a function with one argument, which is a variable-length list of arguments, right?
Some limitations (?): are no global data; no shared data; all data is immutable; the modules are different from CL packages; functions can't have variable number of arguments[]. It does however have support for decent pattern matching and full access to all of Erlang's concurrency, fault-tolerance and scalability properties. Plus real macros as god intended.
[] The macro handling can go part way to hide this.
The users manual has a stub section for macros; does anybody know how LFE macros work? It says "lisp style" but that allows at least 4 options (syntax pattern-matching versus classic defmacro, and capturing versus non-capturing).
There's some more in-depth documentation in the repo in doc/user_guide.txt, at around line 520-ish.
It has Common Lisp style defmacro (augmented with pattern matching), and Scheme-inspired defsyntax.
The documentation warns that both are unhygienic, and `grep -ri gensym` didn't find anything in the repo.
My exposure to the Erlang world is limited to having read the first few chapters of Programming Elixir. Is interop trivial? Can you easily use Erlang, Elixir, and LFE in the same project?
Yes, compiling a module where the source was written in another language is no different from calling a module written in the same one. In Elixir any time you call a module that starts with a `:` it has most likely been written in Erlang.
Technically all modules begin with : as module references are atoms. iex just hides it from for Modules made with defmodule (they have :Elixir prepended to them) /trivia
Etc, if you are interested only in the syntax differences, there is not much difference there (there are obviously some though!). I think generally speaking Erlang has fewer libraries than Java so that is a big difference in my opinion.
One major difference between the JVM and the BEAM is the type of application they target. The BEAM is designed to implement Erlang so it supports everything necessary to run Erlang at the base level. It is concurrency, fault tolerance and scalability from the very bottom all the way to the top.
I doubt it. IMO Erlang is fundamentally a different model of programming than JS and what about mutability and things such as pattern matching? It quickly becomes apparent that it would not be much like JS if it was to take advantage of all of Erlang's best bits.
Const keyword for mutability and I have no idea about pattern matching. Just the js syntax would be great I guess. And special keywords to match what misses or misbehaves . Just a try. Won't be bad!
There have been "hints" that why don't I implement JS on top of erlang as well. Would love to try, and some of the problems have been solved in my luerl implementation, but the main problem is time, the lack of it.
Just give it a try and I think even if it's a limited subset of js it's still worth the try. If I can code in js on erlang vm for making distributed apps then it's going to be fun. Plus noobs like me get to know some stuff! Just ignore the naysayers and go for it! :D
Agreed. Well, with the date, anyway ;-) (though I am an SBCL user) Somewhere around 2000 we saw the end of AI winter. This most likely owes something to the fairly impressive Lisp marketing that PG did. Within a few years, several new Lisp books came out, and a few years after that we saw what the other poster mentioned: but not Just Clojure, a plethora of Lisps. To mention just a few: Clojure, Liskell, and LFE (LFE was actually started in 2007, first released in 2008). To the best of my knowledge all of these were completely unknown to each other at the time of their inception, and thus indicative of probable momentum in the wider Lisp community from an earlier time, possibly the once-again-growing acceptance of Lisp that started ~2000.
Then LispWorks was fully ported to Mac OS X (incl. Cocoa-based GUI and IDE) and there was then a replacement for Macintosh Common Lisp, which was given up and not ported to OSX/x86/Cocoa.
On the other hand, 1999 was the downfall of LISP in the statistical community because that's when Luke Tierney decided to stop working on LISP-STAT, a LISP dialect with extensions for statistics that was semi-popular before the advent of R. While there have been statistical systems based on LISP since (such as Incanter for Clojure and a port of many of the extensions of LISP-STAT to Common Lisp) none have managed to make a dent against R, unfortunately.
Users of maths software usually don't want to use Lisp syntax and are not ready to work in Lisp.
XLisp-Stat had also the problem that it used its own Lisp implementation, based on XLisp (upto Xlisp 2), which itself wasn't going anywhere. David Betz, the original author of Xlisp, rewrote Xlisp as a form of Scheme (Xlisp 3.0) and it died eventually. Xlisp-Plus, another Xlisp version, was mostly abandoned also in that timeframe - though there are updated versions available now.
Other math software, which had been ported to Common Lisp, is still maintained - like Maxima. The maintainers can concentrate on the application and the code is much easier portable to new systems because of a choice of implementations.
Had XLisp-Stat been fully ported to Common Lisp (actually a rough port of the Xlisp-Stat core to Common Lisp was done many years ago) and maintained there - at least the code would still be easier usable.
Having used early versions of Mathematica in university, I'm actually a huge fan of Maxima (a fork of Macsyma, the latter having been the principle inspiration behind Mathematica). I have it installed on several systems and use it now for all the things I used to use Mathematica. In fact, the CL source code for rational numbers in Maxima formed the basis of similar work in LFE (the horatio project).
I was very sad to find out that Xlisp-Stat had not been ported and maintained in CL :-/ ... perhaps a good project for a motivated, if fringe, *SoC project :-)
Sadly, I am old enough to agree with this assertion. I went from SBCL to ECL at one point looking for a small Lisp t embed or make games with, purely a hobby. I have not left the Lisp renaissance since!
> Ruby-til-Death programmers refuse to learn any other non-ruby-like syntax? It's like their brains would shatter into a brillion pieces
You've posted chest-beating things like this before, too. It's destructive to the community, so please don't do it. If you're smarter or more knowledgeable than other readers, use your greater power to improve the quality of HN, not degrade it.
Nope. Elixir was created because of the gap in functionality in Erlang, specifically around documentation and tooling as well as the lack of macros and polymorphism. [0]
The fact that it looks Rubyish at times is just the creator's aesthetic preference, but it wasn't the motivator.
> It's like their brains would shatter into a brillion pieces if they ever had to think about tail recursion.
Come on, man. Your anti-Rubyist bias is showing way too clearly. I switched to Elixir from Ruby (or rather, am still trying to move all my project work over), and I grokked tail recursion just fine.
> LFE is a nice project that grows as people use it without trying to form an army/cult around it like so many other languages do these days
No product (language or otherwise; trying to include Apple, here) ever "tried to form a cult around itself." That is just a natural happening when a new thing is really really cool. So discounting something because of its popularity is sort of an "argumentum ad populum" fallacy in reverse (arguing for OR against something because of its popularity).