records alias with local vars

2019-08-28 Thread Brian Craft
In this example

(defrecord x [y])

(defn b [x] (.getBytes ^String x))


The compiler fails to resolve .getBytes. It emits reflection code, saying x 
is a class. It is resolved by deleting the defrecord, or renaming the 
parameter.

Is this expected, or documented? Are there other cases like this?

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


Re: Blocking behavior of >!! ?

2019-05-20 Thread Brian Beckman
Thanks everyone for your answers. I understand much better now. I just had 
to make up some words like "rendezvous" and "pseudothread" to help me piece 
together these implicit concepts.

On Sunday, May 19, 2019 at 10:33:07 AM UTC-7, Brian Beckman wrote:
>
> The documentation for >!! reads:
>
> -
> clojure.core.async/>!!
> ([port val])
>   puts a val into port. nil values are not allowed. Will block if no
>   buffer space is available. Returns true unless port is already closed.
>
>
> I have a case where I believe that the channel has no buffer, I park a 
> "pseudothread" in a go block reading off that channel via  (lexically, not temporally), put to the unbuffered channel via >!!:
>
> (let [c (chan) ;; NO BUFFER!
>   d (go (   e (>!! c 42)] ;; blocking write to c, will unpark c's pseudothread
> (println {:c-coughs-up '(this will hang (   :d-coughs-up (   :what's-ee})
> (close! c) (close! d))
>
> {:c-coughs-up (this will hang (
>
> This case leads me to wonder whether the documentation might read
>
>  >!! will block if there is no buffer space available *and* if there is 
> no *rendezvous *available, that is, no pseudothread parked waiting for 
> but it's more likely that I completely misunderstand core.async because I 
> just made up the notion of a pseudothread in my struggle to understand!
>
>
>
>

-- 
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/0b243161-9598-490e-ad81-93d53a76a21b%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Blocking behavior of >!! ?

2019-05-20 Thread Brian Beckman
Thanks, Thomas. I shouldn't have included the quoted code about (!! c 42) doesn't block. 

The following is an attempt to clarify my question. I first (go (!! c 42), 
and then (!! c 42) 
will block "if there is no buffer space available," and the documentation 
does not specify any other conditions. Well, I created c with no buffer 
space, so, (>!! c 42) must block unless something else "makes buffer space 
available," assuming the documentation is correct. The only other 
interaction with c that could possibly be alive at the time when I do (>!! 
c 42), is (go (!! c 42) 
should block because there is no buffer available. 

On Sunday, May 19, 2019 at 1:48:16 PM UTC-7, Thomas Heller wrote:
>
> ( by the first go (running in a different thread). So it is blocking until 
> something puts another value into c. Since nothing ever does your program 
> hangs.
>
> If it helps you can read "go" as "please run this somewhere else, possibly 
> at a different time" and let the current thread continue after the go.
>
> I can't explain this very well but the documentation aspect is accurate.
>
> On Sunday, May 19, 2019 at 7:33:07 PM UTC+2, Brian Beckman wrote:
>>
>> The documentation for >!! reads:
>>
>> -
>> clojure.core.async/>!!
>> ([port val])
>>   puts a val into port. nil values are not allowed. Will block if no
>>   buffer space is available. Returns true unless port is already closed.
>>
>>
>> I have a case where I believe that the channel has no buffer, I park a 
>> "pseudothread" in a go block reading off that channel via > (lexically, not temporally), put to the unbuffered channel via >!!:
>>
>> (let [c (chan) ;; NO BUFFER!
>>   d (go (>   e (>!! c 42)] ;; blocking write to c, will unpark c's pseudothread
>> (println {:c-coughs-up '(this will hang (>   :d-coughs-up (>   :what's-ee})
>> (close! c) (close! d))
>>
>> {:c-coughs-up (this will hang (>
>>
>> This case leads me to wonder whether the documentation might read
>>
>>  >!! will block if there is no buffer space available *and* if there is 
>> no *rendezvous *available, that is, no pseudothread parked waiting for > .
>>
>> but it's more likely that I completely misunderstand core.async because I 
>> just made up the notion of a pseudothread in my struggle to understand!
>>
>>
>>
>>

-- 
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/fe9fc48c-d651-434d-8743-0045438291f1%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Blocking behavior of >!! ?

2019-05-19 Thread Brian Beckman
The documentation for >!! reads:

-
clojure.core.async/>!!
([port val])
  puts a val into port. nil values are not allowed. Will block if no
  buffer space is available. Returns true unless port is already closed.


I have a case where I believe that the channel has no buffer, I park a 
"pseudothread" in a go block reading off that channel via !!:

(let [c (chan) ;; NO BUFFER!
  d (go (!! c 42)] ;; blocking write to c, will unpark c's pseudothread
(println {:c-coughs-up '(this will hang (!! will block if there is no buffer space available *and* if there is no 
*rendezvous *available, that is, no pseudothread parked waiting for 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/ef62965f-6132-4f18-9bb8-3d569f10dbdc%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: avoiding casts with aget & friends

2019-01-31 Thread Brian Craft
Is there any way to inspect what the jit does to it?

On Wednesday, January 30, 2019 at 10:07:38 PM UTC-8, Alex Miller wrote:
>
>
>
> On Wed, Jan 30, 2019 at 11:07 PM Brian Craft  > wrote:
>
>> With much experimentation, I ended up with this:
>>
>>   (let [a 1
>> b (.longValue ^Long (:foo {:foo 3}))
>> c (if (< a b) a b)])
>>
>> which seems to avoid the longCast call:
>>
>> Object o;
>> if (_thunk__0__ == (o = _thunk__0__.get(const__3))) {
>> o = (__thunk__0__ = 
>> __site__0__.fault(const__3)).get(const__3);
>> }
>> final long b = (long)o;
>> final long c = (a < b) ? a : b;
>>
>> I don't know if this is advisable. Does anyone do this?
>>
>
> No, I wouldn't do this. `long` can inline so it's going to be better (it's 
> also more likely to jit well as it's used other places and is likely hotter 
> in the jit).
>
> Going back to the original...
>
>   (let [a 1
> b (:foo {:foo 3})
> c (if (< a b) a b)])
>
> let will track primitives if possible.
> - a is going to be a primitive long. 
> - (:foo {:foo 3}) is going to (always) return an Object and it's best to 
> recognize that and make an explicit cast to a primitive long.
> - if a and b are both primitives, then < is able to inline a 
> long-primitive comparison (via Numbers.lt())
> - the if is going to return an Object though, so again you'll probably 
> want to type hint or cast c, but it's hard to know for sure without seeing 
> more code
>
> Without other info, I would probably start with 
>
>   (let [a 1
> b (long (:foo {:foo 3}))
> c (if (< a b) a b)])
>
> Or alternately, it might be better to just type hint b in the comparison 
> to avoid reboxing b, but hard to know without more context:
>
>   (let [a 1
> b (:foo {:foo 3})
> c (if (< a ^long b) a b)])
>
> Comparing the bytecode for these (skipping everything up through the 
> keyword lookup, which is same for all):
>
> Original:  Option 1:  
>Option 2:
> 45: astore_2   45: invokestatic  #41   45: 
> astore_2  
> 46: lload_0 48: lstore_2  
>46: lload_0
> 47: aload_249: lload_0
>   47: aload_2
> 48: invokestatic  #41  50: lload_2  
> 48: checkcast #37
> 51: ifeq  62 51: lcmp  
> 51: invokestatic  #43
> 54: lload_0 52: ifge  60  
> 54: lcmp
> 55: invokestatic  #45  55: lload_0  
> 55: ifge  66
> 58: goto  6556: goto  61  
>   58: lload_0
> 61: pop   59: pop  
>  59: invokestatic  #49
> 62: aload_260: lload_2
>   62: goto  69
> 63: aconst_null   61: lstore4  
>  65: pop
> 64: astore_2   63: lload 4
>66: aload_2
> 65: astore_3   65: invokestatic  #47   67: 
> aconst_null
> 66: aload_3
> 68: astore_2
> 67: aconst_null
>69: astore_3
> 68: astore_3  
>  70: aload_3
>   
>  71: aconst_null
>   
>  72: astore_3
>
> Option 1 does an lstore/lload (long) instead of an astore/lstore (object). 
> Both options use lcmp which is likely the fastest path to compare longs. 
> I've omitted some info here to make these fit, but Original line 48 will 
> invoke Numbers.lt:(JLjava/lang/Object;)Z which is the Numbers.lt(long, 
> Object) - lcmp is definitely going to be preferable to this. Also of 
> importance is that in Option 1, both a and b are stored as longs and loaded 
> as longs so if there is subsequent stuff to do on them, they can avoid 
> boxing (this is also betrayed by the shorter length from fewer casts).
>
> Your longValue one is like Option 1, but starts:
>
>   45: checkcast #37  

Re: avoiding casts with aget & friends

2019-01-30 Thread Brian Craft
With much experimentation, I ended up with this:

  (let [a 1
b (.longValue ^Long (:foo {:foo 3}))
c (if (< a b) a b)])

which seems to avoid the longCast call:

Object o;
if (_thunk__0__ == (o = _thunk__0__.get(const__3))) {
o = (__thunk__0__ = __site__0__.fault(const__3)).get(const__3);
}
final long b = (long)o;
final long c = (a < b) ? a : b;

I don't know if this is advisable. Does anyone do this?

Also just noted this is another case where explicitly calling something 
seems to make it disappear. :-p

On Wednesday, January 30, 2019 at 8:41:49 PM UTC-8, Brian Craft wrote:
>
> The full context is large. But, for example, in this code:
>
>   (let [a 1
> b (:foo {:foo 3})
> c (if (< a b) a b)])
>
> b and c are Object (if the disassembly is to be believed) which leads to 
> casts where c is used later. Also, the compare is calling Numbers.lt, which 
> is going to do a bunch of casting & dispatch.
>
> Adding a :long hint on b, b is still Object, and the compare becomes
>
> if (a < RT.longCast(b)) {
> num = Numbers.num(a);
> }
>
> with a long cast that doesn't seem necessary. Also, c is still Object.
>
> Casting the lookup to long, like (long (:foo {:foo 3})), b and c are now 
> long, but there's now a cast on the return of the lookup
>
> Object x;
> if (_thunk__0__ == (x = _thunk__0__.get(const__4))) {
> x = (__thunk__0__ = __site__0__.fault(const__4)).get(const__4);
> }
> final long b = RT.longCast(x);
> final long c = (a < b) ? a : b;
>
> which is going to hit the RT.longCast(Object) method, and start probing 
> for the class so it can pick a method.
>
>
> On Wednesday, January 30, 2019 at 6:58:07 PM UTC-8, Alex Miller wrote:
>>
>> It would really help to see a full function of code context. From that I 
>> could probably talk a little more about what I would expect the compiler to 
>> understand and how you might be able to influence it.
>>
>> On Wed, Jan 30, 2019 at 8:50 PM Brian Craft  wrote:
>>
>>> If there is unnecessary casting or boxing, how do you avoid it? hinting 
>>> and casting affect it, but not in ways I understand, or can predict.
>>>
>>> On Wednesday, January 30, 2019 at 6:06:37 PM UTC-8, Alex Miller wrote:
>>>>
>>>> Sometimes the insertion of profiling instrumentation magnifies the cost 
>>>> of things in a hot loop or provides misleading hot spot info. If you're 
>>>> using a tracing profiler, you might try sampling instead as it's less 
>>>> prone 
>>>> to this.
>>>>
>>>> Or, this sounds silly, but you can manually sample by just doing a few 
>>>> thread dumps while it's running (either ctrl-\ or externally with kill -3) 
>>>> and see what's at the top. If there really is a hot spot, this is a 
>>>> surprisingly effective way to see it.
>>>>
>>>> For this kind of code, there is no substitute for actually reading the 
>>>> bytecode and thinking carefully about where there is unnecessary casting 
>>>> or 
>>>> boxing.
>>>>
>>>>
>>>>
>>>> On Wed, Jan 30, 2019 at 6:55 PM Brian Craft  wrote:
>>>>
>>>>> I haven't tried much. I'm getting the java 
>>>>> via clj-java-decompiler.core 'decompile' macro.
>>>>>
>>>>> A long cast does drop the cast (which is really counter-intuitive: 
>>>>> explicitly invoke 'long', which calls longCast, in order to avoid calling 
>>>>> longCast).
>>>>>
>>>>> Amusingly this doesn't reduce the total run-time, though longCast 
>>>>> drops out of the hotspot list. :-p There must be some other limiting step 
>>>>> that I'm missing in the profiler.
>>>>>
>>>>> I'm calling it around 1.2M times, so hopefully that engages the jit.
>>>>>
>>>>> On Wednesday, January 30, 2019 at 3:39:41 PM UTC-8, Alex Miller wrote:
>>>>>>
>>>>>> What have you tried? And how are you getting that Java? I would 
>>>>>> prefer to look at bytecode (via javap) to verify what you're saying. 
>>>>>>
>>>>>> Have you tried an explicit long cast?
>>>>>>
>>>>>> (aget flat-dict (bit-and 0xff (long (aget arr j
>>>>>>
>>>>>> Are you running this hot en

Re: avoiding casts with aget & friends

2019-01-30 Thread Brian Craft
The full context is large. But, for example, in this code:

  (let [a 1
b (:foo {:foo 3})
c (if (< a b) a b)])

b and c are Object (if the disassembly is to be believed) which leads to 
casts where c is used later. Also, the compare is calling Numbers.lt, which 
is going to do a bunch of casting & dispatch.

Adding a :long hint on b, b is still Object, and the compare becomes

if (a < RT.longCast(b)) {
num = Numbers.num(a);
}

with a long cast that doesn't seem necessary. Also, c is still Object.

Casting the lookup to long, like (long (:foo {:foo 3})), b and c are now 
long, but there's now a cast on the return of the lookup

Object x;
if (_thunk__0__ == (x = _thunk__0__.get(const__4))) {
x = (__thunk__0__ = __site__0__.fault(const__4)).get(const__4);
}
final long b = RT.longCast(x);
final long c = (a < b) ? a : b;

which is going to hit the RT.longCast(Object) method, and start probing for 
the class so it can pick a method.


On Wednesday, January 30, 2019 at 6:58:07 PM UTC-8, Alex Miller wrote:
>
> It would really help to see a full function of code context. From that I 
> could probably talk a little more about what I would expect the compiler to 
> understand and how you might be able to influence it.
>
> On Wed, Jan 30, 2019 at 8:50 PM Brian Craft  > wrote:
>
>> If there is unnecessary casting or boxing, how do you avoid it? hinting 
>> and casting affect it, but not in ways I understand, or can predict.
>>
>> On Wednesday, January 30, 2019 at 6:06:37 PM UTC-8, Alex Miller wrote:
>>>
>>> Sometimes the insertion of profiling instrumentation magnifies the cost 
>>> of things in a hot loop or provides misleading hot spot info. If you're 
>>> using a tracing profiler, you might try sampling instead as it's less prone 
>>> to this.
>>>
>>> Or, this sounds silly, but you can manually sample by just doing a few 
>>> thread dumps while it's running (either ctrl-\ or externally with kill -3) 
>>> and see what's at the top. If there really is a hot spot, this is a 
>>> surprisingly effective way to see it.
>>>
>>> For this kind of code, there is no substitute for actually reading the 
>>> bytecode and thinking carefully about where there is unnecessary casting or 
>>> boxing.
>>>
>>>
>>>
>>> On Wed, Jan 30, 2019 at 6:55 PM Brian Craft  wrote:
>>>
>>>> I haven't tried much. I'm getting the java via clj-java-decompiler.core 
>>>> 'decompile' macro.
>>>>
>>>> A long cast does drop the cast (which is really counter-intuitive: 
>>>> explicitly invoke 'long', which calls longCast, in order to avoid calling 
>>>> longCast).
>>>>
>>>> Amusingly this doesn't reduce the total run-time, though longCast drops 
>>>> out of the hotspot list. :-p There must be some other limiting step that 
>>>> I'm missing in the profiler.
>>>>
>>>> I'm calling it around 1.2M times, so hopefully that engages the jit.
>>>>
>>>> On Wednesday, January 30, 2019 at 3:39:41 PM UTC-8, Alex Miller wrote:
>>>>>
>>>>> What have you tried? And how are you getting that Java? I would prefer 
>>>>> to look at bytecode (via javap) to verify what you're saying. 
>>>>>
>>>>> Have you tried an explicit long cast?
>>>>>
>>>>> (aget flat-dict (bit-and 0xff (long (aget arr j
>>>>>
>>>>> Are you running this hot enough for the JIT to kick in? Usually this 
>>>>> is the kind of thing it's good at, but it might take 10k invocations 
>>>>> before 
>>>>> it does.
>>>>>
>>>>>
>>>>> On Wednesday, January 30, 2019 at 4:03:43 PM UTC-6, Brian Craft wrote:
>>>>>>
>>>>>> Profiling is showing a lot of time spent in RT.longCast, in places 
>>>>>> like this:
>>>>>>
>>>>>> (aget flat-dict (bit-and 0xff (aget arr j)))
>>>>>>
>>>>>> arr is hinted as ^bytes, and flat-dict as ^objects.
>>>>>>
>>>>>> which compiles to this:
>>>>>>
>>>>>> Object code2 = RT.aget((Object[])flat_dict, RT.intCast(0xFFL & 
>>>>>> RT.longCast((Object)RT.aget((byte[])arr2, RT.intCast(k)
>>>>>>
>>>>>> Is there any way to avoid that RT.longCast? There is 

Re: avoiding casts with aget & friends

2019-01-30 Thread Brian Craft
If there is unnecessary casting or boxing, how do you avoid it? hinting and 
casting affect it, but not in ways I understand, or can predict.

On Wednesday, January 30, 2019 at 6:06:37 PM UTC-8, Alex Miller wrote:
>
> Sometimes the insertion of profiling instrumentation magnifies the cost of 
> things in a hot loop or provides misleading hot spot info. If you're using 
> a tracing profiler, you might try sampling instead as it's less prone to 
> this.
>
> Or, this sounds silly, but you can manually sample by just doing a few 
> thread dumps while it's running (either ctrl-\ or externally with kill -3) 
> and see what's at the top. If there really is a hot spot, this is a 
> surprisingly effective way to see it.
>
> For this kind of code, there is no substitute for actually reading the 
> bytecode and thinking carefully about where there is unnecessary casting or 
> boxing.
>
>
>
> On Wed, Jan 30, 2019 at 6:55 PM Brian Craft  > wrote:
>
>> I haven't tried much. I'm getting the java via clj-java-decompiler.core 
>> 'decompile' macro.
>>
>> A long cast does drop the cast (which is really counter-intuitive: 
>> explicitly invoke 'long', which calls longCast, in order to avoid calling 
>> longCast).
>>
>> Amusingly this doesn't reduce the total run-time, though longCast drops 
>> out of the hotspot list. :-p There must be some other limiting step that 
>> I'm missing in the profiler.
>>
>> I'm calling it around 1.2M times, so hopefully that engages the jit.
>>
>> On Wednesday, January 30, 2019 at 3:39:41 PM UTC-8, Alex Miller wrote:
>>>
>>> What have you tried? And how are you getting that Java? I would prefer 
>>> to look at bytecode (via javap) to verify what you're saying. 
>>>
>>> Have you tried an explicit long cast?
>>>
>>> (aget flat-dict (bit-and 0xff (long (aget arr j
>>>
>>> Are you running this hot enough for the JIT to kick in? Usually this is 
>>> the kind of thing it's good at, but it might take 10k invocations before it 
>>> does.
>>>
>>>
>>> On Wednesday, January 30, 2019 at 4:03:43 PM UTC-6, Brian Craft wrote:
>>>>
>>>> Profiling is showing a lot of time spent in RT.longCast, in places like 
>>>> this:
>>>>
>>>> (aget flat-dict (bit-and 0xff (aget arr j)))
>>>>
>>>> arr is hinted as ^bytes, and flat-dict as ^objects.
>>>>
>>>> which compiles to this:
>>>>
>>>> Object code2 = RT.aget((Object[])flat_dict, RT.intCast(0xFFL & 
>>>> RT.longCast((Object)RT.aget((byte[])arr2, RT.intCast(k)
>>>>
>>>> Is there any way to avoid that RT.longCast? There is an aget method in 
>>>> RT.java that returns a byte, and a longCast for byte, but I suspect the 
>>>> cast to Object is causing it to hit the longCast for Object, which does a 
>>>> bunch of reflection.
>>>>
>>> -- 
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to clo...@googlegroups.com 
>> 
>> Note that posts from new members are moderated - please be patient with 
>> your first post.
>> To unsubscribe from this group, send email to
>> clojure+u...@googlegroups.com 
>> For more options, visit this group at
>> http://groups.google.com/group/clojure?hl=en
>> --- 
>> You received this message because you are subscribed to a topic in the 
>> Google Groups "Clojure" group.
>> To unsubscribe from this topic, visit 
>> https://groups.google.com/d/topic/clojure/vXJFuOujTaw/unsubscribe.
>> To unsubscribe from this group and all its topics, send an email to 
>> clojure+u...@googlegroups.com .
>> For more options, visit https://groups.google.com/d/optout.
>>
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to 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: avoiding casts with aget & friends

2019-01-30 Thread Brian Craft
I haven't tried much. I'm getting the java via clj-java-decompiler.core 
'decompile' macro.

A long cast does drop the cast (which is really counter-intuitive: 
explicitly invoke 'long', which calls longCast, in order to avoid calling 
longCast).

Amusingly this doesn't reduce the total run-time, though longCast drops out 
of the hotspot list. :-p There must be some other limiting step that I'm 
missing in the profiler.

I'm calling it around 1.2M times, so hopefully that engages the jit.

On Wednesday, January 30, 2019 at 3:39:41 PM UTC-8, Alex Miller wrote:
>
> What have you tried? And how are you getting that Java? I would prefer to 
> look at bytecode (via javap) to verify what you're saying. 
>
> Have you tried an explicit long cast?
>
> (aget flat-dict (bit-and 0xff (long (aget arr j
>
> Are you running this hot enough for the JIT to kick in? Usually this is 
> the kind of thing it's good at, but it might take 10k invocations before it 
> does.
>
>
> On Wednesday, January 30, 2019 at 4:03:43 PM UTC-6, Brian Craft wrote:
>>
>> Profiling is showing a lot of time spent in RT.longCast, in places like 
>> this:
>>
>> (aget flat-dict (bit-and 0xff (aget arr j)))
>>
>> arr is hinted as ^bytes, and flat-dict as ^objects.
>>
>> which compiles to this:
>>
>> Object code2 = RT.aget((Object[])flat_dict, RT.intCast(0xFFL & 
>> RT.longCast((Object)RT.aget((byte[])arr2, RT.intCast(k)
>>
>> Is there any way to avoid that RT.longCast? There is an aget method in 
>> RT.java that returns a byte, and a longCast for byte, but I suspect the 
>> cast to Object is causing it to hit the longCast for Object, which does a 
>> bunch of reflection.
>>
>

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


avoiding casts with aget & friends

2019-01-30 Thread Brian Craft
Profiling is showing a lot of time spent in RT.longCast, in places like 
this:

(aget flat-dict (bit-and 0xff (aget arr j)))

arr is hinted as ^bytes, and flat-dict as ^objects.

which compiles to this:

Object code2 = RT.aget((Object[])flat_dict, RT.intCast(0xFFL & 
RT.longCast((Object)RT.aget((byte[])arr2, RT.intCast(k)

Is there any way to avoid that RT.longCast? There is an aget method in 
RT.java that returns a byte, and a longCast for byte, but I suspect the 
cast to Object is causing it to hit the longCast for Object, which does a 
bunch of reflection.

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


partition & fold

2019-01-26 Thread Brian Craft
Still trying to understand reducers & transducers. Is the difference 
between r/folder and r/reducer the parallelization?

Anyone know what this error is about?

(r/foldcat (r/map #(apply + %) (r/folder (into [] (range 1000)) 
(partition-all 5

ArrayIndexOutOfBoundsException 47427  java.util.ArrayList.add 
(ArrayList.java:459)

Is this error to do with partition-all being stateful?

This works as expected, with reducer instead of folder:

(r/foldcat (r/map #(apply + %) (r/reducer (into [] (range 1000)) 
(partition-all 5  ; XXX large output


Is there some way to express "map over partitions, in parallel, without 
creating an intermediate collection" with reducers and transducers?

-- 
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: r/fold combinef and reducef init values

2019-01-26 Thread Brian Craft
hey Sean -- The ones on the reducers reference page:

https://clojure.org/reference/reducers

On Friday, January 25, 2019 at 4:05:12 PM UTC-8, Sean Corfield wrote:

> Which docs are you reading? The docstring for r/fold says this – with no 
> indication of calling (reducef) with no arguments (well, unless you do not 
> supply combinef – in which case reducef will be used for that, so (reducef) 
> would be called to seed the reductions):
>
>  
>
> "Reduces a collection using a (potentially parallel) reduce-combine
>
>   strategy. The collection is partitioned into groups of approximately
>
>   n (default 512), each of which is reduced with reducef (with a seed
>
>   value obtained by calling (combinef) with no arguments). The results
>
>   of these reductions are then reduced with combinef (default
>
>   reducef). combinef must be associative, and, when called with no
>
>   arguments, (combinef) must produce its identity element. These
>
>   operations may be performed in parallel, but the results will
>
>   preserve order."
>
>  
>
> Sean Corfield -- (970) FOR-SEAN -- (904) 302-SEAN
> An Architect's View -- http://corfield.org/
>
> "If you're not annoying somebody, you're not really alive."
> -- Margaret Atwood
>
>  
>
> *From: *Brian Craft 
> *Sent: *Friday, January 25, 2019 3:36 PM
> *Subject: *r/fold combinef and reducef init values
>
>  
>
> From the docs: 
>
>  
>
> r/fold takes a reducible collection and partitions it into groups of 
> approximately n (default 512) elements. Each group is reduced using the 
> reducef function. The reducef function will be called with no arguments to 
> produce an identity value in each partition. The results of those 
> reductions are then reduced with the combinef (defaults to reducef) 
> function. When called with no arguments, (combinef) must produce its 
> identity element - this will be called multiple times. Operations may be 
> performed in parallel. Results will preserve order.
>
>  
>
> So, this seems to say r/fold will partition the collection and reduce each 
> partition using the (reducef) as the init value.
>
>  
>
> Then, all these intermediate results will be reduced with combinef, using 
> (combinef) as the init value.
>
>  
>
> However, in test it seems (reducef) is never called, and (combinef) is 
> used as the init value for calls to reducef.
>
>  
>
>   (defn combinef
>
> ([] {:combine :f})
>
> ([acc v] acc))
>
>  
>
>   (defn reducef
>
> ([] {:reduce :f})
>
> ([acc v]
>
>  (println "acc" acc "v" v)
>
>  v))
>
>  
>
>   (clojure.core.reducers/fold combinef reducef ["foo" "bar"])
>
>  
>
> ; outputs:
>
> acc {:combine :f} v foo
>
> acc foo v bar
>
> "bar"
>
>  
>
> The accumulator in reducef is the init value from combinef, not the init 
> value from reducef.
>
>  
>
> What's going on?
>
> -- 
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@googlegroups.com 
> Note that posts from new members are moderated - please be patient with 
> your first post.
> To unsubscribe from this group, send email to
> clojure+u...@googlegroups.com 
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> --- 
> You received this message because you are subscribed to the Google Groups 
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to clojure+u...@googlegroups.com .
> For more options, visit https://groups.google.com/d/optout.
>
>  
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to 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: r/fold combinef and reducef init values

2019-01-25 Thread Brian Craft
Looks like it's something that's changed over different clojure releases.

On Friday, January 25, 2019 at 3:35:58 PM UTC-8, Brian Craft wrote:
>
> From the docs:
>
> r/fold takes a reducible collection and partitions it into groups of 
> approximately n (default 512) elements. Each group is reduced using the 
> reducef function. The reducef function will be called with no arguments to 
> produce an identity value in each partition. The results of those 
> reductions are then reduced with the combinef (defaults to reducef) 
> function. When called with no arguments, (combinef) must produce its 
> identity element - this will be called multiple times. Operations may be 
> performed in parallel. Results will preserve order.
>
> So, this seems to say r/fold will partition the collection and reduce each 
> partition using the (reducef) as the init value.
>
> Then, all these intermediate results will be reduced with combinef, using 
> (combinef) as the init value.
>
> However, in test it seems (reducef) is never called, and (combinef) is 
> used as the init value for calls to reducef.
>
>   (defn combinef
> ([] {:combine :f})
> ([acc v] acc))
>
>   (defn reducef
> ([] {:reduce :f})
> ([acc v]
>  (println "acc" acc "v" v)
>  v))
>
>   (clojure.core.reducers/fold combinef reducef ["foo" "bar"])
>
> ; outputs:
> acc {:combine :f} v foo
> acc foo v bar
> "bar"
>
> The accumulator in reducef is the init value from combinef, not the init 
> value from reducef.
>
> What's going on?
>

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


r/fold combinef and reducef init values

2019-01-25 Thread Brian Craft
>From the docs:

r/fold takes a reducible collection and partitions it into groups of 
approximately n (default 512) elements. Each group is reduced using the 
reducef function. The reducef function will be called with no arguments to 
produce an identity value in each partition. The results of those 
reductions are then reduced with the combinef (defaults to reducef) 
function. When called with no arguments, (combinef) must produce its 
identity element - this will be called multiple times. Operations may be 
performed in parallel. Results will preserve order.

So, this seems to say r/fold will partition the collection and reduce each 
partition using the (reducef) as the init value.

Then, all these intermediate results will be reduced with combinef, using 
(combinef) as the init value.

However, in test it seems (reducef) is never called, and (combinef) is used 
as the init value for calls to reducef.

  (defn combinef
([] {:combine :f})
([acc v] acc))

  (defn reducef
([] {:reduce :f})
([acc v]
 (println "acc" acc "v" v)
 v))

  (clojure.core.reducers/fold combinef reducef ["foo" "bar"])

; outputs:
acc {:combine :f} v foo
acc foo v bar
"bar"

The accumulator in reducef is the init value from combinef, not the init 
value from reducef.

What's going on?

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


transducer parallelism

2019-01-25 Thread Brian Craft
Are there any docs on transducer parallelism? I had the impression, from 
various sources, that they could operate in parallel, but in doing some 
benchmarks over a largish collection (counting character frequencies in 
1.3M strings), transduce never uses more than one thread. Is this expected? 
If not, how would one debug it?

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


undocumented one-argument call of reducer

2019-01-25 Thread Brian Craft
The transducers doc suggests transduce works with standard reducing 
functions, but then transduce makes a one-argument call to the function.

The code docs for transduce say the reducing function must support a 
one-argument call, but don't give any information about what that call 
should do.

It could be helpful to document this requirement, especially since the 
examples are all written with "+", which is rather misleading since it's 
not a standard reducing function with respect to its arity, and there is 
this unusual requirement on the arity of the function.

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


removing trailing zeros in floating point formatting

2018-07-26 Thread Brian Craft
Probably more of a java question, but I'm finding that floating point 
formats with (format) are inflating data sizes enormously with meaningless 
trailing zeros, because the underlying java conversion methods don't work 
as they do on other platforms.

E.g., in C
printf("%.6g %.6g %.6g %.6g\n", 0.01, 100.1, 10.0, 100.0)

gives
1e-06 100 10 1e+06

in python:

>>> "%.6g %.6g %.6g %.6g" % (0.01, 100.1, 10.0, 100.0)
'1e-06 100 10 1e+06'



while clojure will produce this:

> (format "%.6g %.6g %.6g %.6g" 0.01, 100.1, 10.0, 100.0)
"1.0e-06 100.000 10 1.0e+06"

The desired behavior is to set the max significant digits & get the minimal 
decimal representation. I've been through docs for Formatter, NumberFormat, 
and others, but can't find anything that both 1) supports setting 
significant digits (vs. fractional digits), and 2) doesn't pad meaningless 
zeros on the end.

Is there a standard solution?

-- 
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: D&D + Clojure?

2018-04-05 Thread Brian
I'm interested.

For my own uses I would be curious to see how difficult it would be to
update (degrade? retrograde? :) ) to 3.5/Pathfinder.


On Thu, Apr 5, 2018 at 11:04 AM, Davide Taviani  wrote:

> Hey!
> I'm a DM, a user of OrcPub2 and a full-time clojure + cljs developer (for
> data science stuff).
> I'm definitely interested, let me know!
> Also, I play with another colleague, so there's definitely a few more D&D
> + Clojure nerds out there.
>
> Davide
>
>
> On Tuesday, March 27, 2018 at 11:12:25 PM UTC+3, Larry Christensen wrote:
>>
>> I have a Dungeons & Dragons app built in Clojure and ClojureScript. With The
>> Original OrcPub  and The New OrcPub
>>  I have about 300K monthly users and have been
>> used by millions of people over the past few years. I'm looking for people
>> who might want to contribute to building some cool features for a fun app!
>>
>> -Larry Christensen a.k.a RedOrc
>> Supreme Leader
>> OrcPub
>>
>> --
> 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.async consumer + producer working by chunk?

2018-01-06 Thread Brian J. Rubinton
https://dev.clojure.org/jira/browse/ASYNC-210 
<https://dev.clojure.org/jira/browse/ASYNC-210>

> On Jan 6, 2018, at 12:11 PM, Brian J. Rubinton  
> wrote:
> 
> Thanks! I will. Just signed the CA.
> 
> 
> On Sat, Jan 6, 2018, 12:10 PM Alex Miller  <mailto:a...@puredanger.com>> wrote:
> 
> 
> On Saturday, January 6, 2018 at 10:56:06 AM UTC-6, Brian J. Rubinton wrote:
> Alex - it makes sense to me that the buffer temporarily expands beyond its 
> normal size with the content of the expanding transducer. What does not make 
> sense to me is the buffer also accepts puts even though its buffer is full.
> 
> Why would the take! process puts when the channel's buffer is full?
> 
> I was experimenting with the implementation and I think the patch in this 
> gist leads to more intuitive behavior — though it’s possible it breaks 
> something else. 
> https://gist.github.com/brianru/d30f0319e7a14d875a80762937cccb9c 
> <https://gist.github.com/brianru/d30f0319e7a14d875a80762937cccb9c>
> 
> Possibly, feel free to file a ticket and I will take a closer look.
>  
> 
> -- 
> 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 
> <mailto: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 
> <mailto:clojure%2bunsubscr...@googlegroups.com>
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en 
> <http://groups.google.com/group/clojure?hl=en>
> --- 
> You received this message because you are subscribed to the Google Groups 
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to clojure+unsubscr...@googlegroups.com 
> <mailto:clojure+unsubscr...@googlegroups.com>.
> For more options, visit https://groups.google.com/d/optout 
> <https://groups.google.com/d/optout>.

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


Re: core.async consumer + producer working by chunk?

2018-01-06 Thread Brian J. Rubinton
Thanks! I will. Just signed the CA.

On Sat, Jan 6, 2018, 12:10 PM Alex Miller  wrote:

>
>
> On Saturday, January 6, 2018 at 10:56:06 AM UTC-6, Brian J. Rubinton wrote:
>>
>> Alex - it makes sense to me that the buffer temporarily expands beyond
>> its normal size with the content of the expanding transducer. What does not
>> make sense to me is the buffer also accepts puts even though its buffer is
>> full.
>>
>> Why would the take! process puts when the channel's buffer is full?
>>
>> I was experimenting with the implementation and I think the patch in this
>> gist leads to more intuitive behavior — though it’s possible it breaks
>> something else.
>> https://gist.github.com/brianru/d30f0319e7a14d875a80762937cccb9c
>>
>
> Possibly, feel free to file a ticket and I will take a closer look.
>
>
> --
> 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.async consumer + producer working by chunk?

2018-01-06 Thread Brian J. Rubinton
Typo — I meant to say the channel executes puts during a take! even though the 
buffer is full before executing the puts. This is clearer in code (please see 
the gist).

> On Jan 6, 2018, at 11:55 AM, Brian J. Rubinton  
> wrote:
> 
> Alex - it makes sense to me that the buffer temporarily expands beyond its 
> normal size with the content of the expanding transducer. What does not make 
> sense to me is the buffer also accepts puts even though its buffer is full.
> 
> Why would the take! process puts when the channel's buffer is full?
> 
> I was experimenting with the implementation and I think the patch in this 
> gist leads to more intuitive behavior — though it’s possible it breaks 
> something else. 
> https://gist.github.com/brianru/d30f0319e7a14d875a80762937cccb9c 
> <https://gist.github.com/brianru/d30f0319e7a14d875a80762937cccb9c>
> 
> 
> 
>> On Jan 6, 2018, at 11:43 AM, Alex Miller > <mailto:a...@puredanger.com>> wrote:
>> 
>> 
>> 
>> On Saturday, January 6, 2018 at 10:27:20 AM UTC-6, Rob Nikander wrote:
>> 
>> On Jan 5, 2018, at 8:01 PM, Gary Verhaegen > wrote:
>> What about simply having the producer put items one by one on the channel?
>> 
>> I will do that. My current producer is doing too many other things, but if I 
>> break it up into separate threads or go blocks for each work queue, then 
>> that should work. Thank you.
>>  
>> 
>> On Saturday, January 6, 2018 at 8:22:34 AM UTC-5, Brian J. Rubinton wrote:
>> I think the behavior in our examples differ because the blocking puts will 
>> complete whenever there is a take and the buffer is not full, ignoring 
>> whether the transducer is still outputting values. This bug may be relevant, 
>> though there it arises in a less common scenario (fixed buffer of size 0, 
>> which is now disallowed) https://dev.clojure.org/jira/browse/ASYNC-140 
>> <https://www.google.com/url?q=https%3A%2F%2Fdev.clojure.org%2Fjira%2Fbrowse%2FASYNC-140&sa=D&sntz=1&usg=AFQjCNE8iUd6leBDWTq5mesMFvpziQvA3w>
>> 
>> So, should I report this as a bug? If you have channel with a buffer and a 
>> (mapcat identity) transducer, the number of items in the channel can grow 
>> without bound. I thought channels were supposed to prevent that.
>> 
>> This is by design. Because the transducer executes in the channel, it's 
>> possible for it to temporarily expand the buffer beyond its normal size. 
>> This is certainly something to be aware of when using an expanding 
>> transducer (mapcat is probably the most common case).
>> 
>> -- 
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to clojure@googlegroups.com 
>> <mailto: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 
>> <mailto:clojure+unsubscr...@googlegroups.com>
>> For more options, visit this group at
>> http://groups.google.com/group/clojure?hl=en 
>> <http://groups.google.com/group/clojure?hl=en>
>> --- 
>> You received this message because you are subscribed to the Google Groups 
>> "Clojure" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to clojure+unsubscr...@googlegroups.com 
>> <mailto:clojure+unsubscr...@googlegroups.com>.
>> For more options, visit https://groups.google.com/d/optout 
>> <https://groups.google.com/d/optout>.
> 

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


Re: core.async consumer + producer working by chunk?

2018-01-06 Thread Brian J. Rubinton
Alex - it makes sense to me that the buffer temporarily expands beyond its 
normal size with the content of the expanding transducer. What does not make 
sense to me is the buffer also accepts puts even though its buffer is full.

Why would the take! process puts when the channel's buffer is full?

I was experimenting with the implementation and I think the patch in this gist 
leads to more intuitive behavior — though it’s possible it breaks something 
else. https://gist.github.com/brianru/d30f0319e7a14d875a80762937cccb9c 
<https://gist.github.com/brianru/d30f0319e7a14d875a80762937cccb9c>



> On Jan 6, 2018, at 11:43 AM, Alex Miller  wrote:
> 
> 
> 
> On Saturday, January 6, 2018 at 10:27:20 AM UTC-6, Rob Nikander wrote:
> 
> On Jan 5, 2018, at 8:01 PM, Gary Verhaegen > wrote:
> What about simply having the producer put items one by one on the channel?
> 
> I will do that. My current producer is doing too many other things, but if I 
> break it up into separate threads or go blocks for each work queue, then that 
> should work. Thank you.
>  
> 
> On Saturday, January 6, 2018 at 8:22:34 AM UTC-5, Brian J. Rubinton wrote:
> I think the behavior in our examples differ because the blocking puts will 
> complete whenever there is a take and the buffer is not full, ignoring 
> whether the transducer is still outputting values. This bug may be relevant, 
> though there it arises in a less common scenario (fixed buffer of size 0, 
> which is now disallowed) https://dev.clojure.org/jira/browse/ASYNC-140 
> <https://www.google.com/url?q=https%3A%2F%2Fdev.clojure.org%2Fjira%2Fbrowse%2FASYNC-140&sa=D&sntz=1&usg=AFQjCNE8iUd6leBDWTq5mesMFvpziQvA3w>
> 
> So, should I report this as a bug? If you have channel with a buffer and a 
> (mapcat identity) transducer, the number of items in the channel can grow 
> without bound. I thought channels were supposed to prevent that.
> 
> This is by design. Because the transducer executes in the channel, it's 
> possible for it to temporarily expand the buffer beyond its normal size. This 
> is certainly something to be aware of when using an expanding transducer 
> (mapcat is probably the most common case).
> 
> -- 
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en 
> <http://groups.google.com/group/clojure?hl=en>
> --- 
> You received this message because you are subscribed to the Google Groups 
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to clojure+unsubscr...@googlegroups.com 
> <mailto:clojure+unsubscr...@googlegroups.com>.
> For more options, visit https://groups.google.com/d/optout 
> <https://groups.google.com/d/optout>.

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


Re: core.async consumer + producer working by chunk?

2018-01-06 Thread Brian J. Rubinton
Rob - I’d go with Gary's approach, which essentially moves the splitting up of 
the chunk of results from the core.async channel’s transducer to the producing 
function. You can do that using a channel with a fixed buffer of 50 and >!!. As 
long as the next db query is blocked until each of the results from the 
previous query are put onto the channel it’ll work as you want.

I think the behavior in our examples differ because the blocking puts will 
complete whenever there is a take and the buffer is not full, ignoring whether 
the transducer is still outputting values. This bug may be relevant, though 
there it arises in a less common scenario (fixed buffer of size 0, which is now 
disallowed) https://dev.clojure.org/jira/browse/ASYNC-140 


> On Jan 5, 2018, at 8:01 PM, Gary Verhaegen  wrote:
> 
> On 5 January 2018 at 19:44, Rob Nikander  > wrote:
> Hi,
> 
> I’m wondering if there is a core.async design idiom for this situation...
> 
> - A buffered channel 
> - One producer feeding it 
> - A bunch of consumers pulling from it.
> - Producer should wake up and fill the channel only when it’s empty. In other 
> words, the producer should work in chunks.
> 
> My first idea is to have two channels. The second will be used by consumers 
> to signal the producer that the primary channel is empty. But I'm wondering 
> if there is a better way.
> 
> The motive for this is that the producer is doing a DB query that is more 
> efficient in bulk. `select ... limit 50` rather than `select ... limit 1` 50 
> times.
> 
> Rob
> 
> What about simply having the producer put items one by one on the channel?
> 
> (ns t.core
>   (:require [clojure.core.async :as async]))
> 
> (defn ap
>   "atomic print"
>   [m]
>   (print (str (pr-str m) "\n")))
> 
> (defn produce-next-batch
>   [s]
>   (let [m (+ s 10)]
> [(range s m) m]))
> 
> (defn chunked-producer
>   [init-state]
>   (let [result-chan (async/chan)]
> (async/go
>   (loop [[batch cursor] (produce-next-batch init-state)]
> (ap {:produced batch})
> (doseq [elem batch]
>   (async/>! result-chan elem))
> (recur (produce-next-batch cursor
> result-chan))
> 
> (defn run-consumer
>   [ch id n]
>   (async/go
> (dotimes [_ n]
>   (ap {:id id :received (async/   (async/ 
> (defn run
>   []
>   (let [c (chunked-producer 0)
> c1 (run-consumer c 1 10)
> c2 (run-consumer c 2 10)
> c3 (run-consumer c 3 10)]
> (->> [c1 c2 c3]
>  (mapv async/ (flush)))
> Here produce-next-batch has been deliberately written to evoke the idea that 
> you have some sort of state or cursor that lets you produce the next batch. 
> Real code would obviously need to account for exceptions, handle channel 
> closing, etc., but hopefully this illustrate the idea.
> 
> 
> 
> -- 
> 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.async consumer + producer working by chunk?

2018-01-05 Thread Brian J. Rubinton
I don’t know; I don’t fully understand the implementation differences of >!! 
and offer!. The behavior of offer! makes me think the buffer is not empty until 
all the outputs of the transducer are consumed, but the behavior of >!! makes 
me think otherwise.

Moritz - is the buffer cleared if:
- it’s size is 1
- you’ve put 1 item onto the channel 
- that 1 item is transformed into 3 by the channel’s transducer
- and only 1 of the 3 items are taken from the channel?

Per the docstrings and the behavior it’s both not possible to put another value 
onto the channel immediately (so offer! returns nil) yet buffer space is 
available after only 1 of the 3 values on the channel are taken (so >!! doesn't 
block).
https://github.com/clojure/core.async/blob/master/src/main/clojure/clojure/core/async.clj#L138
 

https://github.com/clojure/core.async/blob/master/src/main/clojure/clojure/core/async.clj#L391
 


This seems like a weird corner case made possible by transducers. Maybe the 
collection put into the buffer is removed from the buffer and passed to the 
transducer on the first take, so the buffer is empty and that’s all >!! cares 
about, yet there are still values to be taken from the channel (from the 
transducer — not the buffer) and somehow that affects offer!’s behavior.


> On Jan 5, 2018, at 4:07 PM, Rob Nikander  wrote:
> 
> 
> 
> On Friday, January 5, 2018 at 4:00:25 PM UTC-5, Moritz Ulrich wrote:
> 
> You have a channel with a buffer-size of one. You clear the buffer by 
> taking one item from it, making room for another one. Therefore the put 
> succeeds. Try just `(async/chan nil xform)` to create a channel without 
> a backing buffer (a rendezvouz channel) where puts only succeed if 
> there's a matching consumer. 
> 
> Then why does Brian's code work the way it does? See how he takes 2 things 
> off the channel, and offer! still fails and returns nil. If offer! is 
> returning nil, shouldn't >!! be blocking?
> 
> 
> 
> 
> -- 
> 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.async consumer + producer working by chunk?

2018-01-05 Thread Brian J. Rubinton
The `mapcat` transducer takes a collection as its input and outputs each of its 
items individually. This example might be helpful:

user> (use ‘[clojure.core.async])
nil
user> (def work-queue (chan 1 (mapcat identity)))
#’user/work-queue
user> (offer! work-queue (range 50))
true
user> ( ( (offer! work-queue (range 50))
nil
user> (dotimes [_ 48] ( (offer! work-queue (range 50))
true
user> ( On Jan 5, 2018, at 2:10 PM, Rob Nikander  wrote:
> 
> 
> 
> On Friday, January 5, 2018 at 2:03:00 PM UTC-5, Brian J. Rubinton wrote:
> 
> What is the buffered channel’s buffer used for? If that’s set to 1 and the 
> channel’s transducer is `(mapcat identity)` then the producer should be able 
> to continuously put chunks of work onto the channel with the puts only 
> completing when the previous chunk is completely consumed.
> 
> The buffer is sort of a work queue, used to break up and distribute one 
> "chunk" to a pool of consumers. I was imaging the buffer would be size 50. So 
> the producer would grab 50 rows (one "chunk") and put them all in the 
> channel. Consumers would pick them out one by one.
> 
> I'm not familiar with the transducer concept so I need to go read a bit 
> before I can understand your point about the channel's transducer being 
> `(mapcat identity)`.
> 
>  
> 
> -- 
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en 
> <http://groups.google.com/group/clojure?hl=en>
> --- 
> You received this message because you are subscribed to the Google Groups 
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to clojure+unsubscr...@googlegroups.com 
> <mailto:clojure+unsubscr...@googlegroups.com>.
> For more options, visit https://groups.google.com/d/optout 
> <https://groups.google.com/d/optout>.

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


Re: core.async consumer + producer working by chunk?

2018-01-05 Thread Brian J. Rubinton
Hi Rob,

What is the buffered channel’s buffer used for? If that’s set to 1 and the 
channel’s transducer is `(mapcat identity)` then the producer should be able to 
continuously put chunks of work onto the channel with the puts only completing 
when the previous chunk is completely consumed.

That would make the producer block/park until the previous chunk is consumed.

For your use case I think an interesting result of this approach (maybe a 
downside?) is initially 2 db queries would be performed, 1 whose result makes 
it onto the channel while 2’s result will be parked until the previous query’s 
result is consumed.

Brian

> On Jan 5, 2018, at 1:44 PM, Rob Nikander  wrote:
> 
> Hi,
> 
> I’m wondering if there is a core.async design idiom for this situation...
> 
> - A buffered channel 
> - One producer feeding it 
> - A bunch of consumers pulling from it.
> - Producer should wake up and fill the channel only when it’s empty. In other 
> words, the producer should work in chunks.
> 
> My first idea is to have two channels. The second will be used by consumers 
> to signal the producer that the primary channel is empty. But I'm wondering 
> if there is a better way.
> 
> The motive for this is that the producer is doing a DB query that is more 
> efficient in bulk. `select ... limit 50` rather than `select ... limit 1` 50 
> times.
> 
> Rob
> 
> -- 
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en 
> <http://groups.google.com/group/clojure?hl=en>
> --- 
> You received this message because you are subscribed to the Google Groups 
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to clojure+unsubscr...@googlegroups.com 
> <mailto:clojure+unsubscr...@googlegroups.com>.
> For more options, visit https://groups.google.com/d/optout 
> <https://groups.google.com/d/optout>.

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


Re: Converting json to work with clojure.spec

2017-08-06 Thread Brian Scaturro
Hi Jonathon,

I am trying to figure out the same thing. I am using all namespace 
qualified keys, but curious how this works when using s/conform on a json 
payload. Did you ever find a solution for this?

Thanks!
Brian

On Sunday, December 4, 2016 at 10:11:55 AM UTC-5, Jonathon McKitrick wrote:
>
> Ah, I see that now.
>
> That being said, I see the benefits in moving to namespace qualified keys. 
> Currently, I'm returning structures directly in Compojure handlers, and the 
> JSON conversion is implicitly handled. I checked Cheshire and didn't 
> immediately see a way to generate namespaced keys. What's the best way to 
> do this?
>
> On Saturday, November 19, 2016 at 9:23:32 AM UTC-5, Alex Miller wrote:
>>
>> s/keys has :req-un and :opt-un alternatives for un-qualified keys.
>
>

-- 
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: with-open pattern

2017-05-05 Thread Brian Craft
This looks like a partial solution:

https://github.com/pjstadig/scopes

perhaps inspired by this discussion:

https://dev.clojure.org/display/design/Resource+Scopes



On Friday, May 5, 2017 at 5:10:27 AM UTC-7, Herwig Hochleitner wrote:
>
> 2017-05-04 19:35 GMT+02:00 Brian Craft >:
>>
>> If there's only one with-open it can be reasonably simple to pass the 
>> consumer into that context (though from ring it's pretty convoluted, due to 
>> needing to pass control to ring first).
>>
>
> Creating streamed ring responses can be kind of tricky. In my experience, 
> there are two patterns, that work well:
>
> 1) Feeding a PipedInputStream from a new thread:
>
> (let [os (PipedOutputStream.)
>   is (PipedInputStream. os)]
>   (future (with-open [rs ...]
> (write-to! os rs)))
>   {:body is})
>
> 2) Use a ring adapter that allows some form of asynchronous response. E.g. 
> with the new ring 1.6 model
>
> {:body (reify ring.core.protocols/StreamableResponseBody
>  (write-body-to-stream [_ _ output-stream]
> (with-open [rs ...
> os output-stream]
> (write-to! os rs}
>  
>

-- 
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: with-open pattern

2017-05-04 Thread Brian Craft
It's definitely the same problem, but I don't think it helps me. This part, 
in particular:

"If you treat this object like a sequence, it will fully consume the input 
stream and fully realize the decoded data in memory."

I'm specifically trying to avoid realizing the full collection in memory, 
because it won't fit.

On Thursday, May 4, 2017 at 11:22:36 AM UTC-7, Josh Tilles wrote:
>
> I think the “reducible streams” approach described by Paul Stadig here 
> <http://paul.stadig.name/2016/08/reducible-streams.html> has potential. 
> It might not cover all of the scenarios you’re thinking of, though.
>
> On Thursday, May 4, 2017 at 1:35:48 PM UTC-4, Brian Craft wrote:
>>
>> The with-open style is used a lot in the jdbc lib, and elsewhere. It's 
>> pretty simple when data is very small, as you can just evaluate the entire 
>> result with doall, etc.
>>
>> How do you deal with larger data, where you need to evaluate iteratively? 
>> If there's only one with-open it can be reasonably simple to pass the 
>> consumer into that context (though from ring it's pretty convoluted, due to 
>> needing to pass control to ring first). But if there are multiple with-open 
>> you have to nest them, with a continuation passing style, or middleware 
>> pattern, or something, which quickly becomes onerous as it affects all the 
>> code surrounding the with-open.
>>
>> Is there some simpler pattern?
>>
>

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


with-open pattern

2017-05-04 Thread Brian Craft
The with-open style is used a lot in the jdbc lib, and elsewhere. It's 
pretty simple when data is very small, as you can just evaluate the entire 
result with doall, etc.

How do you deal with larger data, where you need to evaluate iteratively? 
If there's only one with-open it can be reasonably simple to pass the 
consumer into that context (though from ring it's pretty convoluted, due to 
needing to pass control to ring first). But if there are multiple with-open 
you have to nest them, with a continuation passing style, or middleware 
pattern, or something, which quickly becomes onerous as it affects all the 
code surrounding the with-open.

Is there some simpler pattern?

-- 
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: Seeking critique of "pattern" in clojure.spec (LONG)

2017-04-11 Thread Brian Beckman
I should have called them "blueberries" instead of the more provocative 
"virtual times."  I was trying to go from an abstract mathematical 
definition to a formalization in Clojure. Eventually, virtual times will be 
part of a discrete-even simulation platform, but it's too early to say much 
about that now. I'm just setting up the pylons at present.

Clojure number? excluding NaN will do for now: they have the required 
semantics at the limits and they're comparable amongst Double, Integer, 
Fraction, etc. Later, I may need a density axiom ("between any two finite 
blueberries there is another blueberry") and that's not true for Doubles. 
At that point I will definitely look back at your excellent answer and 
consider s/fdef's.

On Monday, April 10, 2017 at 10:15:19 PM UTC-7, Didier wrote:
>
> Here it is adapted to use a deftype: 
> https://gist.github.com/didibus/2ccd608ed9d226039f944b02a10f9ad5
>
> I gather from your solution that "orchestra" is not needed to spec :ret 
>> types?
>>
>
> It is not. The return spec will be used during st/check. If you want the 
> return spec to be validated outside of st/check though, than you need 
> Orchestra.
>
> I shall have to read up on deftype versus defrecord.
>>
>
> I recommend the clojure.org explanation: 
> https://clojure.org/reference/datatypes#_deftype_and_defrecord
> In a nutshell, deftype is a blank Java class, defrecord is an extended 
> PersistentHashMap.
>
> I am not sure why you need a VirtualTime, and what it will be doing, so I 
> can't really comment on which solution is best. As James said, it appears 
> you might be creating something that behaves the same way Double does? 
> Double already has positive and negative infinity and NaN:
>
> (/ 0.0 0.0) ; NaN
> (* 99e 99e) ; Infinity
> (* 99e -99e) ; -Infinity
> (< Double/NEGATIVE_INFINITY Double/POSITIVE_INFINITY) ; true
> (= Double/NEGATIVE_INFINITY Double/POSITIVE_INFINITY) ; false
>
> I'd suggest, if you need Double, use Double. If you need something close 
> to Double, and you can build on top of it, simpler to go with the style of 
> my first gist. If you can't build on top of double, deftype is probably 
> what you want.
>
> On Monday, 10 April 2017 21:41:35 UTC-7, Brian Beckman wrote:
>>
>> Wow... that's a comprehensive solution, Didier :) Bravo! It's a good 
>> lesson for s/fdef, which I haven't yet studied. I gather from your solution 
>> that "orchestra" is not needed to spec :ret types?
>>
>> As to semantics, on the one hand, I can spec ::virtual-time as a light 
>> overlay over Double and risk conflation of ordinary operators like < <= = 
>> etc. On the other hand, I have several options for full protection. I shall 
>> have to read up on deftype versus defrecord.
>>
>

-- 
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: Seeking critique of "pattern" in clojure.spec (LONG)

2017-04-10 Thread Brian Beckman
Wow... that's a comprehensive solution, Didier :) Bravo! It's a good lesson for 
s/fdef, which I haven't yet studied. I gather from your solution that 
"orchestra" is not needed to spec :ret types?

As to semantics, on the one hand, I can spec ::virtual-time as a light overlay 
over Double and risk conflation of ordinary operators like < <= = etc. On the 
other hand, I have several options for full protection. I shall have to read up 
on deftype versus defrecord.

-- 
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: Seeking critique of "pattern" in clojure.spec (LONG)

2017-04-10 Thread Brian Beckman
James -- just the kind of simplification I was looking for! In fact, I 
think the following will do everything I need --- generate numbers avoiding 
only NaN (which isn't equal to itself, nor less than anything)

(s/def ::virtual-time
  (s/with-gen
(s/and
 number? #(not (Double/isNaN %)))
;; We'd like most values generated in tests to be finite, with the
;; occasional infinity for spice. Adjust these frequencies to taste.
#(gen/frequency [[98 (s/gen number?)]
 [ 1 (gen/return Double/NEGATIVE_INFINITY)]
 [ 1 (gen/return Double/POSITIVE_INFINITY)]])))



-- 
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: Seeking critique of "pattern" in clojure.spec (LONG)

2017-04-10 Thread Brian Beckman
These are good comments that give me things to think about. I'm grateful.
* The pattern concerned me because (1) it was just the first thing I came 
up with, so not sure there wasn't a better way staring me in the face (2) I 
didn't see any clearly better alternatives, so not sure whether I just 
don't know enough Clojure (3) it intuitively felt heavyweight with at least 
four "complected" language features.
* Understood about polymorphism. In my real app, I have a lot of it, but I 
thought I would use protocols & records even when I don't have polymorphism 
just for uniformity of style: one way to express my "testable types." 
* You've pointed out an overlap between two different ways to specify 
structure: (A) requiring keys via records and (B) requiring keys using 
specs over ordinary maps. Starting with records, I sensed that some of my 
specs were actually vapid, and now you've told me why.  
* I think experimenting with mere (collections of) functions over mere maps 
with structure enforced by specs is a good idea. I'll try it and "weigh" it 
against this alternative.


On Monday, April 10, 2017 at 1:13:49 PM UTC-7, Didier wrote:
>
> I think this pattern is fine.
>
> What specifically about it annoys you?
>
> You could do it without records, but then you wouldn't be creating a type. 
> Do you really need a type?
>
> The advantage of types in Clojure are that they let you do polymorphic 
> dispatch of them. So they are useful if you have one function which you 
> want to reuse for many types.
>
> In your case, I'm not seeing other records implementing the protocol. So 
> it doesn't seem you need polymorphic dispatch on type. So maybe you can 
> drop the protocol.
>
> Records are useful if you need a map with guaranteed keys. Spec makes this 
> feature less useful, because you can now spec a map and test that it always 
> has the right keys when used. If you have a record, a fn that works over 
> that record just needs to check the argument has the type of record, and it 
> knows the keys exist. If you have a map instead, the fn would need to check 
> the keys exist.
>
> Records don't support unions, all keys must exist. In your case, you want 
> unions, a map with keys x,y or z. So if you use a record, some keys will 
> always have nil value. So, again, you might be better served by a map.
>
> Recap. Protocols if you want a common interface accross multiple types. 
> Records if you want to create a map with guaranteed keys, which will 
> identify itself as a named java type.
>
> Your spec can't really be made shorter, since they need custom gens.
>
> If I was you, I'd experiment with functions over maps. One thing to 
> consider is that specs are structural types, not nominal. So if you spec a 
> map, it describes its structure. A function says I take a structure of that 
> shape, if you give me anything that conforms, I can successfully do my job. 
> The shape itself has no known runtime name.
>
>

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


Seeking critique of "pattern" in clojure.spec (LONG)

2017-04-10 Thread Brian Beckman
"I apologize for the length of this post ..."  Blaise Pascal?

I am seeking critique of a certain "programming pattern" that's arisen 
several times in a project. I want testable types satisfying a protocol, 
but the pattern I developed "feels" heavyweight, as the example will show, 
but I don't know a smaller way to get what I want. The amount of code I 
needed to formalize and test my specs "feels" like too much. In particular, 
the introduction of a defrecord just to support the protocol doesn't "feel" 
minimal. The defrecord provides a constructor with positional args — of 
dubious utility — especially for large records, but otherwise acts like a 
hashmap. Perhaps there is a way to bypass the defrecord and directly use a 
hashmap?

Generally, I am suspicious of "programming patterns," because I believe 
that an apparent need for a programming pattern usually means one of two 
things:

   1. 
   
   The programming language doesn't directly support some reasonable need, 
   and that's not usually the case with Clojure
   2. 
   
   Ignorance: I don't know an idiomatic way to do what I want.
   
There is a remote, third possibility, that "what I want" is stupid, 
ignorant, or otherwise unreasonable. 
Here is what I settled on: quadruples of protocol, defrecord, specs and 
tests to fully describe and test types in my application:

   1. 
   
   a protocol to declare functions that certain types must implement
   2. 
   
   at least one defrecord to implement the protocol
   3. 
   
   a spec to package checks and test generators
   4. 
   
   tests to, well, test them
   
For a small example (my application has some that are much bigger), 
consider a type that models "virtual times" as numbers-with-infinities. 
Informally, a "virtual time" is either a number or one of two distinguished 
values for plus and minus infinity. Minus infinity is less than any virtual 
time other than minus infinity. Plus infinity is greater than any virtual 
time other than plus infinity." I'll write a protocol, a defrecord, a spec, 
and a couple of tests for this type. 

In the actual code, the elements come in the order of protocol, defrecord, 
spec, and tests because of cascading dependencies. For human consumption, 
I'll "detangle" them and present the spec first:

(s/def ::virtual-time  (s/with-gen(s/and ; idiom for providing a 
"conformer" function below (s/or  :minus-infinity #(vt-eq % 
:vt-negative-infinity) ; see the protocol for "vt-eq"  :plus-infinity  
#(vt-eq % :vt-positive-infinity)  :number #(number? (:vt %))) 
(s/conformer second))  ; strip off redundant conformer tag
#(gen/frequency [[98 vt-number-gen] ; generate mostly numbers ...   
  [ 1 vt-negative-infinity-gen] ; ... with occasional infinities
 [ 1 vt-positive-infinity-gen]])))

That should be self-explanatory given the following definitions:

(def vt-number-gen  (gen/bind   (gen/large-integer)   (fn [vt] (gen/return 
(virtual-time. vt) ; invoke constructor ... heavyweight?​(def 
vt-negative-infinity-gen  (gen/return (virtual-time. 
:vt-negative-infinity)))​(def vt-positive-infinity-gen  (gen/return 
(virtual-time. :vt-positive-infinity)))

The tests use the generators and a couple of global variables:

(def vt-negative-infinity (virtual-time. :vt-negative-infinity))(def 
vt-positive-infinity (virtual-time. :vt-positive-infinity))​(defspec 
minus-infinity-less-than-all-but-minus-infinity  100  (prop/for-all   [vt 
(s/gen :pattern-mve.core/virtual-time)]   (if (not= (:vt vt) 
:vt-negative-infinity) (vt-lt vt-negative-infinity vt) ; see the protocol 
for def of "vt-lt" true)))​(defspec plus-infinity-not-less-than-any  100  
(prop/for-all   [vt (s/gen :pattern-mve.core/virtual-time)]   (not (vt-lt 
vt-positive-infinity vt

The protocol specifies the comparison operators "vt-lt" and "vt-le." A 
defrecord to implement it should now be obvious, given understanding of how 
they're used above:

(defprotocol VirtualTimeT  (vt-lt [this-vt that-vt])  (vt-le [this-vt that-vt]) 
 (vt-eq [this-vt that-vt]))​(defn -vt-compare-lt [this-vt that-vt]  (case (:vt 
this-vt):vt-negative-infinity(case (:vt that-vt)  
:vt-negative-infinity false  #_otherwise true)​:vt-positive-infinity
false​;; otherwise: this-vt is a number.(case (:vt that-vt)  
:vt-positive-infinity true  :vt-negative-infinity false  #_otherwise (< 
(:vt this-vt) (:vt that-vt)​(defrecord virtual-time [vt]  VirtualTimeT  
(vt-lt [this that] (-vt-compare-lt this that))  (vt-eq [this that] (= this 
that))  (vt-le [this that] (or (vt-eq this that) (vt-lt this that

Please see a runnable project here 
https://github.com/rebcabin/ClojureProjects/tree/working/pattern-mve 

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

Re: Priority Map with efficient search on values?

2017-04-08 Thread Brian Beckman
"Much appreciated" to all answerers. Looks like priority-map has maps in 
both directions that I can use quickly. I'll write a protocol with the API 
I need, implement it with priority-map's non-superficial features to get 
going, then investigate more advanced data structures if / when I need to.

On Friday, April 7, 2017 at 10:55:44 PM UTC-7, Brian Beckman wrote:
>
> I have found a few data types in Clojure that support search and priority 
> queues. In particular, I found 
>
> Priority Maphttps://github.com/clojure/data.priority-map
> PSQhttps://goo.gl/Dw4gkV
> data.avlhttps://goo.gl/e07q7H
>
> I would be grateful for a few clarifying words on whether any of these can 
> meet my requirements out-of-the-box before I begin a deep-dive. Forgive me 
> for being a bit lazy (actually, just in a hurry), but I thought I'd check 
> whether someone knows an answer for me off-the-cuff.
>
> I need collections of [k v] pairs supporting efficient peek, pop, get, and 
> subseq-style search on either the key space or on the value space. I need 
> all operations on just one of the two spaces.
>
> Priority map supports efficient peek and pop of the value space on its API 
> surface, but I don't see a get subseq (or rsubseq) or other way to quickly 
> search the value space on the API surface. The comments in the source 
> suggest that there is an auxiliary inverse sorted map from values to keys. 
> The supported "get" operation seems to operate on the key space, but I 
> could use one on the value space (see line 313 of https://goo.gl/qhfXKL). 
> Perhaps that inverse map easy to get at, in which case I'll be done.
>
> PSQ supports peek and pop on values, and efficient search on keys, 
> according to its documentation. Do I read that correctly?
>
> I have not read the documentation for data.avl deeply enough to know 
> whether it will do my job out-of-the box. But I am sure I could build what 
> I need on top of AVL trees, RB trees, 2-3 trees, splay trees, etc. I'm just 
> looking to save myself work (and use tested software).
>

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


Priority Map with efficient search on values?

2017-04-07 Thread Brian Beckman
I have found a few data types in Clojure that support search and priority 
queues. In particular, I found 

Priority Maphttps://github.com/clojure/data.priority-map
PSQhttps://goo.gl/Dw4gkV
data.avlhttps://goo.gl/e07q7H

I would be grateful for a few clarifying words on whether any of these can 
meet my requirements out-of-the-box before I begin a deep-dive. Forgive me 
for being a bit lazy (actually, just in a hurry), but I thought I'd check 
whether someone knows an answer for me off-the-cuff.

I need collections of [k v] pairs supporting efficient peek, pop, get, and 
subseq-style search on either the key space or on the value space. I need 
all operations on just one of the two spaces.

Priority map supports efficient peek and pop of the value space on its API 
surface, but I don't see a get subseq (or rsubseq) or other way to quickly 
search the value space on the API surface. The comments in the source 
suggest that there is an auxiliary inverse sorted map from values to keys. 
The supported "get" operation seems to operate on the key space, but I 
could use one on the value space (see line 313 of https://goo.gl/qhfXKL). 
Perhaps that inverse map easy to get at, in which case I'll be done.

PSQ supports peek and pop on values, and efficient search on keys, 
according to its documentation. Do I read that correctly?

I have not read the documentation for data.avl deeply enough to know 
whether it will do my job out-of-the box. But I am sure I could build what 
I need on top of AVL trees, RB trees, 2-3 trees, splay trees, etc. I'm just 
looking to save myself work (and use tested software).

-- 
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: escape characters to make a string literal

2017-03-30 Thread Brian Craft
The specification seems ambiguous on this point. The definition of strings 
doesn't mention hex or octal escapes, but the definition of characters 
does. No relationship between characters and strings is specified. 
Characters are unicode, apparently; strings are unspecified.

On Thursday, March 30, 2017 at 2:13:23 AM UTC-7, Christophe Grand wrote:
>
> A funny thing is that octal or hexadecimal escapes are not part of EDN 
> (even if most readers recognize them).
>
> On Wed, Mar 29, 2017 at 8:49 PM, Brian Craft  > wrote:
>
>> A funny hole in the meta-programming story. I don't think the String or 
>> Character classes have methods that do this.
>>
>> Also interesting, clojure's print methods will handle some escapes, but 
>> not others:
>>
>> cavm.core=> (println (pr-str "foo\tbar"))
>>
>> "foo\tbar"
>>
>> nil
>>
>> cavm.core=> (println (pr-str "foo\001bar"))
>>
>> "foobar"
>>
>> nil
>>
>>
>> Apparently org.apache.commons.lang3.StringEscapeUtils.escapeJava is one 
>> solution.
>>
>>
>> On Wednesday, March 29, 2017 at 11:02:40 AM UTC-7, Alex Miller wrote:
>>>
>>> Clojure leans on Java to read that literal. There is no Clojure function 
>>> to forcibly print it that way again, but you can probably use the Java 
>>> methods on String or Character to get the String representation of a 
>>> character somehow. 
>>
>> -- 
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to clo...@googlegroups.com 
>> 
>> Note that posts from new members are moderated - please be patient with 
>> your first post.
>> To unsubscribe from this group, send email to
>> clojure+u...@googlegroups.com 
>> For more options, visit this group at
>> http://groups.google.com/group/clojure?hl=en
>> --- 
>> You received this message because you are subscribed to the Google Groups 
>> "Clojure" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to clojure+u...@googlegroups.com .
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>
>
> -- 
> On Clojure http://clj-me.cgrand.net/
> Clojure Programming http://clojurebook.com
> Training, Consulting & Contracting http://lambdanext.eu/ 
>

-- 
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: escape characters to make a string literal

2017-03-29 Thread Brian Craft
A funny hole in the meta-programming story. I don't think the String or 
Character classes have methods that do this.

Also interesting, clojure's print methods will handle some escapes, but not 
others:

cavm.core=> (println (pr-str "foo\tbar"))

"foo\tbar"

nil

cavm.core=> (println (pr-str "foo\001bar"))

"foobar"

nil


Apparently org.apache.commons.lang3.StringEscapeUtils.escapeJava is one 
solution.


On Wednesday, March 29, 2017 at 11:02:40 AM UTC-7, Alex Miller wrote:
>
> Clojure leans on Java to read that literal. There is no Clojure function 
> to forcibly print it that way again, but you can probably use the Java 
> methods on String or Character to get the String representation of a 
> character somehow. 

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


escape characters to make a string literal

2017-03-29 Thread Brian Craft
Is there an easy way to display a string as a string literal that can be 
read by clojure?

E.g.

> (let [x "\001"] (what-goes-here x))
"\001"

-- 
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: instrument code only in dev, with lein

2017-03-23 Thread Brian Craft
So, this seems to work pretty easily, though I'm relying on 'require' 
resolving references in the same order as the directories in :source-paths. 
For :source-paths ["src-dev", "src"], it will find 
src-dev/foo/instrument.clj,instead of src/foo/instrument.clj, when both 
exist.

I can't find anything in the lein or clojure docs that specifies this 
behavior. Is this a safe assumption?

On Friday, March 17, 2017 at 5:24:30 PM UTC-7, Matching Socks wrote:
>
> In a nutshell: leverage distinct classpaths.  Adjust the :dev profile in 
> project.clj to prepend a directory other than src to :source-paths, and 
> likewise a directory other than resources for :resource-paths.  In 
> development, use code or resources from the dev classpath to override 
> default behaviors on the uberjarred classpath.  See the sample Lein 
> project.clj:
>
> https://github.com/technomancy/leiningen/blob/master/sample.project.clj
>
>

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


instrument code only in dev, with lein

2017-03-17 Thread Brian Craft
How do you instrument code, e.g. apply ring wrap-reload, 
wrap-stacktrace-web, etc., only in dev, not in uberjar?

-- 
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: structuring parallel code

2017-01-30 Thread Brian Craft
I think java locks may be the only good answer. I can't usefully divide the 
vector, because the distribution of updates is uniform along the length of 
it.

Perhaps there's a solution with queues, with multiple threads generating 
potential placements, and a single thread updating the vector and 
re-queuing any conflicting placements.

On Monday, January 30, 2017 at 7:11:03 PM UTC-8, Alex Miller wrote:
>
> One technique is to batch locks at a coarser granularity. You've explored 
> both ends of the spectrum - 1 lock and N locks. You can also divide the 
> overall vector into any group of refs between 1 and N.
>
> If refs are too heavy, there are several other locking mechanisms on the 
> JVM. You could try Clojure atoms or Java locks. Atoms can only be used to 
> protect a single value so you would need a protocol for locking acquisition 
> to deal with that. For something like that, you'd probably end up using a 
> mutable data structure like a Java array.
>
>

-- 
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: structuring parallel code

2017-01-30 Thread Brian Craft
I don't think parallel reducers can handle the conflict issue: two threads 
making incompatible changes to the vector.

On Monday, January 30, 2017 at 7:01:22 PM UTC-8, Josh Tilles wrote:
>
> If your goal is “to operate on large data structures in parallel” then 
> you’ll probably find Clojure’s reducers library 
> <https://clojure.org/reference/reducers> to be helpful.
>
> On Monday, January 30, 2017 at 9:38:01 PM UTC-5, Brian Craft wrote:
>>
>> ans: this scales badly.
>>
>> There must be a way in clojure to operate on large data structures in 
>> parallel, no?
>>
>> On Monday, January 30, 2017 at 6:03:39 PM UTC-8, Brian Craft wrote:
>>>
>>> Would this not scale badly? When the vector is hundreds of thousands, or 
>>> millions?
>>>
>>> On Monday, January 30, 2017 at 5:54:32 PM UTC-8, tbc++ wrote:
>>>>
>>>> Instead of looking at the state as a ref with a vector in it, think of 
>>>> it as a vector of refs. That then allows multiple refs to be modified at 
>>>> once without stepping on other unrelated refs. 
>>>>
>>>> On Mon, Jan 30, 2017 at 5:26 PM, Brian Craft  
>>>> wrote:
>>>>
>>>>> I'm experimenting with ref, dosync, and alter to run some code in 
>>>>> parallel, but so far haven't been able to figure out how to structure it 
>>>>> such that it runs faster, instead of slower.
>>>>>
>>>>> The problem looks something like this.
>>>>>
>>>>> The current state is a long vector. Input is a long sequence of 
>>>>> values. At each step some positions in the vector are populated, if 
>>>>> empty, 
>>>>> based on computations over the next value in the sequence.
>>>>>
>>>>> It's like placing puzzle pieces: search for positions that satisfy a 
>>>>> constraint, and fill them.
>>>>>
>>>>> Using threads, I'd like to place the next several values in parallel. 
>>>>> But running in parallel it's possible that two threads would find 
>>>>> solutions 
>>>>> that conflict. In this case, the latter one must continue searching.
>>>>>
>>>>> Is there a way to express this with clojure? The problem is that I 
>>>>> can't tell 'dosync' when a previous transaction invalidates the current 
>>>>> transaction: it just always retries.
>>>>>
>>>>> e.g. if each thread is doing
>>>>>
>>>>>
>>>>> (dosync
>>>>>   (let [positions (find-positions next-value @state)]
>>>>>(alter state (fn [s] (update-state s positions))
>>>>>
>>>>> they interfere with each other constantly, because any write to 
>>>>> 'state' causes the other threads to retry, even if their positions are 
>>>>> still free.
>>>>>
>>>>> One really wants to reverse the order of find-positions and dosync 
>>>>> here, so it computes positions, then tries to commit them, checking in 
>>>>> the 
>>>>> transaction that the positions are still free, and continuing the search 
>>>>> if 
>>>>> they're not.
>>>>>
>>>>> I suppose there's some solution involving exceptions. Is there a 
>>>>> better way to think about this?
>>>>>
>>>>> -- 
>>>>> You received this message because you are subscribed to the Google
>>>>> Groups "Clojure" group.
>>>>> To post to this group, send email to clo...@googlegroups.com
>>>>> Note that posts from new members are moderated - please be patient 
>>>>> with your first post.
>>>>> To unsubscribe from this group, send email to
>>>>> clojure+u...@googlegroups.com
>>>>> For more options, visit this group at
>>>>> http://groups.google.com/group/clojure?hl=en
>>>>> --- 
>>>>> You received this message because you are subscribed to the Google 
>>>>> Groups "Clojure" group.
>>>>> To unsubscribe from this group and stop receiving emails from it, send 
>>>>> an email to clojure+u...@googlegroups.com.
>>>>> For more options, visit https://groups.google.com/d/optout.
>>>>>
>>>>
>>>>
>>>>
>>>> -- 
>>>> “One of the main causes of the fall of the Roman Empire was 
>>>> that–lacking zero–they had no way to indicate successful termination of 
>>>> their C programs.”
>>>> (Robert Firth) 
>>>>
>>>

-- 
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: structuring parallel code

2017-01-30 Thread Brian Craft
ans: this scales badly.

There must be a way in clojure to operate on large data structures in 
parallel, no?

On Monday, January 30, 2017 at 6:03:39 PM UTC-8, Brian Craft wrote:
>
> Would this not scale badly? When the vector is hundreds of thousands, or 
> millions?
>
> On Monday, January 30, 2017 at 5:54:32 PM UTC-8, tbc++ wrote:
>>
>> Instead of looking at the state as a ref with a vector in it, think of it 
>> as a vector of refs. That then allows multiple refs to be modified at once 
>> without stepping on other unrelated refs. 
>>
>> On Mon, Jan 30, 2017 at 5:26 PM, Brian Craft  wrote:
>>
>>> I'm experimenting with ref, dosync, and alter to run some code in 
>>> parallel, but so far haven't been able to figure out how to structure it 
>>> such that it runs faster, instead of slower.
>>>
>>> The problem looks something like this.
>>>
>>> The current state is a long vector. Input is a long sequence of values. 
>>> At each step some positions in the vector are populated, if empty, based on 
>>> computations over the next value in the sequence.
>>>
>>> It's like placing puzzle pieces: search for positions that satisfy a 
>>> constraint, and fill them.
>>>
>>> Using threads, I'd like to place the next several values in parallel. 
>>> But running in parallel it's possible that two threads would find solutions 
>>> that conflict. In this case, the latter one must continue searching.
>>>
>>> Is there a way to express this with clojure? The problem is that I can't 
>>> tell 'dosync' when a previous transaction invalidates the current 
>>> transaction: it just always retries.
>>>
>>> e.g. if each thread is doing
>>>
>>>
>>> (dosync
>>>   (let [positions (find-positions next-value @state)]
>>>(alter state (fn [s] (update-state s positions))
>>>
>>> they interfere with each other constantly, because any write to 'state' 
>>> causes the other threads to retry, even if their positions are still free.
>>>
>>> One really wants to reverse the order of find-positions and dosync here, 
>>> so it computes positions, then tries to commit them, checking in the 
>>> transaction that the positions are still free, and continuing the search if 
>>> they're not.
>>>
>>> I suppose there's some solution involving exceptions. Is there a better 
>>> way to think about this?
>>>
>>> -- 
>>> You received this message because you are subscribed to the Google
>>> Groups "Clojure" group.
>>> To post to this group, send email to clo...@googlegroups.com
>>> Note that posts from new members are moderated - please be patient with 
>>> your first post.
>>> To unsubscribe from this group, send email to
>>> clojure+u...@googlegroups.com
>>> For more options, visit this group at
>>> http://groups.google.com/group/clojure?hl=en
>>> --- 
>>> You received this message because you are subscribed to the Google 
>>> Groups "Clojure" group.
>>> To unsubscribe from this group and stop receiving emails from it, send 
>>> an email to clojure+u...@googlegroups.com.
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>
>>
>>
>> -- 
>> “One of the main causes of the fall of the Roman Empire was that–lacking 
>> zero–they had no way to indicate successful termination of their C 
>> programs.”
>> (Robert Firth) 
>>
>

-- 
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: structuring parallel code

2017-01-30 Thread Brian Craft
Would this not scale badly? When the vector is hundreds of thousands, or 
millions?

On Monday, January 30, 2017 at 5:54:32 PM UTC-8, tbc++ wrote:
>
> Instead of looking at the state as a ref with a vector in it, think of it 
> as a vector of refs. That then allows multiple refs to be modified at once 
> without stepping on other unrelated refs. 
>
> On Mon, Jan 30, 2017 at 5:26 PM, Brian Craft  > wrote:
>
>> I'm experimenting with ref, dosync, and alter to run some code in 
>> parallel, but so far haven't been able to figure out how to structure it 
>> such that it runs faster, instead of slower.
>>
>> The problem looks something like this.
>>
>> The current state is a long vector. Input is a long sequence of values. 
>> At each step some positions in the vector are populated, if empty, based on 
>> computations over the next value in the sequence.
>>
>> It's like placing puzzle pieces: search for positions that satisfy a 
>> constraint, and fill them.
>>
>> Using threads, I'd like to place the next several values in parallel. But 
>> running in parallel it's possible that two threads would find solutions 
>> that conflict. In this case, the latter one must continue searching.
>>
>> Is there a way to express this with clojure? The problem is that I can't 
>> tell 'dosync' when a previous transaction invalidates the current 
>> transaction: it just always retries.
>>
>> e.g. if each thread is doing
>>
>>
>> (dosync
>>   (let [positions (find-positions next-value @state)]
>>(alter state (fn [s] (update-state s positions))
>>
>> they interfere with each other constantly, because any write to 'state' 
>> causes the other threads to retry, even if their positions are still free.
>>
>> One really wants to reverse the order of find-positions and dosync here, 
>> so it computes positions, then tries to commit them, checking in the 
>> transaction that the positions are still free, and continuing the search if 
>> they're not.
>>
>> I suppose there's some solution involving exceptions. Is there a better 
>> way to think about this?
>>
>> -- 
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to clo...@googlegroups.com 
>> 
>> Note that posts from new members are moderated - please be patient with 
>> your first post.
>> To unsubscribe from this group, send email to
>> clojure+u...@googlegroups.com 
>> For more options, visit this group at
>> http://groups.google.com/group/clojure?hl=en
>> --- 
>> You received this message because you are subscribed to the Google Groups 
>> "Clojure" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to clojure+u...@googlegroups.com .
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>
>
> -- 
> “One of the main causes of the fall of the Roman Empire was that–lacking 
> zero–they had no way to indicate successful termination of their C 
> programs.”
> (Robert Firth) 
>

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


structuring parallel code

2017-01-30 Thread Brian Craft
I'm experimenting with ref, dosync, and alter to run some code in parallel, 
but so far haven't been able to figure out how to structure it such that it 
runs faster, instead of slower.

The problem looks something like this.

The current state is a long vector. Input is a long sequence of values. At 
each step some positions in the vector are populated, if empty, based on 
computations over the next value in the sequence.

It's like placing puzzle pieces: search for positions that satisfy a 
constraint, and fill them.

Using threads, I'd like to place the next several values in parallel. But 
running in parallel it's possible that two threads would find solutions 
that conflict. In this case, the latter one must continue searching.

Is there a way to express this with clojure? The problem is that I can't 
tell 'dosync' when a previous transaction invalidates the current 
transaction: it just always retries.

e.g. if each thread is doing


(dosync
  (let [positions (find-positions next-value @state)]
   (alter state (fn [s] (update-state s positions))

they interfere with each other constantly, because any write to 'state' 
causes the other threads to retry, even if their positions are still free.

One really wants to reverse the order of find-positions and dosync here, so 
it computes positions, then tries to commit them, checking in the 
transaction that the positions are still free, and continuing the search if 
they're not.

I suppose there's some solution involving exceptions. Is there a better way 
to think about this?

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


Re: finding clojure functions from the mangled names

2016-12-09 Thread Brian Craft
It doesn't, really, because you can't tell how nested functions are in 
clojure due to all the macros. In my code it wasn't nested at all, but I 
see now that defmethod and core.match added nested anonymous functions.

On Friday, December 9, 2016 at 4:32:51 PM UTC-8, Sean Corfield wrote:
>
> How big a piece of code is clojure.something100/foo ?
>
>  
>
> That sort of name indicates nested anonymous functions inside foo, nested 
> three deep in this case. That should narrow it down quite a bit.
>
>  
>
> (if you give us real names, that might help, especially if it’s in a 
> well-known third party library – or you can post the containing ‘foo’ 
> function for us to see?)
>
>  
>
> Sean Corfield -- (970) FOR-SEAN -- (904) 302-SEAN
> An Architect's View -- http://corfield.org/
>
> "If you're not annoying somebody, you're not really alive."
> -- Margaret Atwood
>
>  
>
> On 12/9/16, 3:00 PM, "Brian Craft"  
> on behalf of craft...@gmail.com > wrote:
>
>  
>
> Trying to profile some code, and the stack traces look like
>
>  
>
> clojure.something0
>
>   clojure.something1
>
>clojure.something2
>
>  
>
>   clojure.something100
>
>  foo$fn_1000$fn_1002$fn_10003.invoke()
>
>  
>
>  
>
> How can I figure out what that last function is? I can access the symbol 
> from the repl, but no idea how to connect it to my code.
>
>  
>
>  
>

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


Re: finding clojure functions from the mangled names

2016-12-09 Thread Brian Craft
This is in a profiler, not a repl: visualvm. If there's a way to make 
visualvm aware of clojure fns, I'll be very happy.


On Friday, December 9, 2016 at 3:52:38 PM UTC-8, Ghadi Shayban wrote:
>
> The stacktrace should be pointing to the correct file & line number -- no 
> need to reverse engineer the mangling.  If it's not for some reason, file a 
> bug.  (It's helpful to eliminate nREPL / lein middleware in case something 
> is transforming the printing of traces)
> If you are missing a trace when the JVM JITs your code, run with -XX:-
> *OmitStackTraceInFastThrow* 
>
> On Friday, December 9, 2016 at 6:25:24 PM UTC-5, Brian Craft wrote:
>>
>> Yes, but not very practical: since I don't know which one to change, this 
>> would be a huge rewrite of code to eliminate #() and (fn []).
>>
>>
>> On Friday, December 9, 2016 at 3:16:06 PM UTC-8, Alex Engelberg wrote:
>>>
>>> If you're seeing "fn_123", it's probably coming from an anonymous 
>>> function. Giving those functions a name with the (fn my-name [] ...) syntax 
>>> will make the stack trace a little easier to decipher:
>>>
>>> user=> ((fn [] (/ 1 0)))
>>>
>>> ArithmeticException Divide by zero  clojure.lang.Numbers.divide 
>>> (Numbers.java:158)
>>>
>>> user=> (pst)
>>>
>>> ArithmeticException Divide by zero
>>> clojure.lang.Numbers.divide (Numbers.java:158)
>>> clojure.lang.Numbers.divide (Numbers.java:3808)
>>> user/eval20851/fn--20852 (form-init8836862334241327650.clj:1)
>>> ​...​
>>>
>>> nil
>>> user=> ((fn my-fn-with-a-name [] (/ 1 0))
>>>
>>> ArithmeticException Divide by zero  clojure.lang.Numbers.divide 
>>> (Numbers.java:158)
>>> user=> (pst)
>>> ArithmeticException Divide by zero
>>> clojure.lang.Numbers.divide (Numbers.java:158)
>>> clojure.lang.Numbers.divide (Numbers.java:3808)
>>> user/eval20857/my-fn-with-a-name--20858 
>>> (form-init8836862334241327650.clj:1)
>>> ​...​
>>>
>>> nil
>>>
>>> On Fri, Dec 9, 2016 at 3:00 PM, Brian Craft  wrote:
>>>
>>>> Trying to profile some code, and the stack traces look like
>>>>
>>>> clojure.something0
>>>>   clojure.something1
>>>>clojure.something2
>>>>  
>>>>   clojure.something100
>>>>  foo$fn_1000$fn_1002$fn_10003.invoke()
>>>>
>>>>
>>>> How can I figure out what that last function is? I can access the 
>>>> symbol from the repl, but no idea how to connect it to my code.
>>>>
>>>> -- 
>>>> You received this message because you are subscribed to the Google
>>>> Groups "Clojure" group.
>>>> To post to this group, send email to clo...@googlegroups.com
>>>> Note that posts from new members are moderated - please be patient with 
>>>> your first post.
>>>> To unsubscribe from this group, send email to
>>>> clojure+u...@googlegroups.com
>>>> For more options, visit this group at
>>>> http://groups.google.com/group/clojure?hl=en
>>>> --- 
>>>> You received this message because you are subscribed to the Google 
>>>> Groups "Clojure" group.
>>>> To unsubscribe from this group and stop receiving emails from it, send 
>>>> an email to clojure+u...@googlegroups.com.
>>>> For more options, visit https://groups.google.com/d/optout.
>>>>
>>>
>>>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to 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: finding clojure functions from the mangled names

2016-12-09 Thread Brian Craft
Well, a truly painful way is to dump the const__ fields on the class, 
which appear to be values in the closure, from which the function might be 
inferred.

Like

(. foo$fn__7840$fn__7846$fn__7847 const__0)
(. foo$fn__7840$fn__7846$fn__7847 const__1)
...




On Friday, December 9, 2016 at 3:25:24 PM UTC-8, Brian Craft wrote:
>
> Yes, but not very practical: since I don't know which one to change, this 
> would be a huge rewrite of code to eliminate #() and (fn []).
>
>
> On Friday, December 9, 2016 at 3:16:06 PM UTC-8, Alex Engelberg wrote:
>>
>> If you're seeing "fn_123", it's probably coming from an anonymous 
>> function. Giving those functions a name with the (fn my-name [] ...) syntax 
>> will make the stack trace a little easier to decipher:
>>
>> user=> ((fn [] (/ 1 0)))
>>
>> ArithmeticException Divide by zero  clojure.lang.Numbers.divide 
>> (Numbers.java:158)
>>
>> user=> (pst)
>>
>> ArithmeticException Divide by zero
>> clojure.lang.Numbers.divide (Numbers.java:158)
>> clojure.lang.Numbers.divide (Numbers.java:3808)
>> user/eval20851/fn--20852 (form-init8836862334241327650.clj:1)
>> ​...​
>>
>> nil
>> user=> ((fn my-fn-with-a-name [] (/ 1 0))
>>
>> ArithmeticException Divide by zero  clojure.lang.Numbers.divide 
>> (Numbers.java:158)
>> user=> (pst)
>> ArithmeticException Divide by zero
>> clojure.lang.Numbers.divide (Numbers.java:158)
>> clojure.lang.Numbers.divide (Numbers.java:3808)
>> user/eval20857/my-fn-with-a-name--20858 
>> (form-init8836862334241327650.clj:1)
>> ​...​
>>
>> nil
>>
>> On Fri, Dec 9, 2016 at 3:00 PM, Brian Craft  wrote:
>>
>>> Trying to profile some code, and the stack traces look like
>>>
>>> clojure.something0
>>>   clojure.something1
>>>clojure.something2
>>>  
>>>   clojure.something100
>>>  foo$fn_1000$fn_1002$fn_10003.invoke()
>>>
>>>
>>> How can I figure out what that last function is? I can access the symbol 
>>> from the repl, but no idea how to connect it to my code.
>>>
>>> -- 
>>> You received this message because you are subscribed to the Google
>>> Groups "Clojure" group.
>>> To post to this group, send email to clo...@googlegroups.com
>>> Note that posts from new members are moderated - please be patient with 
>>> your first post.
>>> To unsubscribe from this group, send email to
>>> clojure+u...@googlegroups.com
>>> For more options, visit this group at
>>> http://groups.google.com/group/clojure?hl=en
>>> --- 
>>> You received this message because you are subscribed to the Google 
>>> Groups "Clojure" group.
>>> To unsubscribe from this group and stop receiving emails from it, send 
>>> an email to clojure+u...@googlegroups.com.
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>
>>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to 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: finding clojure functions from the mangled names

2016-12-09 Thread Brian Craft
Yes, but not very practical: since I don't know which one to change, this 
would be a huge rewrite of code to eliminate #() and (fn []).


On Friday, December 9, 2016 at 3:16:06 PM UTC-8, Alex Engelberg wrote:
>
> If you're seeing "fn_123", it's probably coming from an anonymous 
> function. Giving those functions a name with the (fn my-name [] ...) syntax 
> will make the stack trace a little easier to decipher:
>
> user=> ((fn [] (/ 1 0)))
>
> ArithmeticException Divide by zero  clojure.lang.Numbers.divide 
> (Numbers.java:158)
>
> user=> (pst)
>
> ArithmeticException Divide by zero
> clojure.lang.Numbers.divide (Numbers.java:158)
> clojure.lang.Numbers.divide (Numbers.java:3808)
> user/eval20851/fn--20852 (form-init8836862334241327650.clj:1)
> ​...​
>
> nil
> user=> ((fn my-fn-with-a-name [] (/ 1 0))
>
> ArithmeticException Divide by zero  clojure.lang.Numbers.divide 
> (Numbers.java:158)
> user=> (pst)
> ArithmeticException Divide by zero
> clojure.lang.Numbers.divide (Numbers.java:158)
> clojure.lang.Numbers.divide (Numbers.java:3808)
> user/eval20857/my-fn-with-a-name--20858 
> (form-init8836862334241327650.clj:1)
> ​...​
>
> nil
>
> On Fri, Dec 9, 2016 at 3:00 PM, Brian Craft  > wrote:
>
>> Trying to profile some code, and the stack traces look like
>>
>> clojure.something0
>>   clojure.something1
>>clojure.something2
>>  
>>   clojure.something100
>>  foo$fn_1000$fn_1002$fn_10003.invoke()
>>
>>
>> How can I figure out what that last function is? I can access the symbol 
>> from the repl, but no idea how to connect it to my code.
>>
>> -- 
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to clo...@googlegroups.com 
>> 
>> Note that posts from new members are moderated - please be patient with 
>> your first post.
>> To unsubscribe from this group, send email to
>> clojure+u...@googlegroups.com 
>> For more options, visit this group at
>> http://groups.google.com/group/clojure?hl=en
>> --- 
>> You received this message because you are subscribed to the Google Groups 
>> "Clojure" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to clojure+u...@googlegroups.com .
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>

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


finding clojure functions from the mangled names

2016-12-09 Thread Brian Craft
Trying to profile some code, and the stack traces look like

clojure.something0
  clojure.something1
   clojure.something2
 
  clojure.something100
 foo$fn_1000$fn_1002$fn_10003.invoke()


How can I figure out what that last function is? I can access the symbol 
from the repl, but no idea how to connect it to my code.

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


Re: Two suggestions re: core.spec, `ns`, and clojure 1.9alpha11

2016-08-25 Thread Brian Marick

> On Aug 24, 2016, at 9:28 PM, adrian.med...@mail.yu.edu wrote:
> 
> I do not think your tone and lack of constructive feedback to Alex's (and 
> others) thoughtful responses is helping your case. 


Probably not(*), though I would characterize the responses differently. They 
are polite, and they are intended to be helpful to someone who already agrees 
with axioms like “good error-handling is a nail for which core.spec is the 
hammer” and “it is wise to push the responsibility for error understanding to 
third-party libraries or diligent study”. They do a service in that they lay 
out the rules under which Clojure users should expect to live. But they are 
largely reiterations rather than engagement. I find that rather frustrating.


Let me point to an essential book on business/community management, Hirschman’s 
/Exit, Voice, and Loyalty/. 
https://en.wikipedia.org/wiki/Exit,_Voice,_and_Loyalty 
, and to a clever take 
on group behavior, “Evaporative Cooling of Group Beliefs”, 
http://lesswrong.com/lw/lr/evaporative_cooling_of_group_beliefs/ 
. I think 
there is much to learn from reflecting on those and the direction of Clojure 
design and the Clojure community over the past few years. (I’m not a huge fan 
of the application of Satir’s family counseling theory to software management - 
Gerald Weinberg and the like - but it’s hard not to read books like the 
/Quality Software Management/ series and see people in the Clojure community - 
including me! - playing out stereotypical dysfunctional roles.) 

Read me as someone who’s publicly and self-destructively giving up on Voice and 
is on the way to Exit. As someone who tends to Loyalty (though perhaps the 
loyalty of the traditional Catholic Devil’s Advocate), it’s rather agonizing. 
That is, I still think Clojure is the best raw language out there for 
broad-spectrum work. However, its design has been doubling down on 
long-unfortunate tendencies, and - I’d argue - new languages like Rust, Elixir, 
and Elm (even Pony) - are raising the bar for both community management and 
“peripheral” concerns like documentation and error handling. In the meantime, 
the Clojure ideology - reinforced by memes like “complecting” - has been 
getting more rigid. 

The result is that what seem to me bizarre decisions are treated as normal. We 
have an `any?` in clojure.core that always returns `true`. This deviance from 
probably every other programming language is justified as obvious for a feature 
- clojure.spec - that is largely unproven, certainly when it comes to error 
reporting. (Even worse, we have `any?`, `some?`, and `some` - all 
idiosyncratic.) Yet the idea of changing the name of `any?` is completely 
dismissed, with the justification that people complain about every new name. 
(Think about what that decision criterion entails, broadly applied.)

Also bizarre: the idea that error messages that amount to essentially dumping a 
parse tree + BNF-ish grammar clause (possibly twice with a vomitous stack trace 
between) is a *good* thing. Not a “we wish we could do better, but software 
development is about constraints and tradeoffs” thing. Not a “yeah, but Rich 
Hickey doesn’t want to bother with that stuff” thing. 

(I was honestly flummoxed that, although clojure.spec is supposed to be the 
answer for error handling, there’s been no attempt to work through what good 
error messages would be like and how the current infrastructure would support 
the translation from raw data to such error messages.)

I cannot help but think of this as groupthink. And - to be grandiose - having 
people like me Exit will increase that, per evaporative cooling. 


I also note that my library, Midje, is typically insulted on this mailing list 
whenever a newbie brings it up. One of the contributors to this thread has 
called it “an abomination”. There was no similar concern about *his* tone. 
Because, I suspect, he's on the inside, punching out.

---

(*) Might that not be my fiendish plan? Perhaps I’m being abrasive on this list 
exactly to associate ideas like “error messages are the responsibility of the 
compiler” as being from a hated Other, thus hardening a position that I think 
is bad for Clojure. Why would I do that? Because I’m 90% likely to be going 
all-in on Elixir and Elm. Encouraging destructive behavior in a competitor 
language increases my languages' chances of success. Bwahaha! (Oops, just 
violated rules 6 and 7 of http://www.eviloverlord.com/lists/overlord.html 
 )

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

Re: Two suggestions re: core.spec, `ns`, and clojure 1.9alpha11

2016-08-24 Thread Brian Marick

> On Aug 24, 2016, at 7:46 PM, Brian Marick  wrote:
> So why not do it in the bottom layer? Is there some deep reason why only an 
> unserious programmer would want information in anything other than the 
> current clojure.spec order? (We’re talking here about reordering a list.)

An even crazier idea: given that there are N difference pieces of information, 
they could be presented in a map, with keys that described each of them. 

-- 
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: Two suggestions re: core.spec, `ns`, and clojure 1.9alpha11

2016-08-24 Thread Brian Marick

> On Aug 24, 2016, at 8:39 AM, Stuart Halloway  
> wrote:
> 
> 3. "Follow the inverted pyramid so people see what is most important."  This 
> kind of thing is easily done in a layer above spec, e.g. a custom REPL 
> printer for spec macro errors. Worth working on but not critical to getting 
> spec right.


So why not do it in the bottom layer? Is there some deep reason why only an 
unserious programmer would want information in anything other than the current 
clojure.spec order? (We’re talking here about reordering a list.)

There has been a notable lack of “yeah, we might have made a sub-optimal 
decision” in this discussion. It looks bad, in my opinion. Has looked bad for a 
long time. 


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


Re: Two suggestions re: core.spec, `ns`, and clojure 1.9alpha11

2016-08-23 Thread Brian Marick

> On Aug 22, 2016, at 7:50 PM, Alex Miller  wrote:

> You've complained in other channels about the "learning to read" error 
> messages part and I think you've taken it entirely the wrong way or maybe I 
> just disagree. There are benefits from reporting errors in a generic, 
> consistent way. […]

Do there exist examples of what is desired for error messages in 1.9-final? Not 
promises, but a “this is what we’re shooting for”? What would you all like the 
specific error messages complained about in this thread to look like? 

Colin Fleming wrote: "The error message produced by the code I demoed at the 
conj last year would be:

Unexpected symbol 'require' at  while parsing namespace 
clauses. Expected :refer-clojure, :require, :use, :import, :load or :gen-class.”

Is that the goal? I fear that the goal is that it should be my job to 
understand "(cat :attr-map (? map?) :clauses :clojure.core.specs/ns-clauses)”. 
For what little it’s worth, I consider that completely unacceptable. 

> - Getting the error data (specifically the explain-data output) to be both 
> sufficient and generically useful is the first priority. I think at this 
> point that's pretty close and unlikely to change significantly. 

My bias here is that I come from the learned-from-bitter-experience tradition 
that believes it’s very risky to (1) get the infrastructure right, and then (2) 
pop down the user-visible features on top of it. Very often, the infrastructure 
turns out to be a poor match for the actual needs of the features. But, since 
(1) is already done, the features - and consequently the users - suffer. 

Please understand I’m not being insulting when I say that everyone has 
weaknesses and blind spots, even undoubted geniuses. In Clojure, error messages 
and documentation (especially doc strings) have long been glaring weaknesses. 
So I am wishing to be helpful when I counsel *quickly* getting to worked 
examples of output, especially output that novices are likely to encounter. And 
exposing those messages to typical users, ones who are not familiar with 
core.spec. 

That seems prudent. 

I believe strongly enough in good error messages that I would be willing to do 
some of the scut work, if needed.

-- 
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: Two suggestions re: core.spec, `ns`, and clojure 1.9alpha11

2016-08-22 Thread Brian Marick

> On Aug 22, 2016, at 11:23 AM, Leon Grapenthin  
> wrote:
> 
> Still the error messages are simply far from good enough and that is what 
> appears to me as the main problem OP has. 

This is important. Will the new, stricter error messages be improved before 1.9 
is finalized? 


-- 
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] Shrubbery 0.4.0, a stubbing, spying, and mocking library for Clojure protocols

2016-08-22 Thread Brian Guthrie
Clojure protocols are a great way to encapsulate operations with side
effects, but suffer from a lack of general test tooling. Shrubbery provides
a small set of basic building blocks for working with them.

New in this release:

– A throws function, which returns an object suitable for use with the
stub function
that throws the named exception when invoked, as so:

(defprotocol SomeProtocol
  (explode [t]))

(let [astub (shrubbery/stub SomeProtocol
  {:explode (shrubbery/throws RuntimeException "bang")})]
  (explode astub)) ;; throws RuntimeException "bang"

What Shrubbery provides:

 * stub, which accepts a variable list of protocols and a optional hashmap
of simple value implementations and returns an object that reifies all
given protocols;
 * spy, which accepts an object with at least one protocol implementation
and returns a new implementation that tracks the number of times each of
its members were called;
 * mock, which wraps a stub in a spy, allowing callers to supply basic
function implementations and assert against those calls; and
 * calls/received?, which in conjunction with the Matcher protocol provide
a way to query spies and assert against their state.

Shrubbery is test-framework-agnostic, avoids altering runtime state to the
degree possible, and uses no macros. It supports Clojure versions 1.5-1.8;
I haven't yet tested with 1.9. It should work nicely with automated
refactoring operations like rename-function.

https://github.com/bguthrie/shrubbery

[com.gearswithingears/shrubbery "0.4.0"]


Cheers,

Brian

-- 
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: Two suggestions re: core.spec, `ns`, and clojure 1.9alpha11

2016-08-21 Thread Brian Marick
As an update. I’ve fixed the `ns` oopsie in Suchwow (one file), and the 
coincident `ns` oopsie in Midje (one file). But this happens when running 
Midje’s self-tests against Clojure 1.9alpha11:

> Exception in thread "main" java.lang.IllegalArgumentException: Call to 
> clojure.core/fn did not conform to spec:
> In: [0] val: clojure.core.unify/var-unify fails spec: 
> :clojure.core.specs/arg-list at: [:args :bs :arity-1 :args] predicate: vector?
> In: [0] val: clojure.core.unify/var-unify fails spec: 
> :clojure.core.specs/args+body at: [:args :bs :arity-n] predicate: (cat :args 
> :clojure.core.specs/arg-list :prepost (? map?) :body (* any?))
> :clojure.spec/args  (clojure.core.unify/var-unify [varp v expr binds] 
> (clojure.core/if-let [vb__10124__auto__ (binds v)] 
> (clojure.core.unify/garner-unifiers varp vb__10124__auto__ expr binds) 
> (clojure.core/if-let [vexpr__10125__auto__ (clojure.core/and (varp expr) 
> (binds expr))] (clojure.core.unify/garner-unifiers varp v 
> vexpr__10125__auto__ binds) (if (clojure.core.unify/occurs? varp v expr 
> binds) (throw (java.lang.IllegalStateException. (clojure.core/str "Cycle 
> found in the path " expr))) (clojure.core.unify/bind-phase binds v expr)
> , compiling:(clojure/core/unify.clj:82:18)

I suspect the problem is that Midje uses an old version of clojure.core.unify 
(0.5.2). I use that old version because a later versions (like the current 
0.5.7) failed in my use case for no reason I could quickly understand. So I 
decided to just stick with the older, working version because forced upgrades 
make kittens suffer. And I am a kitten. And also: by semver, why should a 
satisfied user of 0.5.2 care about 0.5.7?

(Note: I don’t know whether clojure.core.unify 0.5.7 is conformant to whatever 
spec is breaking.)

So upgrading Midje to Clojure 1.0alpha11 is not turning out as simple as might 
be hoped. 

I know that, pace Casablanca[*], the problems of a guy trying to provide an 
alternative to clojure.test don’t amount to a hill of beans in this crazy 
world. But I offer this datapoint for clojure.core.team consideration.



[*] 

Rick: But I've got a job to do, too. Where I'm going, you can't follow. What 
I've got to do, you can't be any part of. Ilsa, I'm no good at being noble, but 
it doesn't take much to see that the problems of three little people don't 
amount to a hill of beans in this crazy world. Someday you'll understand that. 
[Ilsa lowers her head and begins to cry]
Rick: Now, now... 
[Rick gently places his hand under her chin and raises it so their eyes meet]
Rick: Here's looking at you kid. 

-- 
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: Two suggestions re: core.spec, `ns`, and clojure 1.9alpha11

2016-08-20 Thread Brian Marick

> On Aug 20, 2016, at 6:30 PM, Timothy Baldridge  wrote:
> 
> Brian, let's make it more concrete then...why should the Clojure compiler 
> continue to support undocumented features that make code unportable?


Because: 

1. People who want to port to clojurescript will incur exactly the same cost as 
they do now.
2. People who don’t want to port to clojurescript will incur no additional cost.
3. Clojurescript maintainers will incur no additional cost.
4. Clojure maintainers will incur the cost of adding “or symbol” to current 
code.
5. No one writing documentation will incur any cost, as what was not mentioned 
before will continue to be unmentioned.

6. There will be a psychic cost because of an undocumented inconsistency 
between clojure and clojurescript.
7. If, at some point, clojure and clojurescript shared code for the 
implementation of `ns`, one or the other would have to change the pre 
1.9-alpha11 behavior.

Do I have this enumeration of costs wrong?

It’s a bit surprising to me that my explicit appeal to consider costs and 
benefits to real people is not being addressed.

-- 
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: Two suggestions re: core.spec, `ns`, and clojure 1.9alpha11

2016-08-20 Thread Brian Marick

> On Aug 20, 2016, at 5:26 PM, s...@corfield.org wrote:
> 
> I disagree (strongly) with your position here Brian. I’ll try to explain 
> clearly why but first a little background…

I too have felt the pain of having to maintain backward compatibility. However, 
I’m reminded, in this case, of Mark Twain’s “The cat, having sat upon a hot 
stove lid, will not sit upon a hot stove lid again. But he won't sit upon a 
cold stove lid, either.”

That’s why I tend to ask questions, not about abstract principles, but about 
what - given these particular alternatives - happens to which people?

The problem with recourse to general principles and past experience is that 
it’s easy to overlook that I’m suggesting a change from:

  ns-clause-header ::= keyword?

… to:

  ns-clause-header ::= keyword? || symbol?


-- 
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: Two suggestions re: core.spec, `ns`, and clojure 1.9alpha11

2016-08-20 Thread Brian Marick

> On Aug 20, 2016, at 9:03 AM, Alex Miller  wrote:
> 
> We discussed this before releasing the specs and decided to start on the 
> strict side. That said, this is still an alpha and there is plenty of time to 
> change our minds prior to official release of 1.9 if that ends up being a 
> catastrophic decision.

I urge you to change your minds. Whose life is harmed, and how, by continuing 
to allow `require` as well as `:require`? 

-- 
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: Two suggestions re: core.spec, `ns`, and clojure 1.9alpha11

2016-08-20 Thread Brian Marick

> On Aug 20, 2016, at 9:03 AM, Alex Miller  wrote:
> 
> You left out this next important line too since it points you to exactly the 
> file and line where the error occurs:
> 
> , compiling:(such/sequences.clj:1:1) 

This is interesting. Here’s why I missed it. I attach the error message I saw 
from `lein midje`. Notice that the spec error appears twice, once at the top, 
once at the end. The line showing the source file appears only with the top 
one. The one at the bottom of the screen is the one I looked at. I think that’s 
pretty natural.

 attach

Exception in thread "main" java.lang.IllegalArgumentException: Call to 
clojure.core/ns did not conform to spec:
In: [2] val: ((require [such.vars :as var] [such.immigration :as immigrate]) 
(require midje.checking.checkers.defining midje.checking.checkers.chatty 
midje.checking.checkers.simple midje.checking.checkers.combining 
midje.checking.checkers.collection)) fails at: [:args] predicate: (cat 
:attr-map (? map?) :clauses :clojure.core.specs/ns-clauses),  Extra input
:clojure.spec/args  (midje.checkers "Checkers are for checking results of 
checkables, or checking \n   that appropriate arguments are passed to 
prerequisites" (require [such.vars :as var] [such.immigration :as immigrate]) 
(require midje.checking.checkers.defining midje.checking.checkers.chatty 
midje.checking.checkers.simple midje.checking.checkers.combining 
midje.checking.checkers.collection))
, compiling:(midje/checkers.clj:1:1)
at clojure.lang.Compiler.macroexpand1(Compiler.java:6795)
at clojure.lang.Compiler.macroexpand(Compiler.java:6861)
at clojure.lang.Compiler.eval(Compiler.java:6935)
at clojure.lang.Compiler.load(Compiler.java:7403)
at clojure.lang.RT.loadResourceScript(RT.java:374)
at clojure.lang.RT.loadResourceScript(RT.java:365)
at clojure.lang.RT.load(RT.java:455)
at clojure.lang.RT.load(RT.java:421)
at clojure.core$load$fn__7645.invoke(core.clj:6008)
at clojure.core$load.invokeStatic(core.clj:6007)
at clojure.core$load.doInvoke(core.clj:5991)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invokeStatic(core.clj:5812)
at clojure.core$load_one.invoke(core.clj:5807)
at clojure.core$load_lib$fn__7590.invoke(core.clj:5852)
at clojure.core$load_lib.invokeStatic(core.clj:5851)
at clojure.core$load_lib.doInvoke(core.clj:5832)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invokeStatic(core.clj:659)
at clojure.core$load_libs.invokeStatic(core.clj:5889)
at clojure.core$load_libs.doInvoke(core.clj:5873)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invokeStatic(core.clj:659)
at clojure.core$require.invokeStatic(core.clj:5911)
at clojure.core$require.doInvoke(core.clj:5911)
at clojure.lang.RestFn.invoke(RestFn.java:512)
at 
midje.parsing.3_from_lexical_maps.from_fake_maps$eval8453$loading__7531__auto8454.invoke(from_fake_maps.clj:1)
at 
midje.parsing.3_from_lexical_maps.from_fake_maps$eval8453.invokeStatic(from_fake_maps.clj:1)
at 
midje.parsing.3_from_lexical_maps.from_fake_maps$eval8453.invoke(from_fake_maps.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:6951)
at clojure.lang.Compiler.eval(Compiler.java:6940)
at clojure.lang.Compiler.load(Compiler.java:7403)
at clojure.lang.RT.loadResourceScript(RT.java:374)
at clojure.lang.RT.loadResourceScript(RT.java:365)
at clojure.lang.RT.load(RT.java:455)
at clojure.lang.RT.load(RT.java:421)
at clojure.core$load$fn__7645.invoke(core.clj:6008)
at clojure.core$load.invokeStatic(core.clj:6007)
at clojure.core$load.doInvoke(core.clj:5991)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invokeStatic(core.clj:5812)
at clojure.core$load_one.invoke(core.clj:5807)
at clojure.core$load_lib$fn__7590.invoke(core.clj:5852)
at clojure.core$load_lib.invokeStatic(core.clj:5851)
at clojure.core$load_lib.doInvoke(core.clj:5832)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invokeStatic(core.clj:659)
at clojure.core$load_libs.invokeStatic(core.clj:5889)
at clojure.core$load_libs.doInvoke(core.clj:5873)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invokeStatic(core.clj:659)
at clojure.core$require.invokeStatic(core.clj:5911)
at clojure.core$require.doInvoke(core.clj:5911)
at clojure.lang.RestFn.invoke(RestFn.java:551)
at 
midje.parsing.lexical_maps$eval8445$loading__7531__auto8446.invoke(lexical_maps.clj:1)
at midje.parsing.lexical_maps$eval8445.invokeStatic(lexical_maps.clj:1)
at midje.parsing.lexical_maps$eval8445.invoke(lexical_maps.clj:1)
at cl

Two suggestions re: core.spec, `ns`, and clojure 1.9alpha11

2016-08-20 Thread Brian Marick
Yesterday, a bug was filed against Suchwow under 1.9alpha11. It turns out to 
have been a use of `ns …(require…` instead of `(ns …(:require`. Not in Suchwow, 
but in Midje. Unfortunately, the Suchwow file the bug report pointed at *also* 
had that typo - apparently I am prone to it - so adding the colon to the 
require there didn’t make the problem go away. 

That caused me to lose my temper and make a fool of myself, which is neither 
here nor there, except that I apologize to @puredanger. 

I have two suggestions, though:

1. It has long been the case that Clojure allowed `(ns (require…)` even though 
that’s strictly incorrect. I suggest that, for backwards compatibility, it be 
allowed going forward. That is, I think it does no harm for a correct `ns` 
statement to allow symbols as well as keywords. That wrong code in Midje has 
been there since Clojure 1.2. 

2. The following is not a good error message:

Exception in thread "main" java.lang.IllegalArgumentException: Call to 
clojure.core/ns did not conform to spec:
In: [2] val: ((require [such.vars :as var] [such.immigration :as immigrate]) 
(require midje.checking.checkers.defining midje.checking.checkers.chatty 
midje.checking.checkers.simple midje.checking.checkers.combining 
midje.checking.checkers.collection)) fails at: [:args] predicate: (cat 
:attr-map (? map?) :clauses :clojure.core.specs/ns-clauses),  Extra input

- It would be better to say “`require` should be a keyword, not a symbol” than 
"fails at: [:args] predicate: (cat :attr-map (? map?) :clauses 
:clojure.core.specs/ns-clauses),  Extra input”

- Suggest Clojure.spec error messages follow the “inverted pyramid” structure 
of news reports: https://en.wikipedia.org/wiki/Inverted_pyramid 
 That would mean the text 
message about the error would come first, the spec second, and the wrong 
expression last. 

- It would be better to name the namespace that has the problem.

- The stack trace adds nothing to the error. If anything, it makes it less 
understandable, as the sheer amount of text is offputting.

My https://github.com/marick/structural-typing 
 does (a small) part of what 
clojure.spec does. I went to a lot of effort to get it to produce good error 
messages, and it turned out OK. I doubt it would be applicable to clojure.spec, 
but I’d be happy to sign over any code that could be of use. 

It’s unfortunate that reporting errors is so much harder than detecting them. 

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


'lein trampoline test' fails on first run with 'No implementation of method'

2016-08-14 Thread Brian Craft
With an empty target directory 'lein trampoline test' fails with a protocol 
exception, 'No implementation of method'.

Running 'lein test' works fine. After running 'lein test', 'lein trampoline 
test' also works.

Anyone know what's going on? Seems like something isn't being compiled, or 
loaded, but I don't know why.

-- 
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] Flake 0.4.0: Decentralized, k-ordered unique ID generator

2016-06-22 Thread Brian Platz


On Wednesday, June 22, 2016 at 7:25:50 AM UTC-4, Bruno Bonacci wrote:
>
>
> To answer Brian on the "potential" problem of the clock drift I would 
> recommend to have a look to 
> https://aphyr.com/posts/299-the-trouble-with-timestamps. Beside the 
> hardware problems you have to account for things like ntpd daemon which is 
> meant to synchronize clocks.
> To keep them in sync it accelerates or decelerates the clock speed on your 
> machine, however if it falls too much behind it will do a hard-reset,
> so what you might see is that your System/currentTimeMillis calls jump 
> back and forward (non-monotonic).
> With VMs (such as cloud environment) this problem is way worse and more 
> frequent.
>

In Max's library he is only calling out to System/currentTimeMillis once at 
startup, he then determines the nanoTime offset and only uses nanoTime from 
there. nanoTime is supposed to be immune from wall clock time, and thus 
ntpd changes. 

Because it will ignore ntpd changes, there could be a delta from wall clock 
as ntpd changes the time. So that is a risk to be aware of, and if you were 
super concerned about it a method to re-sync could probably be devised 
(similar to what is used for leap-seconds). I've noticed this particular 
issue with a sleeping laptop. Assuming the process isn't extremely 
long-lived I think you'd be sufficiently close to not worry about it.

The process ID in many platform is just 16bits, however some platform have 
> 32bits (
> http://unix.stackexchange.com/questions/16883/what-is-the-maximum-value-of-the-pid-of-a-process),
>  
> and the ThreadID in java is a long (
> https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#getId() 
> <https://www.google.com/url?q=https%3A%2F%2Fdocs.oracle.com%2Fjavase%2F7%2Fdocs%2Fapi%2Fjava%2Flang%2FThread.html%23getId()&sa=D&sntz=1&usg=AFQjCNGr6MM7If1XHSF93tlglYW4vRl1xw>)
>  
> which is unfortunate. It would be nice if there was a way to read which CPU 
> core physical thread is executing a particular thread (when the thread is 
> running), i such way you could replace the processId and the threadId which 
> just a CPU core ID. The number of physical threads (core + hyperthreads) 
> is typically much smaller and it fits in a 16 bits. However to my 
> knowledge there is no way in java to retrieve such value.
>

If you were willing to take on another 64 bits, an idea could be to take 
the last 16 (or maybe 32) bits from the ThreadID combined with a random 
bits to round out the 64.

The random bits could be done once per thread combined with keeping a 
ThreadLocal counter where a CAS is still done to avoid issuing the same ID 
at the same time increment in the same thread -- or the counter could be 
ignored entirely and the random bits generated with every ID. I'm not sure 
which would perform better, but I like the randomness per ID which makes 
IDs harder to guess.

-Brian

-- 
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] Flake 0.4.0: Decentralized, k-ordered unique ID generator

2016-06-21 Thread Brian Platz
Bruno,

I think the more you can reduce the chance of collision the better and the 
thread-local capability is a good idea, but in the process you've almost 
doubled the bits.

For me anyhow, an ID need to be produceable at a reasonable rate (1 million 
a second per machine is good for me), have near-zero probability of 
collision and take up the least amount of space possible.

Under those criteria, I think 128 bits is a reasonable target and the 
thread-safe atom I would expect to handle such volume (although I haven't 
tested).

If you need a billion per second and don't want 100 machines producing 
them, then I think you are at the point of needing to have thread 
independence and probably have to increase the bit-count, and your ideas 
provide a good path towards such a solution.

Your comment on the file persistence is a good one, I wonder if the 
potential problems are real enough to warrant the risks.

My other curiosity is if System/nanoTime is guaranteed to increment across 
threads. I know at least a while ago that this guarantee did not exist.

-Brian


On Tuesday, June 21, 2016 at 8:38:58 AM UTC-4, Bruno Bonacci wrote:
>
>
> Hi this change it is actually easier than it sounds. Looking at the code, 
> I came across a couple of things which I think might be better.
>
> 1) use of filesystem persistence.
>
> Not too sure that the file based persistence is a good idea. Maybe this is 
> a good idiomatic design for Erlang, but definitely it doesn't look nice in 
> Clojure.
>  
> In particular I'm not too sure that by storing the init time epoc we 
> actually accomplish anything at all.
> I would argue that there are a number of problems there, race conditions 
> on data, tmp file purged out, and still doesn't protect against the case 
> the clock drift during the use.
>
> 2) use of CAS (atom) for storing the VM state.
> If if is truly decentralized then you shouldn't need an atom at all. The 
> disadvantage of the CAS is that, when many thread race to the same change, 
> only one will succeed and all the other ones will fail and retry. Which 
> mean that if you have 100 threads (for example) only 1 will succeed all the 
> other 99 will fail and retry. Again at the second round only 1 will succeed 
> and 98 will retry, and so on.
> Therefore the total number of attempts will be 
>
>
> <https://lh3.googleusercontent.com/-ZVELcKNoB9M/V2kxgYmlFMI/B8Q/nR6jLFjKSI0611-WiQpQHXAcY3SueVIdwCLcB/s1600/Screen%2BShot%2B2016-06-21%2Bat%2B13.21.24.png>
>
> If you want to develop a real "*decentralized*" id generator, I think, 
> you need to drop the atom in favour of a thread local store.
> Now to do so and make collision impossible we need to add more bits:
>
>
>- 64 bits - ts (i.e. a timestamp )
>- 48 bits - worker-id/node (i.e. MAC address)
>- 32 bits - worker-id/process (pid) 
>- 64 bits - worker-id/thread (thread num)
>- 32 bits - seq-no (i.e. a counter)
>
> By adding the process id (pid) and the thread id there is possibility of 
> having two systems running and creating the same id at the same time.
> Finally by using thread-local storage there is no need of process level 
> coordination (atom) and no risk of retries because every process is 
> stepping on each others toes.
>
> With such setup 100 threads will be able to increment their own thread 
> local counter independently (given that you have 100 execution cores).
>
> What do you think?
> Bruno
>
>  
>
>>
>>

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


Re: clojure.spec - dynamic specs

2016-06-18 Thread Brian Platz

On Friday, June 17, 2016 at 4:04:31 PM UTC-4, Alex Miller wrote:
>
>
>
> On Friday, June 17, 2016 at 2:46:37 PM UTC-5, Brian Platz wrote:
>>
>>
>> I'd like to be able to use clojure.spec for input validation where the 
>> specs are stored in a database using a data structure to represent them.
>>
>
> Why don't you represent them as code loaded by different applications? 
> s/form is designed to give you a wire-portable definition of a spec.
>

Nice feature, thank you for pointing it out.
 

>  
>
>> The following ideas could make this much simpler:
>> - Allow s/keys to accept a spec to use with each key (i.e. the same 
>> format used by s/or).
>>
>
> The independence of attribute specs is a fundamental tenet of spec and 
> this will not be changed.
>

The use of the registry and independence of it I think is great, and the 
two need not confict. I'd primarily use the registry for my applications, 
but testing inputs dynamically lacks support around maps with the exception 
of map-of. 

Right now the only reasonable solution I see is to write my own s/keys-like 
predicate. The request was to allow maps to be tested with a generated spec 
in the same way every other Clojure data structure can be (sans-registry) 
as it seems missing, but not challenge the registry concept and its value.
 

>  
>
>> - Allow a *spec-registry* binding, enabling the use of multiple registries
>>
>
> The notion of multiple registries is something that's been raised, but 
> Rich will have to be the one to comment on that.
>

This could also solve my particular use-case, and I'm sure has some other 
uses.

Thank you for the response.

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


clojure.spec - dynamic specs

2016-06-17 Thread Brian Platz

I'd like to be able to use clojure.spec for input validation where the 
specs are stored in a database using a data structure to represent them.

s/keys and its requirement to use the registry makes this challenging.

I'm able to generate specs dynamically using a workaround like:
(eval (cons 's/and ))

However, I don't see a way of utilizing s/keys in this manner, as the keys 
must first be placed in the registry.

I could register each key also using eval and s/def similarly to my example 
above, however that would eliminate this method's use in a multi-tenant 
environment where one client/instance may have a different spec than 
another.

The following ideas could make this much simpler:
- Allow s/keys to accept a spec to use with each key (i.e. the same format 
used by s/or).
- Allow a *spec-registry* binding, enabling the use of multiple registries

Any other ideas or anything I've missed that would make this use case more 
feasible?






-- 
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 update state in a webapp

2016-05-29 Thread Brian Platz
In a web-app you probably want the thread safety an atom provides, so it 
would be a good choice.

You can include a reference to your atom in your system config if you want 
to retain the reloaded-like / dependency injection pattern:

(def changing-config (atom {}))

;; system-map
(def sys-map
 {:a "a"
  :b 42
  :c changing-config})

(defn my-handler
 [handler sys-map]
 (fn [req] {:status 200 :body @(:c sys-map)}))


On Saturday, May 28, 2016 at 2:16:32 PM UTC-4, babysnakes wrote:
>
> Hey all,
>
> I don't have a lot of experience with clojure but I did write a few small 
> services in clojure. Until now the state of the services I wrote were 
> static so I constructed a system map (more or less following Stuart 
> Sierra's reloaded workflow - without using the component framework) and 
> injected it to the various handlers via middleware closure. This works 
> great when the state is static. Now I have to write a small service where 
> the state should be updated (I have to periodically pull new 
> configurations). The first place I can think of to put this state is in a 
> global atom, but I was wondering if there's a pattern that allows me to 
> dynamically update global state without using global atom.
>
> Thanks in advance
>
> Haim
>

-- 
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] components.md

2016-04-19 Thread Brian Platz

Jeroen,

Happy to talk more about it on Slack.

No matter what you are `def`-ing something somewhere. For Component I’d `def` a 
big config map, and I do the same with Mount. My advantage with Mount in the 
REPL is that I can have local vars for ‘components’ that are easy to reference 
(but still driven from the main config map). In Component I’d accomplish this 
by outputting what I need to a var, usually in the ‘user’ namespace that I 
could get a handle to.

As for several different `mem-db`s, if you mean swapping them out for 
dev/testing, that is explained here: 
https://github.com/tolitius/mount#swapping-alternate-implementations

-Brian



On Apr 19, 2016, at 6:03 AM, Jeroen van Dijk  wrote:

> Hi Brian,
> 
> When looking at the Readme of Mount (I think) I already see global state 
> backed in. 
> 
> (defstate ^{:on-reload :noop} 
>   mem-db :start (connect config) 
>  :stop (disconnect mem-db))
> 
> Do I misunderstand this or do we just disagree on what global state is? What 
> if I want to have several (different) `mem-db` instances, how would that 
> work? 
> 
> 
> 
> On Fri, Apr 8, 2016 at 4:25 PM, Brian Platz  wrote:
> 
> >> This is also something that wouldn't be possible with Mount as this 
> >> library seems to promote global state.
> 
> As a recent switcher from Component to Mount, and without trying to change 
> the thread's topic into a this vs. that -- I'll simply say that I don't 
> believe any of these tools promote global state, it is people who code global 
> state, and that can be with any of these tools... or likewise avoided with 
> any of these tools.
> 
> Some tools (i.e. Component) probably make it more difficult to have global 
> state, but I think it is heavy handed. For projects with a lot of components, 
> I would spend a lot of time backtracking components all feeding into each 
> other to figure out where some var was when working in REPL. I'd also 
> repeatedly deal with errors when adding new components as I didn't set up the 
> dependencies correctly at first... just several interlocking pieces that all 
> need to be coordinated, and I sometimes forget one (or two).
> 
> Mount probably makes it a little easier to have global state, but that is up 
> to the developer - I have no more global state than I had before the switch. 
> I find it easier to work in REPL and get access to a var, or conn, etc. when 
> I need to eval something, and I think all these components are primarily 
> there to make the REPL workflow better. Also, I'm out of the business of 
> managing my dependencies, which my challenges might just root from an 
> absent-mindedness that I possess. Once it is in production, the component 
> stuff matters very little anyhow.
> 
> All to say that these tools, assuming they provide the feature needs that 
> have been outlined well in this thread, should not make anything 'not 
> possible' and can have as much or as little global state as the developer 
> chooses to code in. I cringe a bit when I repeatedly see that Mount promotes 
> global state, I think that is a falsehood.
> 
> -Brian
> 
> 
> -- 
> 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 a topic in the Google 
> Groups "Clojure" group.
> To unsubscribe from this topic, visit 
> https://groups.google.com/d/topic/clojure/hYFEpJ6w80k/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to 
> clojure+unsubscr...@googlegroups.com.
> For more 

ANN: Structural-typing 2.0.1

2016-04-17 Thread Brian Marick
"Structural typing for Clojure, somewhat inspired by Elm. Tailored to 
'flow-style' programming, where complex structures flow through a series 
of functions, each of which makes a smallish change. Can also be used in 
testing tools and the like that need to describe how a nested structure 
differs from a description."


Like prismatic/schema, but coming from a different tradition.

https://github.com/marick/structural-typing/

[Re: 2.X. It is extremely unlikely that you'll have to change client 
code, unless you used functions that were explicitly deprecated.]


--
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: Return from a function

2016-04-17 Thread Brian Marick



Colin Yates wrote:

Also, you might want to invest in either core.typed or prismatic
schema for validating shapes of data. I think Brian Marick of Midje
fame has a similar answer but I can't recall the name.


https://github.com/marick/structural-typing/

--
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] components.md

2016-04-08 Thread Brian Platz

>> This is also something that wouldn't be possible with Mount as this 
library seems to promote global state.

As a recent switcher from Component to Mount, and without trying to change 
the thread's topic into a this vs. that -- I'll simply say that I don't 
believe any of these tools promote global state, it is people who code 
global state, and that can be with any of these tools... or likewise 
avoided with any of these tools.

Some tools (i.e. Component) probably make it more difficult to have global 
state, but I think it is heavy handed. For projects with a lot of 
components, I would spend a lot of time backtracking components all feeding 
into each other to figure out where some var was when working in REPL. I'd 
also repeatedly deal with errors when adding new components as I didn't set 
up the dependencies correctly at first... just several interlocking pieces 
that all need to be coordinated, and I sometimes forget one (or two).

Mount probably makes it a little easier to have global state, but that is 
up to the developer - I have no more global state than I had before the 
switch. I find it easier to work in REPL and get access to a var, or conn, 
etc. when I need to eval something, and I think all these components are 
primarily there to make the REPL workflow better. Also, I'm out of the 
business of managing my dependencies, which my challenges might just root 
from an absent-mindedness that I possess. Once it is in production, the 
component stuff matters very little anyhow.

All to say that these tools, assuming they provide the feature needs that 
have been outlined well in this thread, should not make anything 'not 
possible' and can have as much or as little global state as the developer 
chooses to code in. I cringe a bit when I repeatedly see that Mount 
promotes global state, I think that is a falsehood.

-Brian

-- 
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: conditional logic implemented as pattern-matching and restructuring in the signature of the function

2016-02-13 Thread Brian Marick
To add to the list, I wrote `defpatterned` for /Functional Programming for the Object-Oriented Programmer/. https://github.com/marick/patterned There are probably many others. 

Moving pattern matching closer to `clojure.core` might be a good thing for a roadmap. I'm pretty excited by pattern-matching in Elixir - seems more than a novelty. 


Colin Taylor wrote:

Defm does this too though I've never got round to fully finishing it.

(defm file-or-string-fn []
   ([File] (println "It's a file"))
   ([s :- String] (println "It's a string " s))
   (["magic"] (println "It's magic"))
   ([_] (println "It's a " (type _1



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

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


ANN: Suchwow 5.0.0

2016-02-11 Thread Brian Marick
Suchwow is my grab-bag library of Clojure functions. 5.0.0 is a major 
version bump because I dropped support of Clojure 1.5.


Otherwise, it adds a few new functions plus one potentially significant 
new namespace.


In two jobs, I've wanted to slurp in tabular data (CSV or relational 
queries) and get fast-ish access to parts of it. This basically means 
building indexes to allow quick'n'easy access into (implicit) 
hierarchical structures represented as flat collections of maps.


`such.relational` has some functions to help with that. It also adds new 
doc strings to the relational parts of `clojure.set`, as the existing 
doc strings are perhaps not as clear as the impartial observer might wish.


API: http://marick.github.io/suchwow/such.relational.html
Narrative description: 
https://github.com/marick/suchwow/wiki/such.relational


Enjoy.

Comments welcome.

--
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] fudje - unit testing library vaguely resembling midje, but with less 'calories'

2016-01-31 Thread Brian Marick



Timothy Baldridge wrote:

This is a good example of a DSL, and it falls under the criticisms I
level at most DSLs, mainly they aren't Clojure. If we dive into


I note that Midje once had an intermediate “semi-sweet” functional 
interface that the `fact` macro expanded into. (It was most similar to 
Expectations’.) That’s because I was originally thinking the syntax was 
a little extreme and people would prefer something Lispy or to invent 
their own.


At some point, the extra level of translation got annoying, so I asked 
on the mailing list if anyone objected to my deleting it. No one did.


So there is some user demand for a DSL.

And I think there’s probably a reason why /The Joy of Clojure/ and other 
books write examples in a left-right format like:


 (if true :truthy :falsey);=> :truthy

… rather than:

 (is (= :truthy (if true :truthy :falsey)))

I broadly agree with the idea of avoiding complex macros as DSLs. But 
testing - like textbooks - is a domain where understandability by 
someone new to an API is really important. So it’s a place where user 
experience might trump general principles.


--
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] fudje - unit testing library vaguely resembling midje, but with less 'calories'

2016-01-26 Thread Brian Marick

dimitris wrote:

This is a small testing library inspired by midje.


For what it's worth, I (author of Midje) think this is wonderful.

You might consider emphasizing that you have similar checkers, as I 
think that's one of Midje's strong points. I've been recently 
incorporating https://github.com/marick/structural-typing/ to get better 
error messages when checking collections. Like this:



The checker said this about the reason:
[0 :a :b] should be `even?`; it is `1`
[1 :c] must exist and be non-nil
[2 :a :b] should be `neg?`; it is `2`


Otherwise:


1) The implementation is utterly intimidating (i' ve heard this from
plenty other people)


Yeah. It started as my project to learn Clojure, so it's not... um... 
the way I write code today.



2) Doesn't play nicely with AOT


At two companies, I've used Midje and deployed AOT-compiled uberjars. It 
would be interesting to have a specific example of the problem.


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

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


Re: [ANN] Clojure 1.8.0-RC3

2015-12-14 Thread Brian Marick
Noam: does this mean it's not an issue with Midje? If it is, I'll look 
into it.


Noam Ben-Ari wrote:

After upgrading to [reduce-fsm "0.1.4"] all my tests pass with RC3 :-)

On Tuesday, December 8, 2015 at 3:14:21 PM UTC+2, Noam Ben-Ari wrote:

Thanks for the prompt response, I have filed a ticket to the library
author:

https://github.com/cdorrat/reduce-fsm/issues/9


On Tuesday, December 8, 2015 at 3:07:34 PM UTC+2, Nicola Mometto wrote:

Before 1.8, clojure would accept wrong forms like (throw
my-exception 1 2 3).

This is now an exception
http://dev.clojure.org/jira/browse/CLJ-1456
.


 > On 8 Dec 2015, at 13:05, Noam Ben-Ari  wrote:
 >
 > Hi,
 > I have just tried 1.8.0-RC3 and saw a problem.
 >
 > I have a project in which I run tests with `lein midje`, and
this runs fine with 1.7.0.
 >
 > When I change the clojure dependency to 1.8.0-RC3 and run it
I get this exception:
 >
 > ---
 >
 > Exception in thread "main" java.lang.RuntimeException: Too
many arguments to throw, throw expects a single Throwable
instance, compiling:(reduce_fsm.clj:203:5)
 >
 > ---
 >
 > Let me know what other information I can give to help.
 >
 > Thanks,
 > Noam.
 >
 > On Wednesday, December 2, 2015 at 6:03:31 PM UTC+2, Alex
Miller wrote:
 > Clojure 1.8.0-RC3 is now available. This build is a "release
candidate"! We would appreciate any and all testing you can do
on your own libraries or internal projects to find problems.
 >
 > Try it via
 > • Download:
https://repo1.maven.org/maven2/org/clojure/clojure/1.8.0-RC3

 > • Leiningen: [org.clojure/clojure "1.8.0-RC3"]
 > Below are the changes since 1.8.0-RC2. See the full 1.8
change log here:
https://github.com/clojure/clojure/blob/master/changes.md
.
 > • CLJ-1845 / CLJ-1851 New ^:redef to mark vars that
should not be direct linked
 > • The metadata ^:redef can be used to mark
function vars that should not be direct linked
 > • clojure.core/load was previously marked
with ^:dynamic for this purpose, but is now marked ^:redef
 > • CLJ-1856 Direct linking breaks clojure.test
location reporting for failures
 > • CLJ-1854 Set line number in bytecode prior to
invokeStatic call
 > • CLJ-1853 In socket server, require the ns of the
accept-fn before resolving it
 >
 > --
 > You received this message because you are subscribed to the
Google
 > Groups "Clojure" group.
 > To post to this group, send email to clo...@googlegroups.com
 > Note that posts from new members are moderated - please be
patient with your first post.
 > To unsubscribe from this group, send email to
 > clojure+u...@googlegroups.com
 > For more options, visit this group at
 > http://groups.google.com/group/clojure?hl=en

 > ---
 > You received this message because you are subscribed to the
Google Groups "Clojure" group.
 > To unsubscribe from this group and stop receiving emails from
it, send an email to clojure+u...@googlegroups.com.
 > For more options, visit https://groups.google.com/d/optout
.

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

[ANN] Specter book approach: please evaluate

2015-11-22 Thread Brian Marick
I announced a while back that I'd be writing a short book on Specter 
https://github.com/nathanmarz/specter After some thrashing and the usual 
interruptions, I have the first chapter written. I've taken an unusual 
approach: teaching Specter by having you implement parts of it. I'm 
curious to hear people's opinions.


Here: https://leanpub.com/specter

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: Help with idiomatic clojure.

2015-11-13 Thread Brian
I think I like 'seq' better than 'empty?'.I'm sure my opinions will
firm up after writing some more clojure.

> Also, in no-errors branch you probably want to return status: 200?
I  picked the function where I knew there was a better way.   This
validation function is called from this bit code.
(POST "/usagelog" req
   (let [errors (validate-request req)]
  (if (seq errors)
 errors
 (ring.util.response/response (grep-log-and-response req)))
   )
)


On Thu, Nov 12, 2015 at 4:08 PM, Colin Yates  wrote:

> One other minor point (if (seq some-sequence) true false) is preferred by
> some (I won’t say more idiomatic) than (if (empty? some-sequence) true
> false). Also, in no-errors branch you probably want to return status: 200?
>
>
> On 12 Nov 2015, at 19:44, Brian  wrote:
>
> Thanks Colin, Thanks Erik
> Exactly what I was looking for.
>
> I've updated the gist with Colin's suggestion and a bit of destructuring.
> If this project gets any bigger I will definitely look at vlad
> <https://github.com/logaan/vlad> and Prismatic Schema
> <https://github.com/Prismatic/schema>.
>
> BDF.
>
> On Thu, Nov 12, 2015 at 12:02 PM, Erik Assum  wrote:
>
>> There is also https://github.com/logaan/vlad which helps with
>> validation.
>>
>> Erik.
>> --
>> i farta
>>
>> Den 12. nov. 2015 kl. 17.12 skrev Colin Yates :
>>
>> A nicer equivalent form would be:
>>
>> (cond-> []
>>   this-error? (conj “It failed with this error”)
>>   that-error? (conj “It failed with that error”))
>>
>> However, purely for validation there are a few utilities out there
>> already. Checkout the ‘Validation’ section on
>> http://www.clojure-toolbox.com
>>
>> Also, in terms of enforcing contracts - Prismatic Schema is highly
>> recommended but hard to ‘englishify’ the errors. Failures are considered
>> API failures rather than happy-case failures.
>>
>> On 12 Nov 2015, at 16:09, Brian Forester 
>> wrote:
>>
>> I'm writing a very small REST application in clojure using compojure and 
>> ring.  One problem is that I don't have anyone who can review my work or 
>> provide feedback.
>>
>>
>> I've written a small function to validate a simple JSON request.  I'm 
>> validating the three values that are in the post and collecting the errors 
>> for return.
>>
>> The core mechanic I've used
>>
>>  (swap! errors str "'grepString' must not be null or empty.\n"))
>>
>> does not seem to be a very idiomatic clojure way to solve this simple 
>> problem.
>>
>>
>> https://gist.github.com/BDF/8e61daf8fe8b602a248a
>>
>>
>> Any feedback is appreciated.
>>
>> BDF.
>>
>>
>>
>>
>> --
>> 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.
>>
>>
>> --
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to c

Re: Help with idiomatic clojure.

2015-11-12 Thread Brian
Thanks Colin, Thanks Erik
Exactly what I was looking for.

I've updated the gist with Colin's suggestion and a bit of destructuring.
If this project gets any bigger I will definitely look at vlad
<https://github.com/logaan/vlad> and Prismatic Schema
<https://github.com/Prismatic/schema>.

BDF.

On Thu, Nov 12, 2015 at 12:02 PM, Erik Assum  wrote:

> There is also https://github.com/logaan/vlad which helps with validation.
>
> Erik.
> --
> i farta
>
> Den 12. nov. 2015 kl. 17.12 skrev Colin Yates :
>
> A nicer equivalent form would be:
>
> (cond-> []
>   this-error? (conj “It failed with this error”)
>   that-error? (conj “It failed with that error”))
>
> However, purely for validation there are a few utilities out there
> already. Checkout the ‘Validation’ section on
> http://www.clojure-toolbox.com
>
> Also, in terms of enforcing contracts - Prismatic Schema is highly
> recommended but hard to ‘englishify’ the errors. Failures are considered
> API failures rather than happy-case failures.
>
> On 12 Nov 2015, at 16:09, Brian Forester  wrote:
>
> I'm writing a very small REST application in clojure using compojure and 
> ring.  One problem is that I don't have anyone who can review my work or 
> provide feedback.
>
>
> I've written a small function to validate a simple JSON request.  I'm 
> validating the three values that are in the post and collecting the errors 
> for return.
>
> The core mechanic I've used
>
>  (swap! errors str "'grepString' must not be null or empty.\n"))
>
> does not seem to be a very idiomatic clojure way to solve this simple problem.
>
>
> https://gist.github.com/BDF/8e61daf8fe8b602a248a
>
>
> Any feedback is appreciated.
>
> BDF.
>
>
>
>
> --
> 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.
>
> --
> 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.


Help with idiomatic clojure.

2015-11-12 Thread Brian Forester


I'm writing a very small REST application in clojure using compojure and ring.  
One problem is that I don't have anyone who can review my work or provide 
feedback.


I've written a small function to validate a simple JSON request.  I'm 
validating the three values that are in the post and collecting the errors for 
return.

The core mechanic I've used

 (swap! errors str "'grepString' must not be null or empty.\n"))

does not seem to be a very idiomatic clojure way to solve this simple problem.


https://gist.github.com/BDF/8e61daf8fe8b602a248a


Any feedback is appreciated.

BDF.



-- 
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] Structural-typing 1.0

2015-11-01 Thread Brian Marick

https://github.com/marick/structural-typing/

This is a validation or type-checking library for Clojure, playing in 
roughly the same space as Prismatic Schema, Bouncer, or Validateur. It 
was inspired by Elm's structural typing and my previous need to validate 
complex data structures flowing into Clojure microservices.


Here is an example of a complex-ish type declaration. It could be made 
more terse, but that wouldn't be useful as an example.


(type! :Line (requires :head :tail)
 {:color [rgb-color? not-puce?]}  ; optional by default
 {:head  (includes :Point)
  :tail  (includes :Point)})

(Note that `type!` mutates a "global type repo". That's nice for 
examples, but there's a functional interface as well.)


--

The most common question I'm asked is how this differs from Schema. Let 
me immediately give you reasons to stop reading:


* Schema is roughly a superset (in terms of functionality)
* Schema supports Clojurescript, and this doesn't.

--

If you're still here, I'll describe some of the differences in emphasis 
that might make this library fit your needs. (Note, though, that I 
haven't used Schema in a real project, so my claims about it might be 
ignorant.)


Here are two expressions that do the same thing:

user=> (s/validate s/Keyword 42); Schema

ExceptionInfo Value does not match schema: (not (keyword? 42)) 
schema.core/validator/fn--1807 (core.clj:151)


user=> (t/built-like keyword? 42)   ; Structural-typing
Value should be `keyword?`; it is `42`
=> nil

Several things can be seen here:

1. Schema takes a roughly conventional approach to typing (so-called 
"nominal typing") in which (a) there are primitive types that are 
"things", (b) complex types are built up from primitives, and (c) the 
type system looks much like those that can be checked statically.


In my library, types are entirely about satisfying predicates. There is 
not a "type" called Keyword; there's just Clojure's `keyword?` 
predicate. (Note that, until someone solves the halting problem, this 
throws away any hope that this type system could mesh with one that can 
be statically checked.)


2. By default, a Structural-typing type failure prints a message to 
standard output and returns nil. The reason for not throwing an 
exception is that I love "pipeline" or "threaded" computation:


   (-> structure
   do-this
   do-that)

Structural-typing is designed so that `built-like` can be tidily 
inserted into such a threaded expression:


   (some-> (built-like :MyType structure)
   do-this
   do-that)

(It's very likely that you'd override the default behavior to do 
something other than `println`, but you'd still return `nil`. Or, if 
you're monadically inclined, it's easy to make built-like return 
`Either` values.)


3. I have an unnatural fondness for good error messages, so the default 
error messages have been tweaked to be pleasing to the eye. They are 
also customizable.




If you've read this far, I'll refer you to the documentation rather than 
explain more.


https://github.com/marick/structural-typing  ; README
https://github.com/marick/structural-typing/wiki ; user guide
http://marick.github.io/structural-typing/   ; API

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


lazyseq?

2015-10-18 Thread Brian Marick
Is there a way to tell if `v` is a lazyseq other than `(instance? 
clojure.lang.LazySeq v)`? Seems like there should be, but I'm not seeing it.


[Preparing to say "duh!"]

--
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: deprecation warnings?

2015-10-17 Thread Brian Marick



William la Forge wrote:

Going forward, I'd like to deprecate some functions and have a warning
displayed on first use. So I've done this:


I use defprecate https://github.com/alexander-yakushev/defprecated

--
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] Shrubbery 0.3.0, a stubbing, spying, and mocking library for Clojure protocols

2015-10-06 Thread Brian Guthrie
On Tue, Oct 6, 2015 at 6:16 AM, Atamert Ölçgen  wrote:

> It would be great if multiple return values for multiple calls were
> supported. First use case it something like an iteration, calling some
> protocol method repeatedly (possibly with different inputs). Another use
> case is just calling it with different inputs, expecting different outputs.
> Something like (add (square x) (square y)).
>

That's an excellent suggestion; it's not something I've needed yet but it's
a common enough use-case. It should be easy enough to riff on stubs, though
trickier to set up call-based return values; I'll think on it. Thanks for
the feedback.

Cheers,

Brian

-- 
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] Shrubbery 0.3.0, a stubbing, spying, and mocking library for Clojure protocols

2015-10-05 Thread Brian Guthrie
Great to hear! Let me know if there are any questions I can answer.
Feedback gratefully accepted.

Cheers,

Brian

On Mon, Oct 5, 2015 at 11:56 AM, James Reeves  wrote:

> Very nice. I was looking for something like this.
>
> - James
>
> On 5 October 2015 at 15:14, Brian Guthrie  wrote:
>
>> Clojure protocols are a great way to encapsulate operations with side
>> effects, but suffer from a lack of general test tooling. Shrubbery provides
>> a small set of basic building blocks for working with them:
>>
>>  * stub, which accepts a variable list of protocols and a optional
>> hashmap of simple value implementations and returns an object that reifies
>> all given protocols;
>>  * spy, which accepts an object with at least one protocol
>> implementation and returns a new implementation that tracks the number of
>> times each of its members were called;
>>  * mock, which wraps a stub in a spy, allowing callers to supply basic
>> function implementations and assert against those calls; and
>>  * calls/received?, which in conjunction with the Matcher protocol
>> provide a way to query spies and assert against their state.
>>
>> Shrubbery is test-framework-agnostic, avoids altering runtime state to
>> the degree possible, and uses no macros. It should work nicely with
>> refactorings like rename-function.
>>
>> https://github.com/bguthrie/shrubbery
>>
>> [com.gearswithingears/shrubbery "0.3.0"]
>>
>>
>> New in this release:
>>
>> – Support for multiple protocols in both spies and stubs.
>> – Spies attempt to automatically derive the given implementation's
>> protocols, and tracks calls to all of them. (This behavior can be
>> overridden.)
>> – Replaced all macros with plain functions. (Unfortunately, this means
>> leaning on eval in some cases.)
>>
>> Cheers,
>>
>> Brian
>>
>> --
>> 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.
>

-- 
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] Shrubbery 0.3.0, a stubbing, spying, and mocking library for Clojure protocols

2015-10-05 Thread Brian Guthrie
Clojure protocols are a great way to encapsulate operations with side
effects, but suffer from a lack of general test tooling. Shrubbery provides
a small set of basic building blocks for working with them:

 * stub, which accepts a variable list of protocols and a optional hashmap
of simple value implementations and returns an object that reifies all
given protocols;
 * spy, which accepts an object with at least one protocol implementation
and returns a new implementation that tracks the number of times each of
its members were called;
 * mock, which wraps a stub in a spy, allowing callers to supply basic
function implementations and assert against those calls; and
 * calls/received?, which in conjunction with the Matcher protocol provide
a way to query spies and assert against their state.

Shrubbery is test-framework-agnostic, avoids altering runtime state to the
degree possible, and uses no macros. It should work nicely with
refactorings like rename-function.

https://github.com/bguthrie/shrubbery

[com.gearswithingears/shrubbery "0.3.0"]


New in this release:

– Support for multiple protocols in both spies and stubs.
– Spies attempt to automatically derive the given implementation's
protocols, and tracks calls to all of them. (This behavior can be
overridden.)
– Replaced all macros with plain functions. (Unfortunately, this means
leaning on eval in some cases.)

Cheers,

Brian

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


Re: Clojure/Pedestal vs Go

2015-09-16 Thread Brian Hurt
I have no flipping clue what "system-level programming" means these days,
and I'm hoping someone could spell it out.  I used to think (back when I
was doing that sort of stuff) that it mean operating systems level stuff-
device drivers, embedded, real time, stuff like that.  But no language with
a GC or non-trivial run time is a good fit for that.  From usage, I now
think it means "we refuse to use Java".

On Tue, Sep 15, 2015 at 11:45 PM, Mikera 
wrote:

> Go is fine for system-level programming, but I personally wouldn't use it
> as a web application programming language. Ten reasons to consider.:
>
> 1. There isn't really much speed difference on micro-benchmarks between
> JVM code and Go. See e.g.:
> http://benchmarksgame.alioth.debian.org/u64q/go.html
>
> 2. In many real-world cases JVM code will outperform Go, see e.g.
> http://zhen.org/blog/go-vs-java-decoding-billions-of-integers-per-second/
>
> 3. The JVM GC is superior to the GC in Go. This makes a big difference for
> complex applications with a lot of live objects on the heap, especially
> when dealing with stuff like immutable persistent data structures (and you
> want to use those, right?). Overall, I'd expect Clojure to easily
> outperform Go for these types of applications.
>
> 4. The JVM startup time / memory overhead is irrelevant for long running
> server applications. If you are restarting the JVM regularly, you are
> definitely doing something wrong. The JVM is well tuned for long-running
> server side web applications in general, rather than the lightweight
> processes / scripts that are more suited to Go.
>
> 5. Functional programming is natural in Clojure and is IMHO the future for
> building modern applications
>
> 6. If you like the CSP stuff (goroutines, channels etc.), Clojure has the
> excellent core.async, which basically lets you do all the nice CSP type
> things in Clojure you can do in Go. However that isn't forced on you:
> Clojure supports a lot of other paradigms for concurrent programming.
> Choose what works best for you.
>
> 7. The open source library ecosystem on the JVM is awesome. There's
> nothing like it for any other language. Even if nobody has written a
> Clojure library that wraps up the functionality you need yet, using Java
> libraries from Clojure is very painless (often easier than using Java
> libraries from Java!)
>
> 8. Virtually all the key big data stuff depends on the JVM. Spark, Hadoop
> ecosystem etc. Being on the JVM is a valuable strategic choice if you are
> into data processing. / analytics.
>
> 9. Clojure has an compelling full stack development story with
> ClojureScript on the browser and Clojure on the server. It's pretty useful
> to be able to share code between the server and the client.
>
> 10. Once you've experienced interactive REPL driven web application
> development with stuff like Figwheel, you probably won't want to go back to
> anything else
>
> On Monday, 14 September 2015 03:44:48 UTC+8, Alan Thompson wrote:
>>
>> Hi,
>>
>> I'm about to start a new web project and they are thinking about using Go
>> (golang) instead of a JVM (preferably Clojure) based approach.  The idea is
>> "BARE METAL SPEED!!!", but I really think the network and DB will be the
>> bottlenecks, not Clojure vs Go.
>>
>> Is anybody out there aware of any speed comparisons using
>> Clojure/Pedestal and/or Go?  I'm thinking basic measurements like
>> connections/sec, latency, simultaneous users, etc.
>>
>> Thanks,
>> Alan
>>
> --
> 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: Is there a better way to do this than reduce + nested map?

2015-09-13 Thread Brian Platz
Not sure I follow Colin's suggestion entirely, but his suggestion led me to 
this which is better. I'd still love any other suggestions to improve!

(def entities [{:name "foo" :location "us"} {:name "bar" :location "de"}])
(def locations [{:location "us" :id 100} {:location "de" :id 101}])

;; make an intermediary locations into a large single map of format {"us" 
100 "de" 101}
(def locations* (apply hash-map (mapcat vals locations)))

(map #(assoc % :location (get locations* (:location %))) entities)

=> ({:name "foo", :location 100} {:name "bar", :location 101})


On Sunday, September 13, 2015 at 10:56:14 AM UTC-4, Colin Yates wrote:
>
> I would transform the locations into {location id} and then use merge.
>
> On 13 Sep 2015, at 3:14 PM, Brian Platz > 
> wrote:
>
> I have a pattern that comes up frequently, when I need to merge some value 
> into one map list from matching keys in a second map list.
>
> I've developed a way to handle it, but I think it could be better. Here is 
> a simple example of it:
>
> In the below case, we are looking to replace the :location in entities 
> with the respective location id found in the second list:
>
> (def entities [{:name "foo" :location "us"} {:name "bar" :location "de"}])
> (def locations [{:location "us" :id 100} {:location "de" :id 101}])
>
> (reduce (fn [entities loc]
>   (->> entities
>(map (fn [entity]
>   (if (= (:location entity) (:location loc))
> (assoc entity :location (:id loc))
> entity) 
> entities locations)
>
> => ({:name "foo", :location 100} {:name "bar", :location 101})
>
> This works, however it feels like there should be an easier way in clojure 
> that is at minimum more readable, and ideally even more performant.
>
> Any suggestions?
>
> Thanks!
>
> -- 
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@googlegroups.com 
> Note that posts from new members are moderated - please be patient with 
> your first post.
> To unsubscribe from this group, send email to
> clojure+u...@googlegroups.com 
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> --- 
> You received this message because you are subscribed to the Google Groups 
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to clojure+u...@googlegroups.com .
> For more options, visit https://groups.google.com/d/optout.
>
>
>

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


Is there a better way to do this than reduce + nested map?

2015-09-13 Thread Brian Platz
I have a pattern that comes up frequently, when I need to merge some value 
into one map list from matching keys in a second map list.

I've developed a way to handle it, but I think it could be better. Here is 
a simple example of it:

In the below case, we are looking to replace the :location in entities with 
the respective location id found in the second list:

(def entities [{:name "foo" :location "us"} {:name "bar" :location "de"}])
(def locations [{:location "us" :id 100} {:location "de" :id 101}])

(reduce (fn [entities loc]
  (->> entities
   (map (fn [entity]
  (if (= (:location entity) (:location loc))
(assoc entity :location (:id loc))
entity) 
entities locations)

=> ({:name "foo", :location 100} {:name "bar", :location 101})

This works, however it feels like there should be an easier way in clojure 
that is at minimum more readable, and ideally even more performant.

Any suggestions?

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: midje only 1 test

2015-09-12 Thread Brian Marick



Roland Kaercher wrote:

I *strongly* recommend doing all your testing in a repl buffer. That
given, there are two ways to solve your problem. The first, which I
prefer, is to start by testing everything:

 (use 'midje.repl)
 (autotest)


Other than having a REPL, is this different than doing `lein midje
:autotest`?


In theory, no, but I find having a repl you can switch to and try things 
out to be a big advantage.


--
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: midje only 1 test

2015-09-05 Thread Brian Marick
I *strongly* recommend doing all your testing in a repl buffer. That 
given, there are two ways to solve your problem. The first, which I 
prefer, is to start by testing everything:


(use 'midje.repl)
(autotest)

Then, when you change any text and save the namespace it's in, all tests 
that depend on that namespace will be rerun, including the one you're 
specifically working on.


The other alternative is to rerun your specific test with something like:

(check-facts #"fact description")

... or, once you've run a specific fact:

(recheck-fact)



r/ Wobben wrote:

hello,

Suppose I have this test

(facts "do-a-thing" {:exercise 1  :points 1}  (do-a-thing 3) =>
46656.0 (do-a-thing 1) => 4.0(do-a-thing 0) => 1.0)


Is there a way I can only run this test
I tried lein midje :filter exercise 1
but that one fails.

Roelof

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


Interest in a book on Nathan Marz's Specter?

2015-08-28 Thread Brian Marick
Specter https://github.com/nathanmarz/specter is a library for querying 
and "updating" data structures. For most things, I prefer it to zippers 
or hand-written descent functions. Specter's approach is similar to 
lenses, but I find it easier to understand and more featureful.


When starting out, I would have liked a short, exercise- and 
example-filled book on Specter. I'm thinking of writing that book.


Leanpub lets people indicate their interest on a book's webpage, which 
is here: https://leanpub.com/specter If you are, please do.


Brian Marick

--
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 can find something inside heavily nested data structure ?

2015-08-25 Thread Brian Marick



Dave Tenny wrote:

Specter looks nice.  I didn't see any examples in the readme or tests
for working with more deeply nested data structures such as those
discussed in this thread, any pointers?


Here's an example that might be relevant to the original question. 
Suppose you have this structure:


(def deep {:a [{:b [{:key 33 :uuid "zyx"}]}
   {:b [{:key 4, :uuid "zzz"}]}]})

You want to print out the terminal maps where the `:uuid` is "zyx". You 
can do that like this:


user=> (select [:a ALL :b ALL #(= "zyx" (:uuid %))] deep)
[{:key 33, :uuid "zyx"}]


My `structural-typing` library builds a DSL for sort-of type 
declarations on top of specter. 
https://github.com/marick/structural-typing/ The code is kind of tricksy 
in the parts that use Specter, so I don't know if it'll be of much help.


I plan to propose a short (50 pp.) booklet on specter, to be published 
on Leanpub. I'll announce it on this mailing list shortly, and use 
Leanpub to gauge whether there's enough interest.




--
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: Reviewers needed for new Clojure book!

2015-08-25 Thread Brian
A bit late to the party but please include me in the list of possible
reviews.
thanks,
BDF.


On Tue, Aug 25, 2015 at 12:06 AM, Akhil Wali 
wrote:

> Thank you everyone for the great response!
> I'll notify Packt and they shall contact anyone who is shortlisted as a
> reviwer.
>
>
> On Monday, August 24, 2015 at 12:16:06 PM UTC+5:30, Akhil Wali wrote:
>>
>> If anyone is interested in being a reviewer for a new book "*Mastering
>> Clojure*" by Packt Publishing, please let me know.
>> Reviewers will be entitled to a 6 montn subscription of PacktLib
>> .
>>
>> Here's the list of topics covered in this title.
>>
>>-
>>- Working with Sequences and Types
>>- Orchestrating Concurrency and Parallelism
>>- Parallelization using Reducers
>>- Writing Macros
>>- Composing Transducers
>>- Using Functors and Monads
>>- Programming with Logic
>>- Asynchronous Programming
>>- Reactive Programming
>>- Working with Tests
>>- Troubleshooting and Best Practices
>>
>>
>> --
> 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: How can find something inside heavily nested data structure ?

2015-08-23 Thread Brian Marick



Andy- wrote:

I have yet to evaluate it myself but this might do help you:

https://github.com/nathanmarz/specter



Specter is great.

--
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] suchwow: a grab-bag library with some twists

2015-08-06 Thread Brian Marick



Colin Fleming wrote:

I think that would be great. It would be preferable to have a single
repo for docstring improvements so that tools can obtain them without
bringing in other things from e.g. such-wow.


Note that everything in suchwow is public domain, so the docstrings 
there can be grabbed at will and incorporated wherever.


--
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: Tool authors: ClojureScript support in tools.namespace?

2015-07-25 Thread Brian Marick

Midje

Stuart Sierra wrote:

1. Do you need/want ClojureScript support?


Eventually, but not soon.



2. What namespaces (repl, find, dir, file, parse) do you call in
tools.namespace?


repl, dir, track, reload



3. How would you like to distinguish between "get me Clojure
sources" and "get me ClojureScript sources"?


I don't have an opinion.

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


  1   2   3   4   5   6   7   8   9   10   >