Re: User input validations, design doubt

2017-02-08 Thread Herwig Hochleitner
Of course, for performance you can optimize that apply+hash-map+interleave
(or even your reduce) into reduce+transients, e.g. by using map-vals

.​

-- 
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: User input validations, design doubt

2017-02-08 Thread Herwig Hochleitner
2017-02-08 23:14 GMT+01:00 Rastko Soskic :
> (let [fns [(fn ([] :empty) ([x] "x")) (fn ([] :format) ([y] "y"))] val
> "field value"]
>   (reduce #(assoc % (%2) (%2 val)) {} fns))

The advantage in this approach is that you can get the keys from a set
of validators, but you still need some outside logic to get at the
result (the reduce).

Since in map validators one wouldn't expect to read any mutable state
to get at the keys (which would necessitate a possibly zero-arg fn
call), you could compile the map validator into a closure and keep the
keys as values in metadata:

(defn juxt-vals [& {:as kvs}]
  (with-meta
(let [ks (keys kvs)
  vs (vals kvs)]
  (fn [& args]
(apply hash-map
   (interleave ks (map #(apply % args) vs)
{:validator/map kvs}))

(def ef-validator
  (juxt-vals
:empty (fn [x] "x")
:format (fn [y] "y")))

(ef-validator nil) => {:format "y", :empty "x"}
(meta ef-validator) => #:validator{:map {:format
#function[user/fn--21690], :empty #function[user/fn--21688]}}

-- 
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: Vars as global thread-locals?

2017-02-08 Thread Ernesto Garcia
Hi Alex, thanks for your thorough response.

It seems to me that Clojure vars are just not intended to be used as 
thread-locals in general. They happen to use thread-local storage in order 
to implement dynamic scoping, which is the original intent.

That is why vars are either global (interned in a namespace), or confined 
to a dynamic scope (via with-local-vars).

If one needs thread-local storage, you use a Java ThreadLocal directly.

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


User input validations, design doubt

2017-02-08 Thread Rastko Soskic
Hi everyone,
this is simply question for of course opinionated views of my approach.
I have some user input (nevertheless where it comes from, web form input, 
rich client... whatever).
Single field can be (as usual) "equipped" with couple of validations, 
empty, format, strength (if it is about password) ...etc

So in absence of objects :) my best friends are functions so, when input 
value is validated I need to come out with map like:

{
 :empty "Field empty"
 :format "Format not valid"
 :strength "Weak"
}

So i need "id" of validation (key) which produced message (value)

So, simply, I have vector containing arbitrary set of functions to be 
applied over value and simply reduce over them.
0-arity overload returns validation key of that validator, and 1-arity 
performs actual check.

To avoid excessive code here is "overnaive" example:

(let [fns [(fn ([] :empty) ([x] "x")) (fn ([] :format) ([y] "y"))] val "field 
value"]
  (reduce #(assoc % (%2) (%2 val)) {} fns))


this yields exactly what I need :
{:empty "x", :format "y"}
(real reducing function would check what validator returned and skip or 
assoc particular result into map).

Now, I am not really sure how functional this approach of "self contained" 
function is, where particular 0 arity is used 
to give key. My idea is rooted in fact that e.g. 0-arity + function gives 
neutral element for addition.

Personally, I like it :) but I would like 2nd opinion as I am maybe 
brutally misusing functional programming :)

Thanks! :)

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


Re: How to disable (or limit) test.check shrinking

2017-02-08 Thread Daniel Compton
If the 503 is only returned by failures not relating to what you are
testing (e.g. load), then one option might be to catch the exception and
retry that request?

On Thu, Feb 9, 2017 at 6:48 AM 'Matt Bossenbroek' via Clojure <
clojure@googlegroups.com> wrote:

> I'm using test.check to test a live service. Occasionally it gets a 503
> from the service and spends hours trying to shrink the input & reproduce
> the error.
>
> Is there a way to limit the shrinking process to n iterations? Or disable
> it entirely for some tests?
>
> Is there a better approach for using test.check against a live service
> where transient issues are expected? Should I just retry the actual service
> call many times before allowing test.check to see it?
>
> Thanks,
> Matt
>
> --
> 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.
>
-- 

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/d/optout.


How to disable (or limit) test.check shrinking

2017-02-08 Thread 'Matt Bossenbroek' via Clojure
I'm using test.check to test a live service. Occasionally it gets a 503 
from the service and spends hours trying to shrink the input & reproduce 
the error.

Is there a way to limit the shrinking process to n iterations? Or disable 
it entirely for some tests?

Is there a better approach for using test.check against a live service 
where transient issues are expected? Should I just retry the actual service 
call many times before allowing test.check to see it?

Thanks,
Matt

-- 
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: Vars as global thread-locals?

2017-02-08 Thread Alex Miller


On Wednesday, February 8, 2017 at 8:34:06 AM UTC-6, Ernesto Garcia wrote:
>
> https://clojure.org/reference/vars says
>
> Clojure is a practical language that recognizes the occasional need to 
>> maintain a persistent reference to a changing value and provides 4 distinct 
>> mechanisms for doing so in a controlled manner - Vars, Refs, Agents and 
>> Atoms. Vars provide a mechanism to refer to a mutable storage location that 
>> can be dynamically rebound (to a new storage location) on a per-thread 
>> basis.
>>
>
> https://clojure.org/reference/special_forms says
>
> Using def to modify the root value of a var at other than the top level is 
>> usually an indication that you are using the var as a mutable global, and 
>> is considered bad style. Consider either using binding to provide a 
>> thread-local value for the var, or putting a ref or agent in the var and 
>> using transactions or actions for mutation. 
>
>
This is saying that if you are doing something like this:

(def my-value 10)

(defn inc-value []
  (def my-value (inc my-value)))

Then you are not using vars as intended. Here you have an identity 
(my-value) that refers to a var, that holds the value 10. The inc-value 
function is going to locate the existing var and reset its root value. This 
is not following the Clojure update model for identities which expects that 
you update an identity by providing a function that can be applied to the 
old value to produce a new value. If you really wanted to do this, you 
could do so by using alter-var-root explicitly:

(defn inc-value []
  (alter-var-root #'my-value inc))

However, the point here is that keeping your state in a global var and 
bashing on it is generally bad style (particularly using def). Using a 
dynamic var and bindings for thread-local values effectively switches to a 
model where you are not sharing state across threads. 

Probably if you're doing the code above, that's not really satisfying your 
needs. Dynamic bindings are most commonly used to create per-thread ambient 
context that can be passed down the call stack without explicitly passing 
it as arguments. This should be used sparingly as you are creating implicit 
state - any code that calls into it (like tests) has to be aware of the 
ambient state and properly set it up.

Alternately, you can make the value held by your var a stateful thing (atom 
or ref) itself and thus avoid altering the global var ever:

(def my-value (atom 0))
(defn inc-value []
  (swap! my-value inc))

This is strongly preferred over the var-bashing in the first example.
 

> Clojure encourages avoiding the use of vars as global thread-local 
> storage, by restricting their use to dynamic binding only.
>

I don't think that's really the message here. It's saying that while vars 
are global stateful constructs, it is not idiomatic to modify them unless 
they are dynamic and you are doing so in a thread-local context. If you 
want a global thread-local state, then do that. If you want a global 
stateful construct, it's better to use an atom or ref held in a non-dynamic 
var. 

Generally my advice would be to avoid global stateful constructs as much as 
possible and not do any of these. :) Global state has all the same problems 
of implicit state I mentioned above with bindings.
 

> What is so bad about global thread-locals?
>

Nothing - dynamic vars are effectively global thread locals (in combination 
with a global root value).
 

> It can't be the fact that they are global, as refs are typically made 
> global. 
>

As I said above, atoms/refs can and often are created as part of your 
application state and passed around. Generally, I think you should strongly 
prefer this over creating a (global) var holding a ref. 
 

> They also have a good thread-safe behavior.
>

Agreed. :)
 

>
> Thanks,
> Ernesto
>

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


Looking for new maintainer for "fs"

2017-02-08 Thread Miki
Hi There,

We're looking for a new maintainer for "fs".
See https://github.com/Raynes/fs/issues/106 
and https://github.com/clojars/clojars-web/issues/618 for context.

If you're able and willing, please ping me.

Thanks,
--
Miki

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


Vars as global thread-locals?

2017-02-08 Thread Ernesto Garcia
https://clojure.org/reference/vars says

Clojure is a practical language that recognizes the occasional need to 
> maintain a persistent reference to a changing value and provides 4 distinct 
> mechanisms for doing so in a controlled manner - Vars, Refs, Agents and 
> Atoms. Vars provide a mechanism to refer to a mutable storage location that 
> can be dynamically rebound (to a new storage location) on a per-thread 
> basis.
>

https://clojure.org/reference/special_forms says

Using def to modify the root value of a var at other than the top level is 
> usually an indication that you are using the var as a mutable global, and 
> is considered bad style. Consider either using binding to provide a 
> thread-local value for the var, or putting a ref or agent in the var and 
> using transactions or actions for mutation. 


Clojure encourages avoiding the use of vars as global thread-local storage, 
by restricting their use to dynamic binding only.

What is so bad about global thread-locals? It can't be the fact that they 
are global, as refs are typically made global. They also have a good 
thread-safe behavior.

Thanks,
Ernesto

-- 
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: Tentacles; Going Forward

2017-02-08 Thread Chas Emerick
I only became aware of this conversation yesterday; hopefully no one was 
looking for my reply earlier…

Anthony was a friend, but our project activity was quite separate. I think 
we had a couple of PRs on each other's projects, but that's about it. I 
don't think I have any particular authority in this area, either. In any 
case, I don't have any bandwidth atm for increasing my involvement in 
general-purpose OSS stuff.

I'd suggest that anyone with an important dependency on one of Anthony's 
projects push them forward independently. At least, don't wait for or rely 
upon other volunteers to coordinate these sorts of things. If there end up 
being multiple forks, etc., that'll work out over time. Especially if you 
represent a ~trusted organization (CircleCI being a reasonable example), 
and are accommodating of others' use cases within reason (i.e. act like a 
sane maintainer), then I suspect others will follow your lead.

The clojars/maven coordinate question is stickier. The clojars folks might 
have general policy, and maybe they've addressed this particular situation 
elsewhere. But, this is an excellent object lesson in how the 
organization/project-name convention is a *good thing*, in contrast to 
effectively single-level namespace coordinates like tentacles/tentacles. 
IMO, a com.circleci/tentacles artifact in clojars would be a far better 
direction; it puts multiple forks (if they end up being necessary) on equal 
footing, and properly reflects the divergence in maintenance.

Thanks for picking up where Anthony left off,

- Chas

On Thursday, January 26, 2017 at 7:41:46 PM UTC-5, Alex Miller wrote:
>
> I have no authority to speak on this, but I think it would be nice to see 
> a consensus fork managed by some one or ones with a vested interest in it. 
> (I also have used tentacles off and on.)
>
> Maybe another option would be to create a github org of some people that 
> can act as admins. I'd nominate Chas as someone to act in that capacity 
> given his relationship with raynes.
>

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