Re: Optimizaton for finding the next key in a sorted-map

2020-05-25 Thread Carlo Zancanaro
Hey Harmon,

On Tue, May 26 2020, Harmon Nine wrote:
> Does such an optimization exist?  If not, is there an means of getting the 
> next-key in a sorted-map given a current-key that is better than O(n)?

I just had a look at clojure.core and found that subseq operates on a
sorted collection. Based on my quick test I think it can find the next
element in a sublinear number of comparisons:

(def ^:dynamic comparisons nil)
(defn count-comparisons [x]
  (when comparisons (swap! comparisons inc))
  x)
(def s (into (sorted-set-by (comp count-comparisons compare))
 (range 1000)))

(= (for [i (range 1001)]
 (first (subseq s > (- i 0.5
   (concat (range 1000) [nil]))
;; true

(frequencies
 (for [i (range 1001)]
   (binding [comparisons (atom 0)]
 (first (subseq s > (- i 0.5)))
 @comparisons)))
;; => {10 256, 11 384, 12 192, 13 96, 14 56, 15 16, 16 1}

I can only confirm that this works for > and >= as the comparison,
though, which are interpreted relative to the sort order for the
collection. Switching the sort order in the collection effectively flips
the meaning of >, too.

(def s2 (into (sorted-set-by (comp - compare))
  (range 1000)))
(= (for [i (range 1001)]
 (first (subseq s2 > (- i 0.5
   (cons nil (range 1000)))
;; true

Other comparisons seem to fall back to just calling take-while, which
doesn't seem right to me.

I hope that helps!

Carlo

-- 
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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/clojure/87367nsl23.fsf%40gmail.com.


Re: Bizarre issue when calling protocol-fn wrapper from different namespace

2019-11-22 Thread Carlo Zancanaro

Hey Dimitris,

I think what you're running into here is a fundamental 
misunderstanding of protocols. Specifically, this is not true:



As I understand it, protocol extensions are namespace-specific.


In Clojure, protocol extensions are global. If you extend a 
protocol for a type then it doesn't matter which namespace calls 
the protocol function, it only matters what type the function is 
called on. Protocols are approximately interfaces in Java, except 
they can have implementations added to existing types at runtime.


With your current code, I am a little bit confused why you want to 
use a protocol. You have a multimethod which performs dispatch 
based on a key, but which then calls the same protocol function 
for each dispatch value - why not just call the appropriate 
function in the right namespace? The protocol seems to be 
attempting to add a second level of indirection, but it's not 
clear to me how or why that is useful.


Carlo

--
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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/clojure/87blt3k4e4.fsf%40gmail.com.


Re: mu4e:view show email address after display name in message headers

2018-09-24 Thread Carlo Zancanaro

Hey Jeff,

On Tue, Sep 25 2018, Jeff Kowalczyk wrote:
I would like to configure mu4e:view to display the email address 
along with the display name in the To: From: Cc: Bcc: etc 
fields.


This is definitely the wrong list, but given how easy it is to do 
this, I thought I'd help you out.


 (setq mu4e-view-show-addresses t)

Going a step farther, it would be great to use a function with 
access to this information ...


Setting it to a function is harder, but you could advise 
mu4e~view-construct-contacts-header if you really wanted to. 
That's not a public function, though, so it might change in 
future.


Carlo

--
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: IF, WHEN or SOME

2018-09-20 Thread Carlo Zancanaro

Hey Stephen,

On Fri, Sep 21 2018, Stephen Feyrer wrote:
user=> (def some-numbers ‘(2 4 6 8))  #This is my value to test 
later.

#’user/some-numbers


At this point we have some-numbers = '(2 4 6 8)

user=> (def evens? (partial (when (apply = (map even? 
some-numbers)

#’user/evens?


Let's work through this:

 (map even? '(2 4 6 8)) = '(true true true true)
 (apply = '(true true true true)) = true
 (when true) = nil
 (partial nil) = nil

This means that we have evens? = nil


user=> (evens? (println “one”))
one
NullPointerException   user/eval239 (NO_SOURCE_FILE:74)


So now we have:

 (println "one") = nil (with the side effect of printing "one")
 (nil nil) throws NullPointerException

Clojure is attempting to call nil as a function, which throws a 
NullPointerException.


I hope that helps! I'm not sure what you're actually trying to do, 
so it's hard for me to give advice on how to do it.


Carlo

--
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 does interruptible-eval from tools.nrepl queue evaluations?

2018-05-03 Thread Carlo Zancanaro


On Thu, May 03 2018, Gary Fredericks wrote:
Separately, I use this macro 
 for running 
background things in the repl. It probably targets different 
concerns, but seems related at least.


My use case is quite different. Requiring someone to decide ahead 
of time to run code in the background (ie. by wrapping it in 
another form) won't work for me at all.


I'm trying to write a Common Lisp interactive restart system, 
somewhat similar to what Slime gives you. It actually works pretty 
well, but it's often helpful to be able to redefine things, or to 
run some code to change a data structure, before selecting a 
restart. While waiting for a restart selection the eval thread is 
blocked, though, so other evaluations have to happen in another 
thread. The nrepl protocol seems like it was designed for this, 
given how asynchronous it is, so I was surprised that 
interruptible-eval explicitly queued up evaluations and ran them 
sequentially.


I've ended up doing this as a solution: 
https://github.com/czan/dont-give-up.nrepl/blob/acc20e0c25aa90a5c991b9cd1f7cc4abe2f1cd6b/src/dont_give_up/nrepl.clj#L335. 
This isn't perfect. There are further modifications required to be 
able to interrupt evaluations other than the most recent one, but 
it works well enough to be useful. If anyone has a reason why this 
is a terrible idea, I'm all ears.


Carlo

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups "Clojure" group.

To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


signature.asc
Description: PGP signature


Re: Why does interruptible-eval from tools.nrepl queue evaluations?

2018-05-03 Thread Carlo Zancanaro

Apologies, I forgot to cc the list.

On Thu, May 03 2018, Gary Fredericks wrote:
You would also have race conditions on the meaning of *1, *2, 
*3, and *e.


On Thu, May 3, 2018 at 5:43 AM, Carlo Zancanaro 
<carlozancan...@gmail.com>

wrote:
>But what happens when a user set!s a var? is it effective for 
>all future evals but not the concurrent ones?


I believe so, but I can't check right now. If I'm wrong I'll 
correct myself when I can check.


It turns out I was half-wrong. When you start an evaluation then 
the bindings will be set to the state that they were in at the end 
of the most recent evaluation. This can get a bit confusing when 
there are lots of overlapping evaluations, but when you're using 
the system interactively (eg. with CIDER) then you have a lot of 
control over the evaluation sequence.


The meanings of *1, *2, *3, and *e follow the same rules as the 
above. I still find it a bit weird that evaluating a form with 
C-M-x (or other in-buffer evaluation commands) changes those 
variables, though. I would prefer it if those variables only got 
set by an evaluation from the REPL buffer (which CIDER ensures are 
sequential). That way I could eval stuff with C-M-x without 
affecting the state of my REPL history variables. But that's a 
separate issue in my mind.


Carlo

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups "Clojure" group.

To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


signature.asc
Description: PGP signature


Re: Why does interruptible-eval from tools.nrepl queue evaluations?

2018-05-02 Thread Carlo Zancanaro


>I think dynamic vars in particular would be problematic. The repl is built 
>around being able to set! certain vars, and you can't do that to the same 
>binding from multiple threads.

The dynamic thread bindings are established within the function passed to 
queue-eval, though, so it seems like it will be as close to sensible as 
possible. (That is: use the bindings that were current at the point when the 
evaluation was started.)

I just looked into the interruption code, which is the only thing that looks 
like it actually depends on the serial nature of the evaluation. I think it 
would be possible to make it work with parallel evaluations, though, by storing 
a "message id to thread" map on the session instead of a single message id and 
thread. That would let you interrupt the thread for a given evaluation.

Carlo

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


Why does interruptible-eval from tools.nrepl queue evaluations?

2018-05-02 Thread Carlo Zancanaro

Hey there!

With tools.nrepl, if you eval two expressions they get queued up 
and evaluated in sequence. This means that if I evaluate 
(Thread/sleep 1), and then immediately evaluate (+ 1 2), then 
I have to wait ten seconds for the result of 3 to come back.


Is there a particular reason for this? Given that it's quite easy 
to make it evaluate them in parallel, I figure there's a reason 
why it was decided to evaluate them in sequence.


I have a use-case where I would like to be able to run evaluations 
in parallel without having to wrap everything in (future ...), so 
I'm considering writing some middleware to redefine 
clojure.tools.nrepl.middleware.interruptible-eval/queue-eval to 
just put things straight on the executor. It seems to work from my 
limited tests, but are there any reasons why this would break 
horribly?


Carlo

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups "Clojure" group.

To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


signature.asc
Description: PGP signature


[ANN] dont-give-up 0.1.0: Common Lisp style restarts in Clojure

2018-04-14 Thread Carlo Zancanaro

Hey!

Last week I sent an email announcing some code that I've been 
working on to bring Common Lisp style restarts to Clojure. I just 
released the first version! You can see it at 
https://github.com/czan/dont-give-up.


More interestingly, though, I also have a working CIDER interface 
for dealing with unhandled restarts interactively:


 https://github.com/czan/dont-give-up.nrepl

At the moment I provide restarts for some of the failures in 
clojure.core (some compilation errors, agent failures, future 
failures), it's worth using already! Particularly given you can 
add it to your user profile to get a more interactive CIDER REPL 
without needing to change your code at all.


I'm not comfortable recommending dont-give-up to anyone building 
libraries at the moment, because I don't want to commit to keeping 
the interface stable, but I would love some help thinking about 
and implementing other sensible restarts for things in 
clojure.core.


Carlo

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups "Clojure" group.

To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


signature.asc
Description: PGP signature


[ANN] dont-give-up: Common Lisp style restarts

2018-04-05 Thread Carlo Zancanaro

Hey!

I've been playing around a little bit with Common Lisp lately, and 
I've found the interactive restarts to be pretty amazing. So, I've 
implemented something similar to them in Clojure/Cider!


 https://github.com/czan/dont-give-up

It has support for programmatic restarts, but also includes some 
nrepl middleware which will (when paired with the additional elisp 
code) prompt the user for what to do upon failure.


The restarts should interact sensibly with normal JVM exception 
handling. I've put a lot more thought into the exception/restart 
code than I have into the middleware/elisp code, so the cider 
interface is pretty hacky at the moment. If you have experience 
writing nrepl middleware or extending Cider, I'd love your help!


One big problem with this at the moment is that Cider doesn't let 
you do multiple evaluations in parallel, and the interactive 
prompt blocks the thread until you tell it what to do. This means 
you can't evaluate anything else until you have chosen a restart, 
which limits how interactive the system really feels. Fixing this 
has to be done in Cider itself, I believe.


It still needs a polish/improvement to be as good as slime, but 
it's a start!


Carlo

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups "Clojure" group.

To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


signature.asc
Description: PGP signature


Re: What if ^:const could inline everything before macroexpanssion?

2018-03-15 Thread Carlo Zancanaro

On Thu, Mar 15 2018, Didier wrote:
I feel it would be really cool to be able to factor some input 
to macros into constants, is this something I could open a 
ticket for, to extend ^:const so it can inline all literal 
values and also does the inlining before macroexpanssion so that 
the above would work?


Macroexpansion is given the raw forms that are read, and I think 
that's a good thing. Inside a macro you can always call 
macroexpand yourself if you want to (or resolve values another 
way) but there's no way to "undo" automatic macroexpansion.


As one particular example, how would this work in your world? If 
the `bar` is replaced ahead of time in the usage of `l` then it 
cannot be shadowed as an identifier.


 (def ^:const bar {:a 100})
 (defmacro l [name value & body]
   `(let [~name ~value]
 ~@body))
 (l bar 1
(+ bar 1))

If you want to factor out things for macros (particularly macros 
that you don't control) you can try doing so at read time, with 
something that evaluates at read time, like so:


 (def bar {:a 100})
 (defmacro foo [x]
   (:a x))
 (foo #=(eval bar)) ;; => 100

It's a bit messy, but it draws attention to the fact that there's 
something unusual happening with evaluation order.


Carlo

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups "Clojure" group.

To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


signature.asc
Description: PGP signature


[ANN] stateful-check 0.4.0 - test stateful systems with test.check

2018-02-12 Thread Carlo Zancanaro

Hey everyone!

I've just released a new version of my library for testing 
stateful systems with test.check! Now with added race condition 
detection!


 [org.clojars.czan/stateful-check "0.4.0"]

 https://github.com/czan/stateful-check
 https://clojars.org/org.clojars.czan/stateful-check

This version is a major release, and given the long timescale (my 
last release was August 2015), I've taken the chance to break a 
lot of things. In return, though, we can now run parallel test 
cases to detect race conditions. If you watched John Hughes' talk 
at Clojure/West 2014[1], then you have some idea of what I'm 
talking about. If you haven't watched it, then you should, because 
it's great.


The main changes are:

- more clearly delineate separate phases (generation, execution, 
verification), this most noticeably changes the time when 
postcondition functions are run, and what they are permitted to 
do


- add support for race condition detection (see doc/queue.org[2] 
for an example, and see doc/race-conditions.org[3] for a bit of 
explanation about what it's testing)


- change to the MIT license

If you've used stateful-check before then you should be careful 
and check your assumptions before doing things. If you've not used 
stateful-check before then now might be a fun time to give it a 
go!


Carlo

[1]: https://www.youtube.com/watch?v=zi0rHwfiX1Q
[2]: 
https://github.com/czan/stateful-check/blob/0.4.0/doc/queue.org
[3]: 
https://github.com/czan/stateful-check/blob/0.4.0/doc/race-conditions.org


--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups "Clojure" group.

To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


signature.asc
Description: PGP signature


Re: Literal map keys are checked for duplication before evaluation?

2017-01-04 Thread Carlo Zancanaro

On Thu, Jan 05 2017, Tianxiang Xiong wrote
> We can have:
>
> user=> {(+ 1 2) 1 (+ 2 1) 2}
> IllegalArgumentException Duplicate key: 3  
> clojure.lang.PersistentArrayMap.createWithCheck
> (PersistentArrayMap.java:71)
>
>
> So clearly a check is also made *after* evaluating the key forms. I'm just
> not sure why we need to check *before* evaluating the key forms.

The problem is that the reader produces a *map* as the result of reading
the form. Given '(+ 1 2) is equal to '(+ 1 2), the reader can't store
both values (because a map has only one value per key). Instead of
picking one of them arbitrarily (with the surprising behaviour of
dropping a form at /read/ time) it throws an exception.

Carlo

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


signature.asc
Description: PGP signature


Re: How to email PDF attachments

2015-09-24 Thread Carlo Zancanaro
I don't know anything about your PDF/email problem, but I was under the
impression that you could use the local filesystem in Heroku, but that you
can't rely on it for persistance.

https://devcenter.heroku.com/articles/dynos#ephemeral-filesystem

So, if you had a solution that was "write to disk, then add file as an
attachment to an email" that could work on Heroku.

On 25 September 2015 at 10:13, Jonathon McKitrick 
wrote:

> I'm using clj-pdf to great success to stream a generated PDF when
> requested by URL, and postal to send email.
>
> I now need to output the PDF to an attachment in the email itself, and
> this needs to be Heroku-capable (no local filesystem).
>
> Has anyone done something similar, or any of the pieces?
>
> --
> 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.


Re: Unexpected behavior for symbols or keywords used in the operator position

2015-09-15 Thread Carlo Zancanaro
Symbols and keywords act as functions which look themselves up in their
argument. Essentially:

  ('sym map) => (get map 'sym)
 ('sym map not-found) => (get map 'sym not-found)

  (:key map) => (get map :key)
 (:key map not-found) => (get map :key not-found)

It's often pretty useful, in my experience. It looks cleaner, and it means
that you can just use :keyword instead of #(get % :keyword) in cases where
you provide a function as an argument (for example: (map :type objects)).

On 16 September 2015 at 14:20, Michael O'Keefe 
wrote:

> Hello All:
>
> Noticed the following works in Clojure 1.6 and 1.7 (didn't test prior to
> that):
>
> user=> ('+ 'a 'b)
> b
>
> Also "works" for any set of symbols:
>
> user=> ('abra 'ka 'dabra)
> dabra
>
> My expectation was that using symbols or keywords in the function/operator
> position would throw an exception similar to this:
>
> user=> (3 4)
>
>
> ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn  user
> /eval7668 (form-init2947310628177413729.clj:1)
>
>
> I noticed Keywords can also be used in the operator position:
>
> user=> (:abra :ka :dabra)
> :dabra
>
> And mixing and matching is OK:
>
> user=> (:a 'b 3)
> 3
>
> It seems to act something like an implicit `do` in that it returns the
> last value but, in fact, not quite as you seem to need to have more than
> two items:
>
> user=> ('do)
>
> ArityException Wrong number of args (0) passed to: Symbol
>  clojure.lang.AFn.throwArity (AFn.java:429)
>
>
> user=> ('do (+ 1 2 3))
> nil
>
>
> user=> ('do 'this (+ 1 2 3))
> 6
>
> But more than 3 is not accepted:
>
> user=> ('do 'this 'please 3)
>
>
> ArityException Wrong number of args (3) passed to: Symbol
>  clojure.lang.AFn.throwArity (AFn.java:429)
>
> user=> ('do 'this 'please 'now 'ok?)
>
>
> ArityException Wrong number of args (4) passed to: Symbol
>  clojure.lang.AFn.throwArity (AFn.java:429)
>
>
> A quick search didn't reveal any bug reports or previous discussions on
> this but I may have missed something (feel free to point me in the right
> direction).
>
> Is it just a "quirk" or is it useful in some way? Intended behavior or bug?
>
> Cheers,
>
> Michael O'Keefe
>
> --
> 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.


Re: Need suggestions on how to write rand-interleave test.check generator.

2015-08-14 Thread Carlo Zancanaro
Hey Mayank!

Similarly to your attempt last time, you need to use gen/bind to get the
result of a generator which you can then use to make a new generator.

(defn- rand-interleave* [coll acc]
  (if (seq coll)
(gen/bind (gen/choose 0 (dec (count coll)))
  (fn [index]
(let [value (first (get coll index))
  coll (- (update-in coll [index] next)
(remove empty?)
vec)]
  (rand-interleave* coll (conj acc value)
(gen/return acc)))

(defn rand-interleave [ colls]
  (rand-interleave* (vec colls) []))

The (gen/choose 0 (dec (count coll))) is similar to your rand-count
function, then the generated number is passed to the function as result.
Writing it this way will shrink towards the (apply concat args) (ie. as it
shrinks it will move towards just concatenating the arguments).

In terms of the recursion: this will eventually overflow the stack. I don't
know of a way to trampoline generators, so I don't know how to avoid that.
(This is a bit of a recurring problem with monadic code in Clojure, I feel,
as algo.monads had a similar problem last time I checked.) For the moment
I'm just ignoring this theoretical problem until it becomes a practical
problem.

I hope that helps!

Carlo

On 14 August 2015 at 23:39, Mayank Jain firesof...@gmail.com wrote:

 Hi Everyone,

 Here's the problem I am facing,
 I need to write a generator which takes any number of sequences,
 interleaves them but maintains the order within each sequence.
 Assume each sequence has at least one element.

 For example:

 (rand-interleave [1 2 3 4] [:a :b] [:A :B :C :D :E])
 = [:a 1 2 :b :A :B :C 3 :D 4 :E]


 (rand-interleave [1 2 3 4])
 = [1 2 3 4]


 (rand-interleave [1])
 = [1]


 (rand-interleave [1] [:a] [:A])
 = [:a 1 :A]


 I have been able to write this down as clojure functions.
 But I am unable to convert this into a test.check generator.

 Specifically:

- How to pass random index count without using rand-int i.e. use
gen/choose
- How do I write recursive functions which play well with test.check

 Here's my take on it (without the generators).

 (defn- first-nth
   (first-nth [[1 2 3 4] [:a :b :c :d]]
   1)
= :a
   [coll n]
   (first (nth coll n)))



 (defn- next-nth
   (next-nth [[1 2 3 4] [:a :b :c :d]]
   1)
= [[1 2 3 4] (:b :c :d)]
   [coll n]
   (- n
(nth coll)
next
(assoc coll n)
(remove nil?)
vec))



 (defn- rand-count
   [coll]
   (rand-int (count coll)))



 (defn- rand-interleave*
   [coll acc]
   (let [n (rand-count coll)]
 (if (not-empty coll)
   (rand-interleave* (next-nth coll n)
   (conj acc
   (first-nth coll n)))
   acc)))



 (defn rand-interleave
   [ args]
   ;; Make args a vector as I would like to
   ;; look up elements by their index values.
   (rand-interleave* (vec args) []))


 Looking forward to any suggestions on how to solve it :)

 Thanks,
 Mayank.

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


Re: Need suggestions on how to write rand-interleave test.check generator.

2015-08-14 Thread Carlo Zancanaro
What it means is that the value returned by gen/return can't be shrunk.

Shrinking is done by constructing a (lazily evaluated) tree of smaller
forms of the same thing. So a number, let's say 4, contains a tree of
smaller numbers (0, 1, 2, and 3) which specify how to shrink it. (The tree
is constructed in an intelligent way to make shrinking more efficient than
try everything.) When you use gen/return you don't have any of that
context, so the returned value cannot be shrunk.

This situation is a bit more complex when you use gen/bind, though, because
the result of the gen/bind call inherits a shrink tree from the generator
given to gen/bind. That's why my function can shrink despite using
gen/return for its final value. The gen/return isn't shrinking, but the
gen/bind is.

Carlo

On 15 August 2015 at 02:49, Mayank Jain firesof...@gmail.com wrote:

 Ah right! I knew I had to use gen/choose for this,
 I am still grokking bind :)

 Thanks for your help!
 That indeed did the trick for me :)

 One thing I am clear about is,
 If I use gen/return it says it'll not shrink.
 Does that mean when a test fails for a certain order, it won't try to
 shrink that order of collection?
 Because I have used a gen/return at the end of the generator?

 Thanks again for your help! :)

 On Fri, Aug 14, 2015 at 8:13 PM, Carlo Zancanaro carlozancan...@gmail.com
  wrote:

 Hey Mayank!

 Similarly to your attempt last time, you need to use gen/bind to get the
 result of a generator which you can then use to make a new generator.

 (defn- rand-interleave* [coll acc]
   (if (seq coll)
 (gen/bind (gen/choose 0 (dec (count coll)))
   (fn [index]
 (let [value (first (get coll index))
   coll (- (update-in coll [index] next)
 (remove empty?)
 vec)]
   (rand-interleave* coll (conj acc value)
 (gen/return acc)))

 (defn rand-interleave [ colls]
   (rand-interleave* (vec colls) []))

 The (gen/choose 0 (dec (count coll))) is similar to your rand-count
 function, then the generated number is passed to the function as result.
 Writing it this way will shrink towards the (apply concat args) (ie. as
 it shrinks it will move towards just concatenating the arguments).

 In terms of the recursion: this will eventually overflow the stack. I
 don't know of a way to trampoline generators, so I don't know how to avoid
 that. (This is a bit of a recurring problem with monadic code in Clojure, I
 feel, as algo.monads had a similar problem last time I checked.) For the
 moment I'm just ignoring this theoretical problem until it becomes a
 practical problem.

 I hope that helps!

 Carlo

 On 14 August 2015 at 23:39, Mayank Jain firesof...@gmail.com wrote:

 Hi Everyone,

 Here's the problem I am facing,
 I need to write a generator which takes any number of sequences,
 interleaves them but maintains the order within each sequence.
 Assume each sequence has at least one element.

 For example:

 (rand-interleave [1 2 3 4] [:a :b] [:A :B :C :D :E])
 = [:a 1 2 :b :A :B :C 3 :D 4 :E]


 (rand-interleave [1 2 3 4])
 = [1 2 3 4]


 (rand-interleave [1])
 = [1]


 (rand-interleave [1] [:a] [:A])
 = [:a 1 :A]


 I have been able to write this down as clojure functions.
 But I am unable to convert this into a test.check generator.

 Specifically:

- How to pass random index count without using rand-int i.e. use
gen/choose
- How do I write recursive functions which play well with test.check

 Here's my take on it (without the generators).

 (defn- first-nth
   (first-nth [[1 2 3 4] [:a :b :c :d]]
   1)
= :a
   [coll n]
   (first (nth coll n)))



 (defn- next-nth
   (next-nth [[1 2 3 4] [:a :b :c :d]]
   1)
= [[1 2 3 4] (:b :c :d)]
   [coll n]
   (- n
(nth coll)
next
(assoc coll n)
(remove nil?)
vec))



 (defn- rand-count
   [coll]
   (rand-int (count coll)))



 (defn- rand-interleave*
   [coll acc]
   (let [n (rand-count coll)]
 (if (not-empty coll)
   (rand-interleave* (next-nth coll n)
   (conj acc
   (first-nth coll n)))
   acc)))



 (defn rand-interleave
   [ args]
   ;; Make args a vector as I would like to
   ;; look up elements by their index values.
   (rand-interleave* (vec args) []))


 Looking forward to any suggestions on how to solve it :)

 Thanks,
 Mayank.

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

[ANN] stateful-check 0.3.1 - test stateful systems with test.check

2015-08-13 Thread Carlo Zancanaro
Hey everyone!

I've just released a new version of my library for testing stateful systems
with test.check!

  [org.clojars.czan/stateful-check 0.3.1]

  https://github.com/czan/stateful-check
  https://clojars.org/org.clojars.czan/stateful-check

Changes in this version:

  + :real/setup and :real/cleanup actually work again! There was a bug in
the previous release that broke them, but they're fixed now.

  + :model/generate-command is now optional, with a default value which
randomly selects a command from all the provided command specifications.

  + :model/args now coerces things to generators, so [gen/nat] will be
treated as (gen/tuple gen/nat), for instance.

  + the output of the results of commands is now correct, even when the
objects themselves are mutated later in the test.

  + added :tries to specification-correct? to aid in testing
non-deterministic tests.

  + shrinking is now more aggressive and will shrink more effectively in
some cases.

See the changelog for more details.

I hope somebody finds this useful!

-- 
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] stateful-check 0.3.0 - test stateful systems with test.check

2015-07-30 Thread Carlo Zancanaro
Hey everyone!

I've just released a new version of my library for testing stateful systems
with test.check!

  [org.clojars.czan/stateful-check 0.3.0]

  https://github.com/czan/stateful-check
  https://clojars.org/org.clojars.czan/stateful-check

Important changes in this version:

  + Updated to test.check 0.7.0

  + *Breaking: *Postconditions now take two states: the prior and the next
states. This means that any postconditions being used with 0.2.0 need to be
changed:

(fn [state args result]
arbitrary-logic-for-postcondition)
  ;; needs to change to
  (fn [prev-state next-state args result]
arbitrary-logic-for-postcondition)

  + *Breaking: *The old `reality-matches-model?` function has been both
renamed (to remove the '?', which implied it was a predicate when it's not)
and deprecated. The `specification-correct?` form below is the preferred
form now.

  + Add a new function, `specification-correct?`, which runs a
stateful-test specification using test.check. If used within a clojure.test
`is` assertion it will also print helpful output:

  (is (specification-correct? queue-spec {:seed 1417059242645}))
  ;;
  ;; FAIL in clojure.lang.PersistentList$EmptyList@1
(form-init1067629020891437332.clj:1)
  ;;#0 = (:new) = #Atom@53df198e: #PersistentQueue
clojure.lang.PersistentQueue@1
  ;;#2 = (:push #0 0) = nil
  ;;#3 = (:pop #0)= #PersistentQueue
clojure.lang.PersistentQueue@1
  ;; Error while checking postcondition
  ;; Seed:  1417059242645
  ;;
  ;; expected: :pass
  ;;   actual: :fail

I hope somebody finds this useful!

Carlo

-- 
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: Generating varying sized map using test.check

2015-07-27 Thread Carlo Zancanaro
Whoops, forgot the group on this.

On 27 July 2015 at 18:10, Carlo Zancanaro carlozancan...@gmail.com wrote:

 You're generating two random things: the map, and the subset of the keys.
 You can't generate the subset of the keys without first knowing the full
 set of keys, so bind lets you make the subset generator depend on the
 result of the map generator.

 I should also point out that shrinking isn't the only problem with your
 original function. Normally in test.check you can repeat a test case by
 providing a seed to the generator. With your original code it would be more
 difficult to repeat a test case.
 On 27/07/2015 5:14 pm, Mayank Jain firesof...@gmail.com wrote:


 It also might be helpful to know that there is already a subset generator
 available in this library
 https://github.com/gfredericks/test.chuck#generators.


 Thanks, this looks good, will check it out.


 What you've done here might appear to work, but it will get you into
 trouble when test.check starts to shrink your inputs. When test.check runs
 your generators it relies you you using it as your only source of
 randomness, and so your use of `rand-int` will cause some problems.


 Ah yes, I didn't think of shrinking.
 Thanks a lot for your help! :)



 The trick is to use the `bind` function to make a generator which
 depends on the value of another generator (in this case, to capture the
 generated map so you can call rand-subset with the correct set of keys):



  I didn't get why I had to use a bind here. What if I had only used fmap?



-- 
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: Generating varying sized map using test.check

2015-07-25 Thread Carlo Zancanaro
Hey Mayank!

What you've done here might appear to work, but it will get you into
trouble when test.check starts to shrink your inputs. When test.check runs
your generators it relies you you using it as your only source of
randomness, and so your use of `rand-int` will cause some problems.

The trick is to use the `bind` function to make a generator which depends
on the value of another generator (in this case, to capture the generated
map so you can call rand-subset with the correct set of keys):

(defn rand-subset
  Given a collection coll
   it'll generate a random subset.
  [coll]
  (gen/fmap (fn [i] (combo/nth-subset coll i))
(gen/choose 0 (dec (combo/count-subsets coll)

(defn gen-varying-map
  Given a generator which generates a map,
   it'll randomly select keys from it thus making it
   varying-sized map.
   Note: It can return empty maps as well.
  [map-gen]
  (gen/bind map-gen
(fn [map]
  (gen/fmap (fn [keyseq]
  (select-keys map keyseq))
(rand-subset (keys map))

(gen/sample (gen-varying-map (gen/hash-map
  user (gen/such-that not-empty
gen/string-alpha-numeric)
  level gen/nat
  timezone gen/pos-int)))
=
({user e, level 0}
 {level 1}
 {user M1}
 {timezone 2}
 {user 2, level 2, timezone 0}
 {timezone 3}
 {user W, level 5, timezone 0}
 {timezone 5}
 {}
 {})

This output appears the same as yours, but it will produce predictable
shrink trees, and thus will shrink more effectively.

Carlo

On 26 July 2015 at 07:10, Mayank Jain firesof...@gmail.com wrote:

 Hi,

 I would like to generate variable sized map using test.check i.e.
 given any generator which generates a map, it should randomly select-keys
 from it.

 Here's what I've come up with so far:


 (ns proj.util
   (:require [clojure.test.check.generators :as gen]
 [clojure.math.combinatorics :as combo]))

 (defn rand-subset
   Given a collection coll,
it'll generate a random subset.
   [coll]
   (- coll
combo/count-subsets
rand-int
(combo/nth-subset coll)))

 (defn gen-varying-map
   Given a generator which generates a map,
it'll randomly select keys from it thus making it
varying-sized map.
Note: It can return empty maps as well.
   [map-gen]
   (gen/fmap (fn [m]
   (let [ks (rand-subset (keys m))]
 (select-keys m ks)))
 map-gen))

 Here's an example output,
 (gen/sample (gen-varying-map (gen/hash-map
   user (gen/such-that not-empty

 gen/string-alphanumeric)
   level gen/nat
   timezone gen/pos-int)))
 =
 ({user 1}
  {user l8, level 0, timezone 1}
  {level 1}
  {user oA, timezone 0}
  {level 2, timezone 1}
  {level 5}
  {user 8aP, level 5, timezone 6}
  {user 035rqi, level 7}
  {timezone 4}
  {timezone 2})

 My question is, is this the right way? Or is there a better way to do it?

 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.


-- 
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.match: order of patterns

2015-01-29 Thread Carlo Zancanaro
On Thu, Jan 29, 2015 at 10:46:45AM +, László Török wrote:
 One thing that isn't obvious to me, how it should work when matching more
 than one pattern.

I can't seem to find it anywhere in the core.match wiki, but I'm fairly
sure it tries them in order, returning the first one that matches.

 In the following example, the expression returns 3 or 4 depending on which
 pattern comes first:
 
 (require '[clojure.core.match :as cm])
 
 (cm/match [:a true false]
 [_ _ true] 1
 [:a _ true] 2
 [:a true false] 4
 [:a true _] 3)

This would return 4 because the 4 matches before the 3. If you were to
swap their orders then it would return 3.

  (cm/match [:a true false]
[_ _ true] 1
[:a _ true] 2
[:a true _] 3
[:a true false] 4)
  ;; = 3

 Is it correct to assume, that the algorithm constructs an decision tree
 that will hit a minimum amount of patterns, however, if there are more than
 one matching clauses, its result is an arbitrary choice of the possible
 decisions?

It will try to create a decision tree to efficiently check the patterns,
but they will be checked (at least conceptually) in order.

So this:

  (cm/match [:a true false]
[_ _ _] 1
[:a _ true] 2
[:a true _] 3
[:a true false] 4)
  ;; = 1

doesn't get past the first pattern, despite the fact that the later ones
are more specific.

I hope that helps!

Carlo

-- 
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] stateful-check 0.1.0 - test stateful systems with test.check

2014-12-02 Thread Carlo Zancanaro
On Sat, Nov 29, 2014 at 11:34:37AM -0800, tcrayford wrote:
 Nice! I wrote a sketch of this idea the day after I watched the 
 talk: https://github.com/tcrayford/laundromat, but never pursued it much 
 further (though I do use it in my test suite).

Thanks for laundromat. I shamelessly stole the idea to use namespaced
keywords to differentiate between the model and reality.

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


signature.asc
Description: Digital signature


[ANN] stateful-check 0.2.0 - test stateful systems with test.check

2014-12-02 Thread Carlo Zancanaro
On Fri, Nov 28, 2014 at 11:43:56AM +1100, Carlo Zancanaro wrote:
 I've been working on a library for a little bit which I'm calling
 stateful-check (at least for now). It's mainly my attempt to work
 towards the sort of stateful testing that I first saw in John Hughes'
 talk Testing the Hard Stuff and Staying Sane[1].
 
   https://github.com/czan/stateful-check
   https://clojars.org/org.clojars.czan/stateful-check

I've just released version 0.2.0 to clojars. The main things it fixes
are my frustrations at two things:

  1. not being able to use `(:key state)` in `:model/next-state`

  2. not being able to access the result of the setup function in
  actual commands, leading to needing a dummy command which has to be
  run first before any others (which reduces the effectiveness of
  shrinking)

I've also made some keys more consistent in their model/ and real/
prefixes. This means it's not backwards compatible, but it's a simple
keyword replacement to fix anything that's broken.

Carlo

 [1]: https://www.youtube.com/watch?v=zi0rHwfiX1Q

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


signature.asc
Description: Digital signature


Re: [ANN] stateful-check 0.1.0 - test stateful systems with test.check

2014-11-28 Thread Carlo Zancanaro
Hey Jan!

On Fri, Nov 28, 2014 at 06:37:06AM -0800, Jan Stępień wrote:
 Thanks for sharing! I see that generative testing of statful computations 
 is a popular topic in the Clojure world these days;

Yeah, it certainly seems to be that way. I was re-invigorated to work on
stateful-check after watching a talk from the conj about generative
integration tests.

 I think we've started working on our libraries nearly the same day :)
 
 https://github.com/jstepien/states

I've actually seen your library since writing stateful-check. When I
experimented with it, though, I found its shrinking to be a bit lacking.
With stateful-check I've actually implemented my own shrinking of
commands to try to improve the shrinking results (it essentially tries
to prune irrelevant commands before trying to shrink individual
commands).

I was quite interested in your approach of using a single function per
specification property (precondition/postcondition/next-state). I
thought that would be a bit constricting when it comes to actually
writing test cases, though, so I've opted instead to have each of those
defined per-command. How have you found that to be in practice?

Thanks!

Carlo

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


signature.asc
Description: Digital signature


[ANN] stateful-check 0.1.0 - test stateful systems with test.check

2014-11-27 Thread Carlo Zancanaro
I've been working on a library for a little bit which I'm calling
stateful-check (at least for now). It's mainly my attempt to work
towards the sort of stateful testing that I first saw in John Hughes'
talk Testing the Hard Stuff and Staying Sane[1].

  https://github.com/czan/stateful-check
  https://clojars.org/org.clojars.czan/stateful-check

Thus far I've only got it to perform single threaded operations, but I'm
hoping to enhance it in future to do the sort of concurrent tests that
are shown in the talk (although I'm not exactly sure how I'm going to do
that yet).

Anyway, I'm releasing this now in the hopes that somebody finds it
useful!

Carlo


[1]: https://www.youtube.com/watch?v=zi0rHwfiX1Q

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


signature.asc
Description: Digital signature


Re: Cyclic Agents

2014-09-11 Thread Carlo Zancanaro
Hey Greg,

On Thu, Sep 11, 2014 at 12:30:11AM -0700, Greg MacDonald wrote:
 So how come two agents can't contain one another? The following code causes 
 a StackOverflowError. In the real world things can't contain other things 
 cyclically so I suspect that's why, but if someone could explain this 
 better to me I'd appreciate it. :) - Greg
 
 (defn test-agents
   []
   (let [a (agent {})
 b (agent {})]
 (send-off a #(assoc %1 :other %2) b)
 (send-off b #(assoc %1 :other %2) a)))

As far as I can tell this works properly, but printing it is a problem
(as it's a structure with a cycle in it: a - b - a - b - ... a).

We can see that it works, though:

  user= (defn test-agents []
   (let [a (agent {:a true}),
 b (agent {:b true})]
 (send-off a assoc :other b)
 (send-off b assoc :other a)
 [a b]))
  #'user/test-agents
  user= (def ag (test-agents))
  #'user/ag
  user= (:a @(first ag))
  true ;; the first one is a
  user= (:b @(:other @(first ag)))
  true ;; a's other is b
  user= (:a @(:other @(:other @(first ag
  true ;; b's other is a


Carlo


signature.asc
Description: Digital signature


Re: how to define a variable of type collection to keep other functions.

2014-05-28 Thread Carlo Zancanaro
On Wed, May 28, 2014 at 12:56:43AM -0700, sorin cristea wrote: 
 *( defn some-method[arg]   (def thred (. Thread currentThred)   
 (println on current thread thread use variable arg))*
 
  'thred' - is only visible inside of some-methd, because is a little 
 confuse for me your statement - *`def` and `defn` create global bindings - 
 they are not variable assignments - and you don't want `def` nested into 
 `defn`.*  

In this case your thred var is actually visible globally, not only in
the function.

For example:

  user= (defn a-function [arg]
#_=   (def b (+ arg 1))
#_=   (/ b 2))
  #'user/a-function
  user= (a-function 1)
  1
  user= b
  2
  user= (a-function 3)
  2
  user= b
  4
  user= (a-function 111)
  56
  user= b
  112

See how the value for b keeps changing? It's because a-function is
changing the *global* b value.

Let's try with another function, using let instead:

  user= (defn another-function [arg]
#_=   (let [barg (+ arg 1)]
#_= (/ barg 2)))
  #'user/another-function
  user= (another-function 1)
  1
  user= barg

  CompilerException java.lang.RuntimeException: Unable to resolve symbol: barg 
in this context, compiling:(NO_SOURCE_PATH:0:0) 
  user= (another-function 3)
  2
  user= barg

  CompilerException java.lang.RuntimeException: Unable to resolve symbol: barg 
in this context, compiling:(NO_SOURCE_PATH:0:0) 
  user= (another-function 111)
  56
  user= barg

  CompilerException java.lang.RuntimeException: Unable to resolve symbol: barg 
in this context, compiling:(NO_SOURCE_PATH:0:0) 

Here you can see that the local variable in the let, barg doesn't
escape to the global scope. In fact, there is no global barg variable
at all! It's completely contained within another-function now.

This is why we use let instead of def. def creates a *global* var,
which is then in the global scope. let allows us to introduce our own
bindings for values within the current lexical scope. (There are some
other differences between them, but this is the strongest argument for
using let over def, I think.)

Carlo


signature.asc
Description: Digital signature


Re: emacs - some output goes to stdout when using cider

2014-05-26 Thread Carlo Zancanaro
On Mon, May 26, 2014 at 08:32:45AM -0700, Don Hill wrote:
 I am in a project with a test.clj file and if I do a (println Hi) C-x C-e 
 it goes to repl as expected. If I do something like (+ 1 2 3) it seems to 
 go to stdout below the status bar.

This is the correct behaviour.

When you evaluate (println hi) it should show nil below the status
bar. This isn't actually stdout, but is cider displaying the result to
you in the minibuffer. If you evaluate (+ 1 2 3) then it shows you the
result in the minibuffer, too.

The confusing part is that (println hi) also, as a side effect, prints
the result to the repl. (+ 1 2 3) doesn't print anything, it only
displays in the minibuffer. If you want to display it in the repl you
can evaluate (println (+ 1 2 3)), or you can run the expression in the
repl (by switching to the repl buffer and entering/running it directly).

Carlo


signature.asc
Description: Digital signature


Re: passing a non-anoymous function as an argument to another clojure function

2014-05-22 Thread Carlo Zancanaro
On Wed, May 21, 2014 at 07:53:18PM -0700, David Gartner wrote:
 (defn div [x y]
  (/ x y))

 (defn throw-catch [f]
   [(try
 (f)
 (catch ArithmeticException e No dividing by zero!)
 (catch Exception e (str You are so bad  (.getMessage e)))
 (finally (println returning... )))])

 ...

 Can anyone enlighten me?

So, your issue is that your div function expects two arguments, while
your throw-catch function calls it (although with the name f) with
zero arguments. Using an anonymous function like #(div 10 5) creates a
new function of zero arguments which then calls your div function with
its two arguments.

So, you should find that this will work for your div function:

  (defn throw-catch-2 [f a b]
(try
  (f a b)
  (catch ArithmeticException e No dividing by zero!)
  (catch Exception e (str You are so bad  (.getMessage e)))
  (finally (println returning... 
  (throw-catch-2 div 10 5)

To do this more generally, we can use clojure's rest arguments and
apply to make this work:

  (defn throw-catch-many [f  args]
(try
  (apply f args)
  (catch ArithmeticException e No dividing by zero!)
  (catch Exception e (str You are so bad  (.getMessage e)))
  (finally (println returning... 
  (throw-catch-many div 10 5)
  (throw-catch-many #(div 10 5))

You can even just use / as your function name now, if you'd like:

  (throw-catch-many / 10 5)
  (throw-catch-many / 10 0)


signature.asc
Description: Digital signature


Re: (eval `(def ~(symbol varname) lineseq)

2014-04-28 Thread Carlo Zancanaro
On Mon, Apr 28, 2014 at 06:06:32PM +1000, Peter B. West wrote:
 This is the technique used in the old contrib/io.clj read-lines
 function, isn't it?  That's handy to know.

Correct.

 Still, Stuart is skeptical about it.

I don't think it's a good general solution to the problem, so Stuart's
skepticism is fair. For specific cases where you know how the sequence
will be used, though, it can be acceptable.

 And they don't use with-open. So I guess with-open is a bit of
 problem, and you're back to managing file closing by yourself, which
 is what with-open was trying to circumvent, wasn't it?

with-open is only good for cases where your resource's scope is easily
contained within a form's evaluation. It's not designed for cases where
the resource escapes from the form, which is what you're trying to do.
In cases like that you can either try to force with-open to do what you
want (by tying up a thread and waiting on a signal, as you've attempted
to do), or you can handle closing the resource yourself (tying up no
threads and explicitly performing the close).

Essentially: with-open is designed for one specific use case but what
you're trying to do doesn't fit into that, so you need to use a
different solution. If you can't contain the entire resource's lifetime
in a single scope (ie. have the with-open enclose the entire time when
the resource is used), then you need to open/close it yourself some
other way.


signature.asc
Description: Digital signature


Re: (eval `(def ~(symbol varname) lineseq)

2014-04-27 Thread Carlo Zancanaro
I'm struggling to understand the problem that you're actually trying to
solve. The solution that you are proposing doesn't seem like an elegant
solution to any problem, so could you elaborate on what you're trying to
do?

On Fri, Apr 25, 2014 at 08:58:42AM -0700, Peter West wrote:
 One interesting thing about intern is that it will create *or find* a var, 
 setting its root binding.  That means that var circumvents the immutability 
 of a var, doesn't it? I thought vars were supposed to be immutable.

Vars are not immutable. Clojure has four datatypes which are used for
mutability: Agents, Atoms, Refs and Vars. As I said originally, your
function is mutating the global scope, whether by using `intern` or by
using `def`, and this is generally not a good idea. There is (almost), a
better solution than mutating the global state.


signature.asc
Description: Digital signature


Re: (eval `(def ~(symbol varname) lineseq)

2014-04-27 Thread Carlo Zancanaro
On Mon, Apr 28, 2014 at 12:30:00AM +1000, Peter B. West wrote:
 I have no ambitions to solve the general problem; just to find a
 workable solution for my own use.

What is your own use? Your current solution involves using a shared
global variable to communicate between two functions, and tying up a
thread to wait to close a file handle. Both of these issues I consider
to be unworkable.

There are other ways to manage resource scope, though. For instance, you
could have your lazy-lines function return a lazy-sequence which will
close the file on completely reading the stream:

  (defn lazy-lines [resource]
(let [r ^java.io.Reader (vcf-res-reader resource)
  close #(.close r)]
  (concat (line-seq r)
  (lazy-seq (close)

Or one which provides you a function to close the stream when you want
to:

  (defn lazy-lines [resource]
(let [r ^java.io.Reader (vcf-res-reader resource)
  close #(.close r)]
  (with-meta (line-seq r)
{:close close})))

Or one which does both:

  (defn lazy-lines [resource]
(let [r ^java.io.Reader (vcf-res-reader resource)
  close #(.close r)]
  (with-meta (concat (line-seq r)
 (lazy-seq (close))) ;; close if we're done
{:close close}))) ;; also provide the close function externally

None of these options mutate any global, shared memory. They all return
a sequence directly to the caller, and none of them require any sort of
coordination with other threads.


signature.asc
Description: Digital signature


Re: (eval `(def ~(symbol varname) lineseq)

2014-04-08 Thread Carlo Zancanaro
On Mon, Apr 07, 2014 at 11:23:31PM -0700, Peter West wrote:
 On Tuesday, 8 April 2014 12:20:16 UTC+10, Carlo wrote:
  Your issue here is that the symbol lineseq in the eval form doesn't 
  have a name to refer to. You do have a local binding for lineseq, but 
  it's not visible to the eval: 
 
(let [x 10] (eval 'x)) ;= Unable to resolve symbol: x 
 
 If that were the case, then the reference to r in alternative 2 (def 
 lineseq (line-seq r)) would not work; but it does, so r is in scope. 
 Therefore, linseed from alternative 1 must also be in scope, mustn't it? 
  It was my understanding that the scope of with-open was equivalent to that 
 of let in  that bindings were visible within the entire scope of the 
 with-open.

No, you misunderstand me. The issue is that eval compiles and runs the
code at run-time, whereas the def compiles at compile time and runs at
run-time.

In the case of the def form, it's compiled and run in the environment
of the with-open, so the r resolves correctly to the one in the
with-open form.

The eval, however, runs in a separate environment. You've quoted your
lineseq (so it's not looked up in the current environment), then eval
can't find it in the (new) eval environment. It would have to be looking
in the existing environment. (These terms are poorly used, but
essentially: the eval loses the lexical context of where it is placed
and lineseq can't be located.)

This is why Marc recommended unquoting lineseq (using ~). An unquoted
form will be evaluated, which for a symbol means looking it up in its
current lexical scope.

  There are two ways for you to resolve this. What you're writing sounds a 
  little bit like it should be a macro, so you could write it as such: 
 
(defmacro lines-only [varname prom resource] 
  `(with-open [r# (vcf-res-reader ~resource)] 
 (let [lineseq# (line-seq r#)] 
   (def ~(symbol varname) lineseq#) 
   @~prom))) 
 
  (I think that's right, but I've not actually tested it.) 
 
 
 I think this will run into the same problem, for reasons mentioned above. 

Have you tried actually running it? I'm confident that this will not
have the issues that you had with your eval approach. The difference is
that it is a macro, so it is returning code to be run, rather than
attempting to compile and run code at run-time (as eval does).

  Alternatively, you could write it as a function and use intern: 
 
(defn lines-only [varname prom resource] 
  (with-open [r (vcf-res-reader resource)] 
(let [lineseq (line-seq r)] 
  (intern *ns* (symbol varname) lineseq) 
  @prom))) 
 
  I'm less confident about this approach, but it should work. 

This form of lines-only is a function, but it uses the function
intern instead of the special form def. This lets us maintain our
lexical context while also re-binding a name in the top-level namespace.


signature.asc
Description: Digital signature


Re: (eval `(def ~(symbol varname) lineseq)

2014-04-07 Thread Carlo Zancanaro
On Mon, Apr 07, 2014 at 04:08:03AM -0700, Peter West wrote:
 I'm trying to understand the difference between two alternatives in the 
 following code that reads from a resource file.

 (defn vcf-res-reader
   [res]
   (- res
io/resource
io/reader))

 (defn lines-only
   [varname prom resource]
   (with-open [r (vcf-res-reader resource)
   ; alternative 1
   ;lineseq (line-seq r)
   ]
 ; alternative 2
 (def lineseq (line-seq r))
 (eval `(def ~(symbol varname) lineseq))
 @prom))

 (defn lazy-lines
   [varname prom resource]
   (future
 (lines-only varname prom resource)
 ))


 As the code stands, with alternative 2 enabled, the eval setting a named 
 var to the value of linseq works as intended. However, if I disable 
 alternative 2 and enable alternative 1, and I attempt to access the named 
 var (cards in this case), I get
 #Unbound Unbound: #'vcf.core/cards

You have a few problems with your code as it stands. I'll look at each
of the two alternatives separately.

First, alternative 1:

 (defn lines-only
   [varname prom resource]
   (with-open [r (vcf-res-reader resource)
   lineseq (line-seq r)]
 (eval `(def ~(symbol varname) lineseq))
 @prom))

Your issue here is that the symbol lineseq in the eval form doesn't
have a name to refer to. You do have a local binding for lineseq, but
it's not visible to the eval:

  (let [x 10] (eval 'x)) ;= Unable to resolve symbol: x

The lineseq binding should really be made in a let, too, rather than a
with-open. The result of a line-seq can't be closed, so it's not really
sensible to put it in a with-open.

Now, on to alternative 2:

 (defn lines-only
   [varname prom resource]
   (with-open [r (vcf-res-reader resource)}
 (def lineseq (line-seq r))
 (eval `(def ~(symbol varname) lineseq))
 @prom))

This time, you do have something for lineseq to refer to! The def
special form has created a global binding for lineseq. Now, at the top
level of your application you can lookup lineseq and get a value, but
this isn't good, because your function now modifies the global scope,
just to hold a temporary value.




There are two ways for you to resolve this. What you're writing sounds a
little bit like it should be a macro, so you could write it as such:

  (defmacro lines-only [varname prom resource]
`(with-open [r# (vcf-res-reader ~resource)]
   (let [lineseq# (line-seq r#)]
 (def ~(symbol varname) lineseq#)
 @~prom)))

(I think that's right, but I've not actually tested it.)

Alternatively, you could write it as a function and use intern:

  (defn lines-only [varname prom resource]
(with-open [r (vcf-res-reader resource)]
  (let [lineseq (line-seq r)]
(intern *ns* (symbol varname) lineseq)
@prom)))

I'm less confident about this approach, but it should work.

All this being said: it's generally a bad idea to have a macro/function
modify the global scope without it being very clear that it's doing so.
I usually try to have my macro names start with def if they're
modifying the global scope (because they're defining something is my
logic).


signature.asc
Description: Digital signature


Re: let bindings

2014-01-20 Thread Carlo Zancanaro
Hey Andy!

On Mon, Jan 20, 2014 at 12:38:23PM -0800, Andy Smith wrote:
 So if we can always reformulate in this was, why cant let be implemented as 
 a macro rather than a special form?

It can. Quite easily, in fact:

(defmacro my-let [bindings  body]
  (if (empty? bindings)
`(do ~@body)
(let [var (first bindings)
  val (second bindings)
  others (nnext bindings)]
  `((fn [~var]
  (my-let ~others ~@body))
~val

This is going to be a fair bit less efficient than the existing 'let'
implementation, though. The special form is, as far as I understand it,
an optimisation so that we're not constantly creating and destroying
function objects for the sake of local bindings (which are much simpler
than closures, which is what functions require here).

If there's another reason then I'm hoping someone will correct me, but I
can't think of any other reasons at the moment.

Carlo


signature.asc
Description: Digital signature


Re: map vs map in core.async

2013-12-12 Thread Carlo Zancanaro
On Thu, Dec 12, 2013 at 06:08:11PM -0800, Joachim De Beule wrote:
 I expected to see a sequence of the form  However, only one or
 very few  get printed, so I get a sequence  Why?

They're getting buffered. Try this:

  (as/pipe (as/map (fn [x] (print ) (flush) x) source)
   (as/map (fn [x] (print ) (flush) x) sink))

Those calls to flush will make sure it prints those characters
immediately. Then you'll see the output you're expecting.

I can't help you with whether this is the right way to do things,
unfortunately, as I've only had very limited experience 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/groups/opt_out.


Re: Working with zippers and trees

2013-11-26 Thread Carlo Zancanaro
On Tue, Nov 26, 2013 at 08:30:15PM -0800, martin_clausen wrote:
 To use the zipper library you have to be able to provide branch? children 
 and make-node functions that apply to your data structure.

 I don't see a way to provide a meaningful branch? or children function for 
 the structure you describe. Vector? will not work as branch? as it will not 
 return true if passed the first element in a vector, and next will not work 
 as it will not return the children if passed the first element of a vector.

We can write our own functions, though:

(defn children? [n]
  (and (vector? n) (next n)))

(defn make-node [n children]
  (vec (cons (first n) children)))

(defn tree-zipper [v]
  (z/zipper children? next make-node v))

Dario: I tried this with your gist, and the code in your previous email,
and as far as I could tell it worked, so I hope that helps!

Carlo

-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: Working with zippers and trees

2013-11-26 Thread Carlo Zancanaro
Okay, now after actually reading the documentation I can come back with
an actually correct response!

You should only have to change one function:

 (defn make-node [n children]
   (vec (cons (first n) children)))

Your issue was that your original `make-node` function didn't return a
vector, it returned a ConsCell (with a vector as its tail). This meant
that your new node no longer returned true for children, that is it
identified itself as a leaf.

By making `make-node` return a vector (vec turns any sequable thing into
a vector) your `make-node` now returns a valid branch node, so z/next
behaves as you want it to.

Carlo

-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: [ANN] clojure-sql 0.1.0: relational algebra in clojure

2013-11-20 Thread Carlo Zancanaro
Hi Mark!

On Wed, Nov 20, 2013 at 01:11:11PM -0800, Mark wrote:
 I'm using the 2.0 snapshot.  How should I express a join on multiple 
 columns, ie
 SELECT blah FROM t1 JOIN t2 ON (t1.a=t2.b) AND (t1.c=t2.d) ?

Something like this should work:

(let [t1 (- (table :t1)
 (project [:a :c]))
  t2 (- (table :t2)
 (project [:b :d]))]
  (join t1 t2 :on `(and (= :a :b)
(= :c :d

If you've got shared attributes this won't work for you, though, because
then there's an ambiguity about whether to use a natural join (ie.
joining on equality of shared attributes) or your join condition (which
will leave an ambiguity about which shared attribute to use). In that
case you can use something like this:

(let [t1 (- (table :t1)
 (project [:a :b]))
  t2 (- (table :t2)
 (project [:a :c]))]
  (join (rename t1 (as-subobject :t1))
(rename t2 (as-subobject :t2))
:on `(and (= :t1.a :t2.c)
  (= :t2.a :t1.b


Sorry about the lack of documentation for this. I'm working on it, but
I've been quite busy/distracted lately. Hopefully I'll have some more
time to get back to it soon.

Carlo

-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: [ANN] clojure-sql 0.1.0: relational algebra in clojure

2013-09-18 Thread Carlo Zancanaro
On Wed, Sep 18, 2013 at 09:27:22AM -0700, Daniel Neal wrote:
 One other difference I did notice with clojureql is that in clojureql the 
 database/connection
 is part of the query definition `(table db :users)`, where as in 
 clojure-sql the database/connection
 is a separate thing. This seemed more orthogonal to me, but in practice I 
 found it a bit tricky when working with multiple databases as I kept having 
 to change global state - is there a better way of handling multiple 
 databases using clojure-sql (perhaps I need to write my own query 
 executor...?)

Yeah, writing your own executor is a good option. Personally I would
write one which returns a function of the database, like this:

(set-query-executor! (fn [type query]
   (fn [db]
 (jdbc/with-connection db
   (case type
 :select (jdbc/with-query-results results query
   (dotted-to-nested-maps results))
 :insert (jdbc/do-prepared-return-keys (first 
query) (next query))
 :update (jdbc/do-prepared-return-keys (first 
query) (next query))
 :delete (first (jdbc/do-prepared (first query) 
(next query)))
 (assert false (str Unknown query type:  
type)))

Then you can use (@query db) to run queries, and the slightly-clunkier
((insert! query record ...) db) to modify the database. (I haven't
tried running this code, so it may require some modification to actually
work.)

In my use case I am always working with a single database, so I thought
this approach would be a bit overkill as the default.

 1. Are there any known issues/not-implemented-yet bits I might run into 
 when using clojure-sql?

Almost certainly, but I don't know all of the issues. So far it's been
working for what I've needed it for (which is a fairly small subset of
SQL, admittedly).

I'm not happy with the way the grouping stuff works at the moment, but
at the moment I've not really had much time to fix it. It should work,
but you lose the ability to freely compose things once you do a group
(because a select being applied later can change the group result).

 2. What plans do you have for the library going forward?

A few things, when I get a chance, mostly to do with generalising the
relational algebra approach beyond just SQL. I'd like to make it so
queries can be executed against other possible data stores (eg. an
in-memory structure, files on disk) efficiently.

As part of this would also be re-thinking how queries are executed.
Obviously, as you've seen above, the executor stuff isn't quite as nice
as it could be. I don't like having the global state stuff, but I wanted
executing queries to be both easy and configurable.

I'd also like to start generating SQL for other databases. I've been
putting this off because I don't really have any need for it at the
moment and it's a fair bit of work to do properly.

Carlo

-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: [ANN] clojure-sql 0.1.0: relational algebra in clojure

2013-09-17 Thread Carlo Zancanaro
On Tue, Sep 17, 2013 at 02:28:08AM -0700, Daniel Neal wrote:
 I'd be interested in knowing some more about your approach compared to that 
 of ClojureQL and the motivation behind it.

Sure!

The basic difference is that I tried to be a little bit more rigid in
how queries must be constructed. I tried to ensure that the generated
queries weren't just valid SQL, but that they were also sensible and
unambiguous (or, if there isn't enough information to make a sensible,
unambiguous, query, that it throws an exception).

As an example, in ClojureQL you can create the following query, which
will compile into a query without any issue:

  (join (table :users) (table :people) (where (= :uid :pid)))

but the result of this query (or even the structure of the result) is
difficult to determine by examining the code. Even worse, because the
:uid and :pid aren't from either table explicitly, this could fail on
the database if both tables have a :uid or :pid field.

The equivalent query in clojure-sql,

  (join (table :users) (table :people) :on `(= :uid :pid))

will fail, telling you there's an ambiguous field :uid in the query. If
you disambiguate :uid (by projecting :uid in either of the tables) then
it will complain about :pid.



My ideal is that you could treat a query as some opaque object about
which you can only know two things: the shape of the data it
specifies, and (after executing the query) the data that it specifies.
You should then be able to arbitrarily apply clojure-sql functions to
those queries to produce new opaque queries without any concern about
how the subqueries were produced (with each of the functions causing a
known, predictable, effect on the execution result).

At the moment this should be true of all the relational operators
(project/select/rename/join), the set operations (union/intersection)
and some other operations (take/drop/sort) but it's not true of the
grouping operations (group/having).


Carlo

-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: Can I refer all but specified symbols with 'ns' macro?

2013-08-01 Thread Carlo Zancanaro
I think the way to do it is:

(ns foo
  (:require [bar :refer :all :exclude (quux)]))


On 1 August 2013 18:19, Yoshinori Kohyama yykohy...@gmail.com wrote:

 Hi group.

 Assumed that I want to refer 'baz, 'qux and etc and don't want to refer
 'quux of 'bar namespace within my 'foo namespace.

 With 'ns' macro, I can require a namespace and refer all public symbols in
 it.

   (ns foo (:require [bar :refer :all]))

 I can refer only some specific symbols.

   (ns foo (:require [bar :refer (baz qux)]))

 Can I refer all but specific symbols?

 I'm doing

   (ns foo (:require bar))
   (refer 'bar :exclude '(quux))

 or

   (ns foo)
   (require 'bar)
   (refer 'bar :exclude '(quux))

 for now.

 Thanks in advance.

 Y. Kohyama

  --
 --
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with
 your first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 ---
 You received this message because you are subscribed to the Google Groups
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/groups/opt_out.




-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Ring: How to auto-redirect URI's missing trailing slash

2013-07-25 Thread Carlo Zancanaro
On 26 July 2013 11:17, Sebastian Rojas sebastian.rojas.viva...@gmail.comwrote:

 Checkout this middleware in lib-noir
 https://github.com/noir-clojure/lib-noir/blob/master/src/noir/util/middleware.clj#L70


Unfortunately that middleware only changes the way your handlers see the
URI of the request. The issue Reginald is talking about is that the browser
resolves relative links differently if you have a slash at the end.

For example, from a page of /posts a relative link to comments would go
to /comments, but from /posts/ a relative link to comments would go
to /posts/comments.

Reginald: I don't have a good solution to this problem, but I have
experienced it in the past. In theory it wouldn't be too difficult to make
some middleware to redirect with a 301, but you'd need to make sure you
maintain other important bits of the request (:flash, query parameters,
etc.) which could be quite fiddly.

-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.




Re: [ANN] clojure-sql 0.1.0: relational algebra in clojure

2013-07-06 Thread Carlo Zancanaro
This is a fairly restricted composition, though:

(def triangles (compose (select [:color :num_sides] (from :shapes))
(where '(= :num_sides 3
(def green-triangles (compose triangles
  (where '(= :color green
(sql green-triangles)
;= [SELECT color, num_sides FROM shapes WHERE (color = ?) green]

We've lost our `num_sides` selection, so now our query is wrong. Last
clause wins means you have to be aware of the previous ones to ensure you
don't obliterate them when composing.

The same example in `clojure-sql`:

(def triangles (- (table :shapes)
   (project [:color :num_sides])
   (select '(= :num_sides 3
(def green-triangles (select triangles '(= :color :green)))
(deref green-triangles)
;= [SELECT \shapes2142\.\color\ AS \color\,
\shapes2142\.\num_sides\ AS \num_sides\ FROM \shapes\ AS
\shapes2142\ WHERE ((\shapes2142\.\num_sides\ = 3) AND
(\shapes2142\.\color\ = ?)) green]

On 6 July 2013 22:37, r0man roman.sche...@burningswell.com wrote:

 Composing queries is done via compose.

 Take a look here:
 https://github.com/r0man/sqlingvo/blob/master/test/sqlingvo/test/core.clj#L16


 On Saturday, July 6, 2013 5:46:06 AM UTC+2, Carlo wrote:

 Hey Roman,

 The issue that I see with `sqlingvo`, and the thing which I was trying to
 solve for myself, is that it doesn't compose well. Unless I'm missing
 something, you have to generate the entire query in the one `sql` form. To
 me, this is a big restriction and was the number one thing I was trying to
 fix with `clojure-sql`.

 The basic sort of thing I want to be able to do is this:

 (def users (- (table :users) (project [:id :person :username])))
 (def people (- (table :people) (project [:id :first-name])))

 (def combined-query (- people
 (rename {:id :person})
 (join users)
 (project [:username :first-name])))

 So now in queries I can use `people`, `users` and `combined-query` in the
 same way. The only difference in terms of how I can compose them is that
 they expose different fields (`users` exposes [:id, :person, :username],
 `people` exposes [:id :first-name], `combined-query` exposes [:username
 :first-name]). In this example it's not completely obvious why this would
 be beneficial, but it means that I can change `users`, for instance, to
 also have a `(select '(= :deleted false)` in its definition and no other
 code has to change. They will all join/query against the users where
 `deleted` is false without any other modifications of code.

 This freedom of composition is what you have in relational algebra, and
 what I was trying to get in Clojure as well. All the naming of tables and
 field aliases and everything is handled by the library, so you only have to
 worry about constructing the queries. Unfortunately SQL provides a number
 of operations outside of the relational algebra model (grouping, sorting,
 take/drop), so they've been tacked on as a bit of an afterthought and
 could probably use some improvement.

 Looking at `sqlingvo` did show up a mistake that I made in how I was
 dealing with sorts, though, so thanks for that! I think our libraries just
 have fairly different concerns at the moment.

 Carlo


 On 5 July 2013 20:59, r0man roman@burningswell.**com wrote:

 Hi Carlo,

 if you'are looking for generating more complex SQL there's also:

 https://github.com/r0man/**sqlingvo https://github.com/r0man/sqlingvo

 Roman.

 On Wednesday, July 3, 2013 10:48:07 AM UTC+2, Carlo wrote:

 Hey guys!

 I've been working on a small library to make writing SQL queries a
 little bit easier. It's along the same lines as ClojureQL, but takes a
 different approach and compiles into quite different SQL in the end.

 At the moment it's quite immature, but it should be able to support any
 queries which can be expressed in relational algebra. There will be some
 SQL queries which can't be expressed in clojure-sql, but hopefully there
 won't be too many of those. A greater limitation is that at the moment the
 SQL generation is specific to the PostgresSQL database (although any
 contributions for other databases are welcome!).

 Dependency vector: [clojure-sql 0.1.0]
 Repository: 
 https://bitbucket.org/czan/**clo**jure-sqlhttps://bitbucket.org/czan/clojure-sql
 Clojars link: 
 https://clojars.org/clojure-**sq**lhttps://clojars.org/clojure-sql

 Let me know what you think!

 Carlo

  --
 --
 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=enhttp://groups.google.com/group/clojure?hl=en
 ---
 You received this message because you are 

Re: Walking a tree

2013-07-06 Thread Carlo Zancanaro
Give this a go:

(defn ^:private walk-tree* [all seen to-do]
  (when-let [[curr  others] to-do]
(if (contains? seen curr)
  (recur all seen others)
  (lazy-seq
   (when-let [node (first (filter #(= (:v %) curr) all))]
 (println node)
 (cons curr
   (walk-tree* all
   (conj seen curr)
   (concat others
   (:parent node)

(defn walk-tree [all]
  (walk-tree* all #{} [(- all first :v)]))

I'm still not super happy with it, but it should solve your problem. The
basic trick is to not use things like `mapcat`, as you need to keep
updating some state (the `seen` map) between calls. The approach here is to
pass work to be done and work to be ignored together. Then both can be
kept up to date in sync with each other. Your recursion becomes a bit more
explicit, too.

I hope that helps!


On 7 July 2013 00:33, looselytyped raju.gan...@gmail.com wrote:

 Good morning everyone!

 I have a problem that I have been struggling with for a few days now. I
 have a directed acyclic graph that I am trying to walk, and can't seem to
 figure out a to prevent my walking already visited branches. Here is the
 code

 (def values
   [{:v a :parent [b]}
{:v b :parent [c]}
{:v c :parent [d e]}
{:v d :parent [f]}
{:v e :parent [f]}
{:v f}])

 As you can see, I have a vector of records, each with a value and a
 vector of parents. A node can have more than zero or more parents.

  a o
|
  b o
|
  c o
|\
  d o o e
|/
  f o

 Here is the fruits of several attempts ...

 (defn walk-tree
   ([values]
  (letfn [(in?
[seq elm]
(some #(= elm %) seq))
  (walk [already id]
(when-not (in? already id)
  (when-let [n (some #(if (= id (:v %)) %) values)]
(lazy-seq
 (cons (:v n)
   (mapcat #(walk (conj already (:v n)) %) (:parent
 n)))]
(walk #{} (:v (first values))

 I was hoping to use the set as a way to record which nodes have been
 visited. Unfortunately as you might be able to tell, that's not going to
 work. The result of running this is

 (a b c d f e f)

 Notice that f gets in the list twice. One way to do it would be to make
 a set out of it, but that eliminates the laziness aspect.

 Can anyone point me in the right direction here?

 Thanks,

 Raju

 --
 --
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with
 your first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 ---
 You received this message because you are subscribed to the Google Groups
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/groups/opt_out.




-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.




Re: [ANN] clojure-sql 0.1.0: relational algebra in clojure

2013-07-05 Thread Carlo Zancanaro
Hey Roman,

The issue that I see with `sqlingvo`, and the thing which I was trying to
solve for myself, is that it doesn't compose well. Unless I'm missing
something, you have to generate the entire query in the one `sql` form. To
me, this is a big restriction and was the number one thing I was trying to
fix with `clojure-sql`.

The basic sort of thing I want to be able to do is this:

(def users (- (table :users) (project [:id :person :username])))
(def people (- (table :people) (project [:id :first-name])))

(def combined-query (- people
(rename {:id :person})
(join users)
(project [:username :first-name])))

So now in queries I can use `people`, `users` and `combined-query` in the
same way. The only difference in terms of how I can compose them is that
they expose different fields (`users` exposes [:id, :person, :username],
`people` exposes [:id :first-name], `combined-query` exposes [:username
:first-name]). In this example it's not completely obvious why this would
be beneficial, but it means that I can change `users`, for instance, to
also have a `(select '(= :deleted false)` in its definition and no other
code has to change. They will all join/query against the users where
`deleted` is false without any other modifications of code.

This freedom of composition is what you have in relational algebra, and
what I was trying to get in Clojure as well. All the naming of tables and
field aliases and everything is handled by the library, so you only have to
worry about constructing the queries. Unfortunately SQL provides a number
of operations outside of the relational algebra model (grouping, sorting,
take/drop), so they've been tacked on as a bit of an afterthought and
could probably use some improvement.

Looking at `sqlingvo` did show up a mistake that I made in how I was
dealing with sorts, though, so thanks for that! I think our libraries just
have fairly different concerns at the moment.

Carlo


On 5 July 2013 20:59, r0man roman.sche...@burningswell.com wrote:

 Hi Carlo,

 if you'are looking for generating more complex SQL there's also:

 https://github.com/r0man/sqlingvo

 Roman.

 On Wednesday, July 3, 2013 10:48:07 AM UTC+2, Carlo wrote:

 Hey guys!

 I've been working on a small library to make writing SQL queries a little
 bit easier. It's along the same lines as ClojureQL, but takes a different
 approach and compiles into quite different SQL in the end.

 At the moment it's quite immature, but it should be able to support any
 queries which can be expressed in relational algebra. There will be some
 SQL queries which can't be expressed in clojure-sql, but hopefully there
 won't be too many of those. A greater limitation is that at the moment the
 SQL generation is specific to the PostgresSQL database (although any
 contributions for other databases are welcome!).

 Dependency vector: [clojure-sql 0.1.0]
 Repository: 
 https://bitbucket.org/czan/**clojure-sqlhttps://bitbucket.org/czan/clojure-sql
 Clojars link: 
 https://clojars.org/clojure-**sqlhttps://clojars.org/clojure-sql

 Let me know what you think!

 Carlo

  --
 --
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with
 your first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 ---
 You received this message because you are subscribed to the Google Groups
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/groups/opt_out.




-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.




Re: [ANN] clojure-sql 0.1.0: relational algebra in clojure

2013-07-05 Thread Carlo Zancanaro
Hey Sean,

Most of the points in my reply to Roman also apply to `HoneySQL`. In
particular this phrase in the README summarises a good deal of my
criticism: When using the vanilla helper functions, new clauses will
replace old clauses. You have to go out of your way to get the
composability that I desire.

`HoneySQL` seems like it would fit fairly well as compiler in the
`clojure-sql` sense. A translation of the internal `clojure-sql` query into
a `HoneySQL` format, then run it through the `HoneySQL` compiler. Is there
a reason you don't use the database's table/column name quoting? It means
that keywords like :first-name cannot be used as table names without a fair
bit of trouble. (This was also an issue I had with most other SQL
generation libraries I've seen, and something I made sure to fix in my
`clojure-sql` compiler for PostgresSQL.)

Thanks,

Carlo


On 6 July 2013 02:32, Sean Corfield seancorfi...@gmail.com wrote:

 And there's HoneySQL:

 https://github.com/jkk/honeysql

 (that's the one java.jdbc will recommend going forward since I worked
 with the author, Justin Kramer, on compatibility and direction for
 java.jdbc and HoneySQL at Clojure/conj last year)

 On Fri, Jul 5, 2013 at 3:59 AM, r0man roman.sche...@burningswell.com
 wrote:
  Hi Carlo,
 
  if you'are looking for generating more complex SQL there's also:
 
  https://github.com/r0man/sqlingvo
 
  Roman.
 
  On Wednesday, July 3, 2013 10:48:07 AM UTC+2, Carlo wrote:
 
  Hey guys!
 
  I've been working on a small library to make writing SQL queries a
 little
  bit easier. It's along the same lines as ClojureQL, but takes a
 different
  approach and compiles into quite different SQL in the end.
 
  At the moment it's quite immature, but it should be able to support any
  queries which can be expressed in relational algebra. There will be
 some SQL
  queries which can't be expressed in clojure-sql, but hopefully there
 won't
  be too many of those. A greater limitation is that at the moment the SQL
  generation is specific to the PostgresSQL database (although any
  contributions for other databases are welcome!).
 
  Dependency vector: [clojure-sql 0.1.0]
  Repository: https://bitbucket.org/czan/clojure-sql
  Clojars link: https://clojars.org/clojure-sql
 
  Let me know what you think!
 
  Carlo
 
  --
  --
  You received this message because you are subscribed to the Google
  Groups Clojure group.
  To post to this group, send email to clojure@googlegroups.com
  Note that posts from new members are moderated - please be patient with
 your
  first post.
  To unsubscribe from this group, send email to
  clojure+unsubscr...@googlegroups.com
  For more options, visit this group at
  http://groups.google.com/group/clojure?hl=en
  ---
  You received this message because you are subscribed to the Google Groups
  Clojure group.
  To unsubscribe from this group and stop receiving emails from it, send an
  email to clojure+unsubscr...@googlegroups.com.
  For more options, visit https://groups.google.com/groups/opt_out.
 
 



 --
 Sean A Corfield -- (904) 302-SEAN
 An Architect's View -- http://corfield.org/
 World Singles, LLC. -- http://worldsingles.com/

 Perfection is the enemy of the good.
 -- Gustave Flaubert, French realist novelist (1821-1880)

 --
 --
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with
 your first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 ---
 You received this message because you are subscribed to the Google Groups
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/groups/opt_out.




-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.




[ANN] clojure-sql 0.1.0: relational algebra in clojure

2013-07-03 Thread Carlo Zancanaro
Hey guys!

I've been working on a small library to make writing SQL queries a little
bit easier. It's along the same lines as ClojureQL, but takes a different
approach and compiles into quite different SQL in the end.

At the moment it's quite immature, but it should be able to support any
queries which can be expressed in relational algebra. There will be some
SQL queries which can't be expressed in clojure-sql, but hopefully there
won't be too many of those. A greater limitation is that at the moment the
SQL generation is specific to the PostgresSQL database (although any
contributions for other databases are welcome!).

Dependency vector: [clojure-sql 0.1.0]
Repository: https://bitbucket.org/czan/clojure-sql
Clojars link: https://clojars.org/clojure-sql

Let me know what you think!

Carlo

-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Lazy seq race condition?

2013-06-24 Thread Carlo Zancanaro
On Mon, Jun 24, 2013 at 4:17 PM, Cedric Greevey cgree...@gmail.com wrote:

 Ah, thanks. The locking granularity is local to the cons cell (or
 analogue; first/rest pair) being realized, I hope? So one thread actually
 calculates an element and neither call returns until it's calculated, and
 then both promptly return the calculated value, but threads realizing other
 lazy seqs or crawling along earlier parts of the same one don't get blocked?


This is correct, as far as I understand it. One will do the work, the other
will block (awaiting a lock). The first will return, relinquishing the lock
and allow the other to get the computed value too.

The granularity could be anything from a single cons cell to the entire
seq. In the following instance the evaluation of the thunk will yield the
entire vector in one operation, which is synchronized. (The `println` is
there to make clear when/how evaluation takes place.)

(def lazily-initialized-vector (lazy-seq (mapv println (range 10)))

What gets returned by the thunk is entirely dependent on the thunk. LazySeq
just relies on being able to call `seq` on it. Presumably for fully lazy
sequences it will generate one element at a time, and for chunked sequences
it will generate one chunk at a time.

(Just for the record, I don't have any particular knowledge of the Clojure
internals, but I'm fairly confident in my speculation.)

-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.




Re: database wrapper lib

2013-06-21 Thread Carlo Zancanaro
Hey Justin,

I'm also working on a wrapper lib for SQL queries (which can optionally use
jdbc for performing the queries). At the moment it's pretty new, so it
might not actually work for you, but if you want to take a look the code's
at https://bitbucket.org/czan/clojure-sql. It's also been pushed to clojars
(https://clojars.org/clojure-sql) if you want to try it out.

The main idea is that all queries should be composable, so you can just
think of them in terms of the fields they expose and then you should be
able to join them together however you want.

I plan to do a bit more work before actually announcing a release, but
since it was so relevant to what you're asking about I just had to mention
it.

Carlo


On 22 June 2013 04:38, serialhex serial...@gmail.com wrote:

 Hey, thanks for the links!!  I searched around but never found those, this
 helps a lot!!!

 Justin


 On Fri, Jun 21, 2013 at 11:56 AM, Michael Klishin 
 michael.s.klis...@gmail.com wrote:


 2013/6/21 serialhex serial...@gmail.com

 Hi all, I'm looking for a decent database wrapper library.


 Relational databases: https://github.com/clojure/java.jdbc (this one is
 not very extensively documented but is also small compared to Korma)

 MongoDB: http://clojuremongodb.info
 Cassandra: http://clojurecassandra.info
 Riak: http://clojureriak.info
 Redis: https://github.com/ptaoussanis/carmine
 Graph databases: http://titanium.clojurewerkz.org,
 http://clojureneo4j.info
 ElasticSearch: http://clojureelasticsearch.info

 For data validation, http://clojurevalidations.info is one of about a
 dozen options
 you can easily find with a quick search.
 --
 MK

 http://github.com/michaelklishin
 http://twitter.com/michaelklishin

 --
 --
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with
 your first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 ---
 You received this message because you are subscribed to the Google Groups
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/groups/opt_out.






 --
 * I am rarely happier than when spending an entire day programming my
 computer to perform automatically a task that would otherwise take me a
 good ten seconds to do by hand.
  - Douglas Adams
 ---
 CFO: “What happens if we train people and they leave?”
 CTO: “What if we don’t and they stay?”

 --
 --
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with
 your first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 ---
 You received this message because you are subscribed to the Google Groups
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/groups/opt_out.




-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.




Re: First day with Macros

2013-06-17 Thread Carlo Zancanaro
I can't speak to the issues that Gary raised, but I can help you with your
macro.

(defmacro servlet [servlet-name  meths]
  `(reify Servlet
 ~@(for [meth meths]
 (let [[method-name args  body] meth
   method-name (hyphenated-camel-case method-name)]
   `(~method-name ~args ~@body)

The key here is to keep track of when things are run. The `for` must be run
at compile time in order to generate the code we want, so we have to escape
it with ~@. The code that the `for` creates (in the form of a list) must
then be (quasi-)quoted again by the backtick.

Macros certainly take some getting used to.


On Tue, Jun 18, 2013 at 8:12 AM, Hussein B. hubaghd...@gmail.com wrote:

 Here is my fourth attempt:

 (defmacro servlet [servlet-name  meths]
   `(reify Servlet
  (for [meth ~meths]
(let [[method-name args  body] ~meth
   camel-case-method-name (hyphenated-camel-case ~method-name)]
  (camel-case-method-name ~args ~@body)

 Still it is not working :(

 How to fix it?

 On Tuesday, June 18, 2013 12:04:50 AM UTC+2, Gary Trakhman wrote:

 Unquoting 'camel-case-method-name' is going to try and replace the symbol
 with it's value during compile-time in the context of the macro itself.

 also, reify isn't going to work if you need a named class to actually
 wire up your servlet, for example with a web.xml. Also, consider that
 you'll need some AOT compilation for the container to actually see the
 servlet class.


 On Mon, Jun 17, 2013 at 4:38 PM, Hussein B. hubag...@gmail.com wrote:

 Hi,

 My target is to have something like this:

 (servlet ArticlesServlet
   (do-get [this request response]
 (println Get Request))
   (do-post [this request response]
 (println Post Request)))


 I started with this:

 (defmacro servlet [servlet-name meths]
   `(reify Servlet
  (for [meth ~@meths]
(let [[method-name params  body] meth
   camel-case-method-name (hyphenated-camel-case
 method-name)]
  (~camel-case-method-name ~@body)

 But of course, it is not working :)

 I get:

 CompilerException java.lang.RuntimeException: Unable to resolve symbol:
 camel-case-method-name in this context

 Why?

 And of course, feel super free to correct my Macro :)

 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 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=enhttp://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/**groups/opt_outhttps://groups.google.com/groups/opt_out
 .




  --
 --
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with
 your first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 ---
 You received this message because you are subscribed to the Google Groups
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/groups/opt_out.




-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.




Re: binding funkiness

2013-04-22 Thread Carlo Zancanaro
If you want to capture the binding and have laziness together you can also
use `bound-fn`.

(binding [*funkybind* true] (map (fn [_] *funkybind*) [0 1]))
;= (false false)
(binding [*funkybind* true] (map (bound-fn [_] *funkybind*) [0 1]))
;= (true true)


On Tue, Apr 23, 2013 at 11:52 AM, Travis Vachon travis.vac...@gmail.comwrote:

 Hi Daniel

 map is creating a lazy seq, which isn't evaluated until the REPL's
 forces it to be printed, which is outside the scope of the binding.

 This:

 (binding [*funkybind* true]
   (doall (map (fn [_] *funkybind*) [1 2])))

 forces evaluation inside the binding, and does what you want.

 This is something I've been bitten by a few times, but the power that
 lazyness brings ends up being worth it, IMHO.

 Good luck!

 Travis

 On Mon, Apr 22, 2013 at 9:41 PM, Daniel Higginbotham
 nonrecurs...@gmail.com wrote:
  I've encountered a situation where the binding function doesn't work as I
  expect it:
 
  user (def ^:dynamic *funkybind* false)
 
  ;; expected
  user (binding [*funkybind* true]
*funkybind*)
  true
 
  ;;expected
  (binding [*funkybind* true]
((fn [] *funkybind*)))
  true
 
  ;;... huh?
  (binding [*funkybind* true]
(map (fn [_] *funkybind*) [1 2]))
  (false false)
 
  In the last example, why is the value of *funkybind* false instead of
 true?
 
  Thanks!
  Daniel
 
  --
  --
  You received this message because you are subscribed to the Google
  Groups Clojure group.
  To post to this group, send email to clojure@googlegroups.com
  Note that posts from new members are moderated - please be patient with
 your
  first post.
  To unsubscribe from this group, send email to
  clojure+unsubscr...@googlegroups.com
  For more options, visit this group at
  http://groups.google.com/group/clojure?hl=en
  ---
  You received this message because you are subscribed to the Google Groups
  Clojure group.
  To unsubscribe from this group and stop receiving emails from it, send an
  email to clojure+unsubscr...@googlegroups.com.
  For more options, visit https://groups.google.com/groups/opt_out.
 
 

 --
 --
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with
 your first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 ---
 You received this message because you are subscribed to the Google Groups
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/groups/opt_out.




-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.




Re: limit keys from client JSON (select-keys but nested?)

2013-01-01 Thread Carlo Zancanaro
 2) Is there a good way of doing this with nested maps?  An example:

 { :user { :first John :last Doe :dob { :month 12 :day 30 :year 2012
 :garbage asdf } } }

 I would want to make sure :dob only contains keys :month, :day, :year.

I'd write a simple little helper function to do this, if I were you.
This is what I came up with.


(defn transform-map [model element]
  (cond
   (sequential? model) (if (sequential? element)
 (map #(transform-map (first model) %) element)
 nil)
   (associative? model) (into {} (for [[k v] model
   :when (contains? element k)
   :let [new-value (transform-map
v (get element k))]
   :when (not= new-value ::ignore)]
   [k new-value]))
   (ifn? model) (model element)
   model element
   :else ::ignore))



This transforms a value with a `model`. The model consists of nested
maps/vectors which specify what you want the final data to look like.
The leaves of the model are either transformation functions (which are
applied to the value at that point), truthy values (in which case the
value is kept) or falsy values (in which case the value is discarded).
Things which aren't specified are also discarded.

For example:
(def model {:user {:first true
   :last true
   :dob {:year true
 :month true
 :day true}}})

(transform-map model
   {:user {:first John
   :last Doe
   :dob {:month 12
 :day 30
 :year 2012
 :garbage asdf}
   :role :whatever}})
;= {:user {:last Doe, :dob {:year 2012, :month 12, :day 30}, :first John}}

I hope that helps!

Carlo

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


Re: core.match - how to simplify patterns with repeated guards

2012-11-14 Thread Carlo Zancanaro
Hey David,

 I guess its got something to do with the fact that match itself is a macro?

Correct. The match macro just takes the list `(!nil? a)`, which isn't
a valid match form, so it complains about it.

 Is there some other way that I could extend match to only match when the 
 variable is not nil?

Yep! You just need to replace the match macro itself, rather than
trying to change the rows.

Here's my go at it:

(def not-nil? (complement nil?))

(defmacro match-nn [expr  matches]
  (let [add-guard (fn [e]
(if (symbol? e)
  (list e :guard `not-nil?)
  e))
guard-row (fn [[cond result]]
(if (vector? cond)
  [(vec (map add-guard cond)) result]
  [cond result]))
rows (partition 2 matches)
new-rows (mapcat guard-row rows)]
`(match ~expr
~@new-rows)))

(defmacro match-pred [expr  matches]
  (let [add-guard (fn [e]
(if (and (seq? e)
 (not= (second e) :guard))
  (list (second e) :guard (first e))
  e))
guard-row (fn [[cond result]]
(if (vector? cond)
  [(vec (map add-guard cond)) result]
  [cond result]))
rows (partition 2 matches)
new-rows (mapcat guard-row rows)]
`(match ~expr
~@new-rows)))



`match-nn` will make sure all matched variables satisfy the `not-nil?`
predicate. `match-pred` will allow you to write guards like `(not-nil?
a)` and have it translated to `(a :guard not-nil?)`.

I hope that helps!

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


Re: function calling itself using a generic self reference call?

2012-08-06 Thread Carlo Zancanaro
 1. would it be, or is it possible to have something generic like this?

You could use:

(def v1 (fn self
  ([x] (self x []))
  ([x r] (conj r x)))

 2. What about anonymous fns?

The same idea, just without the def.

(fn call-self
  ([x] (call-self x 0))
  ([x y] ...)))

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


Re: swap! and atom behavior

2012-07-31 Thread Carlo Zancanaro
 1) I assumed that printing out [i @a] instead of [@a i] should realize 'i'
 first and @a should be correctly displayed as 5. This does not happen, it
 simply prints [(1 2 3 4 5) 0] if the order is reversed.

So, this evaluates in two stages.

First the terms `i` and `@a` are evaluated to get their values, so `i`
returns the lazy sequence it contains (not realised at all) and `@a`
returns the value inside the atom (which is 0).

Then the printing statement goes through each of those values and
tries to work out what it needs to print. For `i` this involves
realising the sequence (to get each value to print), but for `@a` it's
already got the value (0, from earlier), so it just prints that. For
the lazy sequence it didn't have a printable value, it just had
something saying this is a sequence that will be generated when you
want it, so it has to do more work before it can print.

 2) If I put a breakpoint in the predicate for take-while, it gets hit ( I
 was expecting it to not get hit if it was lazy)

The lazy sequence still gets realised, just not when you'd expect, so
you still hit the breakpoint, just after you've already retrieved the
value of the atom.

 3) This is the strangest observation of all: In the debugger I can see that
 'a' is getting incremented, its changing when the breakpoint is hit!  but
 the baffling thing is, when the result is printed out, I still get 0 as the
 value for a.

This is also explained by the above.


You're basically getting stung by precisely when a lazy sequence gets
realised. This sort of issue is why you should try to avoid having any
sort of side effects in the generation of lazy sequences.

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


Re: Classpath set by lein swank or clojure-jack-in

2012-06-16 Thread Carlo Zancanaro
On Sat, Jun 16, 2012 at 10:10 AM, Dave Kincaid kincaid.d...@gmail.com wrote:
 Sure can. Here is the project.clj:

 (defproject swank-test 0.1
   :source-path src/main/clj

Are you using lein 1.x or lein 2.x? In lein 2.x you need to use
`:source-paths [src/main/clj]` here.

   :test-path test/clj
   :java-source-path src/main/java

The same goes for :test-paths and :java-source-paths. The leiningen
girhub repository has a sample project.clj which is where I looked
this up (in case you need to look something else up later).

https://github.com/technomancy/leiningen/blob/master/sample.project.clj

   :javac-options {:debug true :fork true}
   :resources-path src/main/resources
   :dependencies [[org.clojure/clojure 1.4.0]
                  [cascalog 1.9.0]
                  [org.apache.hadoop/hadoop-core 0.20.2 :exclusions
 [hsqldb/hsqldb]]])

 I have a file named generator.clj in src/main/clj. When I do a lein swank
 from the directory that project.clj is in then run slime-connect in Emacs
 with the generator.clj file open. Then I try to do (use 'generator) and get

 Could not locate generator__init.class or generator.clj on classpath:
   [Thrown class java.io.FileNotFoundException]

When I do this with your supplied project.clj with lein 1.x it works.
With lein2.x and the changes outlined above it also works.

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


Re: Strange evaluation result of the quoted form on 1.3

2012-06-07 Thread Carlo Zancanaro
A quoted symbol is just a literal symbol typed object. These symbols
act as functions where they evaluate like this:
('x 1) = (get 1 'x) - look itself up in its argument
('x 1 2) = (get 1 'x 2) - look itself up in its argument with a
not-found value.

So, in your example:

(bar '(foo 1 2)) tries to run ('foo 1 2). 'foo can't find itself in
the map 1 (because it's not a map), so it returns the default value
provided (in this case: 2).

On Fri, Jun 8, 2012 at 2:23 AM, Alex Shabanov avshaba...@gmail.com wrote:
 Oh, I see. This is because of the reader that interprets symbols from the
 quoted forms in different way it does for the unquoted ones (and this
 feature still strikes me as odd).
 To make matters more complicated the quoted symbols seems to have some
 meanings as functions for the clojure, since ('foo 1) - nil, ('foo 1 2) -
 2, ('foo 1 2 3 4) - arity exception.

 четверг, 7 июня 2012 г., 20:05:43 UTC+4 пользователь Bronsa написал:

 you' are calling (apply 'foo '(1 2)), what you want is (apply foo '(1 2))
 just call bar as
 (bar (list foo 1 2))

 2012/6/7 Alex Shabanov avshaba...@gmail.com

 I'm curious why the following form evaluates to 2:

 (defn foo [ more]
   (println foo( more  )))

 (defn bar [v]
   (apply (first v) (rest v)))

 (bar '(foo 1 2))

 If the form (bar '(foo 1 2)) extended to, say, (bar '(foo 1 2 3 4)) the
 arity exception will be thrown.
 The behavior can be reproduced after picking another names for foo and/or
 bar functions.

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


Re: Parallel doseq?

2012-05-25 Thread Carlo Zancanaro
You're doing all your computation in the generation of the lazy
sequence (which is in order). Then you're mapping identity in
parallel, but that doesn't do anything.

If you're willing to lose the for style bindings, try something more
like this:

(defmacro pdoseq
  Run over a sequence in parallel (like pmap)
  [seq-exprs  body]
  (let [pairs (partition 2 seq-exprs)]
`(do (doall (pmap (fn ~(vec (map first pairs)) ~@body) ~@(map
second pairs))) nil)))

On Thu, May 24, 2012 at 3:56 PM, Cedric Greevey cgree...@gmail.com wrote:
 For some reason, this doesn't actually seem to be executing in parallel:

 (defmacro pdoseq
  Bindings as for for, but parallel execution as per pmap, pcalls,
 pvalues; returns
   nil.
  [seq-exprs  body]
  `(do
     (doall
       (pmap identity
             (for ~seq-exprs (do ~@body)))
     nil)))

 user= (pdoseq [i (range 10)] (println n))
 0
 1
 2
 3
 4
 5
 6
 7
 8
 9

 Never any interleaving of output and if I give it a big CPU-bound job
 to do for each integer it only saturates one core.

 I thought it might be a chunked-seq issue, but:

 user= (chunked-seq? (range 10))
 false

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