News for hackers. Stuff that matters.
Re:Why I'm Productive in Clojure (2013) by yogthos on Sunday October 22, 2017 @10:39AM (#15527020)
I worked exclusively with statically typed languages for about a decade before moving to Clojure. I've been using it for about 7 years now professionally, and haven't found dynamic typing to be a problem. If it was I would've gone back to using a static language a long time ago.

I think dynamic typing is a lot more problematic in imperative/OO languages. One problem is that the data is mutable, and you pass things around by reference. Even if you knew the shape of the data originally, there's no way to tell whether it's been changed elsewhere via side effects. The other problem is that OO encourages proliferation of types in your code. Keeping track of that quickly gets out of hand.

Clojure embraces immutability, and any changes to the data happen explicitly in a known context. This makes it much easier to know exactly what the shape of the data is at any one place in your application.

Meanwhile, all the data is structured using a set of common data structures. Any iterator function such as `map`, `filter`, or `reduce` can iterate any data structure, and it's completely agnostic regarding the concrete types. The code that cares about the types is passed in as a parameter. Pretty much any data transformations in Clojure are accomplished by chaining functions from the standard library together, with domain specific code bubbling up to a shallow layer at the top.

There's also the culture of using Spec and Schema in Clojure, so you often have assertions at the interface level. For example, there's ring-spec https://github.com/ring-clojure/ring-spec/blob/master/src/ri... providing the specification for Ring.

Re:Why I'm Productive in Clojure (2013) by tomerbd on Sunday October 22, 2017 @12:03PM (#15527406)
Hi, I went on and searched for a random clojure project in github, and have chosen some function which is of a small size:

(defn parse-seq [parse-el form] (when (sequential? form) (reduce #(if-let [parsed (parse-el %2)] (conj %1 parsed) (reduced nil)) [] form)))

without knowing really clojure i take it "[parse-el form]" are the arguments of this function. How is it possible with minimal effort to know what am I supposed to pass as parse-el and form? what are they?

https://github.com/tonsky/datascript/blob/master/src/datascr...

Re:Why I'm Productive in Clojure (2013) by junke on Sunday October 22, 2017 @02:02PM (#15528057)
Let's try to look at it in isolation.

"parse-el" is used as a function, which takes one argument, the first argument when invoked from reduce (the accumulator), which is first [] then another vector (because of conj).

So "parse-seq" parses a sequence (named "form") and produces a vector, or nil. It applies "parse-el" to each form using reduce. When the result of any form gives a nil value, the whole result is also nil (see https://clojuredocs.org/clojure.core/reduced). The result is also nil if form is not sequential.

There is no other contract about "parse-el", it just should be able to "parse" whatever occurs in "form". You could use it on your own with any kind of data that has a corresponding parse function.

A documentation string would have been nice, or different names ("parse-el"?)

Now, if you look at the usage of "parse-seq", you can see for example:

    (let [vars* (parse-seq parse-variable vars)
         ....
And it looks like "parse-variable" parses a form and returns an instance of Variable.

    (defn parse-variable [form]
      (when (and (symbol? form)
                 (= (first (name form)) \?))
        (Variable. form)))
Re:Why I'm Productive in Clojure (2013) by junke on Sunday October 22, 2017 @04:59PM (#15528897)
"the first argument" => "the second argument"
Re:Why I'm Productive in Clojure (2013) by augustl on Sunday October 22, 2017 @12:17PM (#15527473)
This is a very interesting question. To me, understanding in isolation some random function deep down in the code somewhere is not really something I do. Maybe that's why I prefer dynamic languages. And other people like to be able to do that, and therefore prefers static languages.
Re:Why I'm Productive in Clojure (2013) by sgrove on Sunday October 22, 2017 @12:46PM (#15527654)
This has definitely been a challenge for me in Clojure when trying to use a library that isn't well-documented. Using the REPL helps because I can throw random things at it quickly, but it's still very frustrating.

An interesting corollary to this problem though is the wandering type-path, where when consuming (again, poorly documented) a Java library, I know the type of the function I want to call, but not how to get that type. Usually it's:

"I have B value [byte-array, int, whatever] and I need Z from this library so I can call `Z.foo`... Z's constructor takes Y, which takes X, which takes..."

Types help there, but they also hinder quite a bit if I have the correct underlying data type, but can't get Java to accept it.

Re:Why I'm Productive in Clojure (2013) by ajss on Sunday October 22, 2017 @12:34PM (#15527570)
Look at the function doc string. Look at the function spec/fdef Look at the function comments.

OK, there aren't any. Pull requests accepted?