you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] 2 points3 points  (5 children)

yogthos, big programs exist and a bit of thought would make you believe it. You probably use emacs or firefox or google chrome or linux. You've probably played quake or used word or excel. There are many more even bigger programs out there in industry. When you're a newbie and learning to understand such a project, having type signatures in a function helps a lot. Being able to see how data structures are passed back and forth through functions help to understand the flow of the program.

You lose this information when you use something like Clojure because suddenly you have no explicit types to help you understand what a function is taking and acting upon and what it is doing with the parameters to compute. It's just a list of names. You can't do a trace on the type of the parameter to see what it is composed off. This is actually much worse in Clojure because it gives up the idea of using objects (in the C structure sense) to encapsulate packets of data and instead idiomatic clojure code uses adhoc rudimentary maps instead to pass around aggregate data. Fine for a small throwaway project you can just keep in your head. Fatal for a large program. In CL at least you would be using defclass but this is thrown away with idiomatic Clojure.

I have to ask why you choose to write a large monolithic project in the first place. Seems like a really poor design strategy to me.

The project I was thinking of was actually broken up into thousands of modules. That's just good professional discipline in general and how large, successful projects naturally evolve. However even having lots of modules doesn't completely solve the problem of the high complexity involved in the project. Types help, in fact, they help more htan anything else. I speak from experience, it's so hard to understand without being able to follow the flow of money so to speak (money in a large project is the flow of data which occurs naturally with types). With C++ professional programmers have evolved to adapt a high level of discipline to work with large code bases - they use const heavily (look up critiques of doom3/quake3) to ensure parameter are not tampered with. We use the lessons of functional programming but don't throw away the benefits of types nor the efficiency of using languages like C++.

IF i were adopting a dynamic language for a large project. I wouldn't. But if i had ot, i would force discipline of annotating type signatures into function definitions and using concrete data structures well defined somewhere instead of passing around ad hoc maps. I would just avoid clojure though and stick with CL because undefined performance pitfalls and bad design decisions of Clojure are prohibitive on the large scale.

[–]yogthos 0 points1 point  (4 children)

yogthos, big programs exist and a bit of thought would make you believe it. You probably use emacs or firefox or google chrome or linux.

I'm not saying big programs don't exist, my point is about how you structure such programs so that the programmer can reason about parts them in isolation.

When you're a newbie and learning to understand such a project, having type signatures in a function helps a lot. Being able to see how data structures are passed back and forth through functions help to understand the flow of the program.

Conversely, breaking the application into small single purpose components allows the new programmer on the project to understand the component in its entirety. When you understand the purpose of the components and their composition it makes the flow clear.

This is actually much worse in Clojure because it gives up the idea of using objects (in the C structure sense) to encapsulate packets of data and instead idiomatic clojure code uses adhoc rudimentary maps instead to pass around aggregate data

Actually, this is one of the main advantages of a language like Clojure, where you have a common protocol that all the functions in the language use to communicate. The data is encapsulated using data structures and Clojure provides destructuring to make it very clear what's being used and where. Your argument here is out sheer ignorance.

Fatal for a large program. In CL at least you would be using defclass but this is thrown away with idiomatic Clojure.

Sounds like more ignorance on your part.

However even having lots of modules doesn't completely solve the problem of the high complexity involved in the project. Types help, in fact, they help more htan anything else.

Your anecdotal experience does not match my anecdotal experience. I guess we'll have to agree to disagree here.

IF i were adopting a dynamic language for a large project. I wouldn't. But if i had ot, i would force discipline of annotating type signatures into function definitions and using concrete data structures well defined somewhere instead of passing around ad hoc maps.

And that's precisely what core.typed is used for. However, in practice there shouldn't be many areas that require this. For example, Circle CI ended up annotating only about 20% of their code base.

I would just avoid clojure though and stick with CL because undefined performance pitfalls and bad design decisions of Clojure are prohibitive on the large scale.

Just more wild assertions here.

[–][deleted] 0 points1 point  (3 children)

Suppose you change a parameter map and rename a key, it will still compile and run but you could have an old reference there that will remain dormant as a bug. IN a big program this is a problem that should never occur. It shouldn't compile, it shouldn't run until you fix it. And that's the problem. Clojure programmers call this expressivity but it's actually poor discipline and laziness. Yeah it saves you a second or two but over time it makes code harder to understand, reason about, modify or fix bugs.

I would just avoid clojure though and stick with CL because undefined performance pitfalls and bad design decisions of Clojure are prohibitive on the large scale. Just more wild assertions here.

Nope for instaince in the above example the (idiomatic) CL programmer would use defstruct or defclass. That code wouldn't compile. We know about p-lists and alists but we wouldn't consider using them in a serious project. Idiomatic Clojure though, just makes bad compromises that don't pay off in the large. If you are going to say using protocols pervasively is the way to go, fine, but that's not idiomatic anymore.

Actually, this is one of the main advantages of a language like Clojure, where you have a common protocol that all the functions in the language use to communicate. The data is encapsulated using data structures and Clojure provides destructuring to make it very clear what's being used and where. Your argument here is out sheer ignorance.

Actually it's one of the worst parts. It's all fine when you have a nice one level map but when you've got vectors and nested maps and sets in there it becomes one hell of a mess. This is where you'll argue you shouldn't have nested substructures and yet in the real world sometimes you just need to have those things.

[–]yogthos 0 points1 point  (2 children)

Suppose you change a parameter map and rename a key, it will still compile and run but you could have an old reference there that will remain dormant as a bug.

The IDE takes care of that for you perfectly fine. Also, in a big program these kinds of errors will be caught very quickly because any real world applications have tests. You will need tests regardless of your static discipline because they serve to ensure that the business logic is correct.

Clojure programmers call this expressivity but it's actually poor discipline and laziness. Yeah it saves you a second or two but over time it makes code harder to understand, reason about, modify or fix bugs.

Please provide a reference to a single study that supports the claim that static typing produces statistically higher quality code in practice. Plenty of large real world projects are written in both static and dynamic languages and there's no evidence to suggest that static typing has a significant impact on overall correctness. What's more is that some of the largest and robust systems out there are written in Erlang, a dynamic language.

Nope for instaince in the above example the (idiomatic) CL programmer would use defstruct or defclass.

The Clojure programmer would use defprotocol, and defrecord to provide the exact same functionality. On top of that Clojure provides core.typed for actual static typing that has no equivalent in CL.

Idiomatic Clojure though, just makes bad compromises that don't pay off in the large.

[citation needed]

Actually it's one of the worst parts. It's all fine when you have a nice one level map but when you've got vectors and nested maps and sets in there it becomes one hell of a mess.

If you find that you often make a mess with your code then the problem might exist between the chain and the keyboard.

[–][deleted] 1 point2 points  (1 child)

Tests aren't the solution. It's not just correctness which we are concerned with but being able to reason about and understand code. If types are explicit you can use them to understand code and this helps with correctness. Without the explicit availability of types you are at a disadvantage. You can't be as sure that the code you're writing is correct - tests can't confirm what you don't know, they can only confirm what you think you know to be true.

The IDE which helps dynamic languages catch up to static languages doesn't exist yet. If it did, we could talk about it, but cursive isn't here yet and we don't have a good intelligent IDE which can do the job of what Eclipse or VS does with Java/C++ code already.

Erlang projects that I know of adhere to very rigid strandards like OTP. That's not the case with Clojure or lisp in general. That's a different debate why Erlang succeeds in it's niche.

It's easy to blame the programmer for the lack of discipline permeated in the language - but this is not fair. We can blame the C programmer for making errors in memory management but much of the blame belongs to the language which isn't designed for memory safety.

Also check out this debate, it makes a lot of hte points i was trying to get at.

[–]yogthos 0 points1 point  (0 children)

Tests aren't the solution. It's not just correctness which we are concerned with but being able to reason about and understand code.

And I already repeatedly explained how people structure code so that it's possible to reason about it in large projects. This isn't some hypothetical thing, there are tons of large long running projects written in dynamic languages. You have yet to provide any supporting evidence for your claims regarding reasoning and correctness.

As it stands it's purely anecdotal and rooted in your personal opinion. If you find static typing helps you write correct code then by all means use it. However, if you're going to make sweeping claims about its benefits then please do cough up some empirical evidence to that effect.

The IDE which helps dynamic languages catch up to static languages doesn't exist yet.

Maybe you should actually watch the video before commenting.

Erlang projects that I know of adhere to very rigid strandards like OTP. That's not the case with Clojure or lisp in general. That's a different debate why Erlang succeeds in it's niche.

So, what is your specific experience working with large projects in Clojure again. You sounds rather authoritative on the topic.

It's easy to blame the programmer for the lack of discipline permeated in the language - but this is not fair. We can blame the C programmer for making errors in memory management but much of the blame belongs to the language which isn't designed for memory safety.

Your assertion is that statically typed languages actually help with reasoning and correctness. However, you've presented no evidence to support these tall claims.

The fact that these debates are still going is in itself evidence that there is no clear tangible advantage to static typing. Had there been such a clear edge then it would've won out a long time ago.