6 ms·
Lisp - It was one of my first few languages, but really learning it damaged my view of everything else. To use a real Lisp machine, Lisp debugging/backtracing,
by optionalparens 10y ago
Lisp - It was one of my first few languages, but really learning it damaged my view of everything else. To use a real Lisp machine, Lisp debugging/backtracing, and have code as data was such a huge win over writing ASM, C, Fortran, and the many other languages I used a lot back then. I still feel almost all other languages are catching up, while Common Lisp itself I felt got ruined by a lot of nonsense even though I still use it sometimes. So both excitement and disappointment here. This is where I really learned to use functional programming and became productive. All of my code since, even in OOP takes things I learned here like data first, preferring operations on lists/sets of data, and meta-programming. This is also where I learned that syntax really doesn't matter and people while they might have preferences, they are generally too caught up on syntax for the sake of it and not what it can do for you (ex: code is data, macros).
Smalltalk - Some of the best ideas in CS that were warped, misunderstood, or ignored. Commercialism at its finest killed this and ruined the ideas from it. The productivity in this language was huge for me and the environment was and still is a wow. The aesthetics have almost always been awful though so it really bugged me that no one ever gave a practical instead of theoretical effort to improve here. The day I saw things like Gemstone Smalltalk dumping entire running states into a bug tracker and then clicking on the issue and being thrown into the debugger was one of many incredible moments. A lot could be improved, but like Lisp, lots of imitators and few equals. In terms of impact, this really led to me truly learning OOP at a higher level and made me think about code entirely differently - as a living, breathing, environment that was somehow more real than what Lisp offered. The separations from the OS into its own world made it both incredible (I still feel like using files 1-to-1 for code is nonsense) and a pain to use (ex: integrating proper source control and existing tools because of files issue).
Clojure - Finally a practical Lisp-like experience that I don't feel like a crazy person trying to "sell" to coworkers to use on a project. Lots of things here I don't like, but even the author of the language agrees with me on most of those. I like the pragmatism, honesty, openness about what is good/sucks, and more here. It's really productive for me and I feel less in Smalltalk and Lisp land. The moment was like, "Rich Hickey, OK, this guy totally gets it."
Emacs - I hated it at first, but when the concepts started to sink in for me, it made so much sense. Licensing and politics aside, it's pretty incredible. I wish there was less crust or a way to magically rewrite it and have all the good add-ons also magically rewritten. It truly is its own OS for better or worse like Smalltalk, and can be used and abused accordingly. It just still makes so much sense to me in both Smalltalk and Emacs that I'm writing code and I can use code to do things to my editor, both in terms of add-ons and while it is running (ex: if I need a special toolbar, window setup, whatever).
Acme - It's an ugly editor, but wow it's full of great ideas. I didn't particularly enjoy the mouse chording but everything else is amazing. The relationships it had with the system using it in Plan9 just made it so powerful and full of possibilities.
Overall, my best decision to improve my work was to stop listening to the masses and just try to do my own thing, with confidence. That doesn't mean just anything, rather it means follow my instincts and balance things with a healthy dose of pragmatism and extreme skepticism. That also meant ruling out new and shiny things as well as old and awesome things like Smalltalk and Lisp on many projects. Once I learned the difference of being a contrarian vs. an educated independent thinker, I became both tormented by how terrible most software is and encouraged to think completely differently and abstractly about it all. Still trying to do some great things with that attitude, and it's more the non-technical daily life struggles that are the real challenge.
- petagonoral 10y ago>Lots of things here I don't like, but even the author of the language agrees with me on most of those. Working with Clojure..would be great if you could expand on these. Curious as to what they are/Rich agrees with. I find Clojure lacking when it comes to debuggabililty. In so far as everyone in my medium-ish non trivial codebase seems to find 'clever' solutions that are all but impossible to debug efficiently without a) understanding everything around it and b) printing everything. Debug statements seem to "ruin the cleanliness" (as well as genuinely ruining threading macro flows. Do other companies use Clojure for non trivial web applications? Have these Clojurians ever worked on a properly complex system? A lot seem to do just data analysis with Clojure. More importantly, have they ever worked on a properly complex system that they haven't been involved with from the start where debugging comes back to 'intuition' and 'whack a mole' type debugging?
- optionalparens 10y agoWow, lots of questions. I am exhausted but will do my best to provide an initial answer. > impossible to debug efficiently without a) understanding everything around it and b) printing everything. Debug statements seem to "ruin the cleanliness" (as well as genuinely ruining threading macro flows. I've never once had to add a debug statement to my Clojure code, not sure what you are doing honestly. You can easily debug with Emacs + Cider which allows setting breakpoints, inspecting, and evaluating forms while debugging. This is much more than debuggers in many languages. Further, you can also use Cursive + IntelliJ which gives you pretty much the same thing, only more like most people who have done Java, C++, or C# are used to in the various associated IDEs such as IntelliJ, Eclipse, Visual Studio, (or Emacs/Vim for that matter) etc. Given the data you are dealing with most of the time is immutable, things couldn't be clear IMO. The only time I find myself printing things is in the REPL. A few years ago I did this more often in Chrome in ClojureScript, which mostly goes away now with one or more of nREPL, Nightlight, Figwheel (or the many similar libraries). In fact I'd say the debugging situation here is better than most languages because you can instant eval things as well as live code, and see those changes immediately in the browser. Regarding threading macros, I assume you're talking about (->, ->>, ->as, and so on). Again, you can just eval these partially in the debugger, and worst case, bind something to a value you set in the debug session as you would in a plain REPL session. I would agree these are harder to step through. If for some reason you meant macros in general, I'll repeat what I always say to new Clojure and Lisp users in general - do not write macros at the start, and when you do, question the reasons why you are doing so. Macros are insanely useful and powerful when you need them, but most of the time you do not for the average app (obviously many exceptions). Worst case, you can macro expand, paste that, and debug or debug the macro expand in an debug eval. Overall, I've found debugging to be substantially less pleasant in most languages that are popular such as Python and Ruby vs. Clojure but less pleasant than say Smalltalk or a Lisp machine. Like many languages, the situation with Clojure improves over time. People complain about the stack traces but most of the time they don't bother me and each version has improved on that. I came from the assembler, C, Fortran, Lisp world, so in some ways that has made me more keen how to write code that is easy to debug and to not fear debugging. > Do other companies use Clojure for non trivial web applications? Have these Clojurians ever worked on a properly complex system? A lot seem to do just data analysis with Clojure. More importantly, have they ever worked on a properly complex system that they haven't been involved with from the start where debugging comes back to 'intuition' and 'whack a mole' type debugging? Yes, there are various lists out there if you Google some. A brief list: Amazon, Netflix, Pivotal, Walmart, Heroku, Factual, Capital One, Roomkey, Spotify, Soundcloud, the list goes on. I think it's fair to say at least one has a complex app and at least one is a not for data analysis. Clojure is quite often used at very large companies that are almost surely building systems more complex than yours (no offense, just basic probability). Saying Clojure seems to be used mostly for data analysis and therefore implying it might not be good for web apps is like saying that about Python, which in fact is used more than Clojure for data analysis. Regarding, web applications, by nature they are trivial compared to many domains. Of course you can make things complicated by adding a lot of moving parts, but these things are usually complimentary to a web app (ex: stream processors like Spark, Storm, Google Dataflow). You can also make things more complex than they need to be by bolting on frameworks and trying to shoehorn your business and code concerns into it. This is one reason some people like lighter frameworks for some purposes and heavier for others (see Django vs. Flask for instance). Clojure generally spurns heavy frameworks for web stuff because functional programming tends to encourage or even require composition. As such, things already fit together and simply picking well-tested libraries to form your "stack" tends to let you use the right tool for the job more readily. Obviously this is somewhat subjective, but I think other people who insist on heavy frameworks have something to learn here. If their framework was so awesome, we would not need 10 more next week, and yet that is what happens. Regarding "intuition" and "whack-a-mole" debugging, I would agree that the former is important, while the latter is a sign you've done something terribly wrong. Clojure like many functional or data-first languages tends to push you towards certain tracks that should really not lead you to whack-a-mole debugging. The idea of immutability by default and functional composition in part is that it is harder to screw up your state. This should make debugging very clear at runtime since you can quite often literally dump your entire state and have quite high visibility into what is happening in your application. A good example of this WRT web dev as you mention is ClojureScript (yes, not Clojure but same principle applies) and ReFrame or Om-Next. You have a single representation of your state as an immutable database that you update instead of things scattered about, meaning you can inspect it, query it, access it across threads (if it was on the server), etc. In Clojure and many languages, you need to think in terms of operating on data structures not classes, objects, or potential language construct distractions. This again drives away distractions while debugging that leads to shots in the dark. This of course should feed your intuition too in that if you see something with a weird state, you did something wrong like reset! instead of swap! or used mutability or you're just understanding your own code wrong. It's not really fair to compare, but like I said, I find the debugging situation to be excellent. The fact that you can also live code with the browser, work directly in a REPL session (I open them for days), and so on means you can potentially write and test your code easily at the same time. This is somewhat like TDD, but instead of just writing a unit test, you actually run the code and get more immediate iteration and feedback. Of course you can still do test-first TDD too and eval those and even run the tests in the REPL. There are some traps here like stupid things you can do in the REPL, but there are many libraries to help you solve this that promote practices that are good regardless of the REPL (ex: Component, Mount). I'm already writing too much, so I'll say with regard to what Rich says, just read Clojure news groups and JIRA and such. He has said many times Clojure is essentially a pragmatic balance of some of the super powers of Lisp with the practicality but limitations of the JVM. Do you want a perfect language or one that helps you get work done today but maybe better than a lot of what is out there? Moreover, do you want a language you can use in reality or just academia? Clojure solves that via the JVM and a huge existing ecosystem. Anyway, feel free to ask more and good luck. I am sorry if I sound harsh, but I am trying to give you real answers rather than fluff.