Yes, LISP code can be easily parsed for as long as you stick to lists. However the ability to do anything complicated with LISP code is simply not there because LISP code loses type info, which is extremely important for anything you’d want to do with code, like all kinds of non-superficial transformations and refactorings.
So here are some facts given as examples:
(1) LISP code does not make the job of IDE authors easier; just ask the authors themselves
(2) in terms of macros, anything more complicated than lazy evaluation of thunks and kiddie examples is out of reach; for example .NET’s LINQ cannot be expressed in LISP, not unless you add a static type system, but at that point you’re no longer talking about LISP ;-)
In my opinion LISP has been vastly romanticized, yet it doesn’t live up to expectations. It falls short in every department, from functional programming, to available tooling, to the great enlightenment people are supposed to experience once they learn it.
Whereas Haskell really does live up to expectations, being one of those very few ecosystems that does make developers better, at this point being the lingua franca of FP.
I wrote a compile-time test framework in 7 lines of Gambit Scheme code https://github.com/billsix/bug/blob/master/README.md
> (2) in terms of macros, anything more complicated than lazy evaluation of thunks and kiddie examples is out of reach
I've seen and built tons of exotic stuff with macros. On Lisp builds a Prolog compiler if you want a specific example.
Your point about types makes me curious about LINQ. Brings to mind Julia's generated functions.
Doesn't that imply that Lisp, sans-static typing, is not Turing-Complete? Surely that is not the case.
The point of static type systems isn't that they add power -- it's that they take power away. Thus empowering the programmer to reason in a restricted subset of "all the possible things".
[1] I'm ignoring the detail of there actually being a way to interface with the actual physical hardware, but I think we can assume that in any remotely practical TC language.
Good luck expressing LINQ syntax, or Lisp syntax, or even Basic-80 syntax on it.
Syntax is important, it's a tool of thought.
Surely you can write LINQ in any Turing-complete language.
Turing completeness doesn't describe expressivity of source code, as far as I understand it - it describes the ability to produce a desired outcome. So yes, you can perform the same operations LINQ allows, in Lisp or any other Turing-complete language. But can you do it while giving the programmer the same (or a similar enough) experience? From the .NET docs:
> Language-integrated query allows query expressions to benefit from the rich metadata, compile-time syntax checking, static typing and IntelliSense that was previously available only to imperative code. Language-integrated query also allows a single general purpose declarative query facility to be applied to all in-memory information, not just information from external sources.
Now, to be fair, I'm not sure you can express all that in Haskell either. And it could be reasonable to argue that a few of those benefits (e.g. intellisense) just _haven't_ been done for Lisp, not necessarily that they _can't_ be done.
It's lambda complete. Which has been famously proven to be the same as turing complete.
Also type checking is basically more or less putting restrictions on your code. If there is a language that doesn't have the syntax to compute certain things, how would restricting that language via type checking suddenly cause it to be able to compute everything and be turing complete? Makes no sense. To make a language change from not turing complete to turing complete you have to expand.. not restrict ... but expand it's computational ability. Again Type checking serves to restrict.
Type checking is essentially just pre runtime special syntax for:
define add (x,y)
if type(x) != 'int' or type(y) != 'int':
throw TypeError
return x+2
or in a lisp like functional language: (define (int) (x)
(if (equal? type(x) 'int') (x) (error 'Type Error'))
(define add (x y))
(+ int(x) int(y)))
It's not a big deal. I'm not sure what LINQ is, but you don't have to add a type checking system to a language to do type checking if you know what I mean.He doesn't know what he's talking about.
That's an extraordinary claim. Do you have extraordinary evidence to back it up?
Then the provider can decide how it wants to do it, based on the types and operations involved. A SQL DB based provider can’t safely push any work to the database if it doesn’t know the structure or types of the objects and properties in the expression tree. It would have to return whole tables and perform all evaluation in the app where types could be handled dynamically.
I think something like typed racket or clojure may support it, but many lisps would not.
Isn't that the exact definition of the "unquote" and "unquote-splicing" operators inside a quasiquote?
Honestly asking since I'm not past the "makes my head hurt" stage of scheme macros, probably doesn't help that the quasiquote macro is buggy in my minischeme sandbox.
I don't think it's fair to say something is "not so great" because it takes more than a few weeks to learn. That logic leads to a sad place. You suggest using Lisp and maybe Rust, but both of those languages would probably take more than a few weeks to learn.
Also, you could just use the IO type on every function in Haskell, and thus eliminate the separation between pure and impure code. You'd only have to a type a few extra characters here and there, which isn't ideal, but is acceptable while being pragmatic.
Haskell has had a default package manager, called "cabal", for many (15+ ?) years.
I found Haskell much more practical because it makes refactoring truly easy, but I'm very "programmer-centric". I mean 'refactoring' in the strict sense of preserving absolutely all the existing behavior, including side effects. That is extremely difficult if you can have side effects all over the place. (Strictness obviously helps a lot, but it also has downsides.)
Btw, given your experience and if you want to try Lisp seriously I'd probably recommend Racket, Typed Racket and their Turnstile experiment(?).
I’ll look into Racket and friends. Thanks
But it doesn't even have Higher Kinded Types! What a disgrace. /s
I do wonder, what would OP, or any seasoned Haskell programmer, think about Rust. Would they consider it strange? Primitive? Too mainstream?
When I write applications, I don't need a systems language, and Haskell is easier to use.
Also, Rust is a great imperative language, it's not as great as a functional language, and you can't reap the benefits of pure functional programming.
The combination of type classes (traits in Rust) and HKTs in Haskell mean that you can quite easily restrict a function to only be able to do a subset of what's possible in "the world".
A trivial example would be
foo :: Logger m => Int -> m ()
where Logger is a type class (trait in Rust-speak) which implements the Monad type class (thus allowing 'imperative'-style programming), but also has a "log" method which allows the program to emit a string to the log.The thing is that given the restrictions of parametric polymorphism that function 'foo' has to work for any Logger instance we give it, so it absolutely cannot do anything other than pure computation or invoking the "log" method. It cannot do any other side effects at all. So, it's not "pure", but it's also much more restricted than "impure".
That's a very powerful tool for modeling highly effectful systems.
Syntax isn’t as nice as Haskell as well. A Haskell programmer fed up with purity would just move to Ocaml or F# tbh.
Only inside the echo bubble of Haskell.
Rust can be put to use in any place, without advertising it for it even -- and already powers widely used code across the world (and not just in Mozilla).
Haskell use mostly concerns a few financial institutions...
...who somehow have more resources to employ programmers than the organizations using Rust. Funny, that...
It's not like all the financial sector runs on Haskell or something -- the majority uses the usual culprits. The stories behind these organisations that I've read of is of some opinionated PM going in and making Haskell or OcamL and the like the officially supported language -- in Jane Street and Standard Chartered and the like. Which is the definition of being an outlier choice.
So, yeah, they are "more programmers" wanted for those 20+ and 30+ year languages, compared to a merely 3 year old language (Rust 1.0 was released in 2015).
But nowhere near the momentum.
Rust has been used already by Dropbox, Canonical, Cloudflare, Atlassian, Microsoft (Azure), Chef, Mozzila (of course), and tons of others in backend and client code. And that's in 3 years, and while the language is changing and core libs are still being built.
And it's silly to judge by job postings, as those places don't need to advertise for specific Rust roles (they can get regular systems programmers or use their own existing devs and have them do Rust). It's not a huge paradigm shift like with Haskell where you'll need people with that kind of training already. Besides, Rust is so new, there would be little point asking for Rust devs explicitly.
Regardless, having the flexibility to program in the most appropriate style is nice.
Rust is currently in the process of baking asynchronous I/O into the language, and their implementation cannot do this: http://blog.sigfpe.com/2008/12/mother-of-all-monads.html.
I find it extremely pragmatic, but perhaps not in the way most people use the word. It's pragmatic about the abilities of programmers to get every single detail right all of the time, i.e. it discards that notion entirely. We will not get things right enough of the time and so the language must support and help you. This goes all the way from simple static typing to enforcing Purity of Essence, I mean, Functions.
If you don't care about managing side effects you can always just write everything in IO and slap a "pure" here or there. Haskell's actually also a pretty good imperative programming language, IME.
Lisp (Common Lisp) is what you get when you reduce the rules and syntax to a minimum and try at the same time to be a maximal flexible programming language. This simplicity and applied pragmatism is what makes it so great. Like the authors in the Lisp books warned, after learning Lisp, coding won't be the same. Now I see everywhere code that could easily be written in Lisp, but is not so great in language XYZ. All those SDL's and stringified API's and code-generators they need to do real things and data formats like JSON... all obsolete, if they would have chosen Lisp (or a language with brackets and Lisp like evaluation rules).
The other thing that is often overlooked regarding Lisp is, that in a Lisp like language there is no need to wait for a new version of the programming language to be released to get new syntax – you can simply add it yourself (or have a library doing it for you). E.g. a lot of the JavaScript mess could be fixed by code transformation, if they would have chosen a Lisp like syntax in the first place.
I don't see Haskell as uber language. If I want super correct code, speed and I'm okay with using a more complex language, then there is Rust – which is probably more correct than Haskell and faster, too.
Haskell, Lisp and C++ would really benefit form a std library 2.0 and a default package manager... one can dream.