News for hackers. Stuff that matters.
Re:Racket: Lisp for Learning by sdegutis on Thursday August 08, 2019 @11:40AM (#20645530)
Last week I tried writing a new Love2d mode for Emacs in Emacs Lisp, but it was on Windows so my muscle memory for Paredit wasn't helpful. Editing s-expressions is a nightmare without some kind of automatic help. Last night I wrote the same plugin for VS Code which used JavaScript, and naturally it was effortless. It got me thinking about how s-expressions are inherently hostile to non-customized setups, whereas JavaScript just uses arrow keys.

A former employer was led by huge Clojure fans, who requested that the backend be Clojure, and highly encouraged me to use ClojureScript and something like Reagent for the front-end, which I recently noticed that they finished after my departure. But the more I think about it, the more I can't think of a single feature of ClojureScript that's inherently better than JavaScript, whereas s-expressions are inherently hostile and also have no real-world benefits. JavaScript has destructuring, closures, a flexible module system, object/array spread, basically every syntactical feature Clojure has, but without the s-expressions.

The commonly touted benefit of s-expressions is homoiconicity (code is data), which lets the developer customize the language via macros without needing to wait on the compiler/interpreter authors. But we have this exact same benefit in JavaScript with compilers like Babel. Maybe it's pushed onto another layer of development, but it's in no way less legitimate or useful. The slight benefit you get by being able to do this transformation at runtime is negated by the inconvenience of s-expressions. (Although at first glance, it seems like we could use a better Babel API that lets us transform our code more conveniently. But I think they're working on that?)

The main other benefit I commonly see from people using Clojure or ClojureScript is live development. I saw technomancy made some blog posts about how he used Fennel (a Lisp that compiles to Lua) to do live-coding stuff in Love2d. I was impressed, until I realized that none of these features were specific to Lisp. So I borrowed the same underlying concept he utilized, and started to make a really cool Love2d live development thing just like he had, but in pure Lua.

Now I have the ability to press Cmd-E in VS Code while editing some Lua file, and if I have any code selected, it'll be sent to the live Lovd2d game that's running, to be eval'd, and if there's no selection, the whole current file will be sent. It's the coolest setup ever, almost identical to the awesome setup I had with CIDER + Clojure + Emacs, but without Emacs or s-expressions.

Re:Racket: Lisp for Learning by slifin on Thursday August 08, 2019 @02:47PM (#20647357)
"I can't think of a single feature of ClojureScript that's inherently better than JavaScript"

Persistent data structures, multi arity functions, multi methods, transducers, data oriented design, spec, repl driven, better live reloading, meta data, protocols, core async go channels, atoms, Datoms

There are breakthroughs in Clojure/Script that literally do not exist in any other language, let alone JS

Datomic, Fulcro, Crux, garden, hiccup, honeySQL, rebl etc just straight up don't have equivalents in other languages

Your statement blows my mind, sure you don't need s-expressions to do most the above but you can just turn on parinfer and treat it like python whilst still being able to dynamically rewrite source code using data manipulation

Re:Racket: Lisp for Learning by sdegutis on Thursday August 08, 2019 @04:47PM (#20648553)
Persistent data structures: Useful but you can get that in JS too, and if you can get your whole team to agree on it, you can avoid mutable data structures. I've been able to do that 100% for years now.

Multi arity functions: That's actually a minus, not a plus. The vast majority of the usages of this are solved with options params with default values in a much clearer way.

Multi methods: In 5 years of using Clojure professionally, I think I've never seen these used once.

Transducers: This is just an optimization, and I'm pretty sure it's possible in JS too since it's an API design.

Data oriented design: This is a design practice, it can be done in JS too, and it's a questionable one too.

Spec: When Spec came out is around the time I realized the period of true Clojure innovation is over, which peaked from around 1.3 to 1.5 or so. TypeScript is by far a better version of adding type innovations to a dynamic language.

REPL driven: You can do this in any language with a REPL, even JS.

Better live reloading: This is just as good in JS. There's no language feature of ClojureScript that makes this better than in plain JS.

Meta data: The only times I've ever seen this feature used was in storing internal representations of things in DSLs, which can be done in JS by using plain objects for their representations which store an inner object.

Protocols: JS only doesn't have this because it's duck-typed and they are implicit. An explicit counterpart exists in TypeScript's interfaces for those who want it to be explicit.

Core async, Go channels: These have to do with threading, but JS mostly exists in single-threaded runtimes, so it's non-applicable.

Atoms, Datoms: These are library-level concerns which are doable in JS.

Re:Racket: Lisp for Learning by dreamcompiler on Thursday August 08, 2019 @09:24PM (#20650552)
You're rehashing a couple of the most tired arguments Lispers always hear:

1. Parentheses are inconvenient.

2. Everything you can do in Lisp you can do in $other_turing_complete_language.

What you're missing in (1) is that as much as you wish you were stating an objective truth of the universe, you're really just stating your own subjective impression. If parentheses were objectively, universally inconvenient, nobody would ever program in Lisp. And yet many do. So what's the explanation for that?

What you're missing in (2) is that although (2) is certainly true, it's irrelevant. If (2) were relevant, nobody would ever prefer any Turing-equivalent language over another. And yet objectively, people certainly do. So what's the explanation for that?

The other thing you're missing in (2) is Greenspun's tenth rule, but I'll let you look that up.

Re:Racket: Lisp for Learning by kazinator on Friday August 09, 2019 @11:46AM (#20655420)
> So what's the explanation for that?

Why, they are impractical buffoons who lack the benefit of my own vast personal experience, which trumps everything. Or else blind zealots.

Re:Racket: Lisp for Learning by sdegutis on Friday August 09, 2019 @10:51AM (#20654880)
Novelty. That’s the explanation. People love novelty. Especially programmers who tend to get bored easily at their jobs.
Re:Racket: Lisp for Learning by dimovich on Friday August 09, 2019 @10:58AM (#20654955)
Yes, you can do all that in JavaScript using libraries. But in how many of your projects ARE you using all this? That's the question. And what are the steps you have to take and the cognitive load to make sure all the libraries you're using adhere to these conventions, and all the people that contribute code to your project also use the right paradigms?

When all these things are baked into your language, you're free from all the worries and cognitive load to make sure everything works as you expect it to work.

Re:Racket: Lisp for Learning by neilv on Thursday August 08, 2019 @11:58AM (#20645692)
> Editing s-expressions is a nightmare without some kind of automatic help.

I used to write C and C++ code in (non-vim) vi, with only autoindent, and it was fine. I could also type the spaces, if I had to.

For s-expressions, like in a Lisp, you want autoindent a bit more, and some kind of of paren-matching/highlighting is also important.

Fortunately, editors have been doing autoindent and paren-matching for decades. And once your editor is formatting your code correctly, it's pretty visual, not textual.

And few people write any code in something like non-vim vi or notepad.exe anymore, so I see no reason to think less of a language for wanting an editor/IDE developed in the last couple decades.

There's no need for paredit, AFAIK, but paredit is another thing for which s-expressions are especially well-suited, relative to most other syntaxes. (You can also do paredit-like structural-based navigation and editing of JS, for example, but you have to have a clear model of the syntax structure, not only in the tool, but also in the programmer's head.)

Re:Racket: Lisp for Learning by sdegutis on Thursday August 08, 2019 @12:16PM (#20645865)
I agree that a good IDE experience is a core part of the language nowadays. And in my experience, VS Code + TypeScript is by far the best IDE experience, far better than Clojure + Emacs ever was. A significant amount of productivity that I thought that combination was giving me turned out to just be a feeling of productivity because of how ninja the stuff I was doing was. Similar to how I'm faster in Emacs than I was in Vim, but I thought I was faster in Vim simply because the complexity or cleverness of the commands I was typing in before I learned Emacs.
Re:Racket: Lisp for Learning by reirob on Thursday August 08, 2019 @12:54PM (#20646191)
I am going quite in the opposite way. My IDE is getting more and more the shell, the VI(M) and the terminal based development tools (in my case mostly Haskell and Shell-Related). The more I work the more I am getting used to the terminal, get better usage of the tools. And strangely I find my screen more often to just have fullscreen terminal window.

I concede that I do not do any web or graphics development at the moment, this might help. But it's deeply satisfying to be able to discover new helpful functionality in the tools that are there for decades. And it's good to be able to use them almost everywhere, be it on a server over ssh or on a windows box with cygwin.

Re:Racket: Lisp for Learning by sambal on Thursday August 08, 2019 @12:42PM (#20646086)
I know it’s java, I know it’s big and bloated and gross but at some point give IntelliJ idea a chance if you like the ide experience of vs code & ts! It’s mindboggling coming from editors & terminals
Re:Racket: Lisp for Learning by pjmlp on Thursday August 08, 2019 @12:22PM (#20645915)
It has always been core part of the language experience on Amiga, PC and Mac platforms.

Just not on UNIX culture.

Re:Racket: Lisp for Learning by layoutIfNeeded on Thursday August 08, 2019 @02:17PM (#20647070)
On *nix the whole OS is your IDE.
Re:Racket: Lisp for Learning by pjmlp on Thursday August 08, 2019 @02:52PM (#20647399)
That is an old one, except it isn't a match for the integration an IDE is capable of offering, including the graphical capabilities.

Interlisp-D, Lisp Machines, Smalltalk, Mesa/Cedar, XDE, Oberon were an OS as IDE.

UNIX is a poor imitation of their capabilities.

Re:Racket: Lisp for Learning by scroot on Thursday August 08, 2019 @04:36PM (#20648428)
Smalltalk and Oberon especially are complete or near complete systems: they are described from top to bottom, and in some cases described in themselves.

Oberon is interesting because the 2013 book goes much further than any recent system in this regard. One of the (final?) chapters even describes how to implement the custom processor in an FPGA.

Re:Racket: Lisp for Learning by jmiskovic on Thursday August 08, 2019 @01:23PM (#20646482)
I've also came upon Clojure after investing much time in Lua/Love2d, but my takeaways are different from yours.

I enjoyed Lua's simplicity, portability and execution speed. It shares much of JS strengths, with fewer quirks. I was productive after a weekend of reading Programming in Lua book.

Clojure took some more time because I had to unlearn some habits. It's for the best, I think. It's not just about homoiconicity and REPL. In Clojure it's hard to do the wrong thing, compared to JS or Lua. The language makes it easy to isolate a small piece of functionality, develop and test it, and then and put it together into coherent whole. Clojure may be harder to learn, but the cognitive load is smaller and it scales better for large projects.

Persistent data structures are also huge step forward. They eliminate whole class of errors and allow for traceability and reproducibility.

As for s-expressions, yes, they can be a nuisance in editor without proper support. I'm getting by with SublimeText + zprint auto-formater. For REPL I found no better than Atom's proto-repl. Also I hated Lua's "if..then..else..end" and other verbose constructs. I'd say s-expressions are more consistent and compose better. Still, your frustration is familiar to me.

Re:Racket: Lisp for Learning by sdegutis on Friday August 09, 2019 @02:08PM (#20656884)
> "Clojure took some more time because I had to unlearn some habits. [...] In Clojure it's hard to do the wrong thing, compared to JS or Lua."

I've seen and even written a lot of really really awful Clojure code which technically fits the criteria for good code, on paper, but completely misses the bigger picture. (People have made the same argument for Go, that it's idiot-proof, but I've seen plenty of awful Go code too.) I'm more and more convinced that bad programmers will write bad code in any language and good programmers will write good code in any language.

Re:Racket: Lisp for Learning by frou_dh on Saturday August 10, 2019 @08:42AM (#20661732)
Thanks for making me aware of zprint. Cool that they distribute an AOT compiled binary, too!

BTW, for Sublime, you could install the Terminus package to get an integrated terminal to run clj(1) in. Then with a few lines of Python, you could write a command to send text from the editor side to the REPL side.

(I have a half-baked enhanced Clojure package with some features in this vein, but it's not public atm)

Re:Racket: Lisp for Learning by NikkiA on Sunday August 11, 2019 @12:18AM (#20666208)
Have you seen/tried fennel[1] or Urn[2] ?

[1] https://github.com/bakpakin/Fennel

[2] https://urn-lang.com/

Re:Racket: Lisp for Learning by jmiskovic on Sunday August 11, 2019 @05:52AM (#20667344)
I've evaluated both (and also lumen) briefly. I disliked the half-way approach that doesn't isolate Lua's messy state handling from lisp model.

Clojure also interacts with Java, but it feels like CLojure is the host that runs Java methods as needed. The separation is clean and you know exactly when you are crossing the boundary into stateful territory.

I see the value of those languages for lispers wanting to script the platforms where Lua can run, but not really as a core language for modelling your domain.

Re:Racket: Lisp for Learning by yogthos on Thursday August 08, 2019 @04:44PM (#20648514)
I consider stability, consistency, and simplicity to be very important features for writing production code. While it's true that you can do a lot of the same things you can do with ClojureScript in Js, the language and the ecosystem are vastly more quirky and volatile. I wrote regarding this in a bit more detail here [1].

As an example, my team has been using Reagent on the front-end for around 5 years now. We've never had to go back and change code to accommodate changes in ClojureScript or Reagent in that time. And we don't have to deal with stuff like JSX because HTML can be expressed using regular data structures. Things just work. Meanwhile, React itself has had many changes, and some of those are breaking.

I also find that tooling for ClojureScript is strictly superior. You get REPL driven development, reliable hot loading, minification, code pruning, and code splitting out of the box. All these things are difficult to do with Js, and don't work reliably with many NPM modules.

1. https://yogthos.net/posts/2013-08-18-Why-I-m-Productive-in-C...

Re:Racket: Lisp for Learning by sdegutis on Thursday August 08, 2019 @04:50PM (#20648588)
JS tooling has come a long way, and I've had pretty much all of these benefits by using Create-React-App within the past year. I don't remember ever needing to make project-wide changes because of an upgrade.

It's also possible to avoid JSX completely, thanks to a library that uses JavaScript's template strings feature: https://www.npmjs.com/package/htm

Re:Racket: Lisp for Learning by yogthos on Friday August 09, 2019 @12:14AM (#20651298)
Js tooling might've come a long way, but it's still a huge and confusing mess. It's not even possible to prune libraries reliably when you're packaging the code. Meanwhile, ClojureScript compiler will automatically prune any unused code down to function level, and it provides predictable minifcation out of the box. You also don't have to deal with NPM which has a major vulnerability every few months.
Re:Racket: Lisp for Learning by shaunxcode on Thursday August 08, 2019 @02:37PM (#20647275)
The thing is (and this relates to issue of racket changing surface syntax) - s-expressions are not just about the editing experience. They are about the reading/mental parsing experience. The less time I have to wonder about operator associativity rules (let alone magical language keywords/formats) the more time I can think about the actual semantics of the program being expressed. It always amuses me when using a mixfix language that the first thing to do when debugging a tricky math expression is to get hella parenthetical to make sure things are working the way you intend.
Re:Racket: Lisp for Learning by moomin on Thursday August 08, 2019 @12:11PM (#20645818)
You’re absolutely right: there’s nothing inherently Clojure/ClojureScript about painless hot-loading. But the fact remains that culturally, people care about it while getting anything done in TypeScript tends to require bundler fast.

Culture matters, which is why I should probably learn Rust...

Re:Racket: Lisp for Learning by dmux on Thursday August 08, 2019 @02:46PM (#20647349)
>The main other benefit I commonly see from people using Clojure or ClojureScript is live development.

I'm still learning about Scheme/Lisp, but doesn't hot-loading have to do with the size of "compilation units?" Isn't a single s-expression treated as a compilation unit whereas in a language like Java, the compilation unit is an entire Class?

Rich Hickey touched on this in a comment here on HN (2nd paragraph): https://news.ycombinator.com/item?id=2467809

Re:Racket: Lisp for Learning by nudpiedo on Thursday August 08, 2019 @11:53AM (#20645649)
The UI of an S-Expeession and a compiler transformation parse time transformation is just out of any comparison.

Most of projects wouldn’t even consider writing a loader for a compiler or using a syntax parser. Yet to add which method is more prone to errors.

Re:Racket: Lisp for Learning by sdegutis on Thursday August 08, 2019 @12:18PM (#20645877)
True but there's also things like Sweet.js, and non-s-expression languages have been able to get macros too, such as Elixir. I'm firmly convinced that s-expressions are almost pure novelty with no legitimate benefit.
Re:Racket: Lisp for Learning by aeorgnoieang on Thursday August 08, 2019 @07:45PM (#20650085)
I've been programming in Elixir for a few months now, and I like it a lot, but I found your comment amusing because a lot of Elixir's 'macro expressivity' seems to be due to Erlang using a data structure for its own parsing that can be readily manipulated as 'first class citizen' in itself. That's basically what s-expressions do. Apart from a small number of things that most people otherwise encounter in 'infix' notation, e.g. arithmetic, s-expressions seem to be a radically, and brilliantly, simple form of writing programs in a way that makes meta-programming as simple as possible.

(And, of course, meta-programming is powerful, thus 'dangerous', but there's a lot of things that are only really feasible with it.)

Re:Racket: Lisp for Learning by bitwize on Thursday August 08, 2019 @12:42PM (#20646083)
I evaluated Paredit while it was being developed. I thought it was a massive boon to working with Lisp.

Then, one day, I turned it off. I'm not sure why.

I think it's because I didn't want to get too attached to it. I reasoned that Paredit wouldn't always be in the places I was working with Lisp, so I had better remain flexible enough to not need it. And between the editor's paren matching and the way I format my Lisp code, I can be pretty productive in Lisp without Paredit or a similar structural editing tool.

Also, AFAIK Paredit is pure Elisp, so should work just fine in Windows.

Re:Racket: Lisp for Learning by sdegutis on Thursday August 08, 2019 @04:58PM (#20648685)
The modifier key positions are different on an Apple keyboard vs a PC keyboard, so my muscle memory is completely broken when using Windows since I got used to them on Mac.
Re:Racket: Lisp for Learning by lohithvvv on Thursday August 08, 2019 @09:31PM (#20650585)
You can remap keys (xmodmap for GNU/Linux, autohotkeys for Windows).
Re:Racket: Lisp for Learning by Arelius on Thursday August 08, 2019 @02:38PM (#20647292)
Paredit works great in Windows.
Re:Racket: Lisp for Learning by paines on Saturday August 10, 2019 @03:36AM (#20660727)
Could you share some more information about your Love2d development environement, please?
Re:Racket: Lisp for Learning by sdegutis on Saturday August 10, 2019 @11:05AM (#20662433)
Sure, I'll write a blog post about it next week and post it on https://sdegutis.github.io, check back there in a week.
Re:Racket: Lisp for Learning by paines on Sunday August 11, 2019 @02:16PM (#20669555)
Cool! Thank you!
Re:Racket: Lisp for Learning by sdegutis on Wednesday August 14, 2019 @01:01PM (#20697483)
Actually can you just email me instead? You're the only person interested in it and it'd be easier to just email you the details than to setup yet another blog post system.