Live data from Hacker News

A difference between Haskell and Common Lisp

chrisdone.com

191–200 of 203 posts

Re: A difference between Haskell and Common Lisp

#191

Earlier quoted context omitted.

Well, yes. Lisp and CL are not the same. If anything, this has made me rethink possibly going over to common lisp, which I was thinking of for the larger stdlib, because SBCL is very fast, supports TCO, and you can disable case insensitivity.

Common LISP was made to smooth over the differences of the ancient LISP's plus standardize their situation a bit. If those don't matter to you, then the alternatives are often better. SBCL being one of them. If I get back into LISP, I think the Racket Scheme community looks like it's delivering most bang for buck in terms of what the tools can do after investing time learning them.

Most schemes don't have a lot going for them in terms of libraries, which is the primary reason I'd want to go over to Common. I really don't like racket, for mostly aesthetic reasons. It seems a bit over complicated, trying to stuff a lot of cutting edge research into its core, and forcing you to learn about 6 different models at once just to understand what its documentation is saying. Its OO system is apparently lackluster, especially since most schemes fork tinyCLOS for OO, and syntax-case is too complicated for its benefits.

I'll stick with CHICKEN for now. Its module system may be a bit awkward at times, (you can't cleanly bind all your dependent modules into one executable), but it's much more minimal, and while its documentation may not be the best, at least I can understand what its saying.

Re: A difference between Haskell and Common Lisp

#192
post #186

Earlier quoted context omitted.

Significant modification is something different than complete rewrite. The Lisp languages share a common core language, code, ideas, literature, community. Derived languages like Logo, Dylan, Clojure, Racket, ... have their own core language, their own code, their own ideas, their own literature and their own community.

Yes, but they also share a history and a set of syntax and ideas... Well, except Dylan, syntax-wise. But ultimately this is an argument about terminology. And the majority of people would say that scheme is a lisp. A lisp. Not a language derived from lisp, that is independent. A LISP. in the LISP family, because that is a thing. And if you want proof that that is what most people think, you need only check Wikipedia:…

THat's what people thought twenty years. Today this does not matter anymore.

> Yes, but they also share a history and a set of syntax and ideas...

Clojure:

    user=> (cons 1 2)
    IllegalArgumentException Don't know how to create ISeq from: java.lang.Long  clojure.lang.RT.seqFrom (RT.java:542)

    user=> (cdr '(1 . 2))
    CompilerException java.lang.RuntimeException: Unable to resolve symbol: cdr in this context, compiling:(NO_SOURCE_PATH:2:1) 

What I say...

Re: A difference between Haskell and Common Lisp

#193

Earlier quoted context omitted.

You can, but that's a different thing - creating a new shell as a child of the command, rather than talking to the parent shell of the command.

Why would you want to do that? I'm kind of curious. I mean, I'm sure you have an application, I just can't think of one. Blub effect, I guess.

I've hit a number of small "oh, I could do that if..." use cases over the years; none is really immediately springing to mind.

There are things that a shell function can do that a spawned program cannot - mostly to do with affecting shell state. Updating shell variables and opening file descriptors are obvious examples.

Re: A difference between Haskell and Common Lisp

#194
post #187
post #185

Earlier quoted context omitted.

> which means that you can understand the combined program by understanding foo and bar independently. If you can't represent the result of bar() as a value x then that breaks down Can you not understand this program by understanding both statements separately? print("hi") ; print("there") Why is that more understandable if the result of print is a value? (obviously, the result of read() is). In any case, describing…

> Can you not understand this program by understanding both statements separately? Maybe that one - I/O is a bad example, I don't really see the value of monads for I/O and I don't tend to use an I/O monad in my programs. Programs I can't understand by understanding statements separately are something like: openTransaction() writeToDatabase(1) rollbackTransaction() or val myLog = Buffer() myLog :+= "step 1" myLog :+=…

> these cases (database transaction, writer) are things I do find it useful to manage with a monad.

Yeah, I know, but some of us don't :)

> You need some way to encapsulate/isolate the relevant state of a program partway through running

That's exactly what continuations do. The question of global mutable state is an orthogonal one.

> I think that state has to be equational if we're to have any hope of being able to understand programs - if you can't say whether this time at line 20 the program is in the same state it was last time at line 20, or a different state from last time, how can you even begin to debug?

Well, we have been successfully writing programs like that for a long time. Now, don't get me wrong -- the equational abstraction is often very useful, but it has its price, and it's not a complete representation of the computation.

> But will those approaches stop me from tripping myself up when effects don't commute?

I don't understand. We don't trip over ourselves when writing imperative code, and when we do, it mostly has to do with IO or other OS state, and monads won't help you there. Linear types ("typestate") might, but even they are limited.

Re: A difference between Haskell and Common Lisp

#195
post #192

Earlier quoted context omitted.

Yes, but they also share a history and a set of syntax and ideas... Well, except Dylan, syntax-wise. But ultimately this is an argument about terminology. And the majority of people would say that scheme is a lisp. A lisp. Not a language derived from lisp, that is independent. A LISP. in the LISP family, because that is a thing. And if you want proof that that is what most people think, you need only check Wikipedia:…

THat's what people thought twenty years. Today this does not matter anymore. > Yes, but they also share a history and a set of syntax and ideas... Clojure: user=> (cons 1 2) IllegalArgumentException Don't know how to create ISeq from: java.lang.Long clojure.lang.RT.seqFrom (RT.java:542) user=> (cdr '(1 . 2)) CompilerException java.lang.RuntimeException: Unable to resolve symbol: cdr in this context, compiling:(NO_SOU…

... Well, maybe you could be right. I'm not sure. I do know that when most people say "lisp," they think of scheme, clojure, etc. as in that category.

I like to think that I can admit I may be wrong, and in this case I think I might be wrong.

Re: A difference between Haskell and Common Lisp

#196

Earlier quoted context omitted.

Why would you want to do that? I'm kind of curious. I mean, I'm sure you have an application, I just can't think of one. Blub effect, I guess.

I've hit a number of small "oh, I could do that if..." use cases over the years; none is really immediately springing to mind. There are things that a shell function can do that a spawned program cannot - mostly to do with affecting shell state. Updating shell variables and opening file descriptors are obvious examples.

This is one of the reasons shell languages feel kind of functional. But they're not really designed like a functional language so they feel kind of clunky.

On the subject of "oh, I could do that if..." I know exactly how you feel. I really want the ability to pass multiple filestreams to a command, so you could, say, use cat on the outputs of two commands. Assuming the syntax was @``, It would like something like this:

foo|grep bar|cat @`baz|grep bar`|sort -rn|tail

The above script assumes that the commands foo and baz are generating lines with time signatures at the start, and then checking for the most recent entries. I chose the @` syntax for its similarity to the lisp @, syntax, but it could be anything. Unfortunately, I think the only way to do this would be to monkey-patch either open(2) or fopen(2), probably both, which would be a Really Bad Idea (tm).

Re: A difference between Haskell and Common Lisp

#197

Earlier quoted context omitted.

I've hit a number of small "oh, I could do that if..." use cases over the years; none is really immediately springing to mind. There are things that a shell function can do that a spawned program cannot - mostly to do with affecting shell state. Updating shell variables and opening file descriptors are obvious examples.

This is one of the reasons shell languages feel kind of functional. But they're not really designed like a functional language so they feel kind of clunky. On the subject of "oh, I could do that if..." I know exactly how you feel. I really want the ability to pass multiple filestreams to a command, so you could, say, use cat on the outputs of two commands. Assuming the syntax was @` `, It would like something like th…

I'm not exactly sure what semantics you intend, it seems like you might be able to spell this

    { foo; baz; } | grep bar | sort -rn | tail
or, in bash only:

    cat 
This is assuming you didn't intend interleaving, for which the second syntax would work but you'd need something other than cat.

Re: A difference between Haskell and Common Lisp

#198
post #194
post #187

Earlier quoted context omitted.

> Can you not understand this program by understanding both statements separately? Maybe that one - I/O is a bad example, I don't really see the value of monads for I/O and I don't tend to use an I/O monad in my programs. Programs I can't understand by understanding statements separately are something like: openTransaction() writeToDatabase(1) rollbackTransaction() or val myLog = Buffer() myLog :+= "step 1" myLog :+=…

> these cases (database transaction, writer) are things I do find it useful to manage with a monad. Yeah, I know, but some of us don't :) > You need some way to encapsulate/isolate the relevant state of a program partway through running That's exactly what continuations do. The question of global mutable state is an orthogonal one. > I think that state has to be equational if we're to have any hope of being able to u…

> We don't trip over ourselves when writing imperative code

Speak for yourself. Though I guess I'm more concerned with refactoring than with writing. In particular in imperative code it's very hard to tell the difference between semantically important ordering and accidental ordering.

> when we do, it mostly has to do with IO or other OS state, and monads won't help you there.

Yes they will? It's very normal to encapsulate something of that nature with a monad.

Re: A difference between Haskell and Common Lisp

#199

Earlier quoted context omitted.

This is one of the reasons shell languages feel kind of functional. But they're not really designed like a functional language so they feel kind of clunky. On the subject of "oh, I could do that if..." I know exactly how you feel. I really want the ability to pass multiple filestreams to a command, so you could, say, use cat on the outputs of two commands. Assuming the syntax was @` `, It would like something like th…

I'm not exactly sure what semantics you intend, it seems like you might be able to spell this { foo; baz; } | grep bar | sort -rn | tail or, in bash only: cat This is assuming you didn't intend interleaving, for which the second syntax would work but you'd need something other than cat.

the EDIT: Unless you're just piping both of them to STDIN. piping two files to STDIN is useful, just not as useful as the thing that I wanted. This seems to be what you're doing.

Re: A difference between Haskell and Common Lisp

#200
post #198
post #194

Earlier quoted context omitted.

> these cases (database transaction, writer) are things I do find it useful to manage with a monad. Yeah, I know, but some of us don't :) > You need some way to encapsulate/isolate the relevant state of a program partway through running That's exactly what continuations do. The question of global mutable state is an orthogonal one. > I think that state has to be equational if we're to have any hope of being able to u…

> We don't trip over ourselves when writing imperative code Speak for yourself. Though I guess I'm more concerned with refactoring than with writing. In particular in imperative code it's very hard to tell the difference between semantically important ordering and accidental ordering. > when we do, it mostly has to do with IO or other OS state, and monads won't help you there. Yes they will? It's very normal to encap…

> it's very hard to tell the difference between semantically important ordering and accidental ordering.

Not when effects are clearly marked. There is zero difference in that respect between continuations (i.e. imperative) and monads. It's only syntax and whatever your type system is.

> It's very normal to encapsulate something of that nature with a monad.

Sure, but a monad won't help you ensure their proper ordering.

Post reply on HN