Live data from Hacker News

Why Racket? Why Lisp?

practicaltypography.com

211–220 of 295 posts

Re: Why Racket? Why Lisp?

#211

Earlier quoted context omitted.

I understand that. I really like Haskell but I wonder if the type system is actually too strong for the real world. Generalizing algorithms sounds nice but if Haskell is so powerful, why is the Haskell community still not able to provide a convenient working package manager? Perl has CPAN, Ruby has Gems, Lisp has ASDF and Quicklisp but Haskell is still stuck with buggy Cabal. I have been in the Cabal hell many times.…

Wait, are you suggesting that the Haskell type system is too strong to write a package manager? That makes no sense. A much more valid reason that Cabal is annoying is that Haskell is a compiled language that uses static linking, unlike all the languages you mentioned, which are interpreted.

SBCL also uses static linking. It doesn't recompile every ASDF imported library whenever I compile my application. It just does so when it is actually necessary. Why doesn't it work so easily in Haskell?

I think it's the strong type system because every small code change can break the whole fragile structure of a Haskell application. It's like wheels in an old clock. If you break one jag of a gear then the whole system stops. You have to take apart all gears, change the affected one, and assemble everything together. Cabal hell breaks loose when you realize that someone changed the shape of a small gear, and you don't have access to the old one, except you stored some in your sandbox. Over time you get a whole farm of sandboxes full of obsolete parts. Then after a long time when you have to maintain some of the old code you realize that you have to edit even the foreign (!) libraries yourself because they are totally obsolete and incompatible to the current ones :-) Could that be the reason why there are (AFAIK) so many hackage projects aged or even unmaintained?

Re: Why Racket? Why Lisp?

#212

Some practical features I enjoy in CL: 1. Conditions and restarts : As far as error handling in programs go this is the most rock-solid system I've encountered. You can tell the system which bits of code, called restarts, are able to handle a given error condition in your code. The nice thing about that is you can choose the appropriate restart based on what you know at a higher-level in the program and continue that…

Great concrete examples, a couple of things to add about them:

Handler, conditions and restarts are much more expressive than in other languages, you can signal a condition (the analogue of throw) with restarts attached to it which only if you desire to handle it in another part of the program where(/if) you decide to handle the conditions(the analogue to try). It is analogue to throwing an error with catch statements attached and when you write the try statemet the catch statements attach to the throw statement are made available to said catch. Kent Pitman explains it much more eloquently than me[1].

Also to add how well thought out CLOS dynamic redifining of classes is, when one redifines the change is garaunteed to happen between redefinition and the next time you access said class, as to give leeway to the implementation to decide the best strategy to do so (for example if redifining a class with 10K+ instances if you do it all at once the system may become unresponsive). Also if the redefinition isn't just adding or removing slots you can provide a function to handle the updating of slots for the redefinition.[2]

[1]: http://www.nhplace.com/kent/Papers/Condition-Handling-2001.h...

[2]: http://www.lispworks.com/documentation/HyperSpec/Body/f_upda...

Re: Why Racket? Why Lisp?

#213

Earlier quoted context omitted.

"Turing-complete macro system - I've heard C++ is moving in this direction (not sure to be honest) but Lisp is still ahead on this" 1) Turing-complete is a bug, not a feature. 2) C++ template metaprogramming has been Turing Complete for ages. 3) There are nonetheless significant limitations on what you can do with templates in C++, compared to what you can do with macros in Lisp. "Turing Complete" is a theoretical co…

I understand what you're saying. What I mean is not the trivial "nand is turing complete" sense, which I agree is harmful and silly, but full eval capabilities. Lisp macros can fully evaluate Lisp code, and I consider this a great feature, but I don't know how else to describe them. "Full evaluation macros"?

It's hard to describe because even "full access to the language at compile time" would be useless if that language were C++. The advantage of macros is that you have access specifically to Lisp at compile time, not just any old blub language. And that just circles back to "Lisp is great". :)

Re: Why Racket? Why Lisp?

#214
Check it out. For five years I have been developing a tool called TXR. It's a "Unixy" data munging language that is ideally suited for programmers who know something about Lisp and would like to move away from reaching for the traditional stand-bys like awk, sed, perl, ...

You do not have to know any Lisp to do basic things in TXR, like extracting data (in fairly complicated ways) and reformatting it, but the power is there to tap into.

In TXR's embedded Lisp dialect, ("TXR Lisp"), you can express yourself in ways that can resemble Common Lisp, Racket or Clojure.

You can see a glimpse of this in this Rosetta Code task, which is solved in three ways that are almost expression-for-expression translations of the CL, Racket and Clojure solutions:

http://rosettacode.org/wiki/Self-referential_sequence#TXR

Or here, with syntax coloring:

http://www.nongnu.org/txr/rosetta-solutions-main.html#Self-r...

If you closely compare the original solutions, you will see that certain things are done more glibly in TXR Lisp.

Re: Why Racket? Why Lisp?

#215
post #87

Earlier quoted context omitted.

Nonsense. We've figured out how to do type systems. We can even fully infer types if you're willing to accept some quite reasonable restrictions on how polymorphic your code is. We have a bunch of reasonable approaches to effect tracking, which Lisp folk used to have to do by hand (that story about the T garbage collector sounds like the most unmaintainable piece of code I've ever heard of). We know how to solve the…

Type systems are the one exception, but it still remains broadly true that Lisp was way ahead of everybody. There are many things we could talk about besides type systems: Lambda expressions - just now reaching Java and C++, been in Lisp forever Garbage collection – (obviously) Turing-complete (edit: fully evaluating) macro systems – I've heard C++ is moving in this direction (not sure to be honest) but Lisp is still…

I don't know about Swift but equating a REPL to interactivity is a horrible disservice to Lisp (and Smalltalk).

For example, Python has a REPL but it is not very well suited for interactive programming. For example Python does not handle you redefining a module after you import it without some voodoo. Nor it has forward references. For example in Lisp I can define a method that especialices on a class I haven't yet defined. Or define a function that calls function B which I will define later in the code. Nor have I seen something akin the slime Inspector and presentations, which are not quite there as the Symbolics Genera environment for interactive programming

Re: Why Racket? Why Lisp?

#216
post #209

Earlier quoted context omitted.

"CLOS allows me to dispatch based on the types of all of the arguments." But can it dispatch based on the return value?

That sounds like a feature that would both be awesome, and annoy the crap out of me. Are there examples where this actually leads to clearer code in the wild?

Several common typeclasses in Haskell have methods that are polymorphic in the return type, and I find it extremely useful.

The bounds of a bounded type:

    minBound :: Bounded a => a
    maxBound :: Bounded a => a
Converting an integer to an enumerated type:

    toEnum :: Enum a => Int -> a
Casting between numeric types:

    fromIntegral :: (Integral a, Num b) -> a -> b
Parsing a string into a value:

    read :: Read a => String -> a
An empty instance of a container that can be concatenated:

    mempty :: Monoid m => m
An effectful action that simply returns a constant value:

    return :: Monad m => a -> m a
It leads to clearer code because you don’t need to specify so many types—either it’s clear (and inferable) from context, or you want to write generic code. For example, with Monoid (mempty & mappend) I can implement a function called mconcat, which concatenates a list of stuff:

    mconcat :: Monoid m => [m] -> m
    mconcat = foldr mappend mempty
Now I can join a list of strings, concatenate a list of lists, union a list of sets, or even the optional versions of any of those:

    mconcat [Just "foo", Nothing, Nothing, Just "bar"]
    =
    Just "foobar"

Re: Why Racket? Why Lisp?

#217
post #36

Many of the last items in the list should be in the category "Scheme". Racket is a dialect from Scheme, but it still is a Scheme. The syntax-case macro transformations are available in most Scheme systems.

mutable cons cell by default is a very big departure from the Scheme Standard AFAIU (not that I think it is a bad idea, just not Scheme).

Re: Why Racket? Why Lisp?

#218

Earlier quoted context omitted.

Type systems are the one exception, but it still remains broadly true that Lisp was way ahead of everybody. There are many things we could talk about besides type systems: Lambda expressions - just now reaching Java and C++, been in Lisp forever Garbage collection – (obviously) Turing-complete (edit: fully evaluating) macro systems – I've heard C++ is moving in this direction (not sure to be honest) but Lisp is still…

I don't know about Swift but equating a REPL to interactivity is a horrible disservice to Lisp (and Smalltalk). For example, Python has a REPL but it is not very well suited for interactive programming. For example Python does not handle you redefining a module after you import it without some voodoo. Nor it has forward references. For example in Lisp I can define a method that especialices on a class I haven't yet d…

Excellent point. I found myself struggling to describe Lisp in terms that non-Lispers would understand (blub paradox I guess), and I figured almost everyone knows what a REPL is. You're absolutely right that a REPL itself is just scratching the surface, and there is all kinds of interactivity beyond that.

Re: Why Racket? Why Lisp?

#219
post #7

Earlier quoted context omitted.

Oh? What makes you say that? On my OS X computer at least, it honestly looks gorgeous: http://f.cl.ly/items/3o2r3E2T2y3v3M3T291i/Screen%20Shot%2020...

Yeah, except the obnoxious diamond symbols used to denote each link, rather then underlining them, like has been standard for 20 years now.

Underlining isn't very attractive, either, even if it's standard. I don't mind the diamond, but I'm not very enthused by it, either.

Re: Why Racket? Why Lisp?

#220

Earlier quoted context omitted.

> As for the idea of Lisps, well, it sure seems neat. But I've literally never run across a situation where I needed my code to edit itself. I've never run across a situation where the lack of an everything-is-an-expression-is-a-list feature prevented me from doing what I wanted to do. This is classic Blub paradox. You don't feel like you need a feature until you start using it, at which point you start wondering how…

OK, but I've been aware of Lisp macros for a while, and still never seen a situation where I needed them. A couple weeks ago, though, I found myself in a situation where the user needed to be able to specify a filter, and the filter was going to be a tree of expressions, and the program had to take what the user specified and turn it into something the program could execute... and the filter tree looks a lot like an…

I'm not a lisper either, but I think the key idea, and I've looked but can't find the reference for this, is expanding the language space to intersect the problem space. Any given language has a domain of problems it's suited to: manipulating number, strings, objects with loops and conditionals and organizing code with data (oop). This is the language domain. Then users (programmers) create abstractions with the language to represent a problem domain (payment processing, cms, reddit, whatever).

The idea with macros is to extend the syntax of the language to move the entire language to the problem domain, for example the html generating dsl pg and company used at viaweb (see his writing).

This distinction is not as profound today, imo, because languages have come a long way. Php didn't exist when pg and friends were doing viaweb, today templating html is old hat, but at the time specifying a dsl in lisp macros to dyanmcically generate html was quiet innovative.

Post reply on HN