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

It's sad to see that STM is not recommended. It is hugely important in Haskell. I jump to believe that this is an artifact of type-driven STM, but it may be something else instead.

I've recently moved from Component to Mount. It is less powerful but just a vast syntactic overhead reduction.

Absolutely avoid metadata. The worst thing ever is using it like how Reagent does in ClojureScript where it actually provides important program semantics. This is a Terrifically Bad Idea.

Schema is wonderful. Schema is terrible. It is nothing resembling a replacement for static types. The more you use it the more obviously it is deficient for such things.

Absolutely just use Clojure.Test. I don't even understand why this is a question. What is up with cutesy testing APIs?



> Absolutely avoid metadata. The worst thing ever is using it like how Reagent does in ClojureScript where it actually provides important program semantics.

Eh? Reagent does not require any metadata, ever. Much less metadata what provides "important program semantics". So I'm pretty puzzled by your comment. Either you have never used Reagent, or our definitions of metadata is really different, which would be odd, given ClojureScript is pretty clear on what metadata is and isn't.

Optionally, as a convenience, Reagent allows "key" to be provided as metadata but that's really a React thing (and available the same way in OM) and that's because it allows React to supply better performance in some cases, but even then you can supply key via means other than metadata if somehow that offends you. If this is somehow "the worst thing ever" I'd suggest you have lived an overly sheltered life :-)


You can avoid it's use through create-class, but it's freely supported and suggested to use it to access the lifecycle callbacks.

Given that there is a supported and suggested pathway to achieving core functionality of the library which involves the use of metadata to define the semantics of your components I stand by my statement. I'm happy to roll back on "the worst thing ever" if a bit of exaggeration is intolerable, but the fact that this exists in the API is a huge wart even given the fact that it's not required.

Weavejester below suggests that use of metadata like this isn't even such a big deal for Clojure, but I cannot agree. In a language with primarily immutable data structures it's just silly to trust metadata as semantics-bearing given that it's invisible, ubiquitous, and often discarded.

I do really like it on vars, though.


> Given that there is a supported and suggested pathway to achieving core functionality of the library which involves the use of metadata to define the semantics of your components I stand by my statement

Sorry, but you are just completely wrong. Have you ever used Reagent? Reagent doesn't require the use of metadata AT ALL, EVER. Much less in some fundamental way, as you claim.


> Eh? Reagent does not require any metadata, ever.

I am no expert in reagent, but I think it requires it to access Reacts component lifecycle callbacks like `component-did-mount` and such.


Sorry but that's not the case.

    (r/create-class
      {:reagent-render render-fn 
       :component-did-mount (fn [] (js/alert "hi"))})
No metadata there


It's sad to see that STM is not recommended.

Actually, this is not recommendation for a specific use case - a (web based) database application.

For applications that require to manage state internally it might be still way to go (sorry, I am not a Clojure user).


That's true and a good point! I'm reading into this as talking to a much broader context.

STM in a simple request->response web application probably is overkill and I'm much more aligned with his recommendation now.


I don't think I've ever ran across a situation where I've needed STM. Most of the time you can just use pure functions, and when you absolutely need state, an atom is usually the best tool for the job. STM strikes me as a very specialised tool, at least in the context of Clojure.

I don't think metadata is a bad idea. It's data about data. As long as you don't assume something will have the same metadata as the data it's derived from, you should be fine. I don't necessarily like the way Reagent uses it, but it's not out of character for Clojure to use metadata semantically.


Haskell noob here. How is STM used in Haskell? What is type-driven STM?

In Clojure, I don't recommend it because it's Just Another Place To Stick State. It's cool, but provides little semantic value over compare-and-set! on an atom.


If you're using an atom, you're already sticking state in a place; the problem with atoms is choosing granularity. If one atom has everything in it, it will become a point of contention.

If your compare-and-set returns false, what do you do?

STM resolves these issues by letting you coordinate updates to more granular, finer-scoped refs


The drawback here is that the STM (at least the Clojure implementation few years ago when I tested it) is orders of magnitude slower than simple atomic reference.

It actually does not have to be, but this is how it is (was) implemented. I built a simple STM (in Java) as part of my bachelor thesis and its performance was comparable to the atomic reference.


If all you need is a simple atomic reference, then great.

I'm not convinced a single atomic reference sufficiently covers enough use cases, however.


Yes, it probably does not, and I think that using STM is actually fine in Clojure. Just you have to pay attention to the limitations.


> but provides little semantic value over compare-and-set! on an atom

Can you compare and set on multiple atoms at the same time? If not, how do you make updates atomic without using either STM, a global lock, or re-implementing STM yourself with an incremental locking and rollback system.



Aren't atoms a part of STM in clojure?


Nope, atoms are based on simple CAS (Compare And Swap) operation that replaces the reference value. They are pretty much a sugar around AtomicReference in Java (in case of JVM implementation of course).

It is pretty much as like this

  1. Dereference a variable and keep the old reference.
  2. Create a new modified variable.
  3. Use CAS on old reference and new variable 
          to update the reference to point to the new vairable.
    In case of failure (some other thread made the update before) go to 1. 
But the version of SMT implemented in Closure is very similar to the CAS, just now you can apply it to the multiple variables i.e. it is multi variable CAS.

It has the same drawbacks and advantages as atomic references: your code does not depend on lock taking order (as they are managed by the transaction manager) and you avoid dead locks as the locks are taken in the same order before applying the update, but now two different threads can start the transaction to update the same variable, but only one of them can finish as the first one and the other one should be cancelled and repeated.

In principle you can get away with a simple atomic reference (that is much faster) when the set of the updated variables is always the same - you make a pair of them and update them together.


Interesting. I've never needed anything other than the occasional atom.


Nah, you can't update two atoms and make sure they both change at the same time. That being said, 99% of the time you can have one atom, a map, with two keys, and that'll do it.




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

Search: