Re: [ANN] Planck 1.0 - Bootstrapped ClojureScript OS X REPL

2015-08-05 Thread Mike Fikes
Hi Zach,

Yeah, it definitely sounds like your Homebrew install has an issue.

You can also just download the binary from http://planck.fikesfarm.com 
http://planck.fikesfarm.com/ (it is a self-contained single-file executable). 
It works on Mavericks or later.

- Mike

 On Aug 5, 2015, at 1:24 PM, Zach Oakes zsoa...@gmail.com wrote:
 
 Mike, thanks for this tool. I want to use it to introduce ClojureScript to 
 some local JavaScript devs, since they would be less likely to install 
 anything that required the JVM. I cannot seem to get `brew install planck` to 
 work, however. It just hangs. It looks like `brew upgrade` hangs indefinitely 
 as well, though, so this may just be my mac's fault. If anyone knows how to 
 fix this, please let me know.

-- 
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.


Re: [meta] Can't view one unread topic here.

2015-08-04 Thread Mike Fikes
I recently posted in mistake and deleted the post. Perhaps that is causing what 
you are seeing.

- Mike

 On Aug 4, 2015, at 10:09 AM, Fluid Dynamics a2093...@trbvm.com wrote:
 
 The front page of this group shows no unread threads to me, but shows a (1) 
 next to Google Groups in the page title. So there's one topic with unread 
 posts, but I can't get the interface to show it to me. I've tried refresh, 
 shift-refresh, and navigate-away-and-back. I'm sure I haven't done anything 
 that would filter my view of the group. What do I need to do to make the 
 unread topic visible?
 
 -- 
 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 
 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 
 mailto:clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/d/optout 
 https://groups.google.com/d/optout.

-- 
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.


[ANN] Planck OS X REPL

2015-08-04 Thread Mike Fikes
Planck is a self-contained bootstrapped ClojureScript REPL for OS X.

http://planck.fikesfarm.com http://planck.fikesfarm.com/

Planck is now available via Homebrew: 

  http://blog.fikesfarm.com/posts/2015-08-04-pour-a-pint-of-planck.html 
http://blog.fikesfarm.com/posts/2015-08-04-pour-a-pint-of-planck.html

- Mike

-- 
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.


Re: [ANN] Planck 1.0 - Bootstrapped ClojureScript OS X REPL

2015-08-04 Thread Mike Fikes
Planck 1.3 is now available via Homebrew:

   http://blog.fikesfarm.com/posts/2015-08-04-pour-a-pint-of-planck.html

-- 
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.


[ANN] Planck 1.0 - Bootstrapped ClojureScript OS X REPL

2015-07-31 Thread Mike Fikes
Happy to announce that Planck 1.0 is available:

http://planck.fikesfarm.com http://planck.fikesfarm.com/

-- 
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.


Re: [ANN] Replete ClojureScript REPL iOS app available

2015-07-24 Thread Mike Fikes
It was approved as is.

 Out of curiosity, how painful/painless was the process of getting it accepted 
 into the app store? I've heard that Apple is pretty sensitive about letting 
 anything in that does any kind of evaluation of arbitrary code.


-- 
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.


[ANN] Replete ClojureScript REPL iOS app available

2015-07-20 Thread Mike Fikes
Replete 1.0 is now in the App Store

   
http://blog.fikesfarm.com/posts/2015-07-20-ios-clojurescript-repl-available-in-app-store.html

-- 
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.


Re: Different macro definitions via reader conditionals?

2015-07-02 Thread Mike Fikes
I’m interested in whether there is a nice answer to this as well. 

FWIW, I was recently pondering a closely related subject—portability that 
additionally extends to bootstrapped ClojureScript:

  http://blog.fikesfarm.com/posts/2015-06-19-portable-macro-musing.html 
http://blog.fikesfarm.com/posts/2015-06-19-portable-macro-musing.html

(Hoping things don’t become excessively combinatorial.)

- Mike

 On Jul 2, 2015, at 8:09 AM, Michael Sperber sper...@deinprogramm.de wrote:
 
 I'd like to define a macro differently for Clojure and for ClojureScript.
 
 Is there a way to do this via reader conditionals?  (My mind boggles.)
 
 Regards,
 Mike
 
 -- 
 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 
 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 
 mailto:clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/d/optout 
 https://groups.google.com/d/optout.

-- 
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.


[ANN] Replete 1.0 beta: ClojureScript REPL iOS app

2015-06-29 Thread Mike Fikes
Wondering what all this “bootstrapped ClojureScript” hubbub is all about, and 
have an iOS device? There's a REPL app for that!

Try the beta; experience it firsthand:

  https://github.com/mfikes/replete/wiki/Beta

Special thanks to David Nolen and Joel Martin for making this possible!

- Mike Fikes

-- 
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.


Re: [ANN] Bocko 0.2.0

2015-05-09 Thread Mike Fikes
Yeah I agree. I misremembered them from 33 years ago as being HLINE and VLINE 
and corrected them when I looked them up. :)

By the way, it is available for ClojureScript / iOS now:

 https://github.com/mfikes/bocko-ios

(I have to say, CLJC rocks!)

- Mike


 On May 8, 2015, at 10:16 PM, David Sargeant da...@dsargeant.com wrote:
 
 I guess HLIN and VLIN have a historical significance.  Still kind of 
 confusing, but I understand now how you arrived at those names. 
 -- 
 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.

-- 
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.


[ANN] Bocko 0.2.0

2015-05-07 Thread Mike Fikes
I created a tiny library that makes it easy to plot points in a low-res 
graphics mode: 

  https://github.com/mfikes/bocko

The motivation was to help encourage interest in my own kids (10 and 12-yo) 
to learn tidbits of Clojure, and it seems to be working. :)

I remember that, with the BASIC REPLs built into the hardware in the 80s, 
the ability to easily futz with graphics added an extra dimension to the 
learning experience. Bocko imitates the gr mode from the Apple ][.

- Mike

-- 
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.


Re: ANN: ClojureScript 0.0-3211

2015-04-25 Thread Mike Fikes
Hey Tony, try updating the version of Clojure in your project.clj to 
1.7.0-beta1, which is used by 0.0-3211.

(In short, reader/read was given a second arity to allow options to be passed, 
thus supporting #? conditional reading.)

-- 
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.


Re: [ClojureScript] Re: ANN: ClojureScript 0.0-3115

2015-03-16 Thread Mike Fikes


 If that is true, then it is a problem, indicative either of a widespread 
 lack of discipline among the tool makers or (more likely) a strong need for 
 some additional well-specified (and maintained!) APIs in the compiler for 
 tools to hook into. 


Sometimes it is just a simple bug or lack of robustness in a downstream 
tool that needs to be sorted before rushing to blame and/or burden upstream 
ClojureScript.

Take https://github.com/omcljs/ambly/issues/61 as an example. Previously 
ClojureScript 0.0-3030 would not print anything when evaluating (doc 
unknown-symbol), and with 0.0-3053 onwards it prints an empty string. This 
broke Ambly.

This doesn't really reflect a lack of discipline with APIs, but does 
illustrates the need to do downstream triage first.

-- 
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.


Re: [ANN] Clojure 1.7.0-alpha5 now available

2015-01-11 Thread Mike Fikes
Alex, 1.7.0-alpha5 looks OK to me. It passed with some regression testing 
for an AOTd http-kit compojure / core.async REST server using Lucene, 
clojure/java.jdbc / MySQL, Java 1.7.0_65 on Ubuntu 10.04.1 LTS.

-- 
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.


Re: Has the old invalid constant tag: -57 bug been fixed?

2014-12-17 Thread Mike Fikes
I did some digging and for those interested, this appears to be the way 
piggieback and tools.nrepl work for ClojureScript.

Details are in the Cursive ticket: 
https://github.com/cursiveclojure/cursive/issues/680

-- 
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.


Re: Has the old invalid constant tag: -57 bug been fixed?

2014-12-16 Thread Mike Fikes
I've recently seen the same error:

  Loading test/cljs/classroom_checkout/test1.cljs... done
  CompilerException java.lang.ClassFormatError: Unknown constant tag 117 in 
class file classroom_checkout/utils_test$eval12853, 
compiling:(/private/var/folders/m0/161fm8fx069fk_fny08nrmkmgp/T/form-init7703020558715930971.clj:1:1131)
 

I caused this by making a copy of Nolen's recently added cljs.core tests 
and by trying to load them in my browser REPL. It appears to be related to 
the size of the file: If I try just a few forms in the ns, it works, but 
once beyond say 500 or 1000 lines, I get this error, with the exact number 
changing depending on the size of the file.

-- 
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.


Re: Has the old invalid constant tag: -57 bug been fixed?

2014-12-16 Thread Mike Fikes
You are absolutely right, Andy. Getting out my bantha shears in order to 
provide a good reduction for a bug report…

-- 
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.


Re: Has the old invalid constant tag: -57 bug been fixed?

2014-12-16 Thread Mike Fikes
I found that the problem I'm experiencing is, in essence, the same issue as 
discussed (and fixed) here 
https://code.google.com/p/counterclockwise/issues/detail?id=429, but with 
some new tool in my toolchain (Cursive/simple-brepl/Weasel).

TL;DR: Something produces a .class file that exceeds the 65535 bytes 
allowed by the JVM.

The evidence: I can take the large test foo.clj file attached to the thread 
and reproduce the problem, and eliminate it by deleting a few lines. This 
is consistent with what I was seeing earlier when trying to load all of 
ClojureScript's core tests.

I'll start with Colin to see if he has any thoughts on whether Cursive is 
involved. I can successfully evaluate and use the results of a (load-file 
path/to/filename.cljs) form in the REPL, but hit the error only when 
using Cursive's “Load File in REPL” menu item.

-- 
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.


rest arguments and desctructuring / nil vs. empty

2014-11-30 Thread Mike Fikes
For rest arguments, as in (defn foo [x  r] r), when the remaining 
arguments are rolled up into a sequence, you will get nil instead of an 
empty sequence.

Is it fair to say that the rest nomenclature came about back at the 
beginning of Clojure, when rest really did return nil, prior to the 
introduction of next and lazy sequences?

In other words would it be fair to, given today's behavior, characterize 
them as really being next arguments, but with a historical name?

-- 
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.


Re: Clojurescript to target JVM?

2014-11-21 Thread Mike Fikes
I too was intrigued by this and cobbled together a quick test to see if 
this made it possible to create command-line apps that start up more 
quickly [1]. It appears that this is indeed the case, but, of course you 
still need to pay JVM startup time.

I was also interested in what Sam Beran accomplished, wishing the same 
approach was available in iOS. I haven't thought of a clean way to do it 
and simply load the JS into JavaScriptCore [2], paying several hundred 
milliseconds at startup, which would be nice to eliminate.

The main aspect of all of this appears to be the whole-program optimization 
aspect eliminating lots of unnecessary code. I'm currently wondering if 
this is on the plate for Clojure 7.

[1] https://github.com/mfikes/cljs-cl
[2] https://github.com/mfikes/goby

-- 
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.


Re: Persistent Data Structures for Objective-C/LLVM

2014-11-12 Thread Mike Fikes
I'm thinking Anton's persistent collections could be useful on iOS.

Out of curiosity, I made a small iOS project that compares the performance 
of Anton's map to ClojureScript's, when adding lots of key-value pairs 
(using transients): https://github.com/mfikes/persistent-objc-cljs

Interestingly, they both run at nearly the same speed on an iOS device. 
But, when running on a Mac, the ClojureScript is currently about a factor 
of 7 times faster than the Objective-C.

-- 
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.


Re: uniqueness of hash if computed on different jvms across different machines.

2014-10-13 Thread Mike Fikes
In addition to Andy's caveats, remember that hash code equality doesn't 
imply object equality.

In concrete terms,

   a = b implies h(a) = h(b),

with the useful bit being

  h(a) ≠ h(b) implies a ≠ b.

On Monday, October 13, 2014 2:04:57 AM UTC-4, Sunil Nandihalli wrote:

 Hi,
 Is the clojure hash function guaranteed to produce the same hash on 
 different jvms running on different jvms for the same data-structure 
 which would satisfy equality if checked on a single jvm. The data 
 structure is simply a hash-map.
 Thanks,
 Sunil.


-- 
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.


Re: Do this or that

2014-10-11 Thread Mike Fikes
Thanks all!

FWIW, the snake game in Programming Clojure has an example (where refs are 
conditionally updated) which is consistent with the advice given here. 

Two nice things I noticed in that example:

1. The first form inside do is kept on the same line (a small but nice 
improvement reducing the percieved visual weight of the approach).
2. In the snake game, the entire construct is inside a function that explicitly 
returns nil (because there is no intent to return the value that the if might 
evaluate to).

-- 
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.


Re: Why is my function faster with eval?

2014-10-11 Thread Mike Fikes
Hey Michael,

Since your eval solution essentially cookie-cutters out maps, each with 
the same keys, as fast as it can, I was playing around with what would 
happen if you used records, and I cobbled together something that appears 
to run twice as fast as the eval approach:

(defn read-to-structs [rows]
  (let [headers (-
  rows
  first
  (take-while (complement #{}))
  (map keyword))
s (apply create-struct headers)]
(for [row (rest rows)]
  (apply struct s row


Here are comparative timings:

(time-fn read-to-maps)
Elapsed time: 4871.02175 msecs
= nil
(time-fn read-to-maps-partial)
Elapsed time: 4814.730643 msecs
= nil
(time-fn read-to-maps-fn)
Elapsed time: 4815.230087 msecs
= nil
(time-fn read-to-maps-eval)
Elapsed time: 2466.048578 msecs
= nil
(time-fn read-to-structs)
Elapsed time: 1273.462618 msecs

I didn't test it too much, but it passed this:

(= (read-to-maps csv-fix) (read-to-structs csv-fix))
= true

On Friday, October 10, 2014 4:21:01 PM UTC-4, Michael Blume wrote:

 https://github.com/MichaelBlume/eval-speed

 eval-speed.core= (time-fn read-to-maps)
 Elapsed time: 5551.011069 msecs
 nil
 eval-speed.core= (time-fn read-to-maps-fn)
 Elapsed time: 5587.256991 msecs
 nil
 eval-speed.core= (time-fn read-to-maps-partial)
 Elapsed time: 5606.649172 msecs
 nil
 eval-speed.core= (time-fn read-to-maps-eval)
 Elapsed time: 2627.521592 msecs
 nil

 Ben, I'd still like to understand exactly what work the CPU is doing in 
 the uneval'd version that it's skipping in the eval'd version. It seems 
 like in the generated bytecode there's going to be *some* concept of 
 iterating through the row in either case, if only as part of the 
 destructuring process.


 On Friday, October 10, 2014 1:07:08 PM UTC-7, Ben wrote:

 I believe it's because the `mapper` function is just creating and 
 returning a map literal. The mapper function in the evaled version is 
 something like this:

 user (def names '[n1 n2 n3 n4])
 #'user/names
 user (def headers '[h1 h2 h3 h4])
 #'user/headers
 user `(fn [[~@names]] ~(zipmap headers names))
 (clojure.core/fn [[n1 n2 n3 n4]] {h4 n4, h3 n3, h2 n2, h1 n1})   ;; just 
 a map literal, whose keys are already known.

 Whereas in the first version, zipmap has to be called, iterating over 
 headers and names each time.

 On Fri, Oct 10, 2014 at 1:04 PM, Sean Corfield se...@corfield.org 
 wrote:

 It may be more to do with the difference between `for` and `map`. How do 
 these versions compare in your benchmark:

 (defn read-to-maps-partial [rows]
   (let [headers (-
   rows
   first
   (take-while (complement #{}))
   (map keyword))]
 (map (partial zipmap headers) (rest rows

 (defn read-to-maps-fn [rows]
   (let [headers (-
   rows
   first
   (take-while (complement #{}))
   (map keyword))
 mapper (fn [row] (zipmap headers row))]
 (map mapper (rest rows

 Sean

 On Oct 10, 2014, at 11:42 AM, Michael Blume blume...@gmail.com wrote:
  So I'm reading a bunch of rows from a huge csv file and marshalling 
 those rows into maps using the first row as keys. I wrote the function two 
 ways: https://gist.github.com/MichaelBlume/c67d22df0ff9c225d956 and the 
 version with eval is twice as fast and I'm kind of curious about why. 
 Presumably the eval'd function still implicitly contains a list of keys, 
 it's still implicitly treating each row as a seq and walking it, so I'm 
 wondering what the seq-destructuring and the map literal are doing under 
 the hood that's faster.




 -- 
 Ben Wolfson
 Human kind has used its intelligence to vary the flavour of drinks, 
 which may be sweet, aromatic, fermented or spirit-based. ... Family and 
 social life also offer numerous other occasions to consume drinks for 
 pleasure. [Larousse, Drink entry]

  

-- 
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.


Re: best way to edit EDN value in cljs

2014-10-10 Thread Mike Fikes
Can you use update-in or assoc-in?

On Friday, October 10, 2014 2:28:26 PM UTC-4, Dustin Getz wrote:

 I have an arbitrarily nested EDN value stored in an atom in ClojureScript.

 What is the best way to make edits to an arbitrary subtree of this value?


-- 
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.


Do this or that

2014-10-06 Thread Mike Fikes
Here's a style question: If you have to conditionally do one set of side 
effects or another set, is your preference to use when and when-not, or an 
if containing do blocks? Or perhaps some other construct?

In terms of a concrete example:

(let [boolean-value (some-predicate?)]
  (when boolean-value
(do-alpha)
(do-beta))
  (when-not boolean-value
(do-gamma)
(do-delta)))

or:

(if (some-predicate?)
  (do
(do-alpha)
(do-beta))
  (do
(do-gamma)
(do-delta)))

-- 
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.


Re: core.async | compojure ... odd error ... help!!

2014-09-28 Thread Mike Fikes
Hi mond,

I've been using HTTPkit with Compojure and core.async (all fronted by Nginx 
so the entire stack is async FWIW).

To glue core.async with HTTPkit when handling inbound requests, I have a 
utility function

(defn handle-async! [handler req]
  (http-server/with-channel req channel
(take! (handler req) #(http-server/send! 
channel %

and I make use of that utility function when defining routes

(defroutes all-routes
   (GET /covers/v1/:cover [] (partial http/handle-async! 
fetch-cover!))
   (context /books/v1 []
(GET /search [] (partial http/handle-async! 
search-handler!))
(GET /:isbn [] (partial http/handle-async! 
get-book-by-isbn!

The handler functions fetch-cover!, search-handler!, get-book-by-isbn!, all 
return channels (they either call go for stuff that needs to be async, or 
to-chan on collections read directly from memory.

- Mike 

On Saturday, September 27, 2014 5:01:36 AM UTC-4, mond wrote:

 Hi James,

 Er, nice tip on the routes - that was another thing that I didn't expect 
 to work but was happy when it did ;-) I will of course adapt it to your 
 recommendation.

 Speaking to the main point, no I don't want to put a channel on to the 
 response so that's a mistake that I see and would like to avoid. I would 
 like to understand where I have gone wrong.

 Maybe I need to use HTTPkit instead?

 Thanks

 Ray



 On Saturday, 27 September 2014 02:08:50 UTC+2, James Reeves wrote:

 Hi Ray,

 I don't entirely understand why you expected this to work. Channels 
 aren't a valid Ring response body. The error message is essentially telling 
 you that Compojure has no way of turning the channel object you've returned 
 into a valid response.

 The other problem you have is that the Ring Jetty adapter doesn't have 
 any support for asynchronous operations.

 Another small point. You're using * as an argument name, but this isn't 
 really recommended. This only works by coincidence, and it may be removed 
 in future versions. Instead use something like:

 (GET [/:brand/:country/:resource :resource #.*] [brand country 
 resource] ...)

 - James

 On 27 September 2014 00:14, mond r...@mcdermott.be wrote:

 My first core.async program ... all works outside of the web app but 
 barfs once I put the functions inside a web container. I hope somebody in 
 the group can point to my obvious mistake...

 The idea is that the function 'respond-within-sla' will give back a 
 result or a come back later message after N milliseconds. It is passed a 
 number of ms, three functions and the arguments for the final function ... 
 which is the one that should operate within the SLA.

 (defn respond-within-sla [expected-result-milliseconds respond-ok 
 respond-later data-fetcher  args]
   (let [data-channel (timeout expected-result-milliseconds)]
 (go (if-let [data (!! data-channel)]
   ((async/close! data-channel)
(respond-ok data))
   (respond-later)))
 (go
   (! data-channel (apply data-fetcher args)

 To keep the volume of code to parse to a minimum I have made a few toy 
 functions that demonstrate the failure...

 ; test funcs

 (defn ok [data]
   (prn (str send HTTP 200 ... got data  data)))

 (defn later []
   (prn (str send HTTP 202 ... request received, come back later)))

 (defn fetcher [arg1 arg2 arg3]
   (prn (str fetching data with args  arg1   arg2   arg3))
   response-data)

 (defn failer [ args]
   (Thread/sleep 1000)
   (str never gets here  args))

 ; test funcs

 (defn ok [data]
   (prn (str send HTTP 200 ... got data  data)))

 (defn later []
   (prn (str send HTTP 202 ... request received, come back later)))

 (defn fetcher [arg1 arg2 arg3]
   (prn (str fetching data with args  arg1   arg2   arg3))
   response-data)

 (defn failer [ args]
   (Thread/sleep 1000)
   (str never gets here  args))

 (defn generate-response [brand country resource]
   (let [sla (or (env :sla-milliseconds) 100)]
 (respond-within-sla sla ok later fetcher brand country resource)))

 (defn generate-fail [brand country resource]
   (let [sla (or (env :sla-milliseconds) 100)]
 (respond-within-sla sla ok later failer brand country resource)))

 From within the REPL it all works fine...

 (generate-response A B C)
 = #ManyToManyChannel 
 clojure.core.async.impl.channels.ManyToManyChannel@4b7ae3f7
 fetching data with args A B C
 send HTTP 200 ... got data response-data
 (generate-fail A B C)
 = #ManyToManyChannel 
 clojure.core.async.impl.channels.ManyToManyChannel@4eb8b5a9
 send HTTP 202 ... request received, come back later

 Here is the compojure route..

 (defroutes app
(GET /:brand/:country/* [brand country *]
 (generate-response brand country *))

(ANY * []
 (route/not-found You must use a REST style to specify 
 brand and country keys in the URL)))

 If I now start it up 'lein run' and try to exercise the functions from 

Newbie: adding items to a global vector in doseq

2014-08-14 Thread Mike Fikes
Read up on atoms. The results of your conj call are being discarded. 

For example, check out the behavior of this:

(def urls2 (atom []))
(swap! urls2 conj http://foo.bar;)

-- 
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.


Re: Newbie: adding items to a global vector in doseq

2014-08-14 Thread Mike Fikes
Thomas is absolutely right, Philippe.

Things also get easier if you avoid, or defer side effects, and first focus 
on pure functions.

So, for example at the REPL, you might first try processing a literal 
sequence of lines, repeatedly adjusting the processing code, tweaking the 
regex, until you get it right:

(mapv #(re-find #\w+\.\w+ %) [abc def.g apple.com ibm.com foo])
;= [apple.com ibm.com]

You could turn the above into a pure function that works on a sequence of 
lines:

(defn lines-urls [lines] (mapv #(re-find #\w+\.\w+ %) lines))


You could then define your file reading code in terms of that pure function:


(defn readf [file]

   (with-open [r (clojure.java.io/reader file)]

  (lines-urls (line-seq r

-- 
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.


Re: Clojure XML - is there a better way?

2014-07-22 Thread Mike Fikes
My only gut reaction is that, without a root node, it doesn't seem that you 
have XML. (It is certainly not a well formed document, and I would 
suspect lots of XML tools/libraries would have difficulty coping with the 
example you provided.)

-- 
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.


Re: Moving average from Java to Clojure

2014-07-20 Thread Mike Fikes
There actually is a queue implementation. Here is a way to use it for your 
problem:

(defn make-moving-average-queue [n]
  (atom {:lengthn
 :current-total 0.0
 :old-values(clojure.lang.PersistentQueue/EMPTY)}))

(defn update-moving-average-queue [old-queue next-value]
  (let [current-total (+ (:current-total old-queue) next-value)
old-values (conj (:old-values old-queue) next-value)]
(if ( (count old-values) (:length old-queue))
  (let [current-total (- current-total (first old-values))
old-values (pop old-values)]
(assoc old-queue :current-total current-total :old-values 
old-values))
  (assoc old-queue :current-total current-total :old-values 
old-values

(defn moving-average [old-queue next-value]
  (let [new-queue (swap! old-queue update-moving-average-queue next-value)]
(/ (:current-total new-queue) (count (:old-values new-queue)

(def queue-06 (make-moving-average-queue 6))

(def inputs-06 [20 22 21 24 24 23 25 26 20 24 26 26 25 27 28 27 29 27 25 
24])

(doseq [input inputs-06]
  (println (moving-average queue-06 input)))

(def queue-10 (make-moving-average-queue 10))

(def inputs-10 [20 22 24 25 23 26 28 26 29 27 28 30 27 29 28])

(doseq [input inputs-10]
  (println (moving-average queue-10 input)))

-- 
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.


Re: Moving average from Java to Clojure

2014-07-20 Thread Mike Fikes
Hey Cecil, 

In addition to using peek instead of first, as indicated by Plinio, the 
moving-average function above uses some poor names, in hindsight, 
especially the old-queue parameter name. I'd suggest naming it queue, as 
it refers to an atom. You could even consider naming the function 
moving-average!.

-- 
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.


Re: unexpected behavior of clojure.core/empty

2014-07-19 Thread Mike Fikes
MapEntry is a collection:

(coll? (clojure.lang.MapEntry. a 1))

;= true


(ancestors (class (clojure.lang.MapEntry. a 1)))

;= (a set that includes clojure.lang.IPersistentCollection)


The docstring for empty implies it would return an empty MapEntry. But 
perhaps since MapEntry is a special collection type that must have a size 
exactly equal to 2, empty must return nil.


Perhaps ClojureScript will one day introduce a MapEntry type and behave the 
same way as Clojure (ClojureScript currently returns a PersistentVector).

-- 
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.


Re: unexpected behavior of clojure.core/empty

2014-07-19 Thread Mike Fikes
I did a little “code archaeology” in an attempt to elucidate what Rich may 
had been thinking:

In mid 2007, some of the persistent collection implementations had an EMPTY 
value defined. [1, 2]. (But, of course, no such EMPTY value was defined for 
MapEntrys.)

Around a year later, MapEntrys were revised to participate in the vector 
abstraction [3].

A couple of months *after* this, “empty” was added to the collection 
abstraction [4], and usually implemented in terms of the EMPTY value, and 
MapEntry was made to return null.

My analysis is inconclusive: Making MapEntry return null is logical, given 
that there is no EMPTY value to return. But, the MapEntry / vector business 
happening prior to this blurs the argument.

Perhaps the real problem is that not all collections can be emptied, and 
thus thus empty shouldn't have been added to the collection abstraction. 
(ClojureScript separates out the idea, introducing IEmptyableCollection.)

[1] 
https://github.com/clojure/clojure/commit/12457e7bf29747232bbfda2a0de3b72fbb14f3a9
[2] 
https://github.com/clojure/clojure/commit/4232de83a53e12741252d31aef9cecee5b8981da
[3] 
https://github.com/clojure/clojure/commit/978af02b0a7e2b430c917b32b58215edcae2ad2d
[4] 
https://github.com/clojure/clojure/commit/697b69fe9c8f5e2e8d40382e70d4ddd490c4a9ee

-- 
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.


Re: unexpected behavior of clojure.core/empty

2014-07-19 Thread Mike Fikes
In *Clojure Programming* (Emerick, Carper, Grand) a swap-pairs function is 
defined in the section describing how empty allows you to write functions 
against abstractions. That function operates on sequentials, and, 
importantly, is carefully designed (invoking empty) so that its return type 
is consistent with its argument's type.

For example:

(swap-pairs [1 2 3 4])

;= [2 1 4 3]


(swap-pairs '(1 2 3 4))

;= (3 4 1 2)


Things go awry with MapEntry:


(sequential? (first {:a 1}))

;= true


(swap-pairs (first {:a 1}))

;= (:a 1)

Compare this with what you get in ClojureScript:

(sequential? (first {:a 1}))

;= true


(swap-pairs (first {:a 1}))

;= [1 :a]



-- 
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.


Re: unexpected behavior of clojure.core/empty

2014-07-18 Thread Mike Fikes
My guess: Perhaps this is a bug, or alternatively, a known issue that won't 
be addressed because to do so would be a breaking change.

There is an old demo of Clojure given by Rich where MapEntry's were printed 
using some sort of un-readable notation #:foo 5. But clearly MapEntry's 
have been revised to act a lot like 2-element vectors.

user= (rseq (first (mapv identity {:foo 5})))

(5 :foo)

user= (conj (first (mapv identity {:foo 5})) :x)

[:foo 5 :x]

user= (assoc (first (mapv identity {:foo 5})) 1 7)

[:foo 7]

user= (subvec (first (mapv identity {:foo 5})) 0 1)

[:foo]


FWIW, ClojureScript behaves in your expected way:


(empty (first (mapv identity {:foo 5})))

= []

-- 
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.


Re: Calculating the number of timestamps logged within a specific time period

2014-07-18 Thread Mike Fikes
You could use frequencies:

user= (frequencies (map #(quot % 1000) epochs))

{1405060202 1, 1405060201 8, 1405060200 1, 1405060205 1}

-- 
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.


Re: Calculating the number of timestamps logged within a specific time period

2014-07-17 Thread Mike Fikes
As a start, you could use group-by with a function that squashes together 
items that fall in the same second and then count the size of each value.


(reduce-kv (fn [c k v] (assoc c k (count v))) {} (group-by #(quot % 1000) 
epochs))
;= {1405060205 1, 1405060200 1, 1405060201 8, 1405060202 1} 

-- 
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.


Re: handling only a part of a hash-map

2014-07-16 Thread Mike Fikes
select-keys makes it easy to extract a portion of a map:

(select-keys {:id 1 :ts 2 :ignore 3} [:id :ts])
= {:ts 2, :id 1}

-- 
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.


import functions from different .clj files

2014-07-12 Thread Mike Fikes
Normally, the initial elements of the namespace are used to create directories 
and the last element matches the filename. So, for your first example, there 
would be an a/b/c.clj file.

Perhaps this is at the root of the issue.

-- 
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.


import functions from different .clj files

2014-07-12 Thread Mike Fikes
And alternatively you could declare the first namespace as being a.b.c.fileB

-- 
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.


Re: import functions from different .clj files

2014-07-12 Thread Mike Fikes
I think the root cause is that you need to follow the directory name and 
filename conventions. For example clojure.java.jdbc is in a 
clojure/java/jdbc.clj file

  
 
https://github.com/clojure/java.jdbc/blob/master/src/main/clojure/clojure/java/jdbc.clj


-- 
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.


Re: Clojure on iOS devices - Swift as a host?

2014-06-25 Thread Mike Fikes
That's cool!

What I haven't been able to figure out is if we actually get FTL with 
JavaScriptCore on iOS 8, or better yet, if we can somehow gain access to a 
JSContext from the WKWebView.

More detail: I'm using ClojureScript to develop what are otherwise native 
iOS apps. (Meaning using UIKit, StoryBoards, UIButtons, UITextFields, view 
hierarchies, animations, etc.—the same stuff you would work with if you sat 
down at Xcode and wrote a conventional iOS app.) In other words, not 
self-contained web apps that manipulate the DOM of a page hosted in the app 
in order to render its UI (in which case WKWebView would be directly 
applicable and FTL would be enabled).

You can do this using JavaScriptCore, which is akin to a bare-bones 
JavaScript engine that you can use to drive Objective-C objects that you've 
exported into JavaScriptCore, and vice-versa (drive the JavaScript from 
Objective-C). UIWebView, on the other hand, adds additional stuff to its 
JavaScript environment. You can certainly run the output of the 
ClojureScript compiler in JavaScriptCore, but the first thing you will run 
into is the lack console.log, which is easy to add back in via Objective-C. 
Then the next thing you might encounter is the lack of setTimeout (which 
occurs, for example if you use a core.async timeout channel)—which you can 
also add back in. Then, if you try to establish a REPL into JavaScriptCore, 
then you may find you are lacking socket.io, which you could also 
theoretically add to JavaScriptCore.

At that point (essentially trying to run a browser REPL inside something 
that is arguably not a browser), I decided to just use UIWebView, simply 
for the purpose of REPL development, grabbing its JSContext (which is the 
same thing you get when you are working with JavaScriptCore), using private 
API. This is cool for development using the REPL, but it is safer to go 
back to JavaScriptCore for actual release builds that must pass review for 
the App Store. 

So, with WKWebView (the JITed replacement for UIWebView), those same 
questions come into play. Can we gain access to the JSContext of a hidden 
WKWebView using public API? (In that case it can be used all of the time, 
both for REPL dev and for release builds). Failing that, is JavaScriptCore 
JITed in iOS 8?

On Wednesday, June 25, 2014 2:23:32 AM UTC-4, Steve Tickle wrote:

 In the upcoming IOS8, UIWebView has the same (JITed) performance as the 
 Safari, the distinction has been removed due to using the new inter-app 
 communication mechanism. This allows the remote application 
 (Safari/JavascriptCore/UIWebView) to display a view into another process, 
 thus bypassing the no-executable-pages issue.

 So basically... get the IOS8 beta  new XCode beta and play with it...


-- 
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.


Style-question: self-named attribute getters?

2014-06-25 Thread Mike Fikes
I'm curious about this stuff too. (I'm very new to Clojure.)

I wouldn't be surprised if the general sentiment is: “Don't.”

The argument goes along these lines: By encapsulating, you have introduced a 
tiny new little API that clients need to learn the semantics of. Additionally, 
that API is likely not amenable to the plethora of other functions available in 
the standard library that are designed to work against a compact set of 
abstractions.

Part of me is with you, though, and I'm curious if there are patterns that let 
you encapsulate in a way that works out cleanly.

-- 
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.


Re: IntelliJ Cursive ClojureScript IDE slowdown

2014-06-24 Thread Mike Fikes
Thanks. You're all awesome!

-- 
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.


Re: Clojure on iOS devices - Swift as a host?

2014-06-24 Thread Mike Fikes
(Apologies to Greg for having essentially hijacked this thread, but I 
suspect he'd find this cool.) 

I have no experience with the Swift REPL yet, but I'm still finding this a 
little surreal:

https://lh6.googleusercontent.com/-Z7ulXotc4N4/U6nCQgnWuPI/AJc/700UBdqm3d0/s1600/repl.jpg

(It's a picture of me holding an iPod touch, jacked into it wirelessly via 
a ClojureScript REPL, live updating a UITextField's text.)

-- 
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.


Re: Clojure on iOS devices - Swift as a host?

2014-06-24 Thread Mike Fikes
Thanks David! Targeting ClojureScript to iOS just got an order of magnitude 
easier for me.

I want to say that Colin Fleming (Cursive) has been extremely helpful in 
helping me sort out how to achieve this.

-- 
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.


Re: IntelliJ Cursive ClojureScript IDE slowdown

2014-06-22 Thread Mike Fikes
Hi Colin,

I'm still in the habit of manually saving, but I've noticed that IntelliJ saves 
quite often on its own.

I usually work with :whitespace optimizations so that compilation completes 
within 3/10 s of saving. (I'm using this to build an iOS app using 
JavaScriptCore, so this is much quicker than I can switch over to Xcode to test 
a change.)

-- 
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.


Re: IntelliJ Cursive ClojureScript IDE slowdown

2014-06-22 Thread Mike Fikes
Me too. I suspect it is an IntelliJ-specific problem, unrelated to Cursive. 
Perhaps Colin has the ability and insight to see where the problem lies.

-- 
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.


IntelliJ Cursive ClojureScript IDE slowdown

2014-06-21 Thread Mike Fikes
Just sharing a tooling hint:

If you are using IntelliJ / Cursive to edit ClojureScript (on a Mac at 
least), opening a Terminal “pane” at the bottom of the IDE in order to run 
`lein cljsbuild auto` is nice because you can readily see any errors or 
warnings the ClojureScript compiler might emit.

But… this ends up fairly quickly slowing down editing in IntelliJ to the 
point where keystrokes feel “mushy” rather than “crisp.” A more dramatic 
way to see this is to select some lengthy ClojureScript text and drag and 
watch the selection UI updates follow behind the cursor.

The simple fix: Instead run `lein cljsbuild auto` in an OS X Terminal 
window.

-- 
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.


Best tools for profiling Clojure programs?

2014-06-20 Thread Mike Fikes
I can speak to existence but not optimality :)

I've use JProfiler, and my experience is that, just like debuggers work, so 
does this particular profiler.

-- 
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.


Re: Invalid timestamp

2014-06-20 Thread Mike Fikes
It it perhaps reading the first line of your file and running it trough the 
parser?

-- 
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.


Re: ClojureScript ^:export defprotocol

2014-06-19 Thread Mike Fikes
I found the solution to the original question I had posed:

Is there a way to indicate the protocol names should be preserved? 
 (Analogous to the way ^:export can be used on function definitions.)


You simply need to place the meta directly in the method signature forms, 
as illustrated here:

(defprotocol TableViewDataSource
  (^:export number-of-sections [this])
  (^:export number-of-rows-in-section [this section])
  (^:export cell-for-row-at-index-path [this section row]))

I came to this solution after reading the implementation of emit-protocol :)

With this change, the protocol methods can be called as regular functions 
from the JavaScriptCore / Obj-C host, even with :advanced optimizations 
enabled.

-- 
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.


ClojureScript ^:export defprotocol

2014-06-18 Thread Mike Fikes
Is there a way to indicate that a (ClojureScript) protocol is intended to 
be used from the host?

Details:

I can define a protocol and an implementation of it in ClojureScript using 
defprotocol and reify. 

I can also successfully call methods on reified instances returned to the 
host (Obj-C embedding JavaScriptCore on iOS). 

The method names are mangled: In addition to the expected and usual 
conversion of hyphens to underscores, the mangled names incorporate dollar 
signs ($) and arity encoding, an example of which is:

  my$full$ns$MyProtocol$a_method_defined_in_this_protocol$arity$1

This can be called, passing this mangled string in as the method name of 
JSValue 
-invokeMethod:withArguments:.

All cool (so long as this mangling is stable from one ClojureScript release 
to the next—but it smells like the mangling could be an implementation 
detail, subject to change). 

The killer is if I turn on Google Closure advanced optimizations; these 
mangled names get renamed.

Is there a way to indicate the protocol names should be preserved? 
(Analogous to the way ^:export can be used on function definitions.)

-- 
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.


Re: ClojureScript ^:export defprotocol

2014-06-18 Thread Mike Fikes
Even without JIT available in JavaScriptCore, I have been unable to notice 
a difference in the on-device performance of the “view controller” code I 
have been writing when turning on :advanced.

Thanks for the suggestion, I'll go with :simple and :static-fns. The 
reified protocol instance works with those optimizations.

On Wednesday, June 18, 2014 2:34:45 PM UTC-4, David Nolen wrote:

 On iOS is advanced compilation really necessary? :simple + :static-fns 
 true should suffice.


-- 
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.


Re: ClojureScript ^:export defprotocol

2014-06-18 Thread Mike Fikes
Right, Gary,

Initially I simply wrote exported functions.

The motivation for experimenting with protocols is so that I can write a 
ClojureScript protocol that mimics, say the iOS UITableViewDataSource 
Objective-C @protocol. Then, with that in place, I can write ClojureScript 
reifications of that protocol to be passed back to Objective-C. It is then 
a simple matter on the Objective-C side to make that reification *be* a 
UITableView's dataSource delegate (with the help of a little reusable 
wrapper Obj-C object around the JSValue.) 

In addition to perhaps keeping things tidy (keeping like methods together), 
it makes it easier to pass multiple @protocol instances back to iOS. 
(Imagine the case of two or more table views on one iOS screen, each with 
their own distinct ClojureScriipt implementation.) 

Also, a lot of this ends up being boilerplate that needs to only be written 
once, and then, I recoup the costs of fleshing out this plumbing by simply 
spitting out a (reify ... ) form whenever needed.

Arguably, none of this is required because all of the UITableViewDataSource 
methods have the tableView as the first argument, which could be used by 
straightforward exported functions to dispatch or otherwise switch to the 
right implementation, which could in turn be a reified protocol. It just 
seems that, since Objective-C *wants* an object as a dataSource, that it 
would be interesting to try to satisfy that need (more or less directly) 
using the facilities available in ClojureScript.

I'll ditch all of this when Apple introduces FunctionalSwift along with 
functional APIs, and the Clojure(Swift) compiler targets that new language. 
:)

- Mike

On Wednesday, June 18, 2014 2:48:33 PM UTC-4, Gary Trakhman wrote:

 'any problem.. fixed.. by another layer of indirection'

 You could also just make exportable functions that call the protocols, 
 keeping them more as impl-details, core.cljs does this, and you gain things 
 like varargs (hmm, do protocol-varargs work on cljs? nope: 
 http://dev.clojure.org/jira/browse/CLJS-362 )


-- 
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.


Re: ClojureScript ^:export defprotocol

2014-06-18 Thread Mike Fikes
That's cool. I see no reason why Clojure / ClojureScript's “reach” can't 
extend significantly into iOS.

On Wednesday, June 18, 2014 3:58:18 PM UTC-4, Gary Trakhman wrote:

 I was just telling a local ios dev there's like five guys using clojure + 
 objective-c. To me it's impressive. To them, well, I don't know what 
 they'd think :-).


-- 
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.


Help with writing a function to merge two maps

2014-06-17 Thread Mike Fikes
I want to use merge-with * to solve your problem. To do so, define a couple of 
helper functions 

   (defn v-m [v] (into (sorted-map) (for [{:keys [id val]} v] [id val])))
   (defn m-v [m] (mapv (fn [[k v]] {:id k :val v}) m))

that can convert your structure to and from sorted maps. With these, it boils 
down to a call to merge-with

   (m-v (merge-with * (v-m xs) (v-m ys)))

-- 
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.


Re: Clojure on iOS devices - Swift as a host?

2014-06-14 Thread Mike Fikes
Hey Devin,

You had asked to see some code. Here is a little, to give a feel for the 
“top level” without digging into the plumbing.

Let's say you want an authentication UI that lets you enter a 6-digit code 
with a keypad and asterisk indicators showing how many digits have been 
keyed. Here is a screenshot of that UI (actually being driven by 
ClojureScript):

https://lh4.googleusercontent.com/-2RTQ5tlyTZo/U50NOx2DvDI/AJM/PrwustID-0E/s1600/keypad.png
This UI simply comprises some labels and some buttons.

The ClojureScript code that runs the UI binds to those iOS components via 
tag number (which is set in interface builder), and has a little logic to 
maintain a model that consists of a vector of the digits entered so far, 
and code to color the asterisks.

In the picture above, two button presses have occurred and the code has 
logged:

*2014-06-14 22:47:11.291 Test App[2428:60b] JS: code-entered: [1]*

*2014-06-14 22:47:12.213 Test App[2428:60b] JS: code-entered: [1 4]*

The “view controller namespace” hooked up to this view is this 
ClojureScript code below. In it you can see an atom per UI element along 
with bits of code manipulating the maps in the atoms (such as 
set-enabled!). The “plumbing” that I haven't shown is a bit of boring code 
that marshals information between the atom values and the iOS components. A 
sample atom value for a text field might look like {:text foo :enabled 
true}.

(ns test-app.view-controller
  (:require [fikesfarm.ios.interop :refer [bind!]]
[fikesfarm.ios.view-model :refer [set-text! set-callback! 
set-enabled! set-hidden!]])
  (:require-macros [fikesfarm.ios.util :refer [with-try]]))

;; View-Model
(def asterisk-labels (vec (repeatedly 6 #(atom {}
(def number-buttons (vec (repeatedly 10 #(atom {}
(def clear-button (atom {}))

;; Model
(def code-entered (atom [] :validator #( (count %) 7)))

(defn- update-asterisk-labels!
  [count-entered]
  (dorun (map-indexed (fn [n asterisk-label] (set-enabled! asterisk-label 
( n count-entered))) asterisk-labels)))

(defn- set-number-buttons-enabled!
  [enabled]
  (dorun (map #(set-enabled! % enabled) number-buttons)))

(defn ^:export init-myvc!
  [view]
  (with-try

;; Bind the UI elements
(dorun (map #(bind! view %1 %2) (range 21 27) asterisk-labels))
(dorun (map #(bind! view %1 %2 :touch-up-inside) (range 1 11) 
number-buttons))
(bind! view 11 clear-button :touch-up-inside)

;; When a number button is pressed, conj value to the code-entered 
vector
(dorun (map #(set-callback! %1 (fn [] (swap! code-entered conj (mod %2 
10
number-buttons
(range 1 11)))

;; Empty the code-entered vector if clear button pressed
(set-callback! clear-button (fn [] (reset! code-entered [])))

;; Set the asterisk labels to the correct initial rendering
(update-asterisk-labels! 0)

;; As the code-entered model changes, update the number of asterisks 
shown
(add-watch code-entered :code-entered
   (fn [_ _ old-code-entered new-code-entered]
 (when-not (= old-code-entered new-code-entered)
   (println code-entered: new-code-entered)
   (update-asterisk-labels! (count new-code-entered))
   (when (= new-code-entered [1 4 7 2 5 8])
 (set-number-buttons-enabled! false)
 (set-enabled! clear-button false)))

- Mike

On Wednesday, June 11, 2014 10:46:28 PM UTC-4, Devin Walters (devn) wrote:

 If I had a small fortune I would pay you to sit down and show me how this 
 business you're talking about works. Sounds really cool. Is doing this kind 
 if thing documented well anywhere? I'd love to see some code and your 
 workflow. 

 '(Devin Walters) 


-- 
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.


Re: Clojure on iOS devices - Swift as a host?

2014-06-12 Thread Mike Fikes
Hi Devin,

A great place to start is 
http://web.cecs.pdx.edu/~cpinera/javascriptcore-integration-with-clojurescript-in-ios.html
 (some slight modifications are required to get that blog post examples working 
with the latest, but it's not that hard).

Another great resource is the WWDC 2013 video on JavaScriptCore.

Once you have a sample project up and running, then you are “cooking with 
fire.” Roughly the workflow involves editing ClojureScript (I use Cursive in 
IntelliJ, but any IDE would do) where the results of lein cljsbuild auto are 
being consumed in a “sibling” Xcode workspace. Make a change to ClojureScript, 
rebuild your Xcode app, observe the change in behavior, repeat.

Debugging is nearly impossible, so I rely heavily on logging, and on producing 
lots of pure functions that can be independently verified in a REPL. So the 
first thing you would want to do is set up things do that when you call a 
logging function in your ClojureScript, it is routed to iOS and logged in the 
console.

To avoid needing to add lots of new JSExport methods for new functionality, I 
take the approach of writing some plumbing code that can work with the UI by 
referencing UIComponents via their “tag” integer, which I manually set in IB 
and then call a “bind!” function in ClojureScript to set up the needed 
interactions.

For example, I might have a (def text-field (atom {})) and then in an init 
method marked ^:export that takes a view argument, I do (bind! text-field view 
1), where the literal 1 is the tag for a text field in IB. I've written bind to 
call into Objective C and register for notifications on that tag, setting 
things so that, for example, whenever the text changes, it calls back into 
ClojureScript executing a function that ends up calling (swap! text-view assoc 
:text updated-text).

You can take a similar approach to have button tap events drop a message into a 
core.async channel, and associated plumbing to bind a UI button to the channel.

The end result is that you can essentially write what would normally be view 
controller code in ClojureScript.

A lot of the above (especially the code fragments) are from memory—ask if you'd 
like more elaboration. But in the end, it's simpler and less elaborate than you 
might initially think.

- Mike

-- 
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.


Re: Clojure on iOS devices - Swift as a host?

2014-06-12 Thread Mike Fikes
Not me, but if I needed to build a web app, Cappuccino and Om would be on my 
list of things to dig into

-- 
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.


delete-file needs to be vector?

2014-06-12 Thread Mike Fikes
I had the same happen to me several times and then I got wise to it :)

It is a correct diagnostic, but it would arguably be better if it could somehow 
simply indicate “function definition is missing a parameter declaration.”

-- 
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.


if else list of commands

2014-06-12 Thread Mike Fikes
Also, check out when and when-not, which are great for conditionally executing 
some imperative code.

-- 
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.


Functions in data structures?

2014-06-12 Thread Mike Fikes
Is there anything wrong with doing something like this?

(def foo (atom {:fn inc}))
((:fn @foo) 1)
; = 2

This works in Clojure and ClojureScript.

Just wondering if placing functions into immutable data structures could cause 
any grief. 

Or are functions sufficiently “first class” so that this is perfectly fine?

-- 
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.


Re: Clojure on iOS devices - Swift as a host?

2014-06-11 Thread Mike Fikes
While Gal's approach of ditching IB is fine, I still use it, but bind UI 
components to atoms in ClojureScript. Once that is done, you have a lot of 
power at your disposal on the ClojureScript side of the JavaScriptCore bridge: 
With atom watchers you can react to UI state changes, feed them through 
core.async channels if you'd like to create FRP-like solutions, etc. You can 
create macros as needed to simplify any complexities that arise with the fact 
that iOS is on the other side of that bridge. You can nearly have your cake and 
eat it too :)

-- 
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.


Re: bigint and biginteger

2014-06-07 Thread Mike Fikes
Thanks for the historical perspective, puzzler! 

In addition to performance considerations, *Clojure Programming* points to 
an inconsistency between hash codes for longs and BigIntegers as a 
motivation. 

Using the example number from that excellent book on Clojure 1.5.1 (on Java 
8, FWIW), I can cause this:

#{6948736584 (biginteger 6948736584)}

; = #{6948736584 6948736584}


#{6948736584 (bigint 6948736584)}

; = IllegalArgumentException Duplicate key: 6948736584  
clojure.lang.PersistentHashSet.createWithCheck (PersistentHashSet.java:56)

(System/getProperty java.version)

; = 1.8.0_05


(clojure-version)

; = 1.5.1


On Clojure 1.6, thankfully both fail, even in the face of the inconsistency 
between .hashCode implementations. If that essentially addresses the 2nd 
rationale for introducing a special BigInt class, maybe with both things 
being fixed with Java 8 and Clojure 1.6 BigInteger could come back as the 
sole arbitrary precision representation of ℤ.

-- 
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.


Re: Clojure on iOS devices - Swift as a host?

2014-06-06 Thread Mike Fikes
Maybe ClojureSwift does have potential, even with respect to *performance* as 
well: There's decent speculative chatter [1] about Swift’s safety enabling 
aggressive optimizations that can't be performed in unsafe languages like 
Objective-C, with Swift outperforming on RC4 and other benchmarks.

[1] 
http://programmers.stackexchange.com/questions/242816/how-can-swift-be-so-much-faster-than-objective-c-in-these-comparisons

-- 
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.


Clojure on iOS devices - Swift as a host?

2014-06-04 Thread Mike Fikes
I have been experimenting writing an iOS app using ClojureScript embedded in 
JavaScriptCore, where the ClojureScript essentially implements the logic of my 
view controllers which drive native UI.

So far, this approach seems like a reasonable one to “writing iOS apps using 
Clojure.”

You essentially trade off direct tooling support and gain the ease of 
developing using ClojureScript (this is important to me, as my server is in 
Clojure and I can effectively master one language.)

-- 
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.


Effective Clojure book?

2014-06-04 Thread Mike Fikes
Are there any books yet that prescribe best practices for Clojure, à la 
Meyers or Bloch?

-- 
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.


Migrating from 1.5.1 to 1.6 and dependencies

2014-06-03 Thread Mike Fikes
I'm making use of core.async, which specifies 1.6.

Does leiningen help with ensuring any libraries I'm using are also 
compatible with 1.6?

I'm concerned that I may have another dependency (perhaps transitive) that 
is incompatible, perhaps simply by being AOT compiled with 1.5.1.

-- 
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.


Re: Migrating from 1.5.1 to 1.6 and dependencies

2014-06-03 Thread Mike Fikes
Thanks Alex. That's great! My fear of a “dependency yak shave” is unfounded.

I noticed the following (once) in my server log file, but have been unable to 
trace it down not see any ill effects and presumed it could be caused by mixing 
versions. I'll report if I find anything specific.

#NoClassDefFoundError java.lang.NoClassDefFoundError: 
clojure/core$drop_last$fn__4284

-- 
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.


loop/recur being functional

2014-06-03 Thread Mike Fikes
I'm trying to “internalize” loop/recur as being a functional construct.

I'm sure I'm not alone in this: I initially struggled with it, with my view 
unduely influenced by its implementation, especially when multiple loop 
heads are present. (It could be viewed as vulgar but necessary imperative 
optimization, playing tricks with the instruction pointer).

Here is a line of reasoning that I'm interested in comments on:

Take this example:

(defn vrange [n]
  (loop [i 0 v []]
(if ( i n)
  (recur (inc i) (conj v i))
  v)))


This can be rewritten applying a named inline function that closes over n:

(defn vrange2 [n]
  ((fn loop-recur [i v]
 (if ( i n)
   (loop-recur (inc i) (conj v i))
   v)) 0 []))


Then, this could be further transformed:

(defn loop-recur [i v n]
  (if ( i n)
(loop-recur (inc i) (conj v i))
v))

(defn vrange3 [n]
  loop-recur 0 [] n)


which is clearly functional.

I'm cool with this view. It with it, you see recur not so much as as not 
“jumping” to the nearest loop head, but instead as returning a value that 
results from ”calling” a function, where that function is kind-of defined 
by the loop head.

I was wondering? Is the above transformation always possible, even given 
multiple loop heads? Is it always this simple, or are there corner cases 
that this naïve view misses?

-- 
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.


Re: text processing function

2014-06-01 Thread Mike Fikes
Array destructuring appears to provide what you want with respect to nils 
(note the extra set of square braces within the argument list):

(defn make-map 

   [[fullname lastname firstname middlename]]

   {:fullname fullname

:lastname lastname

:firstname firstname

:middlename middlename})


(make-map [John Lou Doe Doe John Lou])

;= {:fullname John Lou Doe, :lastname Doe, :firstname John, 
:middlename Lou}


(make-map [John Lou Doe Doe John])

;= {:fullname John Lou Doe, :lastname Doe, :firstname John, 
:middlename nil}


(make-map [John Lou Doe Doe])

;= {:fullname John Lou Doe, :lastname Doe, :firstname nil, :middlename 
nil}


(make-map [John Lou Doe])

;= {:fullname John Lou Doe, :lastname nil, :firstname nil, :middlename 
nil}


(make-map [])

;= {:fullname nil, :lastname nil, :firstname nil, :middlename nil}


(make-map nil)

;= {:fullname nil, :lastname nil, :firstname nil, :middlename nil}


On Sunday, June 1, 2014 12:09:35 PM UTC-4, Glen Rubin wrote:

 I am doing some text processing using clojure and attempting to extract a 
 person's name by regex and then assign it to a map.  The result I get takes 
 one of several forms:

 nil (if i can't find the name)

 [fullname]

 [fullname lastname]

 [fullname lastname firstname]

 [fullname lastname firstname middlename]

 now, basically want to assign these entries to a map like so {:fullname 
 some name, :lastname some name, etc...}

 if there is no entry than I would like to assign it as nil, e.g. 
 {:fullname nil, lastname nil, etc...}

 I want to code this in the most proper way.  I am thinking I need to 
 define a function that works differently based on how long the vector is?  
 How do I turn the contents of the vector into function arguments? 

 Thanks! 



-- 
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.


Re: text processing function

2014-06-01 Thread Mike Fikes
Just golfing for fun:

(apply hash-map (interleave [:fullname :lastname :firstname :middlename] 
(concat [John Lou Doe Doe John] (repeat nil


;= {:firstname John, :lastname Doe, :middlename nil, :fullname John 
Lou Doe}


-- 
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.


Re: text processing function

2014-06-01 Thread Mike Fikes
Hey Glen, it appears that zipmap most directly corresponds to your initial 
question.

The only complicating aspect is your desire for nils, which (concat result 
(repeat nil)) addresses. 

  (zipmap [:fullname :lastname :firstname :middlename] (concat result 
(repeat nil)))

If it weren't for the need for nils,

  (zipmap [:fullname :lastname :firstname :middlename] result)

is simple and noise-free.  Note that the nils are unnecessary if later 
using map destructuring:

   (defn use-names [{:keys [fullname lastname firstname middlename]}] 
(println fullname lastname firstname middlename))

For example, nils are generated at call time for you by the map 
destructuring:

  (use-names (zipmap [:fullname :lastname :firstname :middlename] [John 
Lou Doe Doe John]))

  ;= John Lou Doe Doe John nil



-- 
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.


core.async variant of some

2014-05-30 Thread Mike Fikes
I want to execute a sequence of database queries (in order) and stop when 
the first one returns a result.

I've set up things so that a query returns a channel that will be 
populated with the result, and I set up the queries lazily using a for 
comprehension.

A simplified illustrative example of all of this is below. Note that 
async/to-chan should not even be called for the items beyond the one 
containing foo.

(async/!! (let [chans (for [coll [[] [] [foo] [] [bar]]]
   (async/to-chan coll))]
   (async/go (loop [[ch  rest] chans]
 (if-let [val (! ch)]
 val
 (when rest
 (recur rest)))
= foo

This smells a lot like a core.async variant of some having behavior 
analogous to the simpler example:

(some identity [nil nil foo nil bar])
= foo

I'm curious if there already exists a core.async construct that either 
directly or indirectly matches what I'm trying to do

I'd also accept advice that the entire approach is wrong. Lazily evaluating 
queries (which cause database I/O only when are evaluated) could seem 
reasonable in blocking / synchronous code, but perhaps there is a much 
better way to achieve this in a style that is consistent with core.async.

-- 
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.


symbol grammar

2014-05-24 Thread Mike Fikes
Hey Greg, did your benchmark compare /|[\\D[^/]] to \\D or did it compare the 
existing Clojure regex to a shortened one, making your substitution?

(If it was the former, perhaps the existing regex is more efficient owing to 
the repetition of the expression /|[\\D[^/]] ).

- Mike

-- 
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.


Non-blocking file I/O Clojure library?

2014-05-18 Thread Mike Fikes
Does anyone know of any libraries for Clojure that wrap up non-blocking 
file I/O?

I'm interested in one suitable for use with core.async on Java 7+.

Below is a naïve stab at a function that reads file and returns it on a 
channel. It blocks somewhat (in the open and length calls), but overall, it 
is trying to be fast and non-blocking enough to usable in one of the 
core.async worker threads under mild load. Of course, there are lots of 
things to be concerned about, such as whether it is safe to pass a 
ByteBuffer across a channel (thread safety concerns), etc. It also puts 
exceptions on the channel, so the client can use Nolen's ? macro [1]. 

I'd rather not be solving a problem alone that I believe lots of core.async 
users will encounter.

(def asynch-file-executor (Executors/newFixedThreadPool 8))

(defn read-file
  [file]
  (let [ch (async/chan)
path (java.nio.file.Paths/get (java.net.URI. file))
fileChannel (AsynchronousFileChannel/open path 
#{StandardOpenOption/READ} asynch-file-executor (make-array FileAttribute 
0))
buffer (ByteBuffer/allocate (.length (.toFile path)))]

(.read fileChannel buffer 0 buffer
   (proxy [CompletionHandler] []
 (completed [result _]
   (.close fileChannel)
   (.flip buffer)
   (async/go
 (async/! ch buffer)
 (async/close! ch)))
 (failed [e _]
   (async/go
 (async/! ch e)
 (async/close! ch)
ch))


[1] http://swannodette.github.io/2013/08/31/asynchronous-error-handling/

-- 
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.


Advice on data structure communication and awareness

2014-05-17 Thread Mike Fikes
I've never used a dynamically-typed language and an issue I've encountered 
with Clojure is a difficulty with readily seeing the data structures 
being consumed or returned by functions I'm writing, especially when I come 
back to them several days later and if those structures get to be somewhat 
nested or otherwise complex.

As a small concrete example, lets say that I currently have a function that 
accepts data that looks like {:a A :b B} and, at some point I change 
the internals of the function to instead operate on data that looks like 
[[:a A] [:b B]].

I could see the docstring communicating that the initial implementation of 
the function accepts a map, and then perhaps it boils down to finding 
suitable language to describe the structure in the revised implementation 
(sequence of pairs, relation, or some other language suitable to the 
abstraction).

I suppose this is no different than the documentation aspect that 
generics provided in Java when we went from raw types like List to 
ListString, but, of course, generics can get unwieldy rather quickly with 
things like ListMapString,SetInteger.

Does there exist idiomatic language that developers employ in their 
docstrings to quickly convey this kind of info? I see that the docstrings 
for clojure.core are fairly readable, but they tend to operate on very 
simple data structures.

-- 
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.


Re: Immutable or Effectively Immutable?

2014-05-16 Thread Mike Fikes
In the sample code I pasted, there is nothing to prevent the fill(1) and 
fill(2) from running concurrently, and essentially write into the same array 
concurrently. My intent was that the fill(1) be complete before the second 
thread proceeds.

A simple change to have the 1st thread instead fill a temporary byte[] followed 
by assigning the temporary reference to the static volatile byte[] causes the 
program to no longer print “false”. 

This behavior, while it doesn't prove anything, is consistent with the JLS 
paragraph I quoted.

But, it doesn't disprove Alexandru's claim either...

-- 
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.


Re: Expected inconsistency between set and map w/ ArrayList?

2014-05-13 Thread Mike Fikes
To facilitate inlining, the patch calls out to a separate larger method 
which handles a group of cases.

+if(o.getClass().getName().startsWith(java.util.))
+return doalienhasheq(o);
+return o.hashCode();


I was wondering whether an efficient improvement is possible that would support 
things like Guava ImmutableList.


In particular, I was wonder which default cases are currently handled by the 
return o.hashCode() above. Replacing the three lines above with 


+return doalienhasheq(o);


would allow the patch to also handle non-java.util collection implementations, 
but push the default cases down into the bottom of that method.


On Tuesday, May 13, 2014 12:38:54 AM UTC-4, Michał Marczyk wrote:

 I've posted a patch that makes java.util.{List,Map,Map.Entry,Set} 
 hashes consistent with those of appropriate Clojure collection types 
 on the ticket. 


-- 
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.


Re: Nominalization

2014-05-10 Thread Mike Fikes
That's interesting. I haven't learned about reductions yet—I'll check it 
out.

If you consider the following,

  (defn dot-product [v1 v2] (reduce + (map * v1 v2)))

perhaps dot-product would be considered a noun, while since the reduce it 
is defined in terms of speaks of *how* instead of *what,* is better though 
of as a verb.

I find the concept of the elimination of time interesting. 

The expression (reduce + (map * [1 2 3] [5 0 1])) brings to mind a tiny 
machine, while (dot-product [1 2 3] [5 0 1]) feels like a *thing*. But, 
they both are simply the thing: 8 and perhaps both could be evaluated at 
compile time, eliminating the time-based machine that mentally cranks away 
while reduce and map “run.”


On Saturday, May 10, 2014 12:52:34 AM UTC-4, Gary Trakhman wrote:

 Never thought of it that way, I always verb the noun.

 Did you learn about reductions, yet? It's clear that the name corresponds 
 to the intended output at least in that case.


-- 
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.


Re: How to convert this list into map?

2014-05-10 Thread Mike Fikes


user= (apply hash-map (conj '(:= :language Clojure) :op))

{:op :=, :language Clojure}

On Saturday, May 10, 2014 5:56:59 PM UTC-4, Hussein B. wrote:

 Hi,

 I have this list:

 (:= :language Clojure)

 And I want to convert it to the following map data structure:

 {:op := , :language Clojure}

 I can't really think of a clear way how to do it.

 Would you please help?

 Thanks for help and time.


-- 
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.


Re: How to convert this list into map?

2014-05-10 Thread Mike Fikes
Here is how you can derive that expression:

{:op :=, :language Clojure}

is the same as

(hash-map :op := :language Clojure)


which is the same as

(apply hash-map '(:op := :language Clojure))


So, all you need is

'(:op := :language Clojure)

which can be produced by prepending :op to your original list

(conj '(:= :language Clojure) :op)

-- 
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.


Re: How to convert this list into map?

2014-05-10 Thread Mike Fikes
That looks much better IMHO :)

-- 
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.


Re: Immutable or Effectively Immutable?

2014-05-09 Thread Mike Fikes


Thanks Alexandru! That was insightful. :)

Even the JLS's (non-normative?) text is confusing IMHO. Section 17.5 ends 
with this paragraph:

The usage model for final fields is a simple one. Set the final fields for 
an object in that object's constructor. Do not write a reference to the 
object being constructed in a place where another thread can see it before 
the object's constructor is finished. If this is followed, then when the 
object is seen by another thread, that thread will always see the correctly 
constructed version of that object's final fields. *It will also see 
versions of any object or array referenced by those final fields that are 
at least as up-to-date as the final fields are.*

If you read that paragraph, it would lead you to believe the bit in bold 
would be applicable to the program below. It seems that the key is, as you 
pointed out, simply extending the concept of this escaping to cover 
mutable references stored during construction.

import java.util.Arrays;

public class Main {

static class Foo {
final byte[] bytes;
Foo(byte[] bytes) {
this.bytes = bytes;
Arrays.fill(this.bytes, (byte) 2);
}
}

static volatile byte[] bytes;
static volatile Foo foo;

public static void main(String[] args) {

new Thread(new Runnable() {
public void run() {
// Create an array filled with 1s and spin for other thread
bytes = new byte[1024*1024];
Arrays.fill(bytes, (byte) 1);
while (foo == null) {}

// Check to see if we get the array contents set by other thread
byte[] expected = new byte[1024*1024];
Arrays.fill(expected, (byte) 2);
boolean match = Arrays.equals(expected, foo.bytes);
System.out.println(match); // Will print false at times
}
}).start();

new Thread(new Runnable() {
public void run() {
// Spin for first thread
while (bytes == null) {}

// Create an immutable object using bytes, while mutating 
bytes prior to construction completion and publication
foo = new Foo(bytes);
}
}).start();
}
}


On Thursday, May 8, 2014 4:43:10 PM UTC-4, Alexandru Nedelcu wrote:

 On Wed, May 7, 2014 at 6:31 AM, Alex Miller 
 al...@puredanger.comjavascript: 
 wrote:

 It does matter with regard to visibility across threads - your example 
 does not use a synchronization mechanism and there is no guarantee that 
 other threads will ever see those changes (so don't ever ever do that :). 
 But if you stick to the normal Clojure apis, all is good. I'd highly 
 recommend reading JCIP to dive into the details. 

 Final field freeze is particularly weird and it baked my noodle when I 
 first encountered it - here's a blog I wrote about it approx 697 years ago 
 in internet time (and Brian Goetz backs me up in the comments :)
 http://tech.puredanger.com/2008/11/26/jmm-and-final-field-freeze/

  I believe that while JCIP is useful, it is also confusing, because it is 
 trying to explain Java’s memory model in layman’s terms. I recently 
 experienced “enlightenment”, by making an effort to understand how things 
 work at a lower level. 

 Happens-before relationships / ordering guarantees are given by the 
 compiler, in combination with the CPU, with the rules being implied by 
 usage of memory fences (barriers). Without ordering guarantees, several 
 things can happen - the compiler could optimize the code by reordering or 
 eliminating instructions, the CPU might optimize the code by reordering or 
 eliminating instructions and - what bits beginners the most - today’s 
 multi-core CPUs are tricky, as each CPU has a store buffer that’s local to 
 each core (i.e. other cores cannot see it) and published values only become 
 visible to other cores when the store buffer gets flushed to the L1 cache. 
 And you have no guarantee that this flush will *ever* happen, or even 
 after it happens, you have no guarantee that other processors that already 
 have a cached value will make an effort to read the more up-to-date value … 
 unless ordering semantics are enforced. And actually thinking in terms of 
 flushes to memory is dangerous, as nothing you do guarantees a flush - 
 everything being relative, specified in terms of happens-before 
 relationships, implied by memory barriers.

 And memory barriers are tricky beasts, as they come in multiple shapes and 
 sizes. The JSR 133 Cookbookhttp://gee.cs.oswego.edu/dl/jmm/cookbook.htmlis 
 a useful document for shedding some light on how they work. In 
 particular, for final fields, you get a guarantee for a *StoreStore*memory 
 barrier, like so:

 x.finalField = v; *StoreStore*; sharedRef = x;

 This guarantee basically says that the finalFields’ value will always be 
 stored before the write sharedRef 

Expected inconsistency between set and map w/ ArrayList?

2014-05-09 Thread Mike Fikes
Perhaps this is a consequence of the hashing changes in 1.6. 
(http://dev.clojure.org/display/design/Better+hashing)

-- 
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.


Nominalization

2014-05-09 Thread Mike Fikes
I am new to functional programming and caught myself reading “reduce” as “the 
reduction of.”

Do you experienced Clojure programmers find yourselves thinking in terms of 
nouns instead of verbs? (Non-temporal expressions as opposed to actions?)

Some of the operations reinforce this way of thinking (“range” and “max”) while 
others don't (“map” and “take”) while some can easily be either (“count” and 
“mod”) and some that resist being either (“if” and “let”).

-- 
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.


Re: Immutable or Effectively Immutable?

2014-05-07 Thread Mike Fikes
Phil, that's an interesting point.

Consider (def x (cons (new java.util.Date) ()))

The object identified by x is *mutable*, but if the contained Date will not 
be modified by the program, then the resulting object can be treated as 
*effectively 
immutable, *as you pointed out.

But, it would seem that you could pass x to another thread without 
synchronization, and then safely read the contained Date instance by that 
thread, because it has been safely published by virtue of having been 
conveyed by a final field of the Cons instance. Of course, you would run 
into trouble if you took that Date instance and passed it directly to 
another thread without synchronization.

In other words, you could step outside of the limited profile of the Java 
memory model that JCIP prescribes treating x as something (useful) between 
*effectively 
immutable *and *immutable, *with the end result being that you can treat x as 
being *immutable.*

On Wednesday, May 7, 2014 7:13:31 AM UTC-4, Phillip Lord wrote:


 Since the data structures and interfaces, they are effectively 
 immutable. 

 Consider this: 

 final public class Cons extends ASeq implements Serializable { 

 private final Object _first; 
 private final ISeq _more; 

 public Cons(Object first, ISeq _more){ 
 this._first = first; 
 this._more = _more; 
 } 
 } 

 Although Cons uses final fields and constructor fields, _more is an 
 ISeq; given that this could be mutable, so could cons. 

 Phil 

 Mike Fikes mike...@me.com javascript: writes: 

  Are the persistent immutable data structures in Clojure truly 
 immutable 
  (using final fields, relying on constructor freezing), or are they mean 
 to 
  be merely effectively immutable (as defined in JICP)? 

 -- 
 Phillip Lord,   Phone: +44 (0) 191 222 7827 
 Lecturer in Bioinformatics, Email: 
 philli...@newcastle.ac.ukjavascript: 
 School of Computing Science,
 http://homepages.cs.ncl.ac.uk/phillip.lord 
 Room 914 Claremont Tower,   skype: russet_apples 
 Newcastle University,   twitter: phillord 
 NE1 7RU 


-- 
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.


Re: Immutable or Effectively Immutable?

2014-05-07 Thread Mike Fikes
Yep. PersistentVector is *mutable* per the JCIP definition.

If it is *mutable* then you need to use locks or synchronization to access 
its contents.

If your program doesn't modify its the vector, it is *effectively 
immutable. *But, you need to ensure that you safely publish it.

But, if you create a PersistentVector, and somehow ensure that the array's 
contents are never modified, you can pass it freely between threads without 
synchronization.

In short, even though you can't claim that PersistentVector is *immutable*, 
if you discipline yourself on how you use it, you can pretend that it is.

This is a consequence of the use of final on the array field in 
PersistentVector.

On Wednesday, May 7, 2014 10:17:38 AM UTC-4, Andy Fingerhut wrote:

 Mike, I believe I understand the definition of truly immutable you are 
 using here, and what it means in the JVM as far as synchronization of 
 object values across threads.

 What seems a bit odd is to use the phrase truly immutable to describe 
 something that is clearly mutable, or at least it is by the definition of 
 mutable: can be modified after construction, which PersistentVector and 
 others can be.

 Thanks,
 Andy


 On Tue, May 6, 2014 at 6:20 PM, Mike Fikes mike...@me.com 
 javascript:wrote:

 Hi Andy,

 Marking Java fields as final has semantics with respect to threading, 
 defined in the JLS in section 17.5 (
 http://docs.oracle.com/javase/specs/jls/se5.0/html/memory.html#17.5)

 If you do this, then it makes it possible to freely pass a truly 
 immutable object instance to another thread and be guaranteed that that 
 other thread will see the value initialized for that field in the 
 constructor.

 If you don't do this, then the object can still be effectively 
 immutable, which essentially means that you can pass the object to another 
 thread, so long as you do it in a safe manner (using a volatile, or some 
 synchronization mechanism).

 JCIP helps clarify all of this unfortunately complex topic.

 The important thing (and key to Closure), is that, if you are 
 implementing the class that you want to be immutable, then if you can mark 
 everything as final, then you truly achieve the benefits immutability give 
 you with concurrency (in short, you need no synchronization whatsoever). If 
 you fail to do this, then you have effective immutability, which is good, 
 but complex and comes with caveats on how you can safely pass objects 
 between threads.

 JCIP is a great book. But, the approach taken by Clojure makes a lot of 
 the complicated concerns covered by the book largely ignorable, IMHO.

 On Tuesday, May 6, 2014 8:35:43 PM UTC-4, Andy Fingerhut wrote:

 Alex, I may be unfamiliar with the definitions of truly immutable and 
 effectively immutable being used here, but if I can mutate the contents of 
 a Java Object array that is a final field after an object is constructed, 
 does it really matter that much if it is final?  It is trivially easy to 
 mutate using Java access.  Here is the example that I mentioned earlier in 
 this thread, copied here for convenience:

 user= (def v [1 2 3])
 #'user/v
 user= (class v)
 clojure.lang.PersistentVector
 user= v
 [1 2 3]
 user= (aset (.tail v) 1 -2)
 -2
 user= v
 [1 -2 3]

 Andy


 On Tue, May 6, 2014 at 4:49 PM, Alex Miller al...@puredanger.comwrote:

  The Clojure persistent data structures are truly immutable - all 
 fields are final and referred objects are not mutated after construction 
 so 
 that freeze occurs.  One obvious exception are the transient variants (
 http://clojure.org/transients). You can look at the code in 
 https://github.com/clojure/clojure/tree/master/src/jvm/clojure/lang - 
 any of the Persistent*.java.


 On Tuesday, May 6, 2014 4:11:49 PM UTC-5, Mike Fikes wrote:

 Are the persistent immutable data structures in Clojure truly 
 immutable (using final fields, relying on constructor freezing), or are 
 they mean to be merely effectively immutable (as defined in JICP)?

  -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clo...@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+u...@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+u...@googlegroups.com.

 For more options, visit https://groups.google.com/d/optout.


  -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clo...@googlegroups.comjavascript:
 Note that posts from new members are moderated - please be patient with 
 your first post.
 To unsubscribe from this group, send email to
 clojure+u

Re: Immutable or Effectively Immutable?

2014-05-07 Thread Mike Fikes
I would offer that the key distinction is whether final is used: This 
prescribes what you must do when using the object.

Take Date for example. You can't just pass one directly from one thread to 
another. The receiving thread could read a date associated with 
System.currentTimeMillis() of 0. 

But, String, since it uses final on its char[], fundamentally changes this. 
(If the final keyword were not present in String, even though you have no 
way to change its char[], it would be broken with respect to threading 
semantics.)

On Wednesday, May 7, 2014 10:35:04 AM UTC-4, Andy Fingerhut wrote:

 Sorry if I'm beating a dead horse here.

 I agree that my example is not using published Clojure APIs, and I never 
 do that kind of thing in a Clojure program, except as an example that 
 PersistentVector's are mutable if you use Java APIs instead of restricting 
 yourself to Clojure APIs.  You don't even need to use reflection in Java or 
 know about JVM security policies to mutate them (I am not suggesting that 
 Clojure should be changed in any way here).

 I've actually got a copy of Java: Concurrency in Practice, and looked up 
 (some of) what they say about immutability.  Here is one definition they 
 give of immutability, with some preceding text.  I have added emphasis to 
 one phrase:

 Neither the Java Language Specification nor the Java Memory Model 
 formally defines immutability, but __immutability is *not* equivalent to 
 simply declaring all fields of an object 'final'__.  An object whose fields 
 are all final may still be mutable, since final fields can hold references 
 to mutable objects.

 An object is *immutable* if:
 + Its state cannot be modified after construction;
 + All its fields are 'final'; and
 + It is *properly constructed* (the 'this' reference does not escape 
 during construction).

 I have no argument with PersistentVector satisfying the 2nd and 3rd bullet 
 points above, but (1) seems not to hold.  According to JCIP's definition of 
 effectively immutable (Objects that are not technically immutable, but 
 whose state will not be modified after publication), PersistentVector 
 appears to me to be effectively immutable, but not truly immutable.

 Andy


 On Tue, May 6, 2014 at 8:31 PM, Alex Miller al...@puredanger.comjavascript:
  wrote:

 Hey Andy,

 It does matter with regard to visibility across threads - your example 
 does not use a synchronization mechanism and there is no guarantee that 
 other threads will ever see those changes (so don't ever ever do that :). 
 But if you stick to the normal Clojure apis, all is good. I'd highly 
 recommend reading JCIP to dive into the details. 

 Final field freeze is particularly weird and it baked my noodle when I 
 first encountered it - here's a blog I wrote about it approx 697 years ago 
 in internet time (and Brian Goetz backs me up in the comments :)
 http://tech.puredanger.com/2008/11/26/jmm-and-final-field-freeze/

 Alex


 On Tuesday, May 6, 2014 7:35:43 PM UTC-5, Andy Fingerhut wrote:

 Alex, I may be unfamiliar with the definitions of truly immutable and 
 effectively immutable being used here, but if I can mutate the contents of 
 a Java Object array that is a final field after an object is constructed, 
 does it really matter that much if it is final?  It is trivially easy to 
 mutate using Java access.  Here is the example that I mentioned earlier in 
 this thread, copied here for convenience:

 user= (def v [1 2 3])
 #'user/v
 user= (class v)
 clojure.lang.PersistentVector
 user= v
 [1 2 3]
 user= (aset (.tail v) 1 -2)
 -2
 user= v
 [1 -2 3]

 Andy


 On Tue, May 6, 2014 at 4:49 PM, Alex Miller al...@puredanger.comwrote:

  The Clojure persistent data structures are truly immutable - all 
 fields are final and referred objects are not mutated after construction 
 so 
 that freeze occurs.  One obvious exception are the transient variants (
 http://clojure.org/transients). You can look at the code in 
 https://github.com/clojure/clojure/tree/master/src/jvm/clojure/lang - 
 any of the Persistent*.java.


 On Tuesday, May 6, 2014 4:11:49 PM UTC-5, Mike Fikes wrote:

 Are the persistent immutable data structures in Clojure truly 
 immutable (using final fields, relying on constructor freezing), or are 
 they mean to be merely effectively immutable (as defined in JICP)?

  -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clo...@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+u...@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+u...@googlegroups.com.

 For more options

Re: Reduce vs. Comp

2014-05-07 Thread Mike Fikes
I agree with the re-implementing comp sentiment.

It reminds me of *A tutorial on the universality and expressiveness of fold 
http://www.cs.nott.ac.uk/~gmh/fold.pdf *where, essentially lots of 
standard functions can be defined in terms of reduce which could be 
considered primitive.

In fact, section 5 of that document defines comp as a reduce involving the 
identify function in some way. (Now, I want to re-read this paper, but 
translated into Clojure.)

On Wednesday, May 7, 2014 9:17:46 AM UTC-4, Mark Watson wrote:

 What is the difference between:

 (reduce #(%2 %) 6 [(partial + 12) (partial * -1)])

 and

 ((apply comp [(partial * -1) (partial + 12)]) 6)

 Using reduce *looks* nicer to me, but I feel like I'm re-implementing 
 comp. Their performance is also the same (go inlining!).


-- 
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.


Immutable or Effectively Immutable?

2014-05-06 Thread Mike Fikes
Are the persistent immutable data structures in Clojure truly immutable 
(using final fields, relying on constructor freezing), or are they mean to 
be merely effectively immutable (as defined in JICP)?

-- 
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.


Re: Immutable or Effectively Immutable?

2014-05-06 Thread Mike Fikes
Hi Andy,

Marking Java fields as final has semantics with respect to threading, 
defined in the JLS in section 17.5 
(http://docs.oracle.com/javase/specs/jls/se5.0/html/memory.html#17.5)

If you do this, then it makes it possible to freely pass a truly 
immutable object instance to another thread and be guaranteed that that 
other thread will see the value initialized for that field in the 
constructor.

If you don't do this, then the object can still be effectively immutable, 
which essentially means that you can pass the object to another thread, so 
long as you do it in a safe manner (using a volatile, or some 
synchronization mechanism).

JCIP helps clarify all of this unfortunately complex topic.

The important thing (and key to Closure), is that, if you are implementing 
the class that you want to be immutable, then if you can mark everything as 
final, then you truly achieve the benefits immutability give you with 
concurrency (in short, you need no synchronization whatsoever). If you fail 
to do this, then you have effective immutability, which is good, but 
complex and comes with caveats on how you can safely pass objects between 
threads.

JCIP is a great book. But, the approach taken by Clojure makes a lot of the 
complicated concerns covered by the book largely ignorable, IMHO.

On Tuesday, May 6, 2014 8:35:43 PM UTC-4, Andy Fingerhut wrote:

 Alex, I may be unfamiliar with the definitions of truly immutable and 
 effectively immutable being used here, but if I can mutate the contents of 
 a Java Object array that is a final field after an object is constructed, 
 does it really matter that much if it is final?  It is trivially easy to 
 mutate using Java access.  Here is the example that I mentioned earlier in 
 this thread, copied here for convenience:

 user= (def v [1 2 3])
 #'user/v
 user= (class v)
 clojure.lang.PersistentVector
 user= v
 [1 2 3]
 user= (aset (.tail v) 1 -2)
 -2
 user= v
 [1 -2 3]

 Andy


 On Tue, May 6, 2014 at 4:49 PM, Alex Miller al...@puredanger.comjavascript:
  wrote:

 The Clojure persistent data structures are truly immutable - all fields 
 are final and referred objects are not mutated after construction so that 
 freeze occurs.  One obvious exception are the transient variants (
 http://clojure.org/transients). You can look at the code in 
 https://github.com/clojure/clojure/tree/master/src/jvm/clojure/lang - 
 any of the Persistent*.java.


 On Tuesday, May 6, 2014 4:11:49 PM UTC-5, Mike Fikes wrote:

 Are the persistent immutable data structures in Clojure truly 
 immutable (using final fields, relying on constructor freezing), or are 
 they mean to be merely effectively immutable (as defined in JICP)?

  -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clo...@googlegroups.comjavascript:
 Note that posts from new members are moderated - please be patient with 
 your first post.
 To unsubscribe from this group, send email to
 clojure+u...@googlegroups.com javascript:
 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+u...@googlegroups.com javascript:.
 For more options, visit https://groups.google.com/d/optout.




-- 
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.


Re: Immutable or Effectively Immutable?

2014-05-06 Thread Mike Fikes
Thanks!

I initially saw that the count field of ArrayNode (in PersistentHashMap) is 
non-final and also mutated in at least one case, and began to question 
things.

But, for that particular example, if that field is only mutated in the case 
of editing transients, then for the non-transient case ArrayNode is 
effectively immutable but also safely published by any truly immutable data 
structures by being referred to in final fields.

Excellent! I had to look for myself, and now I feel much more comfortable 
that Clojure is built upon the bedrock it needs to be :)

On Tuesday, May 6, 2014 7:49:07 PM UTC-4, Alex Miller wrote:

 The Clojure persistent data structures are truly immutable - all fields 
 are final and referred objects are not mutated after construction so that 
 freeze occurs.  One obvious exception are the transient variants (
 http://clojure.org/transients). You can look at the code in 
 https://github.com/clojure/clojure/tree/master/src/jvm/clojure/lang - any 
 of the Persistent*.java.

 On Tuesday, May 6, 2014 4:11:49 PM UTC-5, Mike Fikes wrote:

 Are the persistent immutable data structures in Clojure truly immutable 
 (using final fields, relying on constructor freezing), or are they mean to 
 be merely effectively immutable (as defined in JICP)?



-- 
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.


Re: Achieving structural sharing when composing data

2014-05-05 Thread Mike Fikes
Thanks Gary, Leif, Alex!

I suspected memoization might be the way to go—the leap I needed to make 
was: writing my own data constructors.


On Monday, May 5, 2014 9:10:40 AM UTC-4, Alex Miller wrote:

 To clarify slightly, the Java Language Specification section 5.1.7 
 requires that the implementation cache *boxed* ints from -128 to 127, 
 boolean true/false, and characters from \u and \u007f. Because Clojure 
 defaults to boxing in many cases you'll see the same effect.

 The persistent collections do go through factories and already cache one 
 special case: empty list/vector/set/map. This is also where the choice is 
 made as to the type of persistent map (array or hash impl) based on size (
 https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/RT.java#L1457
 ). 

 I think in general, there is not enough commonality across programs for 
 the cost of the check to be more costly than the benefits to be saved in 
 memory so this is not something Clojure would ever do generically. But, if 
 this is tradeoff is important to you, then creating your own factory 
 function for collections and memoizing it would be a good way to achieve 
 that. 


 On Sunday, May 4, 2014 10:21:28 PM UTC-5, Leif wrote:


 The general technique in lisp is called hash consing (a.k.a. flyweight 
 pattern, a.k.a. interning).  Java strings, clojure symbols, and keywords 
 are interned.  And small integers, apparently.

 The basic idea is to create memoized versions of all the data 
 constructors and only use them.  This is basically what you did in your 
 example and what Gary suggested.  So, if you truly wanted something 
 general, you'd probably have to reimplement a lot of clojure.core, or 
 restrict yourself to a small number of constructor fns.  

 If the vectors in your example are the only composite structure that 
 needs sharing, and they represent points, say:

 (def mk-point (memoize (fn [x y] [x y]))) ; obviously lots of options 
 here (caching strategy, weak refs)

 (def m1 {:a (mk-point 1 2)})

 (def m2 (assoc m1 :b (mk-point 1 2)))

 (identical? (m2 :a) (m2 :b)) ; = true

 If the maps themselves need to be shared, you'll have to make your own 
 version of assoc, dissoc, maybe conj  into, etc etc, and remember to 
 always use them.  It could get complicated.

 --Leif

 On Saturday, May 3, 2014 10:27:29 PM UTC-4, Mike Fikes wrote:

 Are there common techniques or idioms for achieving structural sharing 
 when composing data where equivalences exist?

 (My motivation is to reduce heap usage for a particular problem I'm 
 working on that involves a lot of repeated data.)

 As a specific example, consider sharing equivalent map values:

 (def m1 {:a [1 2]})

 (def m2 (assoc m1 :b [1 2]))


 (identical? (m2 :a) (m2 :b))

 ;; = false


 For this simple example, I can force sharing by introducing a variant of 
 assoc which looks at existing values:


 (defn assoc-id [map key val] (assoc map key (get (apply hash-set (vals 
 map)) val val)))


 And using it results in a map with two identical values:


 (def m3 (assoc-id m1 :b [1 2]))


 (identical? (m3 :a) (m3 :b))

 ;; = true


 But, of course, this approach could get to be expensive and/or unwieldy 
 if not done carefully.


 So, I was wondering if there are general techniques in this area. I'm 
 sure I'm not the first to come across it. We already get this 
 automatically for boxing of small integers:


 (identical? 5 5)

 ;; = true


 (identical? 500 500)

 ;; = false


 So I suppose I'm essentially looking for the same idea but for larger 
 non-primitive values.





-- 
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.


Achieving structural sharing when composing data

2014-05-03 Thread Mike Fikes
Are there common techniques or idioms for achieving structural sharing when 
composing data where equivalences exist?

(My motivation is to reduce heap usage for a particular problem I'm working 
on that involves a lot of repeated data.)

As a specific example, consider sharing equivalent map values:

(def m1 {:a [1 2]})

(def m2 (assoc m1 :b [1 2]))


(identical? (m2 :a) (m2 :b))

;; = false


For this simple example, I can force sharing by introducing a variant of 
assoc which looks at existing values:


(defn assoc-id [map key val] (assoc map key (get (apply hash-set (vals 
map)) val val)))


And using it results in a map with two identical values:


(def m3 (assoc-id m1 :b [1 2]))


(identical? (m3 :a) (m3 :b))

;; = true


But, of course, this approach could get to be expensive and/or unwieldy if 
not done carefully.


So, I was wondering if there are general techniques in this area. I'm sure 
I'm not the first to come across it. We already get this automatically for 
boxing of small integers:


(identical? 5 5)

;; = true


(identical? 500 500)

;; = false


So I suppose I'm essentially looking for the same idea but for larger 
non-primitive values.


-- 
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.