Racket2 Possibilities
groups.google.com
groups.google.com
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.
That said, I consider Haskell to be a Lisp language. But, Haskell was designed from the ground up, from ML, to be as it is.
Out of curiosity: Do you think Julia is not a Lisp, or that Julia doesn’t work?
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."
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.
===
http://jmc.stanford.edu/articles/lisp/lisp.pdf
'lambda calculus' wasn't even explicitly mentioned. But he mentions s-expressions, list structure, multi-level lists, ...
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.
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...
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, ...).
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.
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).
And it remains to be seen for how long, given C++20, Julia, ML.NET, Swift for Tensorflow and other approaches using the same underlying native libs.
https://www.bloomberg.com/news/articles/2016-06-17/why-can-t...
Or perhaps it’s entirely apt.
Things become a little bit simpler (fewer pieces), with indentation syntax. I find that really beautiful.
As far as I can tell it can’t get any simpler than that.
https://github.com/breck7/jtree/blob/master/papers/paper3/co...
The team even implemented Newton OS ahead of the C++ team just to prove a point, even knowing that they would be out anyway.
Search for entries from wrs and mikelevins. https://news.ycombinator.com/item?id=15106802
I suspect luck, timing and fashion have a lot to do with language adoption; perhaps more than technical merit.
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).
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.
https://pdfs.semanticscholar.org/812b/92f2fa587ff78d727c7495...
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)
[1] https://github.com/weskerfoot/JLambda/blob/7508af2c9dcc4db02...
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
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.
[1] https://www.cs.utexas.edu/users/EWD/transcriptions/EWD13xx/E...
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.
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).
Disclaimer: I only know of it because I was looking for something similar once.
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.
Thanks!
Created an issue for it: https://github.com/breck7/jtree/issues/25
Hopefully someone else will take up the challenge, as I find that in person here at the center, often my colleagues explain it better than I.
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.
no more 'you thought you'd use regexp to solve one problem'
Prediction: in 10 years the most popular programming languages will still be C, Java, Python, Javscript, C++ and C#
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.
Am I missing something fundamental?
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.
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%yAs 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.
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: (repeat 5
(displayln "Hello, Word!")
(displayln "------------"))
(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.
[1] https://docs.julialang.org/en/v1/manual/metaprogramming/inde...
[2] https://docs.julialang.org/en/v1/manual/metaprogramming/inde...
[3] https://docs.julialang.org/en/v1/devdocs/ast/#Surface-syntax...
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.
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.
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.
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.
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.
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.
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.
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.
The evolution of projects and their environments is a difficult endeavor.
A Racket or SBCL hosted Clojure might be pretty cool.
It runs inside racket and can interoperate with other racket modules, and is straightforward to add to a racket installation.
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.
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)
- 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,
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).
(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.
AFAIK it works for any operator that takes two operands (or more, but it makes less sense to be using it with three or more operands.)
e.g:
> '(arg0 . operator . arg1 arg2)
'(operator arg0 arg1 arg2)How would it work if you had 2+ operators in one line?
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.)