20 ms·
My Increasing Frustration with Clojure
- meeper16 10y agoTime to go back to Tcl.
- bachback 10y agowhat an annoying post. no real content, but an author desperately trying to prove he's smart. "To say that I was treated pretty shabbily by David Nolen on this issue almost goes without saying."
- vimota 10y agoI would say he backs up his claims quite well, unlike your comment. He gave ample evidence at his frustrations with the progress of the language - what did you find annoying about it?
- awwaiid 10y agoI see a lot of issues but not a lot of PRs. As a maintainer there is a lot of prioritization going on, and it seems that the things that bother the blog author are not things that bother the maintainers. I also agree with some of the replies on the issues - garbage in garbage out for a function is ok behavior. One of the cool things about clojure and other languages like this is that these things can often be fixed at runtime - so even if your fix doesn't get accepted you can have a "my-better-fixes" lib you pull in for yourself. A "consistent-set-opts" lib you add to your project.cls for example.
- bpicolo 10y agoIn what way is "garbage in garbage out" better than consistent handling and explicit failure, especially for something so well-defined mathematically? That's sort of a lazy argument, imo. I shouldn't need to pull in more libs for baseline language expectations, either. Core libraries are what languages really are, much more important than just syntax.
- dragandj 10y agoBecause checks to avoid some kinds of garbage can incure significant performance penalty. There is always a tradeoff in that sense, and I think Clojure is pretty well balanced in that way. So, read the docs, try the functions out to see how they work, write tests, and sanitize the data at the appropriate place.
- mcguire 10y agoIf it's good enough for ANSI C, it's good enough for you...
- bpicolo 10y agoMatters so rarely that it's far better to rewrite in those cases when necessary.
- dragandj 10y agoIn core libraries? If low-level functions checked the inputs for each odd case, they'd (often unnecessarily) spend 90% of time doing those checks.
- maherbeg 10y agoI strongly disagree with garbage in, garbage out. We as programmers and engineers should strive for better tooling in all aspects. I firmly believe that reducing footguns and making our tooling help nudge us in the right direction are extremely important qualities.
- hyperpape 10y agoI clicked through to the github exchange he links to, and I don't think you can call that shabby treatment. Perhaps a bit too terse (though I don't think so), but it's just saying "the docs say data must meet requirement X, and that's good enough". His other examples sound prima facie troubling (I don't know enough clojure to have a real opinion), but he's miss-characterizing that interaction.
- mcguire 10y agoOnce upon a time, many years ago, I was taking a database implementation class at the same time as working as a sysadmin of the university. We started having a weird problem with our AIX 3.2.5 (...years ago...) machines: the NFS subsystem would deadlock and become a tar-baby; any process that touched the affected filesystem would block, including other users' processes, system processes, and (the important part) the automounter. As a result, the boxen were effectively unusable until rebooted. Considering that they were serving 8 x-terminals and remote users, that was a problem. We eventually narrowed it down to students working on their DB implementation projects, and further to the use of mmap. If you mmap'ed a region larger than a physical file and wrote to the outside region, that NFS filesystem went belly-up. Yes, that's explicitly mentioned as a thing not to do in the mmap documentation. (On the other hand, it worked fine on a local AIX filesystem and in fact was how local file systems extended files; I'd spent the previous couple of years working with AIX filesystem developers.) Anyway, after getting the professor to tell the students not to do that, I notified IBM tech support. The response I received was exactly, "the docs say data must meet requirement X, and that's good enough". In a sudden fit of ethics (honestly, I have no idea what came over me), I completely failed to advertise the nifty denial-of-service attack widely. It would have been spectacularly amusing to embarrass my former employer on BUGTRAQ, say. Not to mention imagining the face of the tech support guys when they tried reading their "good enough" spiel to an IBM customer who had more than our handful of machines. On the other hand, AIX 4 was a complete re-write and fixed the problem with the NFS filesystems. Yay. Anyway, the bottom line is that using documentation to cover your ass for implementation infelicities is not a very good idea.
- hyperpape 10y ago
- willvarfar 10y agoI'm not a clojure user but I am a fan of Rich's talks so I am kinda taken aback by this - this is just not the kind of Clojure I was expecting from what I know of the principles Rich preaches. I really was expecting belt and braces defensive error checking and never ever giving a dud result.
- mcguire 10y agoIt's a somewhat common problem with Lisps specifically and dynamically typed languages in general. Because the bottom-level operations won't let you do things that are completely idiotic, everything is "safe", so maintaining the sanctity[1] of higher level abstractions sometimes gets lost in the shuffle. I once wrote a blog post about related issues.[2] [1] Ok, so there are lots of terms with just slightly the wrong meanings. I came up with a new one. Sue me. [2] http://maniagnosis.crsr.net/2011/06/some-lisp-suggestions.html?m=1 http://maniagnosis.crsr.net/2011/06/some-lisp-suggestions.ht...
- jonnybgood 10y agoClojure is not a community-driven language. It belongs to Rich Hickey and by extension Cognitect. The bugs that will be fixed and the features that will be added are the ones Hickey cares about. Not saying this is good or bad. It's just how Clojure development is ran.
- aaron-lebo 10y agoThis is the most realistic answer. Steve Yegge was making similar criticisms years back, saying Clojure was "user-hostile". That's probably not fair and largely a matter of opinion (see the link for a back and forth), but it is another piece of evidence that says the Clojure community does things their own way. Not shocking, it's a lisp! https://www.reddit.com/r/Clojure/comments/3jjit5/what_does_steve_yegge_mean_by_clojure_being/ https://www.reddit.com/r/Clojure/comments/3jjit5/what_does_s... Clojure development is opinionated, for good and bad.
- snaky 10y agoThere's nothing wrong to be user-friendly or user-hostile. But it helps to be clear about that up front. Good example, from not user-friendly (but developers-friendly) Linux distro - http://exherbo.org/docs/expectations.html http://exherbo.org/docs/expectations.html
- slantedview 10y ago> Clojure is not a community-driven language > The bugs that will be fixed and the features that will be added are the ones Hickey cares about Those two statements do not compute. A community driven language, or any technology that wishes to attract and retain users, really, should care about the things that its users care about. I can understand that the significance of these bugs might not be well understood by Clojure's maintainers, but that is the problem here. It is the task of technical maintainers to care about the problems of their users (speaking as the maintainer of several projects). It's also worth answering that argument that Clojure is opinionated and therefore the maintainers don't need to fix certain things, because... opinions. This is bogus. Opinions are what lead you to build certain features, like transducers. Caring about quality is what should lead you to make sure they work in a way that is expected (based on how others parts of the technology work, what is least surprising to users, what is documented, etc.)
- nidu 10y agoOnce I tried to make a union of a sorted set and an unsorted one. Result set inherits behaviour of a bigger input set so when i first got my sometimes-sorted set i thought like loosing my mind.
- village-idiot 10y agoOh, that's really annoying too.
- dilap 10y agoAvoiding madness like this is why I have come to really prefer statically typed languages.
- masklinn 10y agoThe issue doesn't have much to do with dynamic typing, any subtyping support can trigger it. Take Java, if Set had a `Set union(Collection)` method a SortedSet could return a new SortedSet (cast as a set, but still with the actual behaviour of a sorted set).
- sanderjd 10y agoBut you would not be able to pass it to a method that takes a SortedSet, which means you can't rely on the sorted behavior. Incorrectly using behavior that your implementation doesn't support is where the confusion comes from, it doesn't come from your implantation having extra behavior that you can't use.
- yawaramin 10y agoIn Java, you can have: class Set<A> { public Set<A> union(Collection<A> c) { ... } } class SortedSet<A> extends Set<A> { @Override public SortedSet<A> union(Collection<A> c) { ... } } In other words, the more specific type overrides the operations of the more general type into more specialised operations.
- dilap 10y agodefnly agree that you can get these problems in languages with static types, but i think you have to go out of your way vs dynamic languages, where these types of shenanigans are easier and (in my experience) prevalent. e.g., in your example, because your returned type is Set, you presumably would not be relying on the result to be a sorted set! -- so there would be no problem. if you WERE relying on it being a sorted set, you would have to explicitly downcast -- i.e. would pointing a gun and at your foot and pulling the trigger. maybe you know it's unloaded, but the danger is clear from the type system. ;)
- catnaroek 10y agoThere are basically four possible attitudes to abstraction: (0) We don't need no stinkin' abstractions! Obviously not befitting a high-level language like Clojure, move along. (1) We enforce abstractions in our heads. Running into an undocumented scenario is undefined behavior. (Yes, in the C sense.) (2) We enforce abstractions via compile-time checks. Clojure won't have this anytime soon, move along. (3) We enforce abstractions via sensible coercions (whenever possible, if desired) or runtime exceptions (anywhere else). Like the author, I find (3) the most sensible choice, and I'm surprised that the Clojure team would rather choose (1), which is known to be a major productivity killer.
- village-idiot 10y agoWow, wish I'd actually enumerated that list for the article. This is a really good summary of my points on the set/union type bugs.
- sethev 10y agoIt seems disingenuous (in the blog post) to act as if Rich was saying that the results of applying union to a list were correct when he was clearly saying that the fact that it produced any value at all was an implementation detail.
- catnaroek 10y agoI think you misread the author's complaint. He's complaining that the `union` abstraction is leaky - it exposes its own ad-hoc implementation choices.
- rurban 10y agoThe underlying issue to me seems to be that Clojure is still not developed by a team, but by a single developer, who cannot think out of the box. union and intersect not doing the same thing as in common lisp (accepting lists and vectors), and returning buggy values instead is just a bug, even if the developer didn't have that in mind originally, and doesn't like to support that.
- eudox 10y ago>union and intersect not doing the same thing as in common lisp Clojure is a different language.
- zacharypinter 10y agoOf all the people in the world I can think of with the inability to think outside the box, Rich Hickey has to be at the bottom of the list :)
- mcguire 10y agoDifferent people have different boxes.
- KingMob 10y agoYou know CL doesn't have a set type, though, right? It supports lists because it has to use a different data type. This turns several O(1) set functions into O(n), however. Also, are you sure vectors are supported in CL? Looking over Common Lisp the Language, the adjoin/member/intersection functions only mention lists. Finally, it's not even clear CL won't return buggy values, either. From the documentation on CL's intersection function: "If either list has duplicate entries, the redundant entries may or may not appear in the result." So it's just as GIGO as Clojure.
- puredanger 10y agoClojure is developed by a team.
- lkrubner 10y agoI love Clojure, and I use it in every project where I have control over the technology, but I do agree with the points raised by Ashton Kemerling. Clojure is beautiful, and backed by beautiful theories, but its implementation needs to be clean or it will eventually develop enough special cases that its beauty will be ruined. In some sense, you could say this is what happened to Ruby, though there the allowance of "special cases" was more deliberate. I recall, back in 2003, reading the interview between Matsumoto and Bill Venners: http://www.artima.com/intv/ruby.html http://www.artima.com/intv/ruby.html -- and I thought that Ruby had a beautiful philosophy. But having worked with Ruby for many years, I now see how much it is undermined by the many special cases it allows, and the wild ambushes that its most imaginative features allow (monkey patching). I don't want to see Clojure go down that path. I want Clojure to remain beautiful, and that means the implementations must also be beautiful. There is a limit on how much the core team can say "That bug is only an implementation detail". If you take away all the implementation details, then Clojure is only a theory, not a real technology that can be used by real people to do real things. In a truly ideal world, Clojure could be the practical Lisp that pushes itself to bring in as much of the experimental Lisp's beauty as is practical. I would love to see the best ideas from Racket and what Fogus refers to as the Fluchtpunkt Lisps: http://blog.fogus.me/2011/05/03/the-german-school-of-lisp-2/ http://blog.fogus.me/2011/05/03/the-german-school-of-lisp-2/ These are ideas that can make the world better. I have high hopes that Clojure will be the project that makes some of these beautiful ideas practical. I will be very sad if Clojure ends up like Ruby or Groovy or Scala, becoming a bit too muddy to reach its full potential.
- agumonkey 10y agoI kinda despise non dogfooding projects. Like realizing that IBM rarely ever uses it's own modeling tools and principles to develop internal or commercial software (at least arount that time). And yes I liked lisp because of its underlying beauty. Scheme did one step further. It reuses itself in many ways. That clojure implementation isn't leveraging it's own quality feels unlispy but alas... it's also a huge effort to blend an immutable first lisp onto a JVM ecosystem. Reminds me of Scala a bit.. one lead dev quit over frustration about the state of the compiler. Maybe seeking 'beauty' is just an immature phase and after a while whatever works enough for you to sell ...
- daniel-levin 10y agoDo you have any experience with attempting to fix these bugs and then submitting patches / pull-requests? Yes, the core team should just fix these bugs. But if they're receptive to upstream changes you want made, then that makes this much less of an issue, in my mind. An open source project's openness depends critically on the core team's acceptance of user patches.
- dustingetz 10y agoI think this article is spot on. But. I think the root cause here is that many of the tools are build by the community. Great tools cost a lot of money to build, and you need to build the right thing at the right time, the cost needs to be spread across the comminuty. The community is growing and tools are improving. The first generation tools with all their rough edges are being replaced by simpler tools that have incorporated lessons of the first gen. Improvement is accelerating. So when the core team focuses on new features like CLJC, Spec, Transit, Transducers, Datomic, ClojureScript, they are doing things that only the core team can do. There are other more opinionated things (like frameworks) that the core team isn't suited to do, everyone's app is too different. The thing i love most about clojure is that all the pieces seem to fit together and be working towards a grander architectural vision much larger than just a language or just a database. I use Clojure not because it lets me code my java/javascript stuff a little better, but because this grander vision makes impossible things possible. The thing I am trying to build is not possible in any other ecosystem today. So I am willing to eat the many little pains described in the article, pains I feel every day, because the grand vision is so powerful, and hope that one day the little stuff will be better.
- _pmf_ 10y agoI think the author is right in his assessment that it's a community problem: the Clojure core team does not want outsiders to participate in the future of the language, but does not clearly communicate this up front. I absolutely support the right for them to do this (I'm a happy user of the non-open C# language, after all), but they should clearly state that Clojure is defined by Cognitect, not the community. Even one of the most prolific Clojure users with a tremendous track record of extremely well engineered and practically useful libraries, Zach Tellman, has been bitten by Rich Hickey's / the core team's NIH syndrome[0]. That's no way to treat the people who love your language. [0] http://dev.clojure.org/jira/browse/CLJ-1517 http://dev.clojure.org/jira/browse/CLJ-1517
- twoodfin 10y agoWhat's the problem with [0]? I am not a Clojure expert, nor have I looked in detail at the patch, but Rich's concerns about megamorphic call sites in library code sound plausible.
- based2 10y agohttps://www.reddit.com/r/programming/comments/4nlhih/my_increasing_frustration_with_clojure/ https://www.reddit.com/r/programming/comments/4nlhih/my_incr...
- based2 10y agohttps://www.reddit.com/r/programming/comments/4nlhih/my_increasing_frustration_with_clojure/ https://www.reddit.com/r/programming/comments/4nlhih/my_incr...
- calibraxis 10y agoI did not see the link to the intersection issue. Is it this? (http://dev.clojure.org/jira/browse/CLJ-1682?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel#issue-tabs http://dev.clojure.org/jira/browse/CLJ-1682?page=com.atlassi...) So "nonsense values" returned by `intersection` means it returns a seq when you pass in a seq? So `(:key_1)` rather than `#{:key_1}`?
- eric_h 10y ago> The thing I am trying to build is not possible in any other ecosystem today Umm... what? I'm afraid I don't understand how the "grand vision" behind Clojure adds pixie dust that makes it capable of something another Turing complete language isn't. Care to elaborate?
- catnaroek 10y agoTuring-completeness is a statement solely about a system's ability to perform computation, in the mathematical sense of the term (take inputs, do something for a while, return outputs, strictly in that order). It says nothing about other desirable properties like usability, extensibility, comprehensibility, etc.
- JustSomeNobody 10y agoYou're getting down voted; probably because the way you worded your question. I'm giving you an up, because I, too, am very curious how something is possible only in Clojure and nothing else.
- dustingetz 10y agoThis is one architecture that is made possible by clojure: http://tonsky.me/blog/the-web-after-tomorrow http://tonsky.me/blog/the-web-after-tomorrow To build it outside of clojure ecosystem, you would need to first build all the pieces of the clojure ecosystem
- deleted 10y ago[deleted]
- jrcii 10y agoThanks for pointing me to that article. I've been mulling over for years how to architect apps to remove the server, that layer never sat well with me. I've also found I couldn't discuss the problem with anyone because "clients can't access the database directly!" is such a knee-jerk reaction.
- Naomarik 10y agoRespect and treatment of people is a real concern. I made a decision not to pick a certain library after seeing people being shut down in the issue tracker in the most unnecessarily abrasive way possible. Clojure does have a lot of amazing people though, and I've been very welcome reaching out to people for help as a whole.
- pdimitar 10y agoThis is my exact sentiment in many areas of life, being an adult who've seen many different ways of treatment of both myself and many others. This exact HN discussion (and the original article) actually made me stay away from Clojure for good. I was curious, I wanted to learn the LISP way of doing things but I'm not gonna pretend that I am OK with people dismissing the possible irrelevance of their language by a death of 1000 paper cuts -- of which several were outlined the by the original article's author. Same thing like the game Mortal Kombat X. Bought it for both myself and my girlfriend and we love it but it turns out Warner Brothers & Nether Realm Studios figured they'll support it only on the console almost immediately after it was released on PC. I have enough money to buy 5 PS4 machines if I want to, and to buy one MKX copy for each. But I won't. I won't support people who treat their users/customers like that. Same goes to Clojure. Same goes for Rails in the recent months when DHH actually has to write articles defending his strong opinions.
- _halgari 10y agoSomething that is often very hard to understand (it took me years to do so). Is that maintaining a language is insanely hard. Everything has a cost. Let me give a good example: A few years back someone submitted a patch that improved the error messages in Clojure. Worked great, just a single extra "if" and a message. It was committed to master. Then people's code got way slower. Why? Well this was a often used function and that single if blew the JVM inline budget causing that function to never be inlined. And that improvement had to he yanked out. When we talk about patches for a language, we have to realize that if we don't want constantly breaking APIs we have to test that a patch doesn't break existing code, that it also doesn't slow down existing code (or at least not enough that users would care), that in all sorts of cases the JVM won't freak out and do something bad. Then we also have to make sure that the change doesn't restrict the language in the future. Does making some interface public mean it will always be public? Are we happy to keep it that way for all time? Taking all that into consideration, I have to sit back and say , yeah, maybe I'll just remember to only hand sets to the functions in `clojure.set`. Or maybe I'll help out by adding clojure.spec annotations for these functions so I can turn them on during testing. In the end, I'd much rather have a rough-around-the-edges language that takes a garbage-in-garbage-out approach, than one that breaks the API at every turn. Perhaps they aren't mutually exclusive, but it certainly takes a heroic effort, and a lot of prioritization.
- lawpoop 10y agoSounds like there might be a potential for a dev and production codebase?
- msbarnett 10y agoThis is in a sense what the clojure.spec work would allow -- dev time exceptions when you violate a function's contract that have no impact on production speed. For some reason the blog's author dismisses spec as irrelevant greenfield development, when it would quite neatly solve many of his complaints
- puredanger 10y agoThat is one of the things we've been considering for a couple years and it's increasingly likely we will do so.
- daxfohl 10y agoOdd, in two years I've never been bit by a single one of these bugs. And if I had, I could probably pretty easily shrug them off. My frustration came from the lack of a type system, and that there's no "myThing." (myThing-dot) to give you intellisense. Even many dynamic language editors have some variant of this now. So coding in Clojure involves too much looking stuff up and memorizing stuff, and is way slower than it should be in 2016.
- dragandj 10y agoWhat editor do you use? Emacs Cider does this, and does it much better than IDEs (IMO).
- daxfohl 10y agoI use Cursive, and yes it has intellisense equivalent to Cider, but still not good enough. In Scala, Java, C#, F#, C++, I can do `myArray.` and it shows all methods available to arrays. No Clojure editor has anything like this. JetBrains editors take it a step farther and even include "code template" options that apply. So typing "myArray." will also include options for "foreach, for, for-reverse" templates. This, in addition to automatically importing any required library for the method you select. With Clojure, there's no "dot". You're stuck hunting through documentation, trying to figure out first which namespace your function belongs to, then requiring it, then figuring out which function you want. Cursive only helps out with that last step, and even then, it displays every function in the namespace, when generally you only want to see the functions that apply to your variable. While I'm all about immutability and structured data types, I've grown slightly away from functional-first languages in general for that reason. Even in F#, you've got to do `myList |> List.map ... |> List.filter ...` etc, requiring more lookup than C#'s `myList.Select(...).Where(...)`. The "dot" is an underappreciated aspect of OOP.
- erichmond 10y agoCursive IDE also does this quite well.
- gabrielc 10y agoI think elixir is a better choice.
- hugdru 10y agoI was thinking of learning a modern language for the web back end. After analysing elixir, go and clojure I decided to go for clojure. Uhmmm, maybe go? I don't know :X. Stick with php? Meehhh
- qaq 10y agoDepends on features you need for the web backend.
- hugdru 10y agoI was looking for a cool new language to learn in the holidays and hopefully do something with it web related. Like a back-end. Nothing serious though. Elixir seems way different from the languages I am used to maybe that is good.
- qaq 10y agoErlang/OTP has a lot of unique features not available in any other environment and Elixir gives you the power of Erlang/OTP with much easier syntax. It's different not because they are trying to be cool, but because it's driven by the unique requirements that allow all those unique features.
- hugdru 10y agoMy bad, that cool really meant something different from what I am used to. Like functional programming, homoiconicity, different paradigms for concurrency, etc. I don't really have any requirements it is just for fun :). Thanks for the info.
- reitanqild 10y agoYou could do worse than learning modern php. Esp. if you have some experience with it and as long as you are ready to leave bad habits behind. (Going for a full stack framework might help here by more or less forcing you to do things the right way.)
- gabrielc 10y agoI think elixir is a better choice.
- stuarthalloway 10y agoAlex Miller is the person primarily responsible for triaging Clojure tickets. For a thoughtful, balanced assessment of the issues Ashton raises, read Alex's detailed comment on the original post: http://ashtonkemerling.com/blog/2016/06/11/my-increasing-frustration-with-clojure/#comment-2725501771 http://ashtonkemerling.com/blog/2016/06/11/my-increasing-fru...
- lgrapenthin 10y agoAs a dev programming in Clojure professionally day to day this complaint (core team not fixing/prioritizing bugs) seems absurd to me. The only example given for a bug is not even a bug but undefined behavior triggered by undocumented API usage. If the author means clojure.spec by "greenfield development" (I don't see what else he could mean) he should really reconsider his complaint since clojure.spec is going to do what he is asking for (throwing a runtime error during development if you use clojure.set with the wrong datatypes). My impression over the last few years is that the core team became truly excellent in reacting to users needs and reports often instantaneously, especially Alex Miller and David Nolen on the CLJS side.
- mcguire 10y ago"The only example given for a bug is not even a bug but undefined behavior triggered by undocumented API usage." C gets a lot of grief about that sort of thing. It's interesting to see current languages taking the same approach.
- lgrapenthin 10y agoCould you elaborate why? (Haven't done much C) - Is the point of view that it is the languages job to prevent the programmer from relying on uncertainties?
- mcguire 10y agoThe C standards take the rather unique approach of dividing behavior into 4 categories: * standard-defined. You can rely on this; if the code you write is limited to this, you're good to go. * erroneous. The compiler is supposed to give you an error message when you write code like this. * implementation-defined. A particular compiler can do something reasonable with the code. If you write code depending on implementation-defined behavior, you're ok, but your code is not portable. A compiler that doesn't do something reasonable in an I-D situation isn't required to generate an error, IIRC. On the other hand, whatever it does is supposed to be consistent. * undefined. There are explicitly no requirements on the compiler. Whatever it feels like doing is fine with the committee. There's no requirement for a compiler warning or error (and by default, there probably won't be one). The reason for the different categories is twofold: 1. C is a systems language. It's frequently used to do things that depend entirely on the specific hardware the code is running on. The result isn't portable, but in this case, it isn't supposed to be. 2. Performance. The idea is that the compiler can take portable code and produce a program that runs very quickly on the specific hardware. As long as the code doesn't do anything non-standard, the results are guaranteed to be good. An example of the latter is signed integer overflow. (I can't remember whether it's I-D or undefined, but...) If you do MAXINT + 1, the resulting value can differ on different hardware; it could be the most-negative integer, it could be zero, it could cause a hardware trap. Now, the C standard could specify what the behavior should be, say generating a signal that kills the program with an error. But that would be very expensive on hardware that doesn't trap signed integer overflow---it would require a check after every arithmetic operation. So the standard doesn't say what should happen. Another example is poking at memory that isn't allocated by your program (on the stack, or the result of malloc, say). You need to be able to express that for systems programming, but a general standard can't say anything reasonable about it. As a result, C has a lot of unsafe corners where you can unintentionally invoke I-D or undefined behavior. In the first situation, your program will break if you try to port it. In the second, your program might work, most of the time. Or it might toss a runtime error. Or it could generate mangled results. Or it could have a really nasty and embarrassing security hole. As a result, C is regarded as a difficult and (unnecessarily?) dangerous language. And most languages that aren't C and aren't aimed at systems programming try very hard to avoid undefined behavior. Even if you manage to avoid security holes, the bugs resulting from mangled results are a royal pain in the ass to track down.
- blain_the_train 10y ago> And the namespace is completely riddled with bugs. union returns duplicates if some of the inputs are lists instead of sets depending on their length. to be clear I assume he is taking about this: ``` try-spec.core=> (clojure.set/union [1,2] [1,2]) [1 2 1 2] ``` Though im not sure what "depending on their length means". > for the above bugs there are two possible fixes: raise an IllegalArgumentException if anything other than sets are provided Isn't this an argument for types? Wont this type of problem be prolific in any dynamic language? What is the union of anything besides sets? > coerce lists and vectors to sets before continuing This only works for very similar data. How do you coerce a map into a set? Is it based on keys or values? What about a string? is it based on the whole string or the characters. I loaded up python3 to see how it was handled... ``` In [7]: set(["hello"]).union(["hello"]) Out[7]: {'hello'}``` is that what you would expect? Maybe. But honestly it should have thrown an error imo. Python is just skirting the issue. A set needs a hashable type. A list isn't one because its mutable. So python knew you "meant" a set of the items in the list... It throws up its hands if you force the issue further: ``` In [8]: x = [1,2,3] In [9]: set(x) Out[9]: {1, 2, 3} In [10]: set([x]) --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-10-0b079714f02c> in <module>() ----> 1 set([x]) TypeError: unhashable type: 'list'``` The problem is that we have handed the union function the wrong type of arguments. That it fails in further down stream is the trade off we make with dynamic languages. The community seems to admit the trade off and alleviate it with things like clojure.spec. Im not mental equipped to argue type theory here. But i suppose i feel this is an _ancient_ argument and saying its a "bug" seems simplistic. > How you define getting the wrong type with nonsense values counts as “working” is beyond me. Is it just because it doesn’t throw an Exception? Anyone here prefer bad data instead of exceptions when dealing with functions like this? I doubt it. This is maybe the deeper problem. You would expect union to fail given the wrong types. Sure the failure wont be a type error but it will be contained inside the function. Leaking out the wrong data means its harder to debug. I'm generally curious how and why set would work on lists at all. As to the rest of the arguments made here. I don't know enough to hazard a guess. But i would appreciate any feedback on my interoperation of the above situation.
- todd8 10y ago
- brandonbloom 10y agoClojure is a language for people who know what they are doing by people who know what they are doing. If you're giving sequences to the set functions, you either (A) don't know what you're doing or (B) have yet to discover that clojure.set is not what you want. Set union can't be done efficiently on arbitrarily sized sequences. At least one of the two arguments needs to offer fast set membership; ideally the larger one, hence the requirement that all arguments be actual sets. If you have sequences, you need to make an explicit decision to pay the cost of indexing (eg. via set or into functions) or you need custom code for your use case. Sure, static or dynamic enforcement could help catch silly errors here, but then the author goes and poo poos on "greenfield" development of things like spec, despite the fact that would "fix the bug" exactly as requested by throwing when you gave non-sets to the set functions. I've followed a lot of the discussion around the supposedly horrible way the Clojure community is run. So far, the absolutely only complaint that I can sympathize with is that communication could be faster, clearer, and softer. Alex Miller has made dramatic strides in improving this, but he's just one man. Cut these guys some slack, they work crazy hard to build and shepherd something awesome for free.
- jgalt212 10y ago> they work crazy hard to build and shepherd something awesome for free. I'm not so sure about that. I'd say that Clojure now exists and thrives to help Cognitect make money. This is no way a bad thing, only a reminder that there is no such thing as a free lunch. In a similar vein, Go exists to help make Google money. The original purpose of open sourcing it was different for Google (make the language more robust/better) than it was for Hickey (grow the language/community).
- brandonbloom 10y agoI anticipated this response to the word "free", but I stand by my statement. Clojure is _free_. If you don't want Cognitect stuff, don't use it. If you don't like how Rich/Cognitect et al are running the project, take your EPL licensed ball and go home. Similarly, in the case of Go: Substitute Rob/Google and BSD-ish license. Just because these languages serve the interests of their respective maintainers does not make them any less free to you. It may make the community less useful to _you_, but hey, they created these things to be useful to them. There's an implicitly mutually beneficial social contract around contributions and community. If you don't like that contract, don't use the language. In the very unlikely case that Cognitect or Google puts some company-specific stuff in the language in a way that actively destroys the good will of this social contract, then and only then do you have any right to complain.
- undershirt 10y ago> To say that I was treated pretty shabbily by David Nolen on this issue almost goes without saying He maintains projects by trying to triage issues in an efficient and emotionless manner. I wouldn't take it as rude though.
- dantiberian 10y agoThe thing to realise about Clojure is that it isn't an open source language like Python. It is a language controlled very tightly by Rich Hickey and Cognitect. Major work is done in secret (transducers, reducers, spec), then announced to the world as a "Here it is!" and then suggestions are taken. This goes well mostly, though it took a lot of outside persuasion that Feature Expressions weren't the best idea, and to come up with Reader Conditionals instead. The underlying problem Clojure/Core has is their communication. If they would come out and explain their philosophy then people wouldn't get frustrated and confused when they expect the language development to work like other open source projects. Clojure's development is functioning exactly as planned. It's not a mistake. A better way to treat Clojure is closer to a project at Apple (except for Swift). You can submit bugs, and make suggestions for future improvements, and if you really want to provide a patch. But go into it realising that it's not a community project, and you're much less likely to get frustrated. With all that said, the proof of the pudding is in the eating, and for the most part Clojure has developed pretty well from Rich's tight control. I'd love it if there was a Snow Leopard year for Clojure where the focus was fixing longstanding bugs and feature requests, and more focus on those in general, but the language is developing well.
- MikeOfAu 10y agoPlease everyone, upvote dantiberian's answer. He nails it. The moment you get over expecting Clojure to behave like a typical "open source" project and understand it is Rich Hickey's personal project (+ Cognitect's), which happens to also be available to you, if you want to use it, then the whole thing makes more sense. Some frustration disappears. You know where you stand, and what to expect. Hickey and Cognitect have every right to run it the way they like. IMO, the only thing they don't do right is to communicate their intentions. There's a pretense maintained around it being an "open source" project, when it really isn't, not in the way that python is open source. Use it if it works for you. Otherwise don't. Don't expect to have a voice, and don't expect you'll be able to contribute much, and don't expect that something will be fixed unless it suits Hickey's Cognitect's agenda. I use ClojureScript, knowing and accepting these things (with some sadness), because I think the language gives me a competitive edge.
- ddellacosta 10y agoI'm having trouble finding much value in this post. It seems to be a combination of the author picking apart very specific aspects of Clojure (clojure.set? clojure.test fixtures?) in a highly opinionated fashion to represent issues with overall project focus, combined with not acknowledging the project's history (maybe that can explain the inconsistency with Protocol usage--as far as I know Protocols only got added in 1.2), combined with not acknowledging the size of the team and what they have to support, combined with not acknowledging how much time is spent on dealing with real, important bugs and performance issues (please see release 1.8's changelog, for example: https://github.com/clojure/clojure/blob/master/changes.md https://github.com/clojure/clojure/blob/master/changes.md), combined with not acknowledging how much new development is actually about features that users really want (see clojure.spec or reader conditionals in 1.7, both of which address long-standing issues previously solved by third-party libraries, as just two things that immediately come to mind). As someone who has been using it professionally for more than three years, there is a ton I have to gripe about in Clojure. Personally I find the hodge-podge type system and inconsistency with how certain core functions handle associative data structures infuriating, and schema/clojure.spec on some level I see as a hacky half-measure, and yes parts of clojure.test are semantically inconsistent and awkward to use in ways that bug me. But: as a language allowing me to get things done in a professional context, as a community of developers with actual adult leadership who are generally welcoming and share a practical, thoughtful philosophy, I think it holds up just fine against other language ecosystems. It would have been quite reasonable to write a blog post about the deficiencies in clojure.set and clojure.test. Write a post about how Protocols could be better used throughout the Clojure codebase itself, and maybe even push some patches up via Jira and see what responses you get. And sure, I've had some prickly interactions with David Nolen myself; he can be that way--he also addresses bugs quickly, is constantly providing answers to questions on IRC and Slack, and is pushing ClojureScript in new and interesting directions while acting as the primary maintainer of the CLJS codebase (I believe?). Point being, some of the issues raised in the piece may be real issues. But they do not represent some kind of overarching deficiency in the team as the author seems to suggest, nor are they necessarily relevant to the majority of developers using Clojure professionally.
- village-idiot 10y ago
- Bahamut 10y agoI'm not a Clojure user, but this article reads to me like complaints about the language's faults, and frustration it isn't solved a particular way. He may be right in some or all of these cases, but some of the phrasing used does not encourage anyone to look at it further. Attitudes like this make me want to quit open source when I encounter it in projects I maintain and/or contribute to.
- hellofunk 10y agoI'm sad to see someone so clearly disappointed by this interesting and innovative product. But considering his frustration, I think it's fair he get a refund. But that's not possible, because it is free. In his own words, he writes Clojure all day and loves his job, all because of this interesting and free product called Clojure. Clojure is far from a perfect language, but what language is? I also love C++ and you'd be hard-pressed to find anyone who thinks it is perfect. There are flaws and unique quirks with any programming language. A good language is like a person: it has a personality with all the good and bad that come with its unique bundle of traits.
- Chyzwar 10y agoJust because something is free do not make it holy and free from critique. I left Clojure because its inherit both Java and Lisp flaws: memory hungry, difficult setup, enterprise frameworks and hard to read, impure and slow. I believe that there still chance for Lisp in Web Assembly.
- dkersten 10y agoI'm a big fan of Clojure and have been since 2009. I'm such a big fan that I run the local Clojure meetup. I do think that Cognitects interaction with the community could be friendlier in terms of bug reports and community patches. They have a bit of a history of not communicating what they're doing (for example, the Zach Tellman thing someone else mentioned). I don't think they need to change much to fix this, they just need to communicate what they plan to do sooner (in the Zach case, they could have told him sooner "hey stop working on that, we'll think about it but aren't sure, it might take some time" so that he knows not to spend a year on it before it gets rejected/NIH-implemented). A tiny change in behaviour would go a long way. Having said all of that, I still <3 Cognitect and Rich and think they're doing great work. I also think that Clojure has a bit of a stability/quality image problem that could be easily fixed: They should put a feature freeze on the language for ONE release and then spend 6 months or so resolving JIRA issues (bugs, stability, quality; not feature or performance tickets). By spending one release cycle on a "bug bash", I think would show the world that they care and that yes, Clojure IS solid. I've never personally been bitten by any Clojure bugs and don't think it actually has of a quality problem at all. In my experience, Clojure is of excellent quality. Its just a perception thing, really. Sure there of course are bugs, but so does every other language. After the 1.9 release is out would actually be an ideal time: spend 6 months on quality and call it Clojure 2.0 ;-) After that, I think people would be much happier to receive new features. I don't think Cognitect will do that though, at least, going by how they've worked in the past and honestly I won't lose sleep if they don't - I'll still love Clojure and will still have buckets of respect for Rich and his team. However, I do think it would benefit the community (and by extension the ecosystem and language).
- thaumasiotes 10y ago> I've never personally been bitten by any Clojure bugs I actually have encountered one; the cl-format function is documented as "implements the common lisp format function", but does not comply with that function's spec. (Unless they've fixed it since I ran into the problem in 1.4, which is sounding unlikely.)
- MustardTiger 10y agoAnd that he is a well known troll.
- dang 10y agoNot so well known that this doesn't cross into personal attack. Please don't like this here. We detached this comment from https://news.ycombinator.com/item?id=11884356 https://news.ycombinator.com/item?id=11884356 and marked it off-topic.
- MustardTiger 10y agoIt is in his post history here, I didn't know "look at the other things this person says" was considered a personal attack.
- tel 10y agoThis particular complaint feels like a typing issue. If functions can accept anything and use lots of partial duck typing then they might partially accept anything and not quite work. There's just an unstated precondition: the arguments are sets.
- bootload 10y ago"Basically I want Clojure to be a simple to use language backed by a friendly and active community. What I see now is drifting in the wrong direction, and I’d like to see that corrected." Opportunity here to create a company, fix the bugs, improve the broken bits, build an editor and release a better clojure and charge accordingly.
- olivergeorge 10y agoInteresting bit to me is the communication problems, not so much the technical ones, we live with tradeoffs. The thing is communicating takes time and busy people are entitled to prioritise "doing" over "talking". As a community, Clojure is defined by the promises made and the processes established. I think "Brand Clojure" is defined by some truly wonderful attributes but it could be improved. Perhaps this could this be fixed with process? For example * Document architectural decisions [1] [2] * Close tickets WONTFIX with a link to the relevant architectural decisions Make that a process/promise so that it becomes a consistently applied approach and it would give the community confidence they are being treated well, heard and respected. "Brand Clojure" becomes more lovable. But these processes also take time and we don't want to burden Clojure core devs. (More realistically, I doubt they'd allow us to impose on their precious time.) So, can this happen without adding overhead for the core developers? I don't know. It's an interesting question though. Can we learn from others online communities on this topic? Are those who do this well based on dev leads who are naturally inclined to communicate? Are any using community funded positions to deliver on communication" outcomes? Sounds like a community advocate/support role: * Triaging tickets ensures inbound communication is effective and helpful. That helps by saving core dev effort. That helps avoid confusion on both sides. * Generate architectural decision docs which can be linked from tickets * Ensure WONTFIX doesn't feel like a dead end. Link to ADs, blog topical workarounds. * Keep architectural decision docs fresh as consequences become more apparent over time. Few ideas in there. Just a thought exercise. -- [1] See Documenting Architecture Decisions http://thinkrelevance.com/blog/2011/11/15/documenting-architecture-decisions http://thinkrelevance.com/blog/2011/11/15/documenting-archit... [2] Is the 'garbage in/garbage out' architectural decision documented?
- puredanger 10y agoI actually would love to have ADRs for Clojure - that's an exceptional idea. The design wiki pages often record much of the decision record, but it's quite common for them to be out of date by the time something is done. Will consider more.
- mbfg 10y agoHickey's latest tweet: If you think you know how I ought to spend my time, come over and mow my lawn while I expound on the problems of dev entitlement culture. https://twitter.com/richhickey/status/741982205392617472 https://twitter.com/richhickey/status/741982205392617472
- slantedview 10y agoJust saw this tweet from Rich Hickey [1]: > If you think you know how I ought to spend my time, come over and mow my lawn while I expound on the problems of dev entitlement culture. All due respect, but I don't think Rich gets it. Other people are spending _their own_ time as well, researching, writing and reporting issues, and in many cases, would be perfectly happy to submit fixes for those issues (and in some cases, they have). It doesn't take any more work for Rich or someone else to look at an issue and say, yes, this is a problem and thank you for fixing it, then it does to say screw you, WontFix. And that is where Clojure has a problem. Rich's argument is really a strawman. Nobody is telling him what to fix, but neither can anyone force him to recognize the importance of fixing long outstanding bugs _in his own work_, even if, thanks to a great community, fixing those bugs wouldn't require him to lift a finger. 1: https://twitter.com/richhickey/status/741982205392617472 https://twitter.com/richhickey/status/741982205392617472
- nikofeyn 10y agoi saw that too. it seems to be a rather childish response. i have recently become very excited about clojure as someone new to it since there are some greatn resources for the language in the form of books (even one on frp), but this ordeal and the clojure people's response has turned me off of it. it seems all peopme are really crying out for is clear and accurate communication. i mentioned this in another comment that this attitude is a stark contrast to the f# and racket communities.
- OlegYch_real 10y agothis is the experience you'll have with any unityped language, because they explicitly move responsibility from library designers to end users and these undefined-behavior bugs are hard to fix because someone somewhere already depends on that on undefined behavior, and it's just a snowball which understandably leaves library designers unresponsive
- trmsw 10y agoThe OP creates tickets with titles like "Clojure.Set Does the Wrong Thing" and then calls people out for poor communication?