Re: Next release for clojure.tools.cli? Is it dead?

2015-07-27 Thread guns
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

2014-06-09 Thread guns
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?

2014-06-03 Thread guns
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

2014-05-23 Thread guns
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

2014-05-21 Thread guns
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

2014-05-20 Thread guns
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

2014-05-16 Thread guns
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?

2014-05-14 Thread guns
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?

2014-05-08 Thread guns
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

2014-05-02 Thread guns
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

2014-05-02 Thread guns
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)

2014-05-01 Thread guns
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?

2014-04-07 Thread guns
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?

2014-04-04 Thread guns
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

2014-04-02 Thread guns
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

2014-03-24 Thread guns
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

2014-03-18 Thread guns
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

2014-03-14 Thread guns
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

2014-01-22 Thread guns
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

2014-01-22 Thread guns
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

2014-01-22 Thread guns
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

2014-01-21 Thread guns
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?]

2013-12-28 Thread guns
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?]

2013-12-28 Thread guns
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?]

2013-12-27 Thread guns
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?

2013-12-27 Thread guns
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?

2013-12-27 Thread guns
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

2013-12-20 Thread guns
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

2013-12-15 Thread guns
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

2013-12-10 Thread guns
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

2013-12-02 Thread guns
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

2013-12-01 Thread guns
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

2013-12-01 Thread guns
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

2013-11-30 Thread guns
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

2013-11-29 Thread guns
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

2013-11-22 Thread guns
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

2013-11-20 Thread guns
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

2013-11-20 Thread guns
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

2013-08-27 Thread guns
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

2013-08-27 Thread guns
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

2013-08-27 Thread guns
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

2013-08-26 Thread guns
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

2013-08-24 Thread guns
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

2013-08-21 Thread guns
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

2013-08-07 Thread guns
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?

2013-08-02 Thread guns
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

2013-06-30 Thread guns
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.