Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

The “run” button is however you run your CL code. Are you seriously disputing my experience because I said “run” in quotes? Would it please you more if I had instead said I used SLIME with SWANK with emacs and I pressed C-c C-e or whatever?

As I sais, I have programmed CL professional. And yes, Racket doesn’t have a real REPL. And yes, CL with emacs and SLIME and SWANK is nice or whatever, but personally, I’ve found that a REPL provides much more value with a dynamic language vs a static language.

Why? Because with CL you need to be running each function because you have no faith in your code. The most trivial errors that could have been caught by a simple type checker will crash your program. I’ve almost never had the experience of writing say 300 lines of CL and having it work on the first run. Because of this, you have to use the REPL as a crutch.

In contrast, with haskell or scala even though those languages provide a REPL, I rarely find myself using it. In fact, I very rarely run my code at all. With a functional and monadic style and heavy use of type parameters, chances are that if it type-checks, it is correct.

One area in which CL is pretty cool is modifying a running image on the fly. I once fixed a bug mid-meeting with CL and everyone thought that was pretty cool.



> REPL provides much more value with a dynamic language vs a static language

One of the reasons why CL is how it is, is to support incremental & interactive programming. That was a big driver for its language design.

Being able to work on programs of arbitrary size while they are running. For that CL is a dynamic language. Not just a dynamically typed language. 'Dynamic language' means that one can change the program AND the programming language while the code is running. For that Common Lisp does a lot of runtime checks and includes an error system which enables one to repair code while in an error -> in Common Lisp the debugger stays in the context of the error and one may have explicit ways to restart the program. One can use that also programmatically.

Something like a REPL is not just there because you need to test your code to make it run, it is there because it enables us to program AND test a running program without crashing it.


We have to agree to disagree. It's also how you word certain things that make me wonder about the level of exposure you have had to proper Common Lisp development methodologies. For instance, you write: "The most trivial errors that could have been caught by a simple type checker will crash your program".

In Common Lisp you simply pop to the debugger, and don't lose global state. Your process still runs, you simply fix the error and continue. Not to mention that you can use type declarations and SBCL will do compilation-time type checks and spit out warnings for most of the trivial errors you describe. It will even highlight the relevant code _inside your editor_. And since you are compiling at runtime all the time via SLIME, this of course means that you never use the REPL like a crutch.

I find that the main reason I don't use REPLs in languages like OCaml and Haskell is not due to the static type system but because they introduce a huge context switch and break me out of flow. They also make it that much harder to inspect state of a running process since you have to jump through hoops to do so, assuming that it's possible to begin with. Everything meshes together in CL (and Smalltalk and Erlang ) to make it seamless. This does not happen in the statically typed languages you mention and the experience is that much poorer.

At the end of the day, when programming and especially when I'm doing exploratory programming where the problem is hard and the solution not 100% fleshed out, I am trying to quickly model and make concrete an abstract model that only exists inside my mind. Languages like Common Lisp that have short feedback loops are ideal for me entering a state of cybernetic "entanglement" where subject [mind]-object [program] mesh together via the medium [programming language] and I can proceed to do rapid transformation of my mind space into the computer. None of the statically typed languages you mentioned allow one to do that. It's like programming with punch cards versus programming hooked up to a brain-computer interface.


Everything you say is true. CL via a REPL really does make you feel like there is no barrier between your code and your brain.

With regard to programming in CL, yes, if you cause a stacktrace in your code, you can easily debug and fix it on the fly. But most of the problems (atleast with me) could have been caught with a static type checker in the first place.

I just feel like my brain is stupid, imperfect, and error prone. I want and need something that can offload a lot of thinking to the computer.

It’s not like static typing and the immediate feedback CL has are mutually exclusive. With the right language you could definately have both.

Like imagine a CL with static typing (a hindley milner system), would it be worse or better?

I would say it must be objectively better:

What do you think? (You’ve made some good and reasonable points, so I would genuinely be interested in your opinion)


> It’s not like static typing and the immediate feedback CL has are mutually exclusive.

While it's from the Scheme side of the Lisp family tree rather than the CL side, there is Typed Racket.


Alan Kay has talked about what he calls "extreme late binding of all things" [1], where he feels that Lisp and Smalltalk do it particularly well. I'm in full agreement with his point of view but to answer your question I had to do some thinking to figure out exactly why that is the case.

First let me say that these days most of the code that I write, I'm doing it in a dynamic language (CL, Emacs Lisp, Erlang, Lua). But I've also spent decades working with statically typed languages (mostly C and Java) usually for profit. And I do enjoy Haskell and OCaml, but I get a different sort of enjoyment from them that is not linked to the short feedback loop and cybernetic modeling process I've described for CL. It's kind of like the fun one has when laying down a mathematical proof, or working out a mathematical problem. Now you made it clear in your last post that you do understand pretty much everything I talked about. So it's interesting for me to contemplate why you prefer statically typed languages and the most probable explanation is that you've spent a lot more time with them. Programming languages shape the thoughts that you think after all. Second order cybernetics tells us that the emergent metasystem composed of subject-object [mind-program] interaction can begin to model itself in a new round of cybernetics.

After decades of doing exploratory programming in Lisp-like languages, "extreme late binding of all things" is exactly how my mind thinks about the process of modeling but also about itself. Maybe this is why most of the simple programming errors you've talked about seldom arise with me (or pretty much every hardcore Lisper I would say). Maybe this is also why when you switch to a Lisp-like language with your mind being wired to a statically typed system, these sort of errors are very frequent. It's your mind going through the modeling process in the way that it's used to. Fascinating if you think about it.

So to end with, I can see the benefits of a statically typed language. I would never pick Common Lisp when working with groups of people of different skill levels on a shared vision. I will probably pick OCaml when working out problems in compiler theory. But I will pick a Common Lisp-like language _every single time_ when I'm working on manifesting a singular vision - my own - and I want this process to take place via cybernetic emergence of something greater than myself. In a similar way to Steve Jobs instantly knowing what the future will look like during his trip at PARC, it's obvious to me that "programming" has nothing to do with type systems or computers. These constitute only the medium and the medium will eventually disappear..

[1] https://softwareengineering.stackexchange.com/questions/4659...


> chances are that if it type-checks, it is correct.

a - b type checks where b - a or a + b should have been written.

shuffle(list) type checks where sort(list) should have been written.

sin(x) type checks where cos(x) is required.

The type of the average application code contains very little information. The crucial difference between sin and cos gets bulldozed; both are just number -> number.


Powerful enough type system will catch all of these though.


Right, only you don't know what it's called, where to download it, or how to write the code.


Why? I do. Search for dependent types.

https://github.com/FStarLang/FStar


Calling your bluff; you've never used this.


>only you don't know what it's called, where to download it, or how to write the code.

>you've never used this.

What next? You've asked for an example of powerful typesystem, here, you got it. Other examples are SPARK, Coq, Liquid Haskell, Idris, C++20, Agda.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: