The best way to kill a good Lisp is to remove the parentheses.
The people who complain about parens are still going to ignore your language even after you remove the parens, and then the Lispers will ignore you too. See Dylan.
This debate is exasperating. It's like hearing people say "I'm not interested in that Ferrari because it has a manual transmission." The only response to which is a silent, cold stare.
I was at Racketcon when Matthew first brought this up publicly. While it is a good way to kill a LISP, it is important to keep in mind that Racket is really an amazing workbench for creating new languages which interact with each other and being a LISP is mostly for the sake of making this easier.
In addition to that goal, Racket was originally created as a teaching language and continues to be used as such. Some people in the community see the odd syntax of LISP as a barrier to entry and would like to see if it would be possible to use a more Algol-like syntax for ease of learning while also preserving the properties which make it easy to extend and define new languages in.
Currently, there is already a distinction between parsing into s-exp and module-begin (i.e. all the interesting parts of your language) and this tech is already used to support languages which are based on s-exp and those which do fancier parsing such as the Datalog language.
Personally, I would rather keep Racket with s-exp and focus on cleaning up the weird stuff that is a holdover from scheme such as not having a consistent interface for comparators like there is for equal?, adding in growable arrays as part of the standard library, and not insisting upon an enormous block of end parents all on the same line (this is largely a product of the API for extending DrRacket being somewhat obtuse for indentation).
Regarding Racket being a teaching language, I'd like to make what I think is an important distinction...
I don't consider Racket a teaching language. It was created (when it was called PLT Scheme) as a very practical and powerful implementation of Scheme, for at least 3 purposes:
* implement multiple teaching languages (for incrementally introducing language complexity as a beginner learns);
* implement an in-some-ways powerful IDE that would run on all desktop/laptop computers students might have access to;
* be a programming languages research platform.
I have an interest in education, but am not interested in using educational languages myself. I've always used Racket as a practical language, for industry production, university research, and personal techie learning/experimenting.
I also thought about Dylan when I heard of this racket direction; and took another look at it; Open Dylan has tremendous documentation (a very enjoyable read.)
The compiler has been updated relatively recently to use LLVM; the command line programs run fine on Linux; I ran it on WSL2 and it seemed to work well there; it is a very nice and interesting language.
I suspect luck, timing and fashion have a lot to do with language adoption; perhaps more than technical merit.
I don't understand the deal with parens. Or significant whitespace. Or other similar "issues". Surely people have bigger issues when writing applications than where you put your god damned brackets or if they're curved or braces or whatever else.
Particularly when the "solution" to parens always seems to be significant whitespace, which is disliked by many as much as parens are by others. Both are just conventions that people get used to. I didn't care for significant whitespace when I first learned Python, but eventually I stopped seeing the problem, just as I stopped seeing the issue with parens in Lisps.
> That said, I consider Haskell to be a Lisp language.
Then Lisp (aka 'List processor') has lost its meaning.
Haskell is at its core a lazy evaluated, statically typed, purely functional programming language.
Lisp is none of that. The core of Lisp: an eager evaluated, dynamically typed, programming language supporting imperative, procedural and non-pure functional programming.
> But, Haskell was designed from the ground up, from ML, to be as it is.
Haskell was designed to have a common lazy language, instead of a dozen languages under development or in use (Miranda, Lazy ML, Clean, ...).
Why is Haskell a lisp? It is the first time I hear someone classifying Haskell in the “List Processing” family of languages, and although it does process lists I thought its main paradigma symbol and code representation goes in a complete different direction, more into pure function oriented programming.
When people say something "is a Lisp" that usually has little to do with list processing. It's about whether it inherits more from lambda calculus than from Turing machines.
Lisp literally stands for 'List Processor'. To claim that it has little to do with it, is really really strange. One of the main reasons to create Lisp was being able to compute with 'symbolic expressions', represented as linked cons cells in the form of lists...
McCarthy about Lisp:
===
As a programming language, LISP is characterized by the following ideas:
computing with symbolic expressions rather than numbers, representation of symbolic expressions and other information by list structure in the memory of a computer, representation of information in external media mostly by multi-level lists and sometimes by S-expressions, a small set of selector and constructor operations expressed as functions, composition of functions as a tool for forming more complex functions, the use of conditional expressions for getting branching into function definitions, the recursive use of conditional expressions as a sufficient tool for building computable functions, the use of lambda-expressions for naming functions, the representation of LISP programs as LISP data, the conditional expression interpretation of Boolean connectives, the LISP function eval that serves both as a formal definition of the language and as an interpreter, and garbage collection as a means of handling the erasure problem. LISP statements are also used as a command language when LISP is used in a time-sharing environment.
The Lisp community has moved on from McCarthy's taxonomy. In McCarthy's day, there were two high-level computer languages (Lisp and Fortran) and now there are thousands. Today we have different notions of what constitutes a "Lisp-like" language and what doesn't. By McCarthy's strict definition, Clojure is not a Lisp because it doesn't use real cons cells. But I think most people nowadays would agree that Clojure belongs in the Lisp family more than in the Algol family.
Haskell has (very!) first-class functions and is even more naturally compositional than most "classical" Lisps. It feels to me like a Lisp with static typing, laziness, and automatic currying cleverly incorporated.
Likewise Javascript. Javascript feels like a Lisp to me because it has lexical closures. It gets in my way because its syntax and many other design choices are terrible, but it still feels like it descends from lambda calculus.
I guess my point is that whether a language is a Lisp or not can't be reduced to a simple list of bullet points.
Neither Clojure, Haskell nor Javascript are Lisp. Haskell and JavaScript are not even directly derived from Lisp.
Your idea of Lisp lacks any concrete features and suddenly all languages would be Lisp: Prolog, Haskell, ML, SML, Javascript, Java, ... all of them have sone form of functions.
This then is arbitrary. Lisp is a family of languages which share concepts and code. There are a number of concepts (you call it bullet points) which make a language a member of the Lisp family in a wider sense and it may not be that all members share all concepts, but MOST and the important ones,
Haskell for example is very very different from Lisp: syntax, semantics and pragmatics. There is no way one would consider Haskell a member of Lisp languages. Lisps are not statically typed, they are not lazy, they don't use currying, they are not side effect free, etc. If a languages has all these features at its core, it's not Lisp. Claiming that it is Lisp is just creating confusion. Give a student a Lisp book (say Peter Norvig's PAIP) and a Haskell compiler: nothing runs, the concepts and architectures are different, the development style, basically everything.
Pure Functional Programming has been split from Lisp decades ago in the 70s and 80s and we have now thousands of language camps (not just two: Fortran and Lisp). The core of Lisp is still the same:
List processing, dynamically typed, a specific form of evaluation, garbage collection, s-expressions with symbols, code represented as s-expressions, built-in code transformations over s-expressions, procedures are called functions, higher-order functions, eager evaluation, optional interpretation of code in the form of s-expressions, interactive development with read-eval-print-loops, etc etc.
From there new languages families have been forked or maybe only influenced: purely functional PLs (Haskell), logic languages (Prolog), object-oriented languages (Smalltalk, Self) and many others.
Smalltalk is also not Lisp, even though it got stuff like images, GC, blocks, interactive interface, and others via Lisp influence...
You are missing quite a bit of context on the history of Haskell. From https://www.microsoft.com/en-us/research/publication/a-histo... , it seems that Haskell's design did not arise out of Lisp, but out of several languages in the early 80s which were lazy/non-strict and purely functional.
Indeed, removing parents ruins the perception of Lisp languages as just another language family, and promotes Lisp into some sort of privileged position. Simultaneously, mistaking Haskell for a Lisp means mistakenly thinking that Haskell has special meaning for pairs over tuples or lists, that Lisps are statically typed or that Haskell is optionally typed, that Haskell has macros, that Haskell's juxtaposition-based application syntax is related to Lisp's parenthesis-based application syntax, and so on.
Consider example Lisp memes: "Data is code; code is data," or "all structures are lists." Compare with example ML memes: "If it compiles, it works," or "well-typed programs don't go wrong." Or even better, with Haskell memes: "Laziness leads to purity," "monads are programmable semicolons," "show me your types."
The only meme common to these communities is "lambda the ultimate", and you are ignoring decades of Lisp philosophy if you nominate this meme to carry the flag for all of Lisp. When I first read this comment tree, I wondered if everybody had forgotten about the Land of Lisp and the Republic of Haskell: http://www.lisperati.com/landoflisp/panel01.html
I consider Haskell to be an ML, and even then, it's worth remembering that lazy/non-strict MLs have different behavior from the rest of the family.
Completely agree. Haskell is IMO the only paren-free Lisp that works. As you said, it was designed that way from scratch, not as an afterthought from s-expr syntax. I also think automatic currying and pervasive laziness contribute a great deal to making the parens unnecessary, and most Lisps don't work that way.
I know Julia was originally a Lisp and it incorporates a lot of Lisp ideas, but I've never used it so I have no opinion about how well it works.
Lots of Lispers consider Javascript a (primitive) Lisp because it has lexical closures, but I think its syntax is horrible and thus (IMO) it doesn't "work."
Apple was not a unicorn that could single handedly force changes among developers then. Julia has plenty of funding and is pretty much a syntactic clone of Dylan (cleaned up somewhat) and it's trending on HN every other day.
Julia isn't that much positioned as an AI language, it's more of a numerical analysis and scientific computing language at this point competing with matlab, which is something that doesn't go through hype cycles. The fact that it's so well positioned for AI research is the result of that focus (high performance, expressive, interactive and math focused) plus being heavily inspired in Common Lisp, which means the language can be easily extended for new purposes (and CLOS was a brilliant system that didn't get the attention it deserved in the mainstream).
Python is the AI language, and it's already more than large enough to survive many AI winters (plus "AI" is more powerful and useful every winter).
I am not a fervent Lisper, but dropping the parentheses will take me away from the times I do go to Racket, and just go back to SBCL or Gambit or Chicken Scheme. The article admits it is to try and win more share of users, but that is not a good reason for a predominantly academic language. I would even go to Haskell, which avoids success at all costs ;)
Ironically, I think most of Racket's popularity is driven by its Lispiness. People want to get into this 'Lisp' stuff and everyone recommends Racket. I personally learned Racket because as a dumb teen Googled "how to become a hacker".
The first result was Eric Raymond's article How To Become A Hacker, which recommended learning Lisp. I looked into Lisps and ran into the book How to Design Programs which recommended the IDE DrRacket.
The idea is basically to remove implicit `(begin ...)` and then remove the trailing parentheses from many things.
For example:
```
(define (f x y)
(* x y))
```
vs.
```
define (f x y)
(* x y)
```
It works because now you can only have a single expression as the body.
Similarly you get the same kind of thing with many other forms that have `begin`.
It also proposes adding some new syntax for various things, replacing `begin` with `do` and a bunch of other stuff related to indentation. You can easily pick and choose which parts you like though and still get some benefit, which is what I like. And it is still homoiconic.
If I wanted a quick and dirty way of making lisp "more readable", then this is what I'd do.
I even created my own half-assed implementation[1] of this idea years ago (In JavaScript). Disclaimer, it's really messy and incomplete code from when I was just learning how to write parsers/lexers/etc. One other idea I implemented was the ability to mix infix and prefix expressions. I'm not sure if I still think it's a good idea, but it worked (it had to know whether a token could be interpreted as a binary operator ahead of time and it was a bit janky, but you could even add your own custom operators)
I trust M. Flatt to know what he's talking about but really the 'potential users 'argument has always been weak to my eyes (both in breadth and depth).
prefix nested parens are ultra generic, I bet those who don't like that won't like the genericity of the paradigm and idioms either, no matter how mainstream the syntax
Dijkstra's last published thoughts on the merits of infix notation for associative operators come to mind[1]: "It made me realize why I like it so much for associative operators: it allows us to write p+q+r without being forced to choose between (p+q)+r and p+(q+r); in prefix notation, the choice between ++pqr and +p+qr would have been unavoidable."
This show the obvious merit of parenthesis for prefix notation, since then one can write (+ p q r). In essence, the + operator distributes over the operands.
I'm not totally against Racket without parens, but to gain popularity this seems not to be the first action should be taken. Like IDE, tooling, libraries/ecosystem improvements.
For example, the documentation is really great, but Drracket is only good, not great. Probably good VSCode integration would help a lot, since not everyone is using Emacs for serious work.
Instead of moving to a new market, with more potential users - but also with fierce competition - it makes more sense to stay where they are and invest in "being so good that they can't ignore you" by investing in quality, and that means outstanding tooling and ecosystem.
Recently somebody in HN also noticed the need for a "browser scheme" to take advantage of code and data being the same. That might be also an interesting path.
Prediction: In 10 years the most popular programming languages in the world will not use the current BNF or () style syntaxes but instead will use Tree Notation (with Racket like "Language Oriented Programming" on top), OR will use some other "black swan" syntax that I haven't seen, that is even better than Tree Notation...
I think we're all going to learn that syntax does indeed matter, once machines are writing most of the code.
I'm willing to give even odds for that bet, if there is some type of charity betting site that supports that sort of thing, if anyone disagrees. (Even if you don't disagree, it would be silly to not take that bet for even odds, given fewer than 500 people are actively using Tree Notation today).
> Prediction: In 10 years the most popular programming languages in the world will not use the current BNF or () style syntaxes but instead will use Tree Notation
Prediction: in 10 years the most popular programming languages will still be C, Java, Python, Javscript, C++ and C#
This is pretty neat! It seems to be a kind of DSL for making DSLs. The new language is defined in a grammar file and files written in the language can execute directly by adding implementation code to the grammar definition in the form of snippets of js/python/etc associated with the kinds of syntax you define.
The syntax of everything is the same: a of tree of tokens. If that sounds like a broad definition, that's because it is. Afaict the only required syntax is that the tokens form a tree; your dsl can assign arbitrary meaning to the actual structure.
This might be something I could use at $work, I bet it would fit well into an automation framework. I feel like if I knew some lisp it would give me a different perspective on tree notation.
Oh, neat! I did not know longbets was an open platform.
I'll post something on there. It will actually be a good exercise, because I should clarify things like "no, I'm not predicting this will be more popular than Excel", which I would agree is a programming language.
Please do and link it here! (For posterity). Fwiw, unless you mean something much narrower than I interpreted your statement to mean, I’m taking the other side of your bet :).
I'm interested in this kind of thing and followed the links, but I didn't learn enough to decide whether I like your tree notation or not. It might help to write a tutorial just explaining informally what the notation is and what the rules are for using it?
Very interesting. I was recently thinking that it would be nice to have a common language that would compile to many others (at least to a subset of many others).
Do you understand the concept of abstract syntax trees? This already exists in every language and we specifically and deliberately moved away from it because it's not conducive to code.
I think this library is more about a shared common AST representation in order to share some tooling around it and fast prototyping for DSLs. After I read the FAQ I agree with your sentiment, in the way it is documented and worded it sounds quite arrogant to be someone who just discovered the wheel.
I read the post and all the comments here, where people are very adamant about their opinions on parens. It seems to me that while syntax is important, parens in this context is about as close to "just syntax" as we can get. Racket-sans-parens would still be Racket.
From a practical standpoint, basing everything off balanced parens (or square brackets, that makes no difference to me) makes the language much easier to write in. Being able to jump to the matching paren makes it trivial to copy/paste blocks of code, delete code, replace code, etc. It's so much easier than with things like Python. For instance, from the first line of a block of racket, copying that block in vim (not an editor known for being well suited for lisp) is as simple as %y. How do you do that in Python? If you know you're after 5 lines you could do 5Y, but that requires you to count how many lines you're after. You could use visual selection mode with V and then highlight the relevant lines, but that is more keystrokes than %y. You can get extensions for vim that create concise movements for dealing with indented blocks of python code, but with lisp no such extension is necessary. Even in vi-compat mode or things like Busybox's vi implementation that has no extension support, % works.
What's it like for C? A little bit better than python, but worse than lisp. Consider this block of code:
if (foo) {
...
}
How can I yank that entire thing, if my cursor is on the first character of the first line? The obvious answer to me is v$%y, which is pretty convenient, it doesn't require counting, but it's also fragile. What if that opening squiggly brace was on a new line? Then I'd have to do something like vj%y
As far as I'm concerned, despite vim being considered a second rate editor at best for lisp, lisp is arguably still the language vim is best suited for, and that's entirely a consequence of the fundamental usefulness of s-expressions.
IMHO the main problem are macros. Macros in racket/scheme/lisp/clojure are very powerful. You have the complete language available to make any transformation you want.
The idea is that the language look like an AST written as a list of list, and the tools to write macros look like some pattern matching to transform lists of list into lists of list. (In spite they are not lists of list but syntax objects that have much more information.) (And you are not forced to use some subset of tools, you can write arbitrary code in the macros, but some tools make the common tasks easier.)
For example, to create a new macro that run some block of code n times, you can write
(define-syntax-rule (repeat n boby ...)
(for ([i n])
body ...))
and now you can use that as if it is part of the language:
(Note that, you don't have to worry that the counter i in the macro will overwrite a variable i in the main part of the code.)
Nobody is sure where is the magic, but writing macros is easies because the code in the main program and the patterns in the macro look very similar.
It's more difficult to work with a language with more syntax. Is the code desugared before going to the macro? Can you use some sugared version inside the macros? Does the user have to learn the main sugared version of the language and then learn the desugared forms?
What if one of the "arguments" of the macro is an infix operator? How does it interact with the other operators?
What if you have two interoperable languages running side by side? Racket ships with something like 10 or 20 internal languages, and you can download 5 or 10 or 20 or 1000 more. And all of them are (somewhat) interoperable. So you can most of the time use the libraries written in one of them in the other. You can even share macros between languages.
What if you have two interoperable languages running side by side? What if you write a macro in the sugared language and try to use in the other, or vice versa? Does they work? How?
Nobody is sure about the details, but Matthew is optimistic that this is possible, and he is usually right.
At least in Julia, which is a Lisp-inspired language without s-expressions, what you have is a dual representation for all code [1] in which you can manipulate either directly on the normal infix notation with quote and unquote, which is good for code injection [2], or in the s-expression-like representation (Surface syntax AST) [3] in which you have the full control over the structure but you have to deal with a different syntax. Using the s-expression-like is more powerful, but for the function user it doesn't really matter which you use.
The semantics are much, much, more important for sure.
I think the “language oriented programming” semantics of Racket are brilliant.
I’ve been working on this syntax question for 7 years, now full time at the Tree Notation Lab. I think there is a better way to do the syntax, which over time will have strong network effects, which will allow us to code faster and have more reliable code. But you are right, perhaps this will just lead to a 20% across the board improvement in programmer productivity—-the bigger improvements will always come in the semantic realm. I think the thing to keep in mind is that only a tiny amount of people are focused on the syntax issues, they just like to shout at each other.
This just now settles that anyone wanting to use Lisp to do anything practical has only one option: Clojure.
It's a shame, because Racket had the promise to be something really useful. Also throwing your dedicated 1% users under the bus, to attract 99% users who won't use your tool no matter what, is bad idea from a product management perspective.
I honestly feel f# has won the ML family language wars, and you won't be able to do much there. Even if you have decent ideas, you still have to solve the library problem. And yeah, given how scanty your user base is going to be, not many are going to write books either.
The fact that they even consider this idea seems shocking to me, let alone announce such a thing on a mailing list.
Calm down. They're not throwing anyone under the bus. The post starts with "No matter how Racket evolves, the community is committed to preserving what we have achieved: today's `#lang racket` programs will run in the future, and today's `#lang racket` modules can be used in future Racket programs".
Also, basically the point of Racket is solving "the library problem". Every fancy new language you make in Racket has access to every library ever made with Racket.
>>"No matter how Racket evolves, the community is committed to preserving what we have achieved: today's `#lang racket` programs will run in the future
So to put it clearly, the current programs would run, but no new features, fixes and enhancements.
Basically you can't use it for anything production.
>>Every fancy new language you make in Racket has access to every library ever made with Racket.
Libraries, means more number of libraries for the same language. Not same number of libraries for more languages.
In Racket, it's the same thing. Racket #langs are interoperable. Which is why it's untrue to say "no new features, fixes and enhancements". Any improvements to the semantics of the language will be usable from both #lang racket and #lang racket2; any libraries written in #lang racket2 will be usable in #lang racket. This is merely a proposal for an official alternate syntax, which you are entirely free to ignore. It doesn't take anything away from Racket to have this.
Bear in mind that Racket already comes with a plethora of officially supported #langs, many of them with highly non-lispy syntax. The ability to do this is a major part of Racket's unique value proposition in the first place.
At this point, it's not necessarily just an alternate syntax.
Given that, #langs can be interoperable, and are encouraged to be, but not necessarily.
For a simple real-world example of interoperability problems, of the kind we could plausibly encounter between two very similar #langs... Consider that RnRS Scheme wants to use mutable lists, but modern Racket wants to use immutable lists. Code in the two #langs might even look almost identical, and even use the same names and calling conventions, but in practice you have trouble interoperating.
There's also factors like: what syntax is in the documentation everyone reads. If all the manuals people see are in a new syntax, the old syntax effectively becomes a dying language, whether or not it's still implemented.
With priorities and/or work, we can support a high degree of interoperability, as well as keeping the current syntax genuinely supported, but we shouldn't assume we get that for free. Nor should we assume it will happen, unless we make it a top requirement that's tracked and remains a consideration in every change.
C'mon. This is splitting hairs. No one doing anything serious, changes their language syntax for their production code overnight. Just think of what this could possibly mean for those people. They need to retrain their people on the new syntax, new ways of maintaining them and who knows what other regression comes along with it(Test cases, deployment, libraries, performance etc). All of this for 0 gains, when better programming languages committed to maintaining backwards compatibility exist.
I think we should settle for the fact that Racket is more like a toy language for teaching purposes. That is ok, given its use case.
> "From a community perspective, the rub is that the "many people" for Racket syntax is a barrier are mostly people outside the community. It's fair to ask who would benefit. It's difficult to ask a community to tackle a problem whose solution targets a different community."
Yeah no shit, alienating the 1% of the general population who uses your tool to appease to the 99% who don't currently use it might work sometimes, but you could just as easily lose that 1% and pick up jack shit, because the grassroots advocates for your language just evaporated. Dropping s-expressions from the primary lang would likely prove to be the kick in the ass I need to switch to CL.
(Other proposals listed sound a lot better. This syntax matter is my one serious grievance here.)
Edit:
> "From what I've seen there is no advantage that editors can give you with parens, that they can't do better without parens, given that you've written loads of tests and done the grunt work to make that happen."
This seems like one of those cases where lack of editor diversity among a lisp community once again threatens to cause trouble for anybody who doesn't use emacs (see also: terrible default REPL experiences because the devs all use racket-mode or geiser-mode.) What am I meant to replace the % command with when using vim or evil-mode? I don't want to do "loads of gruntwork", nor do I wish to rely on editor extensions for a matter that should be so straight forward. I want to press % and jump to the matching paren.
I think there are lessons to be learned from Python, Perl and Osborne [0].
New and arguably better things aren't created in a vacuum. They are perceived and judged in their context. Irritating users of A with A' can handicap the env of A as well as the env of A'.
I think this is often not thought about well enough.
Forgive me if the answer to this is already widely-known, but at this point is Racket making a play to be a general-purpose, "batteries included" Lisp, rather than a stripped down tool for PLT stuff and making languages? It seems like there's room in the market for something like that. A bit like Clojure, but without all of the big design commitments that Clojure makes, like the deep integration with Java and focus on immutability.
It's already been positioned as a batteries included lisp and arguably has had the best standard library offering + documentation for it of any lisp out there. This move has nothing to do with that, but rather the possibility of having less (to some) off-putting syntax.
I think Clojure commits to being a hosted language with a pragmatic attitude to the underlying platform, rather than committing to Java. It keeps the JVM / JS / .Net layer accessible. Sorry for the nitpick but I think it's an important nuance.
A Racket or SBCL hosted Clojure might be pretty cool.
Other comments make it sound like dropping parentheses is just a craven attempt to make Racket more popular. To me, this epitomizes the distinction that the maintainer drew between trying to get more popular, and lowering barriers of entry. If Racket 2 is no more popular (it loses as many community members as it gains), but the new community members had an easier time joining the community yet still love Racket 2 just as much as the old community loved Racket 1, isn't that still a win?
Conversely, if it turns out that everyone loved Racket 1 not because of the design elements that the maintainer put so much blood, sweat, and tears into, but because of the high barrier of entry due to the parentheses (the one thing that the maintainer didn't put effort into), how is that at all motivating to the maintainer?
I'm less of a community member and more of an admirer of Racket from a distance (and I don't mind parentheses, really, I've used Clojure professionally and it was great), but I look forward to seeing how this initiative turns out.
From some of the comments it feels like this is also intended as a way to research different ways of doing Lisp surface syntax without sacrificing the features of the macro system. I'm not sure if it's possible to do both at the same time.
Did you miss the "How?" section of the post? He wrote a research paper showing it was possible in 2012, "Honu: Syntactic Extension for Algebraic Notation
through Enforestation".
Ignorant question: What's Racket's value proposition beyond being a well maintained Lisp?
What's this Language of Language thing, and is it so awesome that I'd be tempted to learn Racket only for it? Since otherwise its syntax and semantics might be too similar to say Python? (Assuming it drops all the Lispy stuff)
I look a few times to racket in the past. It's distinctive features are:
- Pedagogy first: easy to learn, cute visual tutorial with support for desktop UIs, nice tutorials on the language itself and how to learn several aspects of programming such as sockets etc.
- Very Easy to write a programming language on top of it by creating a new lisp reader (#lang) which transforms the given code and makes the access to the rest of racket's ecosystem very easy.
It is not industry-focused, therefore you might end up frustrated if your main/only goal is to write single web applications or you need good support for commercial libraries, databases etc. On the other hand in software everything is possible so you could always find your way to access those libraries and leverage the existing ecosyste,
React is a perfect example of a lot of Racket’s value proposition. JSX is a mini-language created as a way to write XML which interacts bidirectionally with JS in a seamless way. While it takes quite a bit of effort in JS to create all the tooling for this DSL including not only compilation but also making sure it stays editor friendly, creating something equivalent would take an afternoon in Racket including having sensible error messages and syntax highlighting.
I chose JSX in particular since it really highlights how useful it can be to have seamless interop between languages. Another really interesting #lang for Racket is Rosette which is IMO the easiest to use interface for SMT solvers out there since the code you write is regular racket (it even supports recursion via symbolic execution).
Having followed this fairly closely, I will drop a though here while it is in my head. Surely there would be no obstacle to supporting s-expression syntax and allowing additional syntax around it. Everyone seems to see this as either-or, but is it really truly impossible to have a set of rules that say "you can't start a valid sexp with `(4` so this must be the start of an infix expression" and "you can start an sexp with `(add1` so I'll keep going"? Yes there will be a cost in the reader, but moving away from sexps is already going to be costly in that sense. Further, if we are going to incur the cost of a major complication of the parsing implementation, then why not go all out and allow interleaved expressions? What are the ambiguous cases that make this impossible?
I've always wondered if a good way to do infix would be to simply have the ability to mark an item with a character that means "move this to the front of the expression." Let's say the char is ":". Then this:
(1 :+ 2)
Would be converted to this:
(+ 1 2)
It would also allow for arbitrary placement, so you can do goofy stuff like pretend to be Forth without writing custom macros for the situation:
(1 2 3 4 5 :+)
Whether or not that part is an advantage is another story ;)
This doesn't solve the "too many parens" problem, because you still have parens, but it does solve the "prefix math looks weird" problem. It's quite a bit simpler than what Dylan does, in that there's no special concept of "binary operators" and it's obvious at a glance how everything converts to sexps.
Ah, interesting—thanks for pointing that out. That is practically the same thing. I only wonder if the fact that it's two dots tends to discourage it from general use for things like arithmetic, compared to a single character.
You could do this in Racket by messing with #%app. Supporting arbitrary infix operators could be a bit tricky, but just doing standard math ones wouldn’t be too difficult.
FWIW, the angry negative responses to removing parenthesis from the community would be a much bigger obstacle to adoption than the parenthesis. Nothing is going to turn me away from a technology faster than a hostile community, especially for a programming language, where the ecosystem is both an important asset and an investment you make when you choose a language to write in.
And I’m serious: I adopted Go early on for it’s ecosystem and community. Rust was harder in part due to its early negative reputation for overzealous fanatics, which thankfully no longer feels like an issue (and the ecosystem is getting there, too.)
The people who complain about parens are still going to ignore your language even after you remove the parens, and then the Lispers will ignore you too. See Dylan.
This debate is exasperating. It's like hearing people say "I'm not interested in that Ferrari because it has a manual transmission." The only response to which is a silent, cold stare.