Re: Next release for clojure.tools.cli? Is it dead?
On Thu 23 Jul 2015 at 09:33:13PM -0700, Keith Irwin wrote: There are some handy additions committed to the tools.cli project at: https://github.com/clojure/tools.cli but there hasn’t been a release in ~1.5 years (not even a snapshot release). In fact, these commits have been sitting there for over a year. I’m especially interested in this one: http://dev.clojure.org/jira/browse/TCLI-9 Any chance of a new release? Sean Corfield has volunteered to be the new maintainer of tools.cli, and knowing Sean, there will likely be a new release very soon. Sung Pae -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout. signature.asc Description: PGP signature
Re: A drawback of the less-parentheses approach
On Mon 9 Jun 2014 at 07:07:42PM -0700, Taegyoon Kim wrote: And you can't do this: user= (let [x 1 (comment y 2)] x) Alex Miller (?) once pointed out that the #_ reader macro can be chained like this: (let [x 1 #_#_y 2] x) Pretty nifty. guns pgpn7C26ipuE0.pgp Description: PGP signature
Re: non-lazy clojure?
On Mon 2 Jun 2014 at 10:38:23PM -0400, Lee Spector wrote: PS would a call to vec do the same thing as into [] here? IIRC vec and into [] are equivalent unless the source collection implements IEditableCollection, in which case transients are used for a significant performance boost. guns pgpL2Biq3LnWB.pgp Description: PGP signature
Re: Question regarding tools.analyzer.jvm and the :tag, :o-tag, and :class entries
On Fri 23 May 2014 at 01:29:54AM +0200, Bronsa wrote: When using tools.analyzer.jvm you have to remember that its primary use-case is as a front-end for a compiler, in this case :tag and :o-tag serve to inform tools.emitter.jvm when to emit a cast thus might not always reflect the :tag meta of the expression :form. I see, that makes sense. In that case I will attempt to preserve the type hints in a namespaced metadata entry before calling the analyzer. Regarding the :tag/:o-tag difference, :o-tag (you can read it as original tag) holds the static type of the node known at that point and might be either inferred by the :tag of some children nodes or from the class of the :form of the node in case it's a literal, :tag on the other hand can be either the same of :o-tag or hold the Class that node needs to be cast to, usually because of an explicit type-hint. For example, ^IPersistentCollection [] will have :o-tag PersistentVector and :tag IPersistentCollection. :class is an attribute of some nodes that deal with host interop forms, like :new, :instance-call and others and holds the Class that node deals with; for example it might hold the Class a :new node is going to instantiate, the Class an :instance-method belongs to etc. This is very helpful, thank you very much. BTW, you don't need to roll your own `analyze` function providing those bindings, jvm/analyze already sets up the right bindings for you. Ah, I should have looked at the source of jvm/analyze. That's much friendlier. Thank you for the reply! guns pgpp_1NFoctow.pgp Description: PGP signature
Question regarding tools.analyzer.jvm and the :tag, :o-tag, and :class entries
Hello, This question is primarily addressed to Nicola Mometto, but I am sending it to the list so it may be helpful to other Clojure developers. Help is appreciated, regardless of the source. I am using tools.analyzer(.jvm) to build a Closeable resource linter, but I have run into the following problem: a function call's type hint is lost when an instance method is called on its output. For example, given the following setup: (alias 'ana 'clojure.tools.analyzer) (alias 'ast 'clojure.tools.analyzer.ast) (alias 'jvm 'clojure.tools.analyzer.jvm) (defn analyze [form] (binding [ana/macroexpand-1 jvm/macroexpand-1 ana/create-varjvm/create-var ana/parse jvm/parse ana/var? var?] (jvm/analyze form (jvm/empty-env (defn analyze-debug [form] (for [ast (ast/nodes (analyze form)) :let [{:keys [op form tag o-tag class]} ast]] (array-map :op op :form form :tag tag :o-tag o-tag :class class))) (defn ^java.io.FileInputStream fis [^String x] (java.io.FileInputStream. x)) I would like to detect that (fis x) returns a java.io.FileInputStream. If I call: (analyze-debug '(str (fis x))) I receive: ({:op :invoke, :form (str (fis x)), :tag java.lang.String, :o-tag java.lang.Object, :class nil} {:op :var, :form str, :tag clojure.lang.AFunction, :o-tag java.lang.Object, :class nil} {:op :invoke, :form (fis x), :tag java.io.FileInputStream, ; ◀ The desired metadata :o-tag java.lang.Object, :class nil} {:op :var, :form fis, :tag clojure.lang.AFunction, :o-tag java.lang.Object, :class nil} {:op :const, :form x, :tag java.lang.String, :o-tag java.lang.String, :class nil}) However, if I call: (analyze-debug '(.toString (fis x))) - ({:op :instance-call, :form (. (fis x) toString), :tag java.lang.String, :o-tag java.lang.String, :class java.lang.Object} {:op :invoke, :form (fis x), :tag java.lang.Object, ; ◀ The type hint is missing! :o-tag java.lang.Object, :class nil} {:op :var, :form fis, :tag clojure.lang.AFunction, :o-tag java.lang.Object, :class nil} {:op :const, :form x, :tag java.lang.String, :o-tag java.lang.String, :class nil}) The :tag of (fis x) is now java.lang.Object, and java.io.FileInputStream is not present in the node. Calling java.io.InputStream#markSupported sheds more light on the matter: (analyze-debug '(.markSupported (fis x))) - ({:op :instance-call, :form (. (fis x) markSupported), :tag boolean, :o-tag boolean, :class java.io.InputStream} {:op :invoke, :form (fis x), :tag java.io.InputStream, ; ◀ The instance method's class :o-tag java.lang.Object, :class nil} {:op :var, :form fis, :tag clojure.lang.AFunction, :o-tag java.lang.Object, :class nil} {:op :const, :form x, :tag java.lang.String, :o-tag java.lang.String, :class nil}) Finally, calling java.io.FileInputStream#getFD on (fis x) returns the expected :tag entry: (analyze-debug '(.getFD (fis x))) - (… {:op :invoke, :form (fis x), :tag java.io.FileInputStream, ; ◀ Also the instance method's class :o-tag java.lang.Object, :class nil} …) Is there a reliable way to retrieve the original type hint of (.method (fis x))? If not, does it make sense to ensure that the metadata of the (fis x) node is constant regardless of its context? And finally, while we're on the topic, what is the difference between the :tag, :o-tag, and :class entries? I have a vague idea based on a quick perusal of the library, but I would be delighted if you could provide a quick summary. Thank you for your hard work on these analyzers! You are laying the groundwork for a whole new generation of Clojure tools. guns pgpfLMYGxbQQb.pgp Description: PGP signature
Re: Count vowels in a string
On Tue 20 May 2014 at 04:22:17PM -0700, Ben Wolfson wrote: There are three vowels in naïve, not two. And watch out for those un-normalizable combining character combinations! Also, another one-liner: (defn ascii-vowel-count [s] (count (re-seq #(?i)[aeiou] s))) Doing this in a multilingual setting, as Ben Wolfson points out, would properly require a second parameter: the set of acceptable vowels in a given Language/Locale/Script (which are all different things). guns pgpCjnJtOko9u.pgp Description: PGP signature
Re: implicit :required behavior in Tools.cli is deceptive
On Thu 15 May 2014 at 10:45:52AM -0700, Bob Larrick wrote: A single element in the cli-options can be as brief as [-p --port A port number] What is non-obvious is that specifying --port PORT has entirely different semantics than specifying --port Like I mentioned on the issue page, this is just a shortcut around passing a `:required` entry with the same information. The motivation behind this is that the resulting option summary mirrors the option vectors: [[-p --port PORT A port number :parse-fn #(Integer/parseInt %)] [-q --quiet Shhh]] -p, --port PORT A port number -q, --quiet Shhh It is easy to tell at a glance that --port requires an option argument, while --quiet does not. If you dislike this syntax (which I borrowed from Ruby), you may replace it with: [-p --port A port number :required PORT :parse-fn #(Integer/parseInt %)] In the first case the command lein run -p 3000 will result in an options map of {:options {:port 3000}}. Can you guess what the same command would produce given the second case? I would expect that an option flag that has not been marked as requiring an argument to be a boolean toggle. This is the convention in C's getopt(1), bash's getopts builtin, Perl's GetOpt::Long, and Ruby's OptionParser. If you're like me, you wouldn't guess {:options {:port true}}. :-/ It is worth noting that in earlier versions of this library --port did result in {:options {:port 3000}}, so this is a change in behavior from previous versions. Yes, this is a change. The old tools.cli/cli still exists for people who do not want to bother with learning a new API (I can sympathize). It has also been upgraded to use the new option tokenizer. The current behavior is neither simple nor easy to understand, and complects the behavior of the flag with the definition of the long option. Again, this is optional sugar. The option vectors are actually compiled to maps: (#'clojure.tools.cli/compile-option-specs [[-p --port PORT A port number] [nil --host :required HOST]]) - ({:id :port :short-opt -p :long-opt --port :required PORT :desc A port number} {:id :host :short-opt nil :long-opt --host :required HOST :desc nil}) You may, if you like, supply the underlying maps instead of the option vectors to parse-opts. The option specification is documented here: https://github.com/clojure/tools.cli/blob/master/src/main/clojure/clojure/tools/cli.clj#L265-L309 I suggest that this implicit behavior be removed and that all options be treated as required unless :required false is explicitly declared. Or perhaps there should be :boolean flag similar to :parse-fn or :default, since :required feels a little overloaded. That way given lein run -p 3000, [-p --port A port number] would result in {:options {:port 3000}} and [-p --port A port number :boolean true] would result in {:options {:port true}}. That would make when a flag will be treated as a boolean explicit and obvious, and make this library a little less frustrating and foot-gunish. You are suggesting that options require arguments by default is less implicit than options are boolean toggles by default. This is unclear to me. As to which default is preferable and less surprising, I prefer the latter since it matches the conventions in C, bash, Perl, and Ruby. My understanding is that the former is the default on Python. Perhaps this is the source of our disagreement? I do agree that the documentation is not clear enough on this matter; I will ameliorate this later today. guns pgp60HSRLzVmo.pgp Description: PGP signature
Re: setting environment variables for all repls?
On Wed 14 May 2014 at 02:41:39PM -0800, Christopher Howard wrote: Hey all, I want (set! *print-length* 40) to be run each time I open lein repl (regardless of the project, preferably). I thought that is what the ~/.lein/init.clj file was for, but apparently not. Set {:repl-options {:init (set! *print-length* 40)}} in your :user profile in ~/.lein/profiles.clj. https://github.com/technomancy/leiningen/blob/master/sample.project.clj#L311 guns pgpSx2dX6LKDq.pgp Description: PGP signature
Re: What does ^{} actually translate to?
On Thu 8 May 2014 at 05:34:19AM -0700, Pascal Germroth wrote: (def f1 doc ^{:x 1} (partial inc)) (meta f1) ; nil, unexpected (meta #'f1) ; contains :doc, but not :x, as expected The definition of partial is: (defn partial ([f] f) ([f arg1] (fn [ args] (apply f arg1 args))) …) So it just calls out to fn. fn is a macro, and returns metadata on form, i.e. the metadata on the literal (fn) form itself. Your ^{:x 1} therefore is lost. (def f2 doc ^{:x 2} #(inc %)) (meta f2) ; {:x 2}, as expected (meta #'f2) ; contains :doc, but not :x, as expected #() returns an instance of FnReader at read-time, so metadata can be attached as usual. (def f3 doc (with-meta (partial inc) {:x 3})) (meta f3) ; {:x 3} (def f4 doc (with-meta #(inc %) {:x 4})) (meta f4) ; {:x 4} with-meta calls .withMeta on its argument at runtime, so everything that implements IObj works. What's interesting is that (meta ^:x inc) ; - nil does not work. I suppose this is because the reader cannot know if the symbol `inc` represents an object that implements IMeta. Hope this is accurate. guns pgpAjaltFssRA.pgp Description: PGP signature
Re: Vim+fireplace+lein repl+tools.namespace give: nREPL: namespace not found
On Fri 2 May 2014 at 09:06:59AM -0700, Oskar Kvist wrote: Hi! I'm using Vim, vim-fireplace, `lein repl`, and tools.namespace. When I run `(tools.namespace.repl/refresh)` from within vim via fireplace, it usually (perhaps always) works the first time. Say there is a simple error like a misspelled word. The second time I try to run `(tools.namespace.repl/refresh)`, I get back the error nREPL: namespace not found. I don't know exactly what causes it. If I search for it on the web, most hits are fireplace issues. But it says nREPL, and maybe namespace not found can have something to do with tools.namespace unloading them while refreshing. If I quit and restart `lein repl`, the error disappears the first time I do `(tools.namespace.repl/refresh)`. But for the second error after the restart, it comes back, i.e. the exact same thing happens as before, only I have managed to fix one more error in my code. Hi Oskar, ctnr/refresh is a good way to reboot the REPL's state without having to restart the process. To do this, it removes namespaces, then re-requires them in dependency order. If you have an error in one of your namespaces, that namespace and all namespaces that depend on it will no longer be available, so you will get namespace not found. There is probably a way to change fireplace to deal with this situation, but for now you should be able to work around this by creating the namespace manually from a namespace that does exist, like the `user` ns: user= (create-ns 'my.broken-ns) The namespace will still be broken, but you should now at least see compiler errors. HTH guns pgpDW8xGdWbno.pgp Description: PGP signature
Re: Vim+fireplace+lein repl+tools.namespace give: nREPL: namespace not found
On Fri 2 May 2014 at 05:16:41PM -0700, Oskar Kvist wrote: Hi guns, thanks for your input! I see, but it only happens from within Vim, not if I run `ctnr/refresh` in the repl outside vim. I made an issue on fireplace's github that describes how to reproduce the problem. https://github.com/tpope/vim-fireplace/issues/149 Oh, I meant that you should run `(create-ns 'my.ns)` from another namespace _within_ Vim. OTOH, I'm happy you've posted an issue. I run into this problem too, but I was content to just work around it. guns pgp11_PruTzNp.pgp Description: PGP signature
Re: Proposing a new Clojure documentation system (in Clojure)
On Thu 1 May 2014 at 09:05:29AM -0700, Mars0i wrote: 1. Functions have complex intended type signatures: Functions can have multiple parameter sequences, because of optional arguments with , and because of complex arguments such as maps. Schema expresses these scenarios quite well, as does core.typed AFAIK. 2. Many functions with a base intended use are also intended to have more general uses. This is particularly common for functions that are part of the Clojure language itself. Constraining inputs to those that satisfy protocols and interfaces goes a long way, and provides considerable flexibility, while still providing meaningful constraints. Have a function that uses `slurp` or `spit` on a parameter? Declare that the parameter satisfies clojure.java.io/Coercions. Have a function that expects any kind of map-like object that supports `get`? Declare that it must satisfy clojure.lang.Associative. And so on. Together with Java type hierarchies, I have found it quite easy to declare polymorphic function signatures using Schema. guns pgpbQdkXAUa7G.pgp Description: PGP signature
Re: How do I detect the end of a file without catching an exception?
On Mon 7 Apr 2014 at 11:07:37AM -0700, Simon Brooke wrote: OK, the second question I've sort of answered for myself, by riffing on the source of line-seq: (defn expr-seq Returns forms from src (assumed to be Clojure source) as a lazy sequence of expressions [^java.io.PushbackReader src] (when-let [expr (read src)] (try (cons expr (lazy-seq (expr-seq src))) (catch RuntimeException eof However, line-seq doesn't bother with catching an exception (presumably because it's not using a PushbackReader). So I come back to my first question: how do I detect the end of a file? Use clojure.core/read with three params: [stream eof-error? eof-value] From the Slamhound source: (take-while #(not= ::done %) (repeatedly #(read rdr false ::done))) guns pgpOWqGF7SNcJ.pgp Description: PGP signature
Re: list all functions in namespace?
On Fri 4 Apr 2014 at 03:53:54PM -0800, Christopher Howard wrote: Is there some trick Clojure command to list all functions defined in a namespace? I use these functions to create cheatsheets on the fly: (defn fn-var? [v] (let [f @v] (or (contains? (meta v) :arglists) (fn? f) (instance? clojure.lang.MultiFn f (defn cheat-sheet [ns] (let [nsname (str ns) vars (vals (ns-publics ns)) {funs true defs false} (group-by fn-var? vars) fmeta (map meta funs) dmeta (map meta defs) flen (apply max 0 (map (comp count str :name) fmeta)) dnames (map #(str nsname \/ (:name %)) dmeta) fnames (map #(format (str %s/%- flen s %s) nsname (:name %) (string/join \space (:arglists %))) fmeta) lines (concat (sort dnames) (sort fnames))] (str ;;; nsname {{{1\n\n (string/join \newline lines which produces output like this: user= (println (cheat-sheet 'clojure.java.io)) ;;; clojure.java.io {{{1 clojure.java.io/Coercions clojure.java.io/IOFactory clojure.java.io/default-streams-impl clojure.java.io/as-file[x] clojure.java.io/as-relative-path [x] clojure.java.io/as-url [x] clojure.java.io/copy [input output opts] clojure.java.io/delete-file[f [silently]] clojure.java.io/file [arg] [parent child] [parent child more] clojure.java.io/input-stream [x opts] clojure.java.io/make-input-stream [x opts] clojure.java.io/make-output-stream [x opts] clojure.java.io/make-parents [f more] clojure.java.io/make-reader[x opts] clojure.java.io/make-writer[x opts] clojure.java.io/output-stream [x opts] clojure.java.io/reader [x opts] clojure.java.io/resource [n] [n loader] clojure.java.io/writer [x opts] Combine (cheat-sheet) with a regex filter on (all-ns), and presto, you have instant, up-to-date Clojure references on command. guns pgpy9lPrkKL1Q.pgp Description: PGP signature
Re: Basic string modification question
On Wed 2 Apr 2014 at 04:06:40AM -0700, Andy Smith wrote: If there is nothing better then I wonder why there isn't something like this in the clojure standard libraries (must be a good reason I suppose)? Its a fairly standard function for a string library isnt it? It would be a terrible function for an immutable string library. StringBuilder and StringBuffer are solid, fast, and working with them in Clojure is painless. the first isnt pure clojure wo I would probably try to avoid this... e.g. what if I want to port to clojureCLR? There are languages that attempt to be multiplatform (e.g. Haxe), but Clojure is not one of them. Seamless interaction with the host platform is an explicit goal. This is an easy trade-off IMO; you give up the hypothetical freedom of switching to entirely new OS/runtime in the future for access to more features and better performance now. guns pgpQEvfXJVwDk.pgp Description: PGP signature
Re: ANN simple-time
On Mon 24 Mar 2014 at 10:24:11AM -0700, ian.tegebo wrote: I found a stackoverflow question discussing :const metadata, but I can't seem to find any official clojure docs about it. Are you aware of any? Well, to be fair, I see it mentioned on the cheatsheet but I can't find any further explanation: http://clojure.org/cheatsheet https://github.com/clojure/clojure/blob/master/changes.md#215-const-defs pgp6eDHO6mMmE.pgp Description: PGP signature
Re: condp first matching predicate
On Mon 17 Mar 2014 at 09:16:25PM -0700, Timothy Pratley wrote: Is there a better way to write (cond (neg? 1) neg (zero? 1) zero (pos? 1) pos :default default) … But I think I'm missing a more idiomatic approach. FWIW, the `compare` function works well in this particular case. ([neg zero pos] (inc (compare x 0))) guns pgpnKxNxu6_4y.pgp Description: PGP signature
Re: STM and persistent data structures performance on mutli-core archs
On Fri 14 Mar 2014 at 02:15:07PM -0400, Gary Trakhman wrote: Everything has tradeoffs. One more example was when Martin explained how he was able to get a 10x performance boost by pinning a JVM to each socket in a server, then pinning that JVM's memory to the RAM sockets closest to that CPU socket. Then he carefully setup shared memory message passing via burning one core on each CPU to monitor the queues, and moving messages only in the directions directly supported by the Hyper Transport bus. Once again, that's amazing...once again I've never needed that to ship a product. This is absolutely fascinating to me. The ability to do this sort of thing is a tradeoff from using abstractions (threads, OS threads, Java threads) that closely match or can be massaged to match or 'have sympathy' for the hardware realities. I think this can get lost when we stray too far. cf. the C10M project: http://c10m.robertgraham.com/p/blog-page.html tl;dr The kernel gets in the way of extreme hi-throughput, so if that's what you want, don't lean on the kernel to do your packet routing, thread scheduling, etc. guns pgp0TBkBnDTzD.pgp Description: PGP signature
Re: tools.cli and required arguments
On Wed 22 Jan 2014 at 01:48:22PM +0100, Alf Kristian Støyle wrote: From the documentation it seems that specifying the second part of the long option should be enough to make an argument required. So this minimal example should also produce errors: (def cli-options-simplified [[-p --port PORT Port number]]) ;= (var user/cli-options-simplified) (:errors (parse-opts [] cli-options-simplified)) ;= nil So what are we misunderstanding? Any pointers would be greatly appreciated. Using Clojure 1.5.1 with tools.cli 0.3.1. Hi Alf, An option with a required argument (via --port PORT or the :required entry) only specifies that the option must be followed by an argument _if_ it is specified on the command line. For example, $ cmd --port is an error, but simply $ cmd is not. If you would like require that --port must be specified in every invocation, you can assert its existence/value in the options map: (let [{:keys [options errors …]} (parse-opts argv cli-options)] … (assert (:port options) `--port` must be specified) …) You can, of course, set a :default value for a required option. HTH guns pgpBXXVLuJtaf.pgp Description: PGP signature
Re: Simple Macros
On Tue 21 Jan 2014 at 07:33:43PM -0800, Alejandro Ciniglio wrote: I was wondering if people had advice on when to write these sorts of macros vs. when to just use the trivial expansion in the code? (Or alternatively, what am I missing in this macro definition?) (defmacro go-loop Like (go (loop ...)) [bindings body] `(go (loop ~bindings ~@body))) go-loop needs to be a macro to capture the unevaluated let bindings: (go-loop [i 0] …) If go-loop were a function, this code would throw an error because i is undefined. guns pgpV9FBLIxrCe.pgp Description: PGP signature
Re: tools.cli and required arguments
On Wed 22 Jan 2014 at 02:21:51PM +0100, Alf Kristian Støyle wrote: Would be nice to be able to specify that an option must be specified in every invocation though. I think it would lead to better error messages, e.g. if several mandatory options are forgotten, they will be shown at once. That is a bit of a hassle when doing it yourself. Haven't looked too hard at the source though, but any chance of contributing a patch to something like that? E.g. [[-p --port PORT Port number :mandatory true]] I think the nicest thing about the original design of tools.cli is that it is conceptually a transformation of a default map of values into another map of values. Kind of like: (reduce option-rules default-map ARGV) ; = new-map From this POV, it makes more sense to me to assert the shape and value of `new-map` than to validate the membership of `ARGV`. I hope this makes sense. That said, there is definitely plenty of room for a more convenient framework on top of tools.cli. The recent reboot of the library was primarily aimed at increasing the flexibility of the argument tokenizer (e.g. supporting GNU option conventions) and that of summary generation. I purposefully made no attempts at adding anything fancier than that since the API change was already jarring. Also, in my experience with CLI libraries in other languages, programmers simply cannot agree on a single way to structure command line programs. Therefore, it my hope that `parse-opts` can at least serve as a common base between such libraries and for Clojurists interested in rolling their own.¹ If a clear favorite does emerge in the future, then that will be a great candidate for inclusion in tools.cli before an eventual 1.0 release. Cheers, guns ¹ What is unfortunate is that many libraries ship with their own ad-hoc parsers that use regular expressions or simple word matching. `parse-opts` tokenizes input before parsing so things like clumped options (`-abc`) are properly handled. pgp3eImZv75sZ.pgp Description: PGP signature
Re: avoiding repetition in ns declarations
On Tue 21 Jan 2014 at 11:15:50PM -0800, t x wrote: Hi, I have the following problem: (ns foo.bar ... ... ... ) There's basically 10 lines of require that I want as part of nearly _every_ ns I declare is there a way to define some soft of alias / abbrevraviation that is used in namespaces at will? Have you taken a look at Slamhound? https://github.com/technomancy/slamhound You can avoid the onus of manually managing ns references while retaining the advantages of explicit declaration. guns pgpTA26r2eu4H.pgp Description: PGP signature
Re: Namespaces [was Re: Is Clojure right for me?]
On Sat 28 Dec 2013 at 12:21:22AM -0800, Mark Engelberg wrote: You have to thread your shared state through all the functions (what I described as Solution 2), and if you don't want the difficulty of refactoring to that way of doing things, you better just do it that way from the beginning. I agree that the approach outlined by Component is essentially your Solution 2 + stop complaining and just do it this way. You stated earlier: Solution 2 is irritating because if you use a map for shared-info, you end up having to repeat the destructuring in every single function. Also, you need to thread this information through all the functions, not only the functions that directly use, but also the functions that call other functions that use it. This is where one could argue that passing the entire local context to every function to approximate the convenience of OO is sloppy design. I have found that carefully writing functions in terms of very specific input has resulted in very modular, reusable, and testable code. Of course, this is no surprise; these are the rewards of FP. Writing programs in this fashion often feels difficult because it demands more design up front, whereas writing closures/methods in the environmental soup of the namespace/global configuration/instance is really quite easy because all the necessary data is at hand. Furthermore, it would be absurd to have to thread some precision variable as the first input to every single arithmetic operation. Can you imagine how annoying Clojure would be if it made you do that? … So we have a dilemma -- it's awkward to thread decimal precision through all operations, and binding isn't good enough. It would be annoying if it were mandatory, but it is easy to make it optional. Alternately, you could create versions that take an explicit precision argument, then write a macro that takes a precision and rebinds the these arithmetic fn symbols with partially applied versions within the body: (defn +. [precision xs] …) (defn *. [precision xs] …) … (defmacro with-precision [precision body] `(let [~'+ ~(partial +. precision) …] ~@body)) The amount of magic in this macro can be adjusted to taste, but it will work with lazy-seq, and is also pretty convenient. Can we do better? Overall, it seems to me that you are looking for a better way to manage implicit parameters¹. However, I imagine a sizable part of this community is here precisely because of negative experiences with systems with large amounts of implicit data. To the extent this is true, you're likely to get the same don't do that as a response. guns ¹ Perhaps with something akin to an instantiable namespace? :) pgpoYxal8Gnkm.pgp Description: PGP signature
Re: Namespaces [was Re: Is Clojure right for me?]
On Sat 28 Dec 2013 at 05:12:24AM -0600, guns wrote: (defn +. [precision xs] …) (defn *. [precision xs] …) … (defmacro with-precision [precision body] `(let [~'+ ~(partial +. precision) …] ~@body)) I just realized that this does not help with functions already defined in terms of the existing arithmetic functions, which is the problem that you posed. So I guess the answer is still to explicitly pass your precision to every function that requires it. This seems onerous, but we gain the important advantage of transparency. guns pgprpWXAVEfE8.pgp Description: PGP signature
Re: Namespaces [was Re: Is Clojure right for me?]
On Fri 27 Dec 2013 at 11:40:45AM -0800, Mark Engelberg wrote: On Fri, Dec 27, 2013 at 11:03 AM, Gary Trakhman gary.trakh...@gmail.comwrote: Why should functions share information? Maybe I'm the odd one out, but every project I've done has at least a few bits of info shared by many functions. It might be something like BUFFERSIZE or NUM-THREADS or DATABASE_URL. In OO systems we typically have an Application class with a constructor that receives a map of configuration values. This allows more flexibility than defining static constants as the methods of our Application class close over the instance values. We can achieve the same thing in Clojure, but creating closures over dynamic configuration values is difficult to reconcile with REPL driven development. Typically then, the Clojurist chooses to store these instance values in vars, which creates the tension described in this thread. Stuart Sierra has been thinking quite a bit about this issue, and I think he's developed a great solution: https://github.com/stuartsierra/component/ Designing a system as outlined above results in a modular application with the benefits of an instance constructor, while still allowing easy access from the REPL via a single var bound to the current running instance of the application. I encourage everyone to look into it; I have had great success with it so far. (Thanks Stuart!) guns pgp8B_Qd2JTzv.pgp Description: PGP signature
Re: In your opinion, what's the best, and what's the worst aspects of using Clojure?
On Fri 27 Dec 2013 at 11:03:20PM -0500, Lee Spector wrote: On Dec 27, 2013, at 10:53 PM, Alex Baranosky wrote: I always hear people say that the errors are bad, but I just don't see it. The stacktraces say exactly what went wrong and at what line of the source. To me that's all I can hope for. I'll have to agree with Alex, I've never really had that much of a problem with Clojure errors. A stacktrace is certainly better than Segmentation fault. One can hope to see the values of locals, which for me would make a big difference. This is apparently possible (through some combination of nrepl-ritz and avoiding locals clearing, I think), but not at all easy. In other parts of the Lisp universe this has been standard for decades and, I think, central to common debugging practices. I personally use the following macro from my user.clj: (defmacro dump-locals [] `(clojure.pprint/pprint ~(into {} (map (fn [l] [`'~l l]) (reverse (keys env)) It's not the automatic break-on-exception-and-start-local-repl of CL + Emacs, but it's editor agnostic and usually does the trick. I find that my desires for a stepping debugger are mostly absent with Clojure as data is immutable, and the reference types may be monitored with add-watch. guns pgpGmxZq3WqAn.pgp Description: PGP signature
Re: In your opinion, what's the best, and what's the worst aspects of using Clojure?
On Fri 27 Dec 2013 at 11:23:22PM -0500, Lee Spector wrote: On Dec 27, 2013, at 11:18 PM, guns wrote: I personally use the following macro from my user.clj: (defmacro dump-locals [] `(clojure.pprint/pprint ~(into {} (map (fn [l] [`'~l l]) (reverse (keys env)) It's not the automatic break-on-exception-and-start-local-repl of CL + Emacs, but it's editor agnostic and usually does the trick. When and where do you call this? I call this inside of the closest function that raised the exception. I can live without the local REPL (although I'll always miss it), but what I want is to see the locals when I hit an exception somewhere that I didn't expect one. I'd like every exception to dump locals, all up the stack if possible. Can this, or something like it, do that? Like you mentioned, I've heard nrepl-ritz does this in emacs, and David Greenberg has something like this set up for vim: https://github.com/dgrnbrg/vim-redl I don't use this myself, however. The dump-locals macro is essentially a fancy way to do printf debugging, which I have found sufficient. guns pgpIhJDs6U1gr.pgp Description: PGP signature
Re: computed docstrings
On Fri 20 Dec 2013 at 05:04:13PM -0800, Dave Tenny wrote: Is there any alternative I'm missing short of writing my own macro to allow non-string forms for docstrings? Use the ^ reader macro to set the :doc entry: (def my-docstring foo bar) (defn ^{:doc my-docstring} foo []) guns pgpGliEWfoje7.pgp Description: PGP signature
Re: [ANN] clojure.tools.cli 0.3.0 released
On Tue 10 Dec 2013 at 01:54:21PM -0600, guns wrote: I am happy to announce the beta release of the next version of clojure.tools.cli: https://github.com/clojure/tools.cli Okay, tools.cli 0.3.0 has been released. Thanks to everyone for trying the beta! I look forward to fielding questions and feature proposals on JIRA and the github page. Leiningen dependency information: [org.clojure/tools.cli 0.3.0] Maven dependency information: dependency groupIdorg.clojure/groupId artifactIdtools.cli/artifactId version0.3.0/version /dependency Cheers, guns pgpCT8Mbdtcrt.pgp Description: PGP signature
[ANN] clojure.tools.cli 0.3.0-beta1
Hello everyone, I am happy to announce the beta release of the next version of clojure.tools.cli: https://github.com/clojure/tools.cli#new-features Leiningen dependency information: [org.clojure/tools.cli 0.3.0-beta1] Maven dependency information: dependency groupIdorg.clojure/groupId artifactIdtools.cli/artifactId version0.3.0-beta1/version /dependency The project README linked above has the details, but here is a summary: * There is a new function, clojure.tools.cli/parse-opts, that supports - GNU option conventions (`-abc` - `-a -b -c`, `--long-opt=ARG`) - In-order argument processing (for separate subcommand options) - Option argument validations - Custom option summaries - Error handling without throwing exceptions * tools.cli now ships with a ClojureScript namespace: cljs.tools.cli parse-opts has been ported to CLJS with feature parity. * The previous function, clojure.tools.cli/cli, has been adapted to use the new option tokenizer, but otherwise remains unchanged. Upgrading is therefore encouraged even if you do not plan on migrating to parse-opts. Though it has been superseded, cli/cli will not be removed in the forseeable future. My goal with this new version is to convince application and library authors to choose tools.cli/parse-opts over hand-rolled parsers! In pursuit of this, I welcome feedback from the community so we can make amendments before a final release. Finally, I would like to express sincere thanks to Gareth Jones for giving me the opportunity to contribute to the tools.cli project. Cheers, Sung Pae pgpXoqWmJQKEz.pgp Description: PGP signature
Re: [ANN] Slamhound 1.5.0 + screencast + Vim plugin
On Mon 2 Dec 2013 at 12:42:46AM -0800, Patrick Kristiansen wrote: On Sun, Dec 1, 2013, at 05:16 PM, guns wrote: I hope you find this information useful. Exactly one year ago I became very unsatisfied with Vim for working with Clojure, and toyed with Emacs for a bit (evil-mode). It was nice, but I decided to stay with Vim and create the tools that I felt I was missing. Today, I am a very happy hacker! Well, I'm familiar with both your static Clojure files for Vim (which I know Meikel Brandmeyer is the original author of) and vim-sexp, and these make me a happy hacker too :-) Ah, sorry for the lengthy ad for vim-sexp then :) Thanks for your work. I really appreciate it. Especially thanks for getting good enough to write VimScript, which I haven't had the courage for yet. ;-) Yes, VimScript is pretty terrible; it actually reminds me quite a bit of PHP. When Github used to list the supposed favorite languages of users, my top language was listed as VimL, which was embarassing. That said, there's still lots of low-hanging fruit as far as Vim/Clojure plugins, so such projects are well-appreciated the dozens of us in the community. Thanks for trying Slamhound! guns pgpWCbf66WU2n.pgp Description: PGP signature
Re: [ANN] Slamhound 1.5.0 + screencast + Vim plugin
On Sun 1 Dec 2013 at 01:24:15AM -0800, Ruslan Prokopchuk wrote: Does it work with ClojureScript? If yes, how should I process? I'm sorry to say it does not. However, as the CLJS compiler is more accessible than the Clojure compiler, I imagine CLJS would be the first candidate for a hypothetical future version of Slamhound that uses static analysis. I hope to give this a try in the future, if someone else doesn't get to it first! guns pgp9YKuS_RKFV.pgp Description: PGP signature
Re: [ANN] Slamhound 1.5.0 + screencast + Vim plugin
On Sun 1 Dec 2013 at 02:31:54PM -0800, Patrick Kristiansen wrote: Great work! Thank you for the compliment :). Slamhound is a great tool, so I hope I can convince more people to try it out. Regarding the screencast: I would be very interested to hear about your Clojure development setup with Vim, especially the plugins and configuration you are using. I see you are using some sort of split view with Vim on top and a REPL at the bottom. Is that GNU screen split in two or something? The split view is a tmux feature. I typically run a headless nREPL in one pane, then use the zoom feature to focus on the pane running Vim. I was once a GNU screen user, but tmux is superior in most aspects, and also sports some of the prettiest C I've ever seen. As for Vim, version 7.3.803+ now ships with Clojure runtime files¹, which I use together with fireplace.vim². Many people don't know that fireplace exposes a generic eval function³ that makes writing Vim-nREPL plugins extremely easy. For instance, vim-slamhound is essentially just this bit of VimScript: ``` function! slamhound#reconstruct(file, textwidth) let file = escape(a:file, '') let tw = a:textwidth 1 ? 80 : a:textwidth call fireplace#eval( \ (require 'slam.hound 'clojure.pprint) \ . '(let [file (clojure.java.io/file ' . file . ')]' \ . ' (binding [clojure.pprint/*print-right-margin* ' . tw . ']' \ . '(slam.hound/swap-in-reconstructed-ns-form file)))' \ ) edit endfunction command -bar Slamhound call slamhound#reconstruct(expand('%'), textwidth) ``` As Vim users we have to settle for building strings rather than composing S-expressions, but this works quite well despite. Finally, I use vim-sexp⁴ for manipulating code. I wrote this plugin earlier in the year because I wanted to work with Clojure's S-expressions as first-class text-objects. The builtin bracket and string text objects are often lacking in subtle ways, so I spent a bit of time making text objects for all three types of compound forms, patterns and strings, comments, and a generic element type. Combining these with Vim's operators makes hacking on Clojure a very pleasant experience. Vim-sexp also provides commands for wrapping, splicing, raising, capturing, emitting, and moving S-expressions, as well as paredit-like bracket and quote insertion (i.e. balanced insert, auto-insertion of leading and trailing spaces). Unlike paredit.el, however, vim-sexp does *not* try very hard at all to keep brackets and quotes balanced, since that is not very Vim-like. IMHO manipulating S-expressions in Vim should generally be done precisely with operator + text-object, not sloppily with the backspace key. I had hoped to release a screencast on vim-sexp months ago, but I never did finish it. When I do complete it, I plan on announcing it to the VimClojure mailing list⁵, which is recommend for discussions specific to Vim and Clojure. I hope you find this information useful. Exactly one year ago I became very unsatisfied with Vim for working with Clojure, and toyed with Emacs for a bit (evil-mode). It was nice, but I decided to stay with Vim and create the tools that I felt I was missing. Today, I am a very happy hacker! Cheers, guns ¹ Otherwise available at https://github.com/guns/vim-clojure-static courtesy of Meikel Brandmeyer, the primary author of these files. ² https://github.com/tpope/vim-fireplace ³ https://github.com/guns/vim-fireplace/blob/master/plugin/fireplace.vim#L525-L527 ⁴ https://github.com/guns/vim-sexp ⁵ https://groups.google.com/forum/#!forum/vimclojure pgpa87x6to9IW.pgp Description: PGP signature
Re: [ANN] Slamhound 1.5.0 + screencast + Vim plugin
On Sat 30 Nov 2013 at 09:29:30AM -0500, Bob Hutchison wrote: This is a great idea… but I’m having an awful time getting it to work. Hello Bob, I'm sorry to hear that setup is problematic. If it's trouble for you, it's bound to be trouble for others. Would you be willing to open a new issue on the bug tracker? https://github.com/technomancy/slamhound/issues/new Just copying and pasting your email would be very helpful. I suspect there are a couple of hidden problems that are general to all users, so I am eager to help you. However, the changes it makes to the namespaces are excellent! I'm glad to hear there is some good news! guns pgpKzv1zuBJH4.pgp Description: PGP signature
[ANN] Slamhound 1.5.0 + screencast + Vim plugin
Hello, I am happy to announce version 1.5.0 of Slamhound, technomancy's amazing ns rewriting tool. ;; ~/.lein/profiles.clj {:user {:dependencies [[slamhound 1.5.0]]}} This is a *major* bugfix release. If you've tried Slamhound in the past and felt frustrated, now is a great time to give it another try. If you're unfamiliar with Slamhound, I've posted a short screencast here: https://vimeo.com/80650659 Many thanks to Phil Hagelberg for allowing me to take the reins for this release. Enhancements since the last version include: - Greatly improved detection and disambiguation of missing ns references. Slamhound is now much better at DWIM. - References in the existing ns form are always preferred over other candidates on the classpath. - Mass-referred namespaces (via :use or :refer :all) are preserved as (:require [my.ns :refer :all]). Simply remove it from the ns form to get a vector of explicit refers. - File comment headers, ns metadata maps, docstrings, and :require flags (:reload et al), are correctly preserved. - Multiple options per require libspec are emitted correctly. e.g. (:require [clojure.test :as t :refer [deftest]]) - Classes created via defrecord/deftype etc are correctly found. - Capitalized vars that shadow class names are no longer ignored. A full changelog is available here: https://github.com/technomancy/slamhound/blob/master/CHANGES Finally, for Vim users there is a new plugin for Slamhound integration: https://github.com/guns/vim-slamhound It was always easy to use Slamhound from fireplace.vim, but now it's just a Pathogen infect away. Cheers, guns pgprTWW8hPLqL.pgp Description: PGP signature
Re: [ANN] optparse-clj: Functional GNU-style command line options parsing
On Fri 22 Nov 2013 at 07:22:20PM -0500, John Szakmeister wrote: This looks very nice. Have you considered something along the lines of Python's argparse? http://docs.python.org/dev/library/argparse.html Thank you. I am not familiar with Python's argparse. My experience with option parsers are primarily the C functions getopt and getopt_long, the getopts builtin in bash, and Ruby's OptionParser. On first scan, argparse and OptionParser appear to be very similar, both in capability and programming interface. I know OptionParser particularly well, and while I enjoy its flexibility and power, the actual implemention and scope of what it tries to accomplish are quite un-Clojuresque. The beautiful thing about tools.cli is that it is conceptually very simple: it reduces an option specification and a list of arguments into a map of configuration options. IMHO, printing elaborate usage banners, associating subcommands with methods, managing options of subcommands, and invoking behaviour should be handled separately from option parsing. The guiding principle of optparse-clj and the next version of tools.cli is to provide data and let the user take it from there. It's nice to see you thought about subcommand support as well. Thank you for your contribution! The gist I linked to earlier¹ contains a detailed proposal for how I'd like to advance tools.cli. If you are interested, comments on that are much appreciated. Cheers, guns ¹ https://gist.github.com/guns/7573819/raw pgpLaYZua_fTs.pgp Description: PGP signature
Re: [ANN] optparse-clj: Functional GNU-style command line options parsing
On Sun 25 Aug 2013 at 09:05:15PM -0500, gaz jones wrote: Hey, i am the current maintainer of tools.cli - i have very little time to make any changes to it at the moment (kids :) ). I'm not sure what the process is for adding you as a developer or transferring ownership etc but if I'm happy to do so as I have no further plans for working on it. Hello Paul, Gareth, and everyone else interested in tools.cli, I finally noticed that my Clojure CA acceptance was noted on http://clojure.org/contributing, so I have submitted my proposal on JIRA: http://dev.clojure.org/jira/browse/TCLI-6 The formatting is a bit ugly, so here is a plain text version: https://gist.github.com/guns/7573819/raw/26fc5a741d78b9cf1753fcde1a071dd467d44b4f/tools.cli.proposal.mail Comments are appreciated. If this is acceptable to all, then I will happily begin work on it ASAP. Cheers, guns pgpWntqn55ldL.pgp Description: PGP signature
Re: [ANN] optparse-clj: Functional GNU-style command line options parsing
On Wed 20 Nov 2013 at 06:32:49PM -0600, guns wrote: The formatting is a bit ugly, so here is a plain text version: https://gist.github.com/guns/7573819/raw/26fc5a741d78b9cf1753fcde1a071dd467d44b4f/tools.cli.proposal.mail Sorry for the double post. The url above should be: https://gist.github.com/guns/7573819/raw The first one posted contains an error. guns pgphmd5ugC3vj.pgp Description: PGP signature
Re: core.async - handling nils
On Wed 28 Aug 2013 at 09:38:06AM +0800, Mike Anderson wrote: Of course, if anyone has an actual technical argument why it is necessary/better to use nil as a sentinel value, I would be delighted to learn of it and would consider myself enlightened. Forgive me if someone already mentioned this, but isn't this simply a consequence of building on the existing Java Queue implementations? Quoting http://docs.oracle.com/javase/7/docs/api/java/util/Queue.html: Queue implementations generally do not allow insertion of null elements, although some implementations, such as LinkedList, do not prohibit insertion of null. Even in the implementations that permit it, null should not be inserted into a Queue, as null is also used as a special return value by the poll method to indicate that the queue contains no elements. I think most would agree with you that a configurable sentinel value is best (I like using ::namespaced-keywords myself), but the existing machinery has already decided on null, so that's what we have. guns pgp6xD5GT3rVU.pgp Description: PGP signature
Re: core.async - handling nils
On Tue 27 Aug 2013 at 07:42:53PM -0700, Mikera wrote: On Wednesday, 28 August 2013 09:54:51 UTC+8, guns wrote: On Wed 28 Aug 2013 at 09:38:06AM +0800, Mike Anderson wrote: Of course, if anyone has an actual technical argument why it is necessary/better to use nil as a sentinel value, I would be delighted to learn of it and would consider myself enlightened. Forgive me if someone already mentioned this, but isn't this simply a consequence of building on the existing Java Queue implementations? Quoting http://docs.oracle.com/javase/7/docs/api/java/util/Queue.html: Queue implementations generally do not allow insertion of null elements, although some implementations, such as LinkedList, do not prohibit insertion of null. Even in the implementations that permit it, null should not be inserted into a Queue, as null is also used as a special return value by the poll method to indicate that the queue contains no elements. I don't think that this necessarily implies that we have to follow this model in the future Clojure API though. The Java designers didn't always get everything right :-) I agree with you that this is an inconvenience. The bit about avoiding null even in collections that support null elements because poll uses null as a sentinel value is a classic leaky abstraction. That said, I haven't found designing around it to be a terrible nuisance. I often use queues as messaging channels, so it is natural to simply send maps or tuples instead of atomic values. As for configurable sentinel value: I'm less sure that there's a need for this. In fact, I think it's more useful to guarantee a standard sentinel value so that different channel-handling code can interoperate. I just think that this sentinel shouldn't be nil (or any other regular Clojure value). A simple singleton object that is privately owned by core.async should suffice? Oh, I was confused; I was thinking about sentinel values in user code. Yes, I imagine a single private (Object.) would work just fine, with very little overhead. guns pgp0C89I2s0Ka.pgp Description: PGP signature
Re: core.async - handling nils
On Wed 28 Aug 2013 at 12:50:19PM +0900, Alan Busby wrote: On Wed, Aug 28, 2013 at 12:18 PM, guns s...@sungpae.com wrote: Oh, I was confused; I was thinking about sentinel values in user code. Yes, I imagine a single private (Object.) would work just fine, with very little overhead. Third, I'd recommend reviewing, http://clojure.com/blog/2013/06/28/clojure-core-async-channels.html to understand why core.async is not just a better queue. In my mind, core.async is a nice marriage of BlockingQueues, async processing, and a supercharged POSIX select(2) that works on queue objects. Nothing about these ideas necessarily requires that null be reserved by the channel implementation. Fourth, if you dislike how core.async works, just wrap it in your own library so it works the way you'd like. It looks like core.async-with-nil is available on Clojars. ;) With nil, without nil, it's just bike shedding. Clojure gives you the freedom to do it the way you want. Rich Hickey, from: http://clojure.com/blog/2013/06/28/clojure-core-async-channels.html While the library is still in an early state, we are ready for people to start trying it out and giving us feedback. I think mikera is trying to be constructive. For my own part, I am quite ambivalent since I am already used to avoiding pushing nulls onto Queues. I am quite happy to accept that this is an implementation detail and move on, but I can also see why it might be worth it to support nil channel values to avoid confusing users that are not familiar with this quirk of java.util.Queue. guns pgpQWVvS0WkaO.pgp Description: PGP signature
Re: [ANN] optparse-clj: Functional GNU-style command line options parsing
On Sun 25 Aug 2013 at 09:05:15PM -0500, gaz jones wrote: Hey, i am the current maintainer of tools.cli - i have very little time to make any changes to it at the moment (kids :) ). I'm not sure what the process is for adding you as a developer or transferring ownership etc but if I'm happy to do so as I have no further plans for working on it. I would be honoured to have commit access to tools.cli. I am very keen on API stability and smooth transitions, so there would be no need to worry about crazy breaking changes at the hands of a new maintainer. My Clojure CA will be in the post today, and when I receive confirmation I will mail you a proposal of how I would like to add to the project. I see that you're in Chicago; perhaps I can convince you to meet in person so that I may procure one of these secret rings of power that Rich Hickey is rumoured to pass to Clojure developers. :) guns pgpNErNn80zRF.pgp Description: PGP signature
Re: [ANN] optparse-clj: Functional GNU-style command line options parsing
On Fri 23 Aug 2013 at 05:02:50PM -0700, Paul deGrandis wrote: Guns, Have you signed a Clojure CA yet? I'd love to help get this merged into tools.cli Okay, since there is interest, I will mail a CA on Monday morning. Paul, if you are a maintainer or committer of tools.cli, I would be happy to submit the patch to you. guns pgpf48eifgtFx.pgp Description: PGP signature
Re: [ANN] optparse-clj: Functional GNU-style command line options parsing
On Wed 7 Aug 2013 at 10:53:00AM -0500, guns wrote: I'd like to announce optparse-clj, a command line options parser that supports GNU option parsing conventions: https://github.com/guns/optparse-clj Hello again, optparse-clj 1.1.1 now supports ClojureScript and may be used from Node.js command line scripts produced by the CLJS compiler's :nodejs target. [guns.cli/optparse 1.1.1] If you're writing Node.js scripts in CLJS and want to present users with a conventional GNU command line interface (clumped short options `-abc`, --long-options with or without `=`), give optparse-clj a try! guns pgpeN00rmvwYc.pgp Description: PGP signature
Re: [ANN] optparse-clj: Functional GNU-style command line options parsing
On Wed 7 Aug 2013 at 05:35:41PM +0100, Wolodja Wentland wrote: Do you have a particular reason why you didn't simply add this functionality to tools.cli ? I did think of sending this upstream, but the parser is not the only point of difference with tools.cli. Given that both libraries are so small, a patch would have rewritten a majority of the project. Large patches require lots of convincing (and in this case, a Contributer Agreement I have yet to submit), so I just wrote myself a new implementation for a Clojure mail daemon I was writing. tools.cli is, of course, free to swipe the parser from optparse-clj! I would be happy to see it. guns pgpz00_ZBkWC_.pgp Description: PGP signature
Re: Can I refer all but specified symbols with 'ns' macro?
On Fri 2 Aug 2013 at 04:32:32PM -0400, Lee Spector wrote: I can believe that these assertions are true in some (maybe many) programming contexts, but from other perspectives anything that requires you to type stuff that's not directly about the problem you're trying to solve or the idea you're trying to express can be seen as an anti-feature. Of course, this is the tension of simple vs easy. Coming from languages like C and Ruby, the explicit namespacing in Clojure is a breath of fresh air, and one of my _favorite_ features of the language. Let's keep adding header files until it compiles, and let's mixin this entire module for a single method is easy at first, but you're adding a lot of incidental complexity for comparatively little gain. For example, tightly controlled namespacing is what allows Golang to compile at ludicrous speed, and even relatively small programs can become incomprehensible when they fall into the hole of super calls and method shadowing. In my own case I generally don't want to spend my time maintaining catalogs of all of the locations of the functions that I call or cluttering up function calls with project plumbing; I want to spend my time thinking about and developing and testing my algorithms. … I'd personally like it even better if you could accomplish the same thing without listing the conflicts explicitly, but I'm sure that will seem totally nuts to others. It has been mentioned before, but if you are going to depend on tools to manage vars for you, why not use Slamhound?¹ It's quality DWIM: do what's easy, Slamhound makes it simple. It will take the following buffer: (ns example) (split (trim hello, world. ) #,) and transform it into: (ns example (:require [clojure.string :refer [split trim]])) (split (trim hello, world. ) #,) It also removes unused :refers, so it's useful for cleaning up a namespace after refactoring. I have the call to slam.hound bound to a key sequence in my editor², so I do not have to suffer a context switch: https://gist.github.com/guns/6144732 There remain a few small problems (and one admittedly large one WRT macros), but I think automated ns management is a killer feature for Clojure. I found hacking on the Slamhound codebase straightforward, so I encourage people to send patches for any small annoyance they might have. (it's easy!) guns ¹ https://github.com/technomancy/slamhound ² I'm pretty sure technomancy has something similar for Emacs users. pgp_ov2P9N9Pm.pgp Description: PGP signature
Re: Offline Clojure docs
On Mon 1 Jul 2013 at 07:44:17AM +0800, David Pollak wrote: Is there an offline package of Clojure docs (the full core.* api docs, cheat sheets, etc.)? If you work with an editor with clojure REPL integration, you can fashion your own cheat sheet. I have a vim command that dumps a list of all public vars with arglists (filtered by an optional pattern) into a scratch buffer like this: ;;; clojure.core {{{1 clojure.core/*1 clojure.core/*2 clojure.core/*3 … clojure.core/xml-seq [root] clojure.core/zero?[x] clojure.core/zipmap [keys vals] ;;; clojure.core.protocols {{{1 … Then I use the REPL commands in the buffer to look up docs, source, and search vars with the editor. It's quite handy, and always up to date. The funny {{{1 bits are fold markers that allow code folding by namespace. A cheat sheet in org-mode format would be pretty nice for emacs. My apologies if you've already considered this. If you haven't, I hope you find the suggestion useful. guns -- -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.