13 ms·
Why Racket? Why Lisp? (2014)
- clusterhacks 4y agoA fun essay that really tries to nail down the "Why" in a real-world way. It mentions that functional programming removes the tripwire of state mutation as one of the "whys", but my experience slightly differs here. I found, after years of struggling with the "why" of object-oriented programming and its early obsessions with design patterns, that functional programming simply resonated with me personally. To this day, I have a bit of inner cringe when reading (for example) Java code. Early in my career, I thought my lack of "getting OOP" was due to some profound missing piece of understanding. But then Lisp (and Clojure) just made sense. Thinking functionally just works for me. It's not so much that I couldn't use OOP but just that each time I worked in deeper OOP projects, I felt some internal friction or vague uneasiness with the code. I did find that functional programming made me significantly more comfortable with OOP languages. YMMV.
- drnewman 4y agoMy experience has been exactly the same.
- orangepurple 4y agoThat friction and vague uneasiness for me is as the nagging thought that it's simply not correct code. In my case I prefer to write as much SQL as reasonably possible to prevent having to write any code in an imperative language.
- klysm 4y agoI’m very much in this camp as well. A significant number of applications can be expressed with sql and a thin layer around it
- adamddev1 4y agoInteresting. You mean make all the queries as detailed and specific as possible, processing things as much as possible in SQL so you don't have to mess around with the data you get from/put in the DB in an imperative langauge? Do you have any good examples of this? Code bases that can be read?
- orangepurple 4y agoMessing with data significantly outside of SQL is often asking for trouble. SQL queries are compiled into very efficient operations which would take a lot longer to get right imperatively. Not only that, but database engines are improving all the time, so the same code you wrote which declares your desired transformations tends to get faster over time and there is nothing to update or refactor. The transformations you write are sort of timeless because they are strongly decoupled from the implementation and hardware. Lots of data transformation steps in imperative languages require the persistence of an intermediate calculation (e.g., np.ndarray). SQL database only do this when the query planner deems it absolutely necessary. It will show up in your query plan as a "materialize" step. The EXPLAIN feature of SQL is the most useful performance debugging tool. It also alerts me to a potential logic flaw quickly when the proposed plan looks insane. I have personally replaced several analytical programs a very large bank used to monitor loan originations and performance. I don't use any special SQL language features to this day. The most sophisticated it typically gets is involving lots of subqueries, joins, and window functions. The real skill is distilling the convoluted imperative mess into its essence. I got really good at this. Half the work effort is usually spent on socializing the changes I have to make to their logic to get it working right in SQL when it changes the behavior of their existing application's logic. Often times I find the client's imperative code attempting to perform a logical operation such as a join but it is implemented incorrectly. Their existing imperative code operations actually produced the wrong results (subtly) frequently or their imperative code depended on the order of the data returned from the database (undefined behavior). Yikes. What they actually wanted was provably implemented incorrectly or relied on undefined behavior and their mistakes and the proper resolution in SQL could be easily verified with paper and pen on a sample set of loans if necessary to drive the point home.
- FpUser 4y agoI am not against / for any reasonable paradigm. I use multiple however I see fit depending on particular situation. Never wanted to be a "purist".
- Tao3300 4y agoIndeed. Sometimes it's more obvious to say "here are the steps to make this thing, now go" and sometimes it's more obvious to say "here's a description of the things I want."
- adamddev1 4y agoMe too. I've also been trying to learn more about OOP and reading "Smalltalk, Objects and Design" bc I heard a lot about how Smalltalk is the real, good OOP. But there were points I just felt squeamish, like when they were talking about the danger of the difference of effect vs. output on methods where I felt anxiety and thinking "ooo, why would I wanna do that??" I can just feel my code getting messier... Some ideas like using polymorhism to avoid branching conditionals was interesting though and I'm sure there's times it can be helpful.
- bcrosby95 4y agoI'm pretty similar. People like to ask "why should I use <insert language>?" I never really think about it too much - I don't pull out my weights and measures, and say "well, language X is 83.72% optimal for the problem, but language Y is 91.22% optimal, obviously using language X is a huge mistake!" If something is obviously better for a problem, I'll pick that language. But if you have to dig too deeply into what language to use, the language probably doesn't actually matter that much. I was "raised" on OOP, and I "got" it, but I've always preferred more standard procedural programming. I prefer Go over Java, and C over C++. I like FP more than procedural programming. I prefer Elixir and Haskell over Go. I like Lispy languages more than other languages. I prefer Clojure over Elixir and Haskell.
- agumonkey 4y agosyntax, imperative statements and classical object verbosity and inappropriate structure always hurt me whenever I read a lisp / ml book, I sweat a bit and then I gain superpowers and insights, whenever I read mainstream OO books I just get a neverending stream of "please stop.. why ??" and it's not only lisp to be frank but a mindset that lisp embodies a lot.. even using an hp48 felt better than basic+algebraic programming calcs .. (at the time I had no idea what was RPL)
- 13415 4y agoFor me, it's the opposite, I like Lisp and Scheme because they don't force me into one programming paradigm. I'm not very fond of FP but used OOP almost in every project when I was programming in Racket (for a decade or so). I often wrote more functional code first and then wrapped it into classes to "assemble" it under one roof. Lisp and Scheme are great languages for object-oriented programming.
- drnewman 4y agoMy comments where not at all to make a statement about FP vs OOP, for me they both have their place, and I agree that Lisps are great OOP languages. It just turned out for me that FP came more naturally as a new programmer, and learning about the subtleties of lambda the ultimate, lexical scope and state from an FP perspective helped me to finally feel like I grok OOP. I was pleasantly surprised to see someone else express a similar sentiment.
- ducktective 4y agoShow me a GUI framework that follows FP patterns not OOP.
- skruger 4y agohttps://phoenixframework.org/ https://phoenixframework.org/
- fredrikholm 4y agoOff the top of my head: * React * Elm * Halogen * Phoenix * Phoenix LiveView * Re-frame * Reagent
- fny 4y agoSwiftui
- pjmlp 4y agoReact is using JavaScript OOP, with the instances of JavaScript objects for data types and DOM manipulation, it doesn't exist.
- hajile 4y agoReact moved away from OOP quite a while ago. It's mostly pure functions and closures that return what are functionally records. When the JS tuple/record proposal is finally implemented, I suspect they go even farther in that direction. Of course, you could argue that closures are simply objects with one method (or that objects are a poor man's closures), but that's a rather pedantic line of discussion.
- felideon 4y agoWhich is funny, because OOP should be[1] about the in-between of the objects: the messages[2]. Not about the objects themselves or the classes and GOF design patterns. With Common Lisp you get generic functions and design your classes around those. [1] “OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things. It can be done in Smalltalk and in LISP. There are possibly other systems in which this is possible, but I'm not aware of them.” - Alan Kay (http://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay_oop_en http://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay...) [2] “The key in making great and growable systems is much more to design how its modules communicate rather than what their internal properties and behaviors should be.” - Alan Kay (https://wiki.c2.com/?AlanKayOnMessaging https://wiki.c2.com/?AlanKayOnMessaging)
- gmfawcett 4y agoWe should stop invoking Alan Kay's ancient opinion in OOP discussions. I suggest we rebrand his flavour of programming as "message oriented programming" (MOP), thank it for its continuing contributions to the field, and recognize that contemporary OOP is a valid but different solution space.
- felideon 4y agoClarity is certainly important, in which case I could have said “OOP should have been...” Except: Smalltalk still lives (Squeak) and Erlang takes messaging to the extreme.
- Twisol 4y agoI've not used Erlang much, really, but it seems like a really nice fusion of messaging across agents and immutable state within agents. Elixir has long been on my list of languages to properly pick up...
- deleted 4y ago[deleted]
- 4y ago
- invisiblerobot 4y agoDon't stop there. I thought racket was the holy grail due to the macro system but my real metamorphosis came after learning Haskell. I realize now that my previous preference for Clojure was because I was stuck in prototyping mode. Once you truly understand your problem domain then types trump macros. So while I owe a huge debt to Clojure/Racket for rescuing me from my java nightmare, and introducing me to other approaches like Erlang, it was Haskell/Purescript that matured me the most as a programmer. It was so worth the (considerable) effort, because it has generalized the very nature of computation in a way that just never happened for me in all my years with lisp.
- AgentOrange1234 4y ago“Types trump macros” is a nice way to put it. Macros are amazing for creating new languages, but a good type system with strong case matching and sum types is just incredible to work with.
- invisiblerobot 4y agoI was in the process of creating my own language in racket. It was going to codify everything I had learned over the years into powerful abstractions and target JavaScript. Halfway though I realized I was inventing a shittier Purescript. Dsls are mostly masturbation. Custom syntax? Custom evaluation semantics? I always regret it after like cocaine. The only thing macros are reasonable for is custom bindings. Most people are not qualified to invent dsls. Myself included. And the people who are qualified don't need "language oriented programming" ala racket. They can spin up a lexer which is the least complicated part of the task anyway. As for types, they have a HUGE power to weight ratio. All of my efficiency gains in Clojure due to macros were forfeited 10x over hunting down null pointer exceptions at runtime. I still love Racket. And I still prototype in Clojure. But Haskell brings you closer to math. Closer to category theory. Most programmers don't need new symbols and semantics. They need a deeper understanding of combinatorial logic.
- rscho 4y agoRacket DSLs aren't the same as 'spinning up a new lexer' at all. Making DSLs is hard, and being a PLT expert does not make one an expert at language implementation. Those are completely different skills (see Brady's reimplementation of Idris on Chez Scheme and the reason for it). Racket allows people with new ideas to prototype them efficiently by easily implementing a compiler that would've been an interpreter otherwise.
- epolanski 4y ago> Early in my career, I thought my lack of "getting OOP" was due to some profound missing piece of understanding It simply does not have formal definitions and examples. Almost everything in OOP books and content is defined like "imagine you have this situation and you want to do this thing..." and then it starts with ships, containers, ports, cranes or animals and lions. The thing I like about fp is that there's surprisingly little things to know, and they all have formal definitions. The definitions are also quite simple and build on previous definitions. If you know what a data type and a `map` operation is, you can easily understand a functor. You add to it another ingredient and you have an applicative functor. Another one, and you get a monad. You make small steps towards knowledge that are solid.
- michaelwww 4y agoAfter years of reading Lisp articles, my take is that the macro system is what sets Lisp languages apart. I was surprised then that the author didn't find them that useful. [Paul Graham] describes Lisp as his “secret weapon”. OK, so what’s the secret? He says “programming languages vary in power”. Fine, but what exactly makes Lisp more powerful? ...Lisp’s macro facility, which he describes as its ability to make “programs that write programs”. After four years using a Lisp language, I’d agree with Graham that macros are great when you need them. But for someone new to Lisp languages, they’re not necessarily a bread-and-butter benefit. Further down... Paul Graham calls Lisp a “secret weapon”. I would clarify: Lisp itself isn’t the secret weapon. Rather, you are—because a Lisp language offers you the chance to discover your potential as a programmer and a thinker, and thereby raise your expectations for what you can accomplish. What's the secret weapon if it isn't macros? I know what I need from a language that matches my particular quirks as a programmer and helps me shine and it's not Lisp. This article made me interested in Racket's libraries because it sounds like they might be more interesting than other languages libraries.
- openfuture 4y agoNot everything is about secret weapons... it is just simple and clear to use S-expressions, people like simple and clear.
- runevault 4y agoI took the first quote as you need to hold a certain amount of comfort with lisp before macros matter, not that they aren't an incredible once you understand everything well enough to use them.
- michaelwww 4y agoA couple of people were nice enough to take the time to explain Lisp macros to me in case you're interested: https://news.ycombinator.com/item?id=32730470 https://news.ycombinator.com/item?id=32730470 I can definitely see their power, but I don't have any ideas on what I would do with them. I guess I'd have to write Lisp for awhile to figure that out.
- revskill 4y agoEnough praise for FP. Now let's go back to real world. Please help tell me what's the best way to replicate what's good in OOP, like how to use FP to solve expression problem ?
- panzerklein 4y agoExpression problem exists in both OOP and FP[1] [1] https://wiki.c2.com/?ExpressionProblem https://wiki.c2.com/?ExpressionProblem
- deltasevennine 4y agoOOP is a mass delusion not dissimilar to religion.
- deleted 4y ago[deleted]
- hither_shores 4y ago> like how to use FP to solve expression problem Some common approaches: - Tagless final style: https://okmij.org/ftp/tagless-final/ https://okmij.org/ftp/tagless-final/ - Datatype-generic programming: https://markkarpov.com/tutorial/generics.html https://markkarpov.com/tutorial/generics.html - Polymorphic records and variants: https://www.cl.cam.ac.uk/teaching/1415/L28/rows.pdf https://www.cl.cam.ac.uk/teaching/1415/L28/rows.pdf
- Twisol 4y agoI'm a very big fan of the "object algebras" approach [0], which is essentially tagless final minus the automatic instance resolution you get with typeclasses. It works great even in fairly restrictive type systems like Java's. [0]: https://www.cs.utexas.edu/~wcook/Drafts/2012/ecoop2012.pdf https://www.cs.utexas.edu/~wcook/Drafts/2012/ecoop2012.pdf
- BeetleB 4y agoI can understand the pushback against FP, but it doesn't follow that if FP is a poor choice, then the only realistic alternative is OOP. I do a lot of Python stuff - much of it is not functional programming. And very little of it is OOP. The programming world doesn't consist of just these.
- myth_drannon 4y agoFrom the article - "[2021 update: I no longer contribute to Racket due to abuse & bullying by the project leadership. Everyone in the broader Racket community, however, has always been helpful and kind.]"
- waynesonfire 4y agomaybe the author was the bully? i don't see how it's helpful to perpetuate hearsay especially without any context.
- michaelwww 4y agohttps://beautifulracket.com/appendix/why-i-no-longer-contribute-to-racket.html https://beautifulracket.com/appendix/why-i-no-longer-contrib...
- eternalban 4y agoHe actually attributes malicious intent ("campaign") to this other person. Based on no evidence whatsoever, just feelings apparently. The apology was gracious, forthright, and entirely believable. The guy is uptight and blows up. Does that make him a "bully" who "campaigns" to harrass other people?
- throwaquestion5 4y agoThere is context, if you just open the article and see the link in the same sentence. But I guess is asking too much
- BeetleB 4y agoLet's not derail the discussion. To be clear, the author still continues to use Racket. His statement is more about his contributions and evangelizing.
- neilv 4y agoThe article mentions X-expressions for XML and HTML. If you decide to play with that, you might also want to look at another representation, SXML, which has more advanced library support in the Racket ecosystem. https://docs.racket-lang.org/sxml-intro/index.html https://docs.racket-lang.org/sxml-intro/index.html (Basically, early in Scheme, there were a bunch of independently-invented representations for XML. It turned out that Oleg Kiselyov's XML parsing work, SSAX, was better than anyone else's. So I converted my libraries to be compatible with his SXML representation, and others also built tools using SXML. But core Racket (then called PLT Scheme) seemed stuck with X-expressions. Today, one of the core Racket professors maintains the Racket packaging for Oleg's SXML libraries, but it's contrib rather than core. People starting with the core docs might only hear of X-expressions, until they start searching the contributed package directory, and find those packages generally use SXML.)
- cperkins 4y agoIt can be difficult to explain why Lisp is so great to non-Lisp programmers. For Lisp, the whole is greater than the sum of the parts.
- macintux 4y agoThat's true of Erlang as well. The language (and VM) design elements are very complementary.
- ncfausti 4y agoThis article just kind of did that for me. Loved that they likened Lisp to Lego blocks a few paragraphs after I had the exact same thought (when they mention that "everything is an expression"). Even after having read Hackers and Painters and some of Clojure for the Brave and True, this is the article that makes the power of Lisp click the most for me.
- cancandan 4y agoThis might help https://malisper.me/category/debugging-common-lisp/ https://malisper.me/category/debugging-common-lisp/ I am not aware of another lang/platform that can offer this kind of flexibility except may be Smalltalk or Erlang, but then they don't have the homoiconicity.
- nnm 4y agoComment on the functional programming and mutation of data. I learnt R before learnt python. In R y = c(1, 2, 3) x = y # now x is a copy of y I was surprised that in python y = [1, 2, 3] x = y # now x is y! What, why? In R, I am used to the fact everything is an expression: a = if (x > y) { 0 } else { 1 }
- fspeech 4y agoBecause it is expensive to copy a large container? Which is why you want immutable data structures, in which case copying is superfluous. So the problem with Python is not the aliasing in assignment, rather it is the mutability of the objects that could create unpleasant surprises.
- fny 4y agoR has call-by-value semantics. Python has call-by-reference. These are entirely two different programming paradigms. https://stackoverflow.com/questions/15759117/what-exactly-is-copy-on-modify-semantics-in-r-and-where-is-the-canonical-source https://stackoverflow.com/questions/15759117/what-exactly-is...
- moonchild 4y agoPython is not call-by-reference. If it were, we would expect 2 to be printed below, but it is not: >>> def f(x): ... x = 2 >>> x = 1 >>> f(x) >>> x 1 One might refer to r as being referentially transparent, or immutable (I don't know if it is--I am assuming). I would refer to python as using uniform reference semantics - http://metamodular.com/common-lisp-semantics.html http://metamodular.com/common-lisp-semantics.html
- kazinator 4y agoWhat does that Python mean, by the way? The passing of the value into the function is clear enough, but I have no idea whether f is assigning to the local x, or binding a new one. If we capture a lambda before "x = 2", and then call it afterward, does it see an x which holds the original argument value or which holds 2? In Lisps, this stuff is clear. Mostly. Except Common Lisp has some areas where it waffles: in some iteration constructs, implementations can bind a new variable or reuse the same one. Those choices are individually clear, though.
- tombert 4y agoI think Racket is pretty awesome, but I will admit that I think Clojure is a ten times easier sell. The value of being able to interop with existing JVM languages really cannot be overstated, and it makes employers substantially easier to buy in. That said, when I'm doing personal projects, I don't particularly care about what my employers think...but I still prefer Clojure. I think the native hashmap data type makes it just an exceptionally appealing Lisp, and I find that the language never gets in my way.
- dunefox 4y agoAbcl should be an easy sell then as well.
- emmelaich 4y ago(2016), according to the comment in the source
- dang 4y agoRelated: Why Racket? Why Lisp? - https://news.ycombinator.com/item?id=28966533 https://news.ycombinator.com/item?id=28966533 - Oct 2021 (2 comments) Why Racket? Why Lisp? - https://news.ycombinator.com/item?id=19952714 https://news.ycombinator.com/item?id=19952714 - May 2019 (122 comments) Why Racket? Why Lisp? - https://news.ycombinator.com/item?id=15473767 https://news.ycombinator.com/item?id=15473767 - Oct 2017 (1 comment) Beautiful Racket: Why Racket? Why Lisp? - https://news.ycombinator.com/item?id=13884234 https://news.ycombinator.com/item?id=13884234 - March 2017 (7 comments) Why Racket? Why Lisp? (2014) - https://news.ycombinator.com/item?id=9268904 https://news.ycombinator.com/item?id=9268904 - March 2015 (164 comments) Why Racket? Why Lisp? - https://news.ycombinator.com/item?id=8206038 https://news.ycombinator.com/item?id=8206038 - Aug 2014 (280 comments)
- eminent101 4y ago> ((if (< 1 0) + ) 42 100) This gives me an error in SBCL. Error below: ; in: (IF (< 1 0) ; + ; *) 42 ; ((IF (< 1 0) ; + ; *) ; 42 100) ; ; caught ERROR: ; illegal function call ; ; compilation unit finished ; caught 1 ERROR condition Why does it not work and how to make it work?
- moonchild 4y agoCommon lisp has separate function and value namespaces, unlike scheme. Try (funcall (if (< 1 0) #'+ #'*) 42 100).
- jlg23 4y agoSee moonchild's response for the why, here is the how: (funcall (if (< 1 0) #'+ #'*) 42 100) Edit: this is actually a pretty famous interview question for lisp jobs: write a program that is valid in CL and in scheme but produces different output. The solution is always to use the fact that scheme is a lisp-1, i.e. it has ONE namespace for variables and functions) and CL is a lisp-2, with TWO distinct namespaces.
- sph 4y agoFinding out about lisp-1 and lisp-2 when hacking in elisp turned me off so much I've decided to write my own editor in Scheme. This is my personal crusade for the next X months.
- flipflip 4y agoI love racket. It helped me understand the concept of limited continuations and macros.
- abrax3141 4y agoMaybe when the same URL is posted again in HN, the platform should automatically insert a first post with links to the previous discussions, as someone did here. It’s not irrelevant to repost, but it could be useful to have pointers to previous conversations. Similarly, the platform could warn the poster that its a repost (a bit like stackoverflow does, but simpler - just using link equality).
- bitwize 4y agoI swear, Lisp fandom is the Amiga fandom of programming languages. You have these dedicated supporters who are willing to go to extreme, Herculean lengths to prove that their chosen thing can not only keep up, but in some sense surpass what is popular, combined with nostalgia about the past and "what could have been". In the distant past, Ph.D.s have been awarded based on such feats, like "Look, we can compile Lisp code to run half as fast as Fortran" and "Look, we designed a chip that runs Lisp as a native instruction set". Simultaneously ridiculous and cool, the very picture of hack value. But you're still engineering around the drawbacks of a slow, dynamically typed language. The Lisp machines were amazing in 1979. But no one is seriously building a Lisp machine today, because modern languages with modern IDEs on ordinary hardware have nearly all the features that Lisp machines had -- including hot-reloading code inside a live, running system -- and get you so, so much farther in the same amount of time than Lisp machines ever could. Use a modern language inside a modern IDE, and you'll be fine.
- tartoran 4y agoIs there anything wrong with Amiga fandom? Amigas were cool as hell. They deserve their cult following. As far as LISPS, they’re cool as hell too. Just because they’re not up to par with corporate backed modern languages doesn’t mean you should use them for the same purposes. Be a bit open minded for a change and you’ll learn a thing or two.
- bitwize 4y agoI own an Amiga and use Lisp all the time. But the Amiga's coolness peaked around 1990; Lisp's coolness peaked in the late 70s or so. Lisp still feels great to use, but it doesn't really have an advantage over modern programming languages the way it did over languages from the 70s/80s, or even stone-knives-and-bearskins Unix development without an IDE. Many of the killer features of Lisp machines could be found in 90s Visual Basic. It kind of parallels the Amiga situation: by 1994 PCs had closed the gap, offering more CPU power and even a better gaming experience than the Amiga but diehards still keep comparing their boxes to the 5150 PC with CGA to feel superior. So if you want to use Lisp because it feels good to use -- it's fun to drive like an MGA is -- that's fine, but in the end you're no better off with Lisp than you would be with C# or TypeScript and in some ways you're worse off.
- abrax3141 4y agoThe bottom line, made explicitly by this commentary (although attributed to only one component), is that various good design choices (improved over its over 60 years!!) make lisp very close to the language of thought and of natural expression. You can almost turn the natural expression of your computation directly into lisp by judicious use of parens and reading the phrase “of the” between function names and arguments, and where you can’t do this, that’s a hint that you need a macro.