Re: [ANN] Clojure 1.10.1-beta1

2019-03-31 Thread Ben Brinckerhoff
I see that this handler uses `ex-str`, which is nice because `ex-str` in 
turn calls `*explain-out*` which is user-configurable. 

Is there a recommended way to configure `s/*explain-out*` such that this 
configuration will be run before other namespaces are loaded?

For instance, this code would set up Expound, but right now I'm not sure 
how to reliably run it before other namespaces load:

(require '[expound.alpha :as expound] '[clojure.spec.alpha :as s])
(alter-var-root #'s/*explain-out* (constantly (expound/custom-printer 
{:print-specs? false :show-valid-values? true :theme :figwheel-theme})))

Thanks,
Ben

On Thursday, March 21, 2019 at 10:35:32 PM UTC-6, Alex Miller wrote:
>
> 1.10.1-beta1 is now available. You can try it with clj using:
>   clj -Sdeps '{:deps {org.clojure/clojure {:mvn/version 
> "1.10.1-beta1"}}}'
>
> 1.10.1-beta1 includes the following changes since 1.10.0:
>
>- CLJ-2484  - Fix Java 
>performance regression loading user.clj
>- CLJ-2463  - 
>clojure.main uncaught exception handling
>- CLJ-2491  - Fix 
>fragile tests that fail under Java 12
>
> The issue in CLJ-2484 was introduced in Java itself, specifically Java 1.8 
> u202, Java 11.0.2, and Java 12. It primarily affects loading of user.clj 
> and can cause a significant load time difference for anything done in 
> user.clj. CLJ-2463 affects how errors are reported from clojure.main. This 
> includes many Clojure uses under tools like Leiningen, such as compile, 
> test,  etc.  
>
> We would greatly appreciate feedback if you could check out this release 
> in your own project and give it a try!! 
>

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

2017-12-11 Thread Ben Brinckerhoff

Very cool! Excellent work.


On Monday, December 11, 2017 at 7:23:38 AM UTC-7, OHTA Shogo wrote:
>
> Hi, all
>
> I’m happy to announce the first release of Pinpointer, yet another 
> implementation of spec error reporter based on a precise error analysis.
>
> - https://github.com/athos/Pinpointer
>
> Pinpointer provides functionalities very similar to the existing spec 
> error reporters (eg. Expound[1], Inspectable[2] etc.), that is, reporting 
> spec errors in a more human-readable way.
>
> [1] https://github.com/bhb/expound
> [2] https://github.com/jpmonettas/inspectable
>
> Unlike those libraries, which analyze spec errors using several 
> heuristics, Pinpointer performs a systematic error analysis traversing a 
> pair of the spec and the input. This makes it possible to report the error 
> even in complicated cases where s/conformer would transform the input 
> value, like the following:
>
> => (require '[pinpointer.core :as p] '[clojure.spec.alpha :as s])
> => (p/pinpointer (s/and string? (s/conformer seq) (s/* #{\a})) "aabaa")
> Detected 1 spec error:
> --
> (1/1)
>
>
> Cause: (\a \a \b \a \a)
>   ^^   
>  Expected: #{\a}
>
>
>--- This comes originally from ---
>
>
>  Original: "aabaa"
>^^^
>  Spec
>   Applied: (s/and string? (s/conformer seq) (s/* #{\a}))
>
>
> --
> nil
> user=>
>
>
> (BTW the above example is just a demo for Pinpointer's capability, and it 
> doesn't mean to encourage you to write specs like that.)
>
> On the other hand, one of the downsides of the library is that Pinpointer 
> has to know in advance the behaviors of the spec macros involved in a spec 
> form for its error analysis. Note also that, Pinpointer occasionally uses  
> eval under the hood (at least for now), so it’s basically intended to be 
> used for development purpose only.
>
> I hope you’ll like it :)
>
> Thanks,
> Shogo
>

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

2017-12-08 Thread Ben Brinckerhoff
Thanks Juan! This works in Clojure, but it doesn't work for me in 
Clojurescript due to the use of "resolve"

" Assert failed: Argument to resolve must be a quoted symbol"

This is where I got stuck too. 

It looks like spec does have access to the predicate at runtime (after all, 
it can figure out the right spec when I call 'valid', etc), but there 
doesn't seem to be a way for a caller to get access to that predicate. If 
there was, I think this would be solvable.

Andy - yes, you're right, a tool like eastwood could inspect the AST and 
catch this. Maybe that's the best approach if the spec registry and spec 
implementations don't expose the information to support a linter like this.

On Friday, December 8, 2017 at 7:42:33 AM UTC-7, Juan Monetta wrote:
>
> I added some stuff on 
> https://gist.github.com/stuarthalloway/f4c4297d344651c99827769e1c3d34e9 
> 
>  that 
> makes your example work I think.
>
> We can use in Clojure and ClojureScript something like:
>
> (defn multi-spec-sub-specs
>   "Given a multi-spec form, call its multi method methods to retrieve
>   its subspecs in the form of [multi-method-key sub-spec-form]."
>   [multi-spec-form]
>   (let [[_ multi-method-symbol & _] multi-spec-form]
> (->> (resolve multi-method-symbol)
>  deref
>  methods 
>  (map (fn [[spec-k method]]
> [spec-k (s/form (method nil))])
>
> to go down inside multi-specs.
>
> Juan
>

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

2017-12-07 Thread Ben Brinckerhoff
I ran into a case today where I mistyped the keyword in a `keys` spec and 
was surprised that validation was not catching invalid data. For my 
purposes, it would be sufficient to have a automated test that looks at my 
specs and identifies typos in the spirit of 
https://gist.github.com/stuarthalloway/f4c4297d344651c99827769e1c3d34e9

However, I ran into a problem because my `keys` specs are often generated 
by the various multi-methods in a multi-spec. I took a stab at implementing 
a version of a "spec linter" that would catch typos in multi-specs, but I 
couldn't get anything that worked (at least in Clojurescript, I haven't 
tried implementing it in Clojure).

Is it possible to write a CLJS linter that will catch the missing spec in 
the example below? If so, great! If not, I worry that the recommended 
approach of adding a linter on top of spec may not be sufficient in this 
case. 

 (s/def ::name string?)
 (defmulti msg :msg-type)
 (defmethod msg :greeting [x]
(s/keys :req-un [::name]))
 (defmethod msg :count [x]
   (s/keys :req-un [::num]))
 (s/def ::msg (s/multi-spec msg :msg-type))

(I suppose it's always going to be possible to write a linter that walks the 
Clojure code and understands the semantics of the above macros, but I was 
hoping I could write one using the data contained in the spec registry instead)


Ben

On Thursday, November 23, 2017 at 7:09:15 AM UTC-7, Nico Schneider wrote:
>
> Hello everyone,
>
> On Thursday, 16 November 2017 23:29:56 UTC+1, John Newman wrote:
>>
>> [...] when we constrain maps in that closed way, aren't we creating some 
>> new subtype of a map, with fundamentally different semantics? If you are 
>> going to fully close a map, you might as well use a deftype and make a 
>> custom object and not call it a map, right?
>>
>
> Just to add my two cents, I've been following the discussion and this has 
> been my thinking for quite some time. Is it not a valid argument? Having a 
> validation mechanism pick only certain keys, or ensuring that keys in a map 
> are specced, look as trivial to me than other data wrangling we do in 
> Clojure. My (preliminary) conclusion in cases like this is to build 
> validation tooling around spec, instead of using it directly.
>

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


Re: [ANN] expound 0.1.2

2017-07-25 Thread Ben Brinckerhoff
Please keep in mind that I have not yet used Inspectable, but my impression 
from reading the README is they both help developers understand 
spec-related failures.

Inspectable does this by providing rich, interactive UI that allows 
developers to explore the specifics of a spec failure at the REPL. This UI 
can be brought up at the REPL manually or you can set up a `caught` 
function to automatically open this UI upon instrumentation or macroexpand 
failures. 

Furthermore, Inspectable lets you explore specs interactively via 
`browse-spec`.

On the other hand, Expound is a drop-in alternative for the string returned 
by by Spec in the case of failures. You can use this output wherever a 
human might read about a spec failure: in the REPL, in unit tests, in the 
browser console, in an error message for a REST API, and more. Since it is 
just static text, you can't interactively explore the failure or browse 
specs.

Personally, I expect I'll use Inspectable during REPL-driven-development, 
but use Expound in my unit tests or when validating data that I consume 
from a 3rd party API.

I hope that Juan Monetta (the author of Inspectable) will correct me if 
I've gotten anything wrong and add his perspective. Juan?

Ben

On Tuesday, July 25, 2017 at 6:12:21 PM UTC-6, Andy Fingerhut wrote:
>
> inspectable was recently announced in this group as well.  Do you know 
> what the similarities and differences are between these projects?
>
> Andy
>
> On Tue, Jul 25, 2017 at 4:16 PM, Ben Brinckerhoff <bhbrinc...@gmail.com 
> > wrote:
>
>> Expound formats clojure.spec errors in a way that is optimized for humans 
>> to read. Expound works in Clojure and Clojurescript.
>>
>> This release provides human-optimized error messages when using a number 
>> of spec features, including instrumentation and `assert`.
>>
>> More information is available in the README 
>> <https://github.com/bhb/expound/blob/master/README.md>.
>>
>> -- 
>> 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.


[ANN] expound 0.1.2

2017-07-25 Thread Ben Brinckerhoff
Expound formats clojure.spec errors in a way that is optimized for humans 
to read. Expound works in Clojure and Clojurescript.

This release provides human-optimized error messages when using a number of 
spec features, including instrumentation and `assert`.

More information is available in the README 
.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from 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: Trouble understanding clojure.spec.alpha/problems :path :via :in

2017-07-13 Thread Ben Brinckerhoff
> I'm currently trying something very similar to expound but with a GUI 
approach to explore errors.

I look forward to seeing what you come up with!

Ben

On Thursday, July 13, 2017 at 8:48:45 AM UTC-6, Juan Monetta wrote:
>
> Yeah, I read your expound code, really nice btw.
>
> I'm currently trying something very similar to expound but with a GUI 
> approach to explore errors.
>
> I think encoding map paths as [key pos-in-map-entry] should work in all 
> cases as is currently doing in s/map-of. I can't see any issues if s/keys 
> explains in the same way, which it currently doesn't because it just 
> reports [key].
>
> Juan
>
> El jueves, 13 de julio de 2017, 11:27:44 (UTC-3), Ben Brinckerhoff 
> escribió:
>>
>> No, you're not missing anything. I've run into the same issue. I see 
>> you've found the related JIRA issue, but for those who haven't it's 
>> https://dev.clojure.org/jira/browse/CLJ-2192
>>
>> > So the thing is that if you see a problem in [::k 1] you don't know if 
>> its the ::k value, or the value is a sequence and the problem is its 
>> element at pos 1.
>>
>> Yes, you're correct, this is ambiguous right now. In Expound (
>> https://github.com/bhb/expound) I have some code that tries to determine 
>> which case it is, based upon some heuristics, but I'm sure there are cases 
>> in which I'll get it wrong.
>>
>> There are two other interesting related cases I've run into related to 
>> the `:in` path.
>>
>> First, there is the case where the key is wrong, not the value:
>>
>>   (s/def ::spec-1 (s/map-of keyword? int?))
>>
>>   (-> (s/explain-data ::spec-1 {"foobar" 5})
>>   :clojure.spec.alpha/problems
>>   first
>>   :in)
>>   ;; ["foobar" 0]
>>
>> This is also ambiguous in the way you've noted above, but it's not clear 
>> how to construct this path - how do we "point to" a key of a map?
>>
>> Second, there is the case where we want to use 'coll-of' with a map. In 
>> this case, the `in` path is just [0]
>>
>>   (s/def ::coll-of (s/coll-of int? :kind map?))
>>   (-> (s/explain-data ::coll-of {"foobar" 5})
>>   :clojure.spec.alpha/problems
>>   first
>>   :in)
>>   ;; [0]
>>
>> AFAICT, we don't know from looking at that path whether it means: "look 
>> up the key `0` in the map" (incorrect) or "convert the map to a sequence, 
>> then get the 0th element" (correct). Again, Expound has some heuristics to 
>> try to figure this out.
>>
>> Right now, this logic is buried in the (messy) internals of Expound, but 
>> I will soon be providing a cleaner set of functions that allows clients to 
>> do more with the :clojure.spec.alpha/problems, including one that will 
>> provide a `in` path that works around these issues (in most common cases).
>>
>> Ben
>>
>> On Wednesday, July 12, 2017 at 8:50:19 AM UTC-6, Juan Monetta wrote:
>>>
>>> Hi everyone,
>>>
>>> I started exploring the clojure.spec "better user errors" thing and I'm 
>>> having some trouble matching clojure.spec.alpha/problems inside
>>> :clojure.spec.alpha/value in explain-data.
>>>
>>> I'm trying to understand if there is currently a way of using problem to 
>>> directly find the part of the value that is causing the issue independent of
>>> the spec that failed.
>>>
>>> For example given a spec :
>>>
>>> (s/def ::spec-1 (s/map-of keyword? int?))
>>>
>>> (-> (s/explain-data ::spec-1 {::k 8.8})
>>>  :clojure.spec.alpha/problems
>>>  first
>>>  :in)
>>> => [::k 1]   ;; which means the problem was with the value, not the key
>>>
>>> but given a different spec for the same data :
>>>
>>> (s/def ::k int?)
>>> (s/def ::spec-2 (s/keys :req [::k]))
>>>
>>> (-> (s/explain-data ::spec-2 {::k 8.8})
>>>  :clojure.spec.alpha/problems
>>>  first
>>>  :in)
>>> => [::k]
>>>
>>> So the thing is that if you see a problem in [::k 1] you don't know if 
>>> its the ::k value, or the value is a sequence and 
>>> the problem is its element at pos 1.
>>>
>>> Does it make sense or I'm missing something?
>>>
>>> I'm trying with [org.clojure/clojure "1.9.0-alpha17"]
>>>
>>>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from 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: Trouble understanding clojure.spec.alpha/problems :path :via :in

2017-07-13 Thread Ben Brinckerhoff
No, you're not missing anything. I've run into the same issue. I see you've 
found the related JIRA issue, but for those who haven't it's 
https://dev.clojure.org/jira/browse/CLJ-2192

> So the thing is that if you see a problem in [::k 1] you don't know if 
its the ::k value, or the value is a sequence and the problem is its 
element at pos 1.

Yes, you're correct, this is ambiguous right now. In Expound 
(https://github.com/bhb/expound) I have some code that tries to determine 
which case it is, based upon some heuristics, but I'm sure there are cases 
in which I'll get it wrong.

There are two other interesting related cases I've run into related to the 
`:in` path.

First, there is the case where the key is wrong, not the value:

  (s/def ::spec-1 (s/map-of keyword? int?))

  (-> (s/explain-data ::spec-1 {"foobar" 5})
  :clojure.spec.alpha/problems
  first
  :in)
  ;; ["foobar" 0]

This is also ambiguous in the way you've noted above, but it's not clear 
how to construct this path - how do we "point to" a key of a map?

Second, there is the case where we want to use 'coll-of' with a map. In 
this case, the `in` path is just [0]

  (s/def ::coll-of (s/coll-of int? :kind map?))
  (-> (s/explain-data ::coll-of {"foobar" 5})
  :clojure.spec.alpha/problems
  first
  :in)
  ;; [0]

AFAICT, we don't know from looking at that path whether it means: "look up 
the key `0` in the map" (incorrect) or "convert the map to a sequence, then 
get the 0th element" (correct). Again, Expound has some heuristics to try 
to figure this out.

Right now, this logic is buried in the (messy) internals of Expound, but I 
will soon be providing a cleaner set of functions that allows clients to do 
more with the :clojure.spec.alpha/problems, including one that will provide 
a `in` path that works around these issues (in most common cases).

Ben

On Wednesday, July 12, 2017 at 8:50:19 AM UTC-6, Juan Monetta wrote:
>
> Hi everyone,
>
> I started exploring the clojure.spec "better user errors" thing and I'm 
> having some trouble matching clojure.spec.alpha/problems inside
> :clojure.spec.alpha/value in explain-data.
>
> I'm trying to understand if there is currently a way of using problem to 
> directly find the part of the value that is causing the issue independent of
> the spec that failed.
>
> For example given a spec :
>
> (s/def ::spec-1 (s/map-of keyword? int?))
>
> (-> (s/explain-data ::spec-1 {::k 8.8})
>  :clojure.spec.alpha/problems
>  first
>  :in)
> => [::k 1]   ;; which means the problem was with the value, not the key
>
> but given a different spec for the same data :
>
> (s/def ::k int?)
> (s/def ::spec-2 (s/keys :req [::k]))
>
> (-> (s/explain-data ::spec-2 {::k 8.8})
>  :clojure.spec.alpha/problems
>  first
>  :in)
> => [::k]
>
> So the thing is that if you see a problem in [::k 1] you don't know if its 
> the ::k value, or the value is a sequence and 
> the problem is its element at pos 1.
>
> Does it make sense or I'm missing something?
>
> I'm trying with [org.clojure/clojure "1.9.0-alpha17"]
>
>

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


[JOB] Clojurescript/React Native jobs at Figly (remote)

2017-02-17 Thread Ben Brinckerhoff
Figly is building the next-generation platform as a service (PAAS) to 
transform enterprise software. We are led by a world-class team with a 
track record of successful cloud startups, as well as leadership experience 
at the largest software companies.

The platform includes a native mobile client written in written in 
ClojureScript and uses React Native. The mobile team is a small team, 
offering our engineers a large share of independence and responsibility. We 
focus primarily on the end user aspects of the platform: making offline 
first data characteristics the default, ensuring smooth, custom animations, 
designing a templating language for non-programmers templating language and 
making the platform as performant as possible across widely varying 
application domains and workloads. In pursuit of this, we work closely with 
everyone in the company: other engineering teams, go-to-market teams, and 
the founders themselves.

You will:

* Attend a daily stand-up via video call to synchronize your work with the 
rest of the team
* Design new features, expand the scope and capability of our mobile 
platform
* Implement those features using ClojureScript compiled to JavaScript 
integrated with React Native
* Write clean, testable code
* Participate in peer review of your own and other team member's code
* Be responsible for shipping, updating and generally maintaining our 
mobile application
* Attend regular team tech talks, architecture reviews, iteration 
retrospectives

Our ideal candidate is:

* Versed in Clojure / ClojureScript development practices: tooling, 
testing, libraries, idioms
* Able to navigate modern JavaScript tooling and libraries, React primarily
* Has exposure to iOS development: using XCode, reading Objective-C / Swift 
source, understanding iOS APIs

You'll love working here:

* Fast paced startup environment, rapidly growing and expanding
* Culture of “Freedom & Responsibility” 
* Sustainable work ethos
* Health Insurance
* Work remotely from anywhere in the world: we currently collaborate across 
4 time zones and two continents

Please send your resume to j...@figlyinc.com

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


Re: Clojure.spec, maps, restrict valid keywords, easier way?

2017-02-03 Thread Ben Brinckerhoff
The eastwood linter can also be configured to look for possibly misspelled 
keyword typos

https://github.com/jonase/eastwood#keyword-typos

On Friday, February 3, 2017 at 3:47:21 AM UTC-7, John Schmidt wrote:
>
> I suggest something like (defn fetch-encrypted [] (fetch-important-data 
> {:encrypt true})) + unit tests
>
> On Friday, February 3, 2017 at 2:56:34 AM UTC+1, Michael Gardner wrote:
>>
>> What would be the Right Way to deal with typos like (fetch-important-data 
>> {:encypt true}), where the :encrypt key is optional? Timothy mentions 
>> auto-complete, which is better than nothing but doesn't feel like a real 
>> solution (especially to those who don't use auto-complete). 
>>
>> > On Feb 2, 2017, at 16:37, Alex Miller  wrote: 
>> > 
>> > Ugh, don't do that. Introducing layers that add no value is a bad idea. 
>> Just use the keyword directly. 
>> > 
>> > -- 
>> > 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: Thoughts on clojure.spec

2016-12-10 Thread Ben Brinckerhoff
I would certainly welcome and use an `overinstrument` function if added to 
schpec (or another library).

One reason spec is great because it provides "a la carte" validation: a can 
add an appropriate amount of validation to the parts of my code that would 
most benefit from it. In my experience using spec so far, optionally 
running `fn` and `ret` specs during instrumentation would give me more 
options to pick the correct amount of validation.

For instance, since side-effecting functions are harder to unit test (and 
difficult to test generatively), I would like to spec the functions and 
then run integration tests. Running `ret`/`fn` specs would help me detect 
errors closer to their source and also confirm the specs are accurate, 
which improves the value specs as documentation. In my current project, I 
have been avoiding writing `ret` specs for side-effecting functions because 
I worry they'll get out-of-sync and mislead other programmers.

Also, having `ret`/`fn` specs checked during instrumentation would add 
value during development when I'm not yet ready to build generative tests. 
For example, during early development of a function, I might just spec a 
parameter with `map?` even though it actually requires certain keys. That 
spec far too vague for generative testing, but immediately adds value when 
I turn on instrumentation, since it catches bugs where I've passed, say, 
`nil` as the parameter. When the feature is more stable, I can invest the 
time in creating a generator and running generative tests. With the current 
implementation of `instrument`, I find that I've been tempted to over-spec 
early in development in order to get working generative tests that will 
confirm my `ret` and `fn` specs are correct.

I understand Rich and Alex have thought all this through and have provided 
a detailed rationale for the current behavior. But in my own workflow, 
being able to turn on `ret`/`fn` specs during instrumentation would be a 
big help, and I'd very much like to see this feature added to schpec. I'm 
happy to look at this when my schedule allows (not this week or next due to 
travel). Perhaps the best approach is to add an `over-instrument` function 
that has options for turning on/off `args`, `fn`, and `ret` specs (enabling 
all by default) and see how people use it in practice?

Thanks to everyone who have worked so hard on all aspects of spec!
Ben










On Tuesday, December 6, 2016 at 4:42:44 PM UTC-7, Brandon Bloom wrote:
>
> I was just very surprised to discover my :ret specs were not being checked 
> via instrument. I've read the rationale above, but I'm not yet convinced. 
> While of course I can (and will) use spec/assert from a post condition, I 
> lose the nice selective instrumentation features.
>
> I'd also like to make a counter-point to this reasoning:
>  
>
>> Running return-value instrument-style checking on whatever few 
>> hand-written tests you might have isn’t going to give you better coverage 
>> than a simple (even hardwired) generator that captures similar ranges.
>
>
> In my case, I was already testing the root-level return value, but this 
> function is deeply recursive. A small non-conforming value deep in the 
> evaluation stack was yielding non-conformance at a path deep in the root 
> return value. I was confused by why the :ret check wasn't finding it 
> earlier. By relying on the top-level check rather than inline checks 
> per-call (as per instrument or :pre/:post) I lost access to the call stack. 
> Adding the post condition pin-pointed the problem instantly.
>

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

2015-09-22 Thread Ben Brinckerhoff
On my team, we tried using RoboVM to compile Clojure to iOS. It worked fine 
once it booted, but startup time was a concern. We didn't spend a lot of 
time optimizing it though. We also found the compile/boot cycle to be quite 
long (over 50s to see a change). My understanding (perhaps mistaken) is 
RoboVM must compile all code before boot, so live-loading code via a REPL 
won't work.

We switched to using Clojurescript/React Native and it's been a net 
positive for us so far, even though we had to rewrite some internal 
libraries for CLJS. We had a REPL briefly (Ambly, although we've recently 
had to drop support for it due to breaking changes from React Native 
upgrades) and our compile/boot cycle is about 20s.

My coworker Chris Vermilion created these slides about our 
experience 
https://docs.google.com/viewer?a=v=forums=MTUyOTIzOTE0MjU1MDA0MDI3NjQBMTExMTI3MjYwMjc1OTc4MDg3MzQBXzVfV0tNdUZDQUFKATAuMQEBdjI

Hope that helps,
Ben

On Tuesday, September 22, 2015 at 3:51:04 PM UTC-7, Roger Keays wrote:
>
> Hi all,
>
> Thanks for giving the world Clojure. It's already made my life better just 
> by applying the idioms to my Java code (e.g. 
> http://www.ninthavenue.com.au/java-with-no-design-patterns).
>
> I'm starting on a new project soon and would like to use Clojure, however 
> in my experiments so far performance seems to be a bit of a problem. Since 
> the project will target mobile devices performance is pretty important 
> (especially startup time).
>
> To be honest, even for the server I'm a little deterred by the stats I've 
> seen online of Clojure vs Java performance. I can always just write Java in 
> a functional style and embed beanshell for a REPL.
>
> So I guess it would be good to hear from the community how things have 
> worked out for them performance-wise, and especially on Android/iOS.
>
> Also, are there any known showstoppers compiling Clojure bytecode to iOS 
> using RoboVM?
>
> Thanks in advance,
>
> Roger
>
>
>

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

2013-11-01 Thread Ben Brinckerhoff
Thanks for the links to the talks. I enjoyed them.

In particular, in Thinking in Data, Stuart discussed a way to isolate 
side effects:

;; Bad
(defn complex-process [state]
  (let [result (computation state)]
(if (condition? result)
  (launch-missile)
  (erase-hard-drive

;; Better
(defn complex-process [state]
  (assoc state :analysis (computation state)))

(defn decision [state]
  (assoc state :response
(if (condition? (:analysis state))
  :launch-missile
  :erase-hard-drive)))

(defn defend-nation [state]
  (case (:response state)
:launch-missle (launch-missile)
:erase-hard-drive (erase-hard-drive)))

The benefits of the second approach are that you don't have to use mocks to 
test the interesting parts of the code.

However, I wonder how to expand this approach when the state itself 
requires IO - say, it exists in the DB. One approach would be to construct 
the full state before calling complex-process by querying the DB. But 
that would be inefficient especially if complex-process only 
conditionally needs some of the data.

That's more a matter of dependency injection, passing components around, 
and being careful to return a new object from each operation. Once you 
decouple your components from each other via some kind of abstract 
interface (protocols are nice for this), it would be relatively easy to 
create side-effect-free mock implementations for your tests or other use 
cases.

Can you expand on that? It's very intriguing but I'm not quite seeing how 
it all fits together.

One approach I've been trying is to have functions return a request 
(which describes some IO action) plus a callback. So, instead of reading 
directly from the DB, a function would describe a DB query that should 
occur, and then provide a callback for processing the result. When I write 
my tests, I can just test that the function returns the right request (or 
series of requests).

Ben


On Thursday, October 31, 2013 9:56:52 AM UTC-7, Gary Trakhman wrote:

 Well, though your DB is side-effects, your functions that write to it 
 don't have to be aware of that.  That's more a matter of dependency 
 injection, passing components around, and being careful to return a new 
 object from each operation.

 Once you decouple your components from each other via some kind of 
 abstract interface (protocols are nice for this), it would be relatively 
 easy to create side-effect-free mock implementations for your tests or 
 other use cases.

 So, 
 1. Create a suitable functional abstraction, where the side-effects are a 
 hidden implementation detail.
 2. Be rigorous about using it.

 We do this in our code via datomic, though we're not disciplined about 
 using a functional style with return-values from DB operations.  Injecting 
 the database as a dependency is enough to help testing use-cases and 
 overall code decoupling, and the implementation is all hidden behind a set 
 of protocols specific to our app.


 On Thu, Oct 31, 2013 at 6:31 AM, Jozef Wagner 
 jozef@gmail.comjavascript:
  wrote:

 Following presentations may help

  http://www.infoq.com/presentations/Clojure-Design-Patterns
 http://www.infoq.com/presentations/Thinking-in-Data

 JW


 On Thu, Oct 31, 2013 at 3:42 AM, Ben Brinckerhoff 
 bhbrinc...@gmail.comjavascript:
  wrote:

 Clojure is the first functional programming language I've used for 
 anything more than toy examples, so I'm learning functional programming in 
 general as well as Clojure specifically. I understand the value of 
 creating pure functions in theory, but when writing applications, I'm 
 finding that logic and IO are getting hopelessly entangled.

 Specifically, in my web application, there is interaction with the DB on 
 most requests. The interaction may be quite complicated: e.g. first get 
 some user data, inspect it, and then make more DB calls if a user is 
 allowed to view some resource.

 Does anyone know of any books or articles on structuring functional code 
 to separate pure and impure functions? Or other resources? Projects that 
 are good examples?

 Although I've found good resources on writing pure functions and good 
 resources on using Clojure IO libraries, I haven't yet found anything that 
 talks about architectures that let you cleanly integrate the two in 
 real-world projects.

 Thanks,
 Ben

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

Resources for learning techniques for isolating pure functions

2013-10-30 Thread Ben Brinckerhoff
Clojure is the first functional programming language I've used for anything 
more than toy examples, so I'm learning functional programming in general 
as well as Clojure specifically. I understand the value of creating pure 
functions in theory, but when writing applications, I'm finding that logic 
and IO are getting hopelessly entangled.

Specifically, in my web application, there is interaction with the DB on 
most requests. The interaction may be quite complicated: e.g. first get 
some user data, inspect it, and then make more DB calls if a user is 
allowed to view some resource.

Does anyone know of any books or articles on structuring functional code to 
separate pure and impure functions? Or other resources? Projects that are 
good examples?

Although I've found good resources on writing pure functions and good 
resources on using Clojure IO libraries, I haven't yet found anything that 
talks about architectures that let you cleanly integrate the two in 
real-world projects.

Thanks,
Ben

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