News for hackers. Stuff that matters.
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?