Re: Conceptual difference between map and class

2020-04-05 Thread James Gatannah
"A language that doesn't affect the way you think about programming is
not worth knowing." - Alan Perlis

A lot  clojure's culture and philosophy is centered around Rich's talks.

I resisted this for a very long time. I'd rather spend 10 hours
reading a book than 1 hour watching someone speak. I was wrong.

Joy of Clojure is really a...well, maybe not an "advanced" clojure
book. But it also definitely isn't a beginner's introduction.

I've gotten rave reviews from very senior programmers about "Clojure
for the Brave and True." Its whimsical style isn't for people who just
want to dive into the nuts and bolts, but those people are almost
definitely going to miss the bigger picture.

Personally, I wound up loving clojure from the perspective of a python
programmer. I got to python from c++ because I got fed up with all the
stupid boiler plate code and time I wasted waiting on the compiler.

>From there, I ran across enough people raving about common lisp to
convince me to read http://www.gigamonkeys.com/book/

I spent a couple of years trying to do anything worthwhile with common
lisp in my spare time.

I kept hitting limitations in the C library layers. x can't work in
64-bit Windows. Y cannot compile on Thursdays. That sort of thing.

I really, really wanted to turn that into my goto, every day,
"my-time" programming language.

And I just couldn't.

The support base of people who are using it just is not broad enough.

This is why clojure's decision to embrace the "hosted platform" thing
is brilliant. Clojure on the JVM has access to anything that java can
get to. ClojureScript has the potential to be even broader, since
javascript.

I still treasure fantasies of going back to common lisp. But, really,
clojure has a better answer to a lot of modern computing problems.

When I ran across clojure for the first time (because people I
respected convinced me to look at it, even though I thought I knew
that common lisp must be better), I hated it. This was way before
lein, so you had to deal with all the baseline java stupidity to build
your CLASSPATH. And the way it manages state seemed idiotic. I was a
seasoned C programmer who thought I knew how to handle all the issues
that came with multi-threading.

I was wrong.

It gets more complicated. Things like AWS lambdas push back on the
problems that clojure solves.

In a lot of ways, they force you to do the same things that clojure
does naturally, because they're stateless. And they're a poor fit for
clojure because its startup time still isn't great.

This is all me rambling. I'm sorry.

Is clojure a good language for you to learn now?

Well, that depends on where you are and what you already know.

I work with a bunch of people who went through the same programming
101 course. It forced them to learn things like Haskell and Clojure,
because the professor is a technical programming weanie.

I feel sad for these people and have to fight against them constantly
because there is no way for them to appreciate what you get from a
functional programming paradigm until you've dug the trenches and seen
1st-hand just how awful the alternatives are.

I don't know where you are in your life/career, so I don't have any
justification for offering this opinion. I'm going to anyway.

 I think that may be the litmus test for your question: have you hit
the point where you think "there must be a better way to do this?"

It never hurts to learn a new language. That's always a good idea.
But, if you're still content with what you can do with python, then I
advise you to keep working in python. Just keep clojure in mind the
next time you hit an "OMFG! How did this bug escape into production?!"
moment.

It isn't a trivial transition. But it's almost guaranteed that
translating your web server from python to clojure will make it more
stable.

Clojurescript is awesome, but (in this scenario), it's also just icing.


On Sat, Apr 4, 2020 at 12:24 AM Dieter Van Eessen
 wrote:
>
> Thanks, I'm currently reading the book you mentioned (Joy of Clojure). Just 
> started on 'Types, protocols and records'...
> Still doubting if I should continue learning clojure. From my point of view, 
> the only major advantages of the language so far, are 'clojurescript' and the 
> idea that I can evaluate stuff that I've 'printed' (data is code is data).
> Other than that, they are messing with my head by redefining existing 
> abstraction and making them 'almost equal but slightly different'.
>
> kind regards,
> Dieter
>
> On Wednesday, April 1, 2020 at 6:44:07 AM UTC+2, James Gatannah wrote:
>>
>> It might be worth mentioning that, ultimately, python class instances are 
>> syntactical sugar built around an internal __dict__. It gets twistier, since 
>> classes are also instances of the base class object.
>>
>> It would be tricky (though I've seen an e

Re: Conceptual difference between map and class

2020-03-31 Thread James Gatannah
It might be worth mentioning that, ultimately, python class instances are 
syntactical sugar built around an internal __dict__. It gets twistier, 
since classes are also instances of the base class object.

It would be tricky (though I've seen an example...maybe in Joy of Clojure? 
I think the author's conclusion was that it was an interesting experiment, 
but not worth doing in practice) to implement inheritance using clojure 
maps.

For me, the conceptual difference has been that it's better to just write 
functions that work on simple data structures, rather than tying a few 
together into a unit that only work on a single data structure (plus its 
derived classes). Clojure's emphasis on functional purity is another major 
piece of this puzzle.

Unit testing is one thing that becomes much easier with this approach.

I deal with a ton of python code that has tests built around dozens of mock 
objects mimicking things like database records from an ORM. And then we 
mock out a few low-level HTTP calls in base classes so the class instances 
we're trying to test in isolation don't break when we run the tests with no 
web server to call. Then someone refactors the code, and all the tests 
break because they're tied to a specific package/module structure.

By contrast, if you have your business logic in one set of pure functions, 
and you keep your side-effecting parts well isolated on the fringes of your 
system, you don't need any of that. Just call the business logic function 
with appropriate values and double-check the results.

You absolutely can write python code that way. But your pythonic colleagues 
will hate you for it.

Hope that helps,
James

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


Re: Silly ns question

2019-02-26 Thread James Gatannah
It just got stranger.

Same project. I've been tinkering with it for about an hour a night.

I don't think I've changed anything significant structurally, although
I have restarted the JVM.

I created a new file, world_test.cljc, in the same shared/ folder as
connection_test.cljc.

cider set up the ns directive the same way, so it's

(ns .shared.world-test ...)

This time, trying to compile it failed with the error "Namespace
.shared.world-test has a segment starting with an invaild JavaScript
identifier"

Aside from misspelling "invalid", that's about what I expect.

And now the original '.shared.connection-test ns fails with the same error.


On Sun, Feb 17, 2019 at 9:40 PM James Gatannah  wrote:
>
> Oops, yes. I typoed the file name.
>
> On Sun, Feb 17, 2019 at 9:26 AM Daniel  wrote:
> >
> > Weird. Also I thought your file name would need an underscore.
> >
> > --
> > You received this message because you are subscribed to the Google
> > Groups "Clojure" group.
> > To post to this group, send email to clojure@googlegroups.com
> > Note that posts from new members are moderated - please be patient with 
> > your first post.
> > To unsubscribe from this group, send email to
> > clojure+unsubscr...@googlegroups.com
> > 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/COrsNoavQqI/unsubscribe.
> > To unsubscribe from this group and all its topics, 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: Disable swagger.ui in production

2019-02-22 Thread James Gatannah
I'm going to buck a trend here.

Why do you want to do this? (That's rhetorical. Don't feel like you need to 
answer).

One of the fundamental principles behind REST is that it is discoverable. 
Maybe even that it's explorable.

Maybe you aren't building a REST end-point. It's totally possible that I 
read too much into your post.

But I'm curious about bigger-picture issues: why wouldn't you include 
something like swagger as part of your public API?

(Don't get me wrong: I can think of 4 different reasons off the top of my 
head. I'm just curious why you don't want to).

On Wednesday, February 20, 2019 at 11:24:01 AM UTC-6, Brjánn Ljótsson wrote:
>
> Hi,
>
> I'm trying out compojure-api and have included swagger.ui in my api:
>
> (api
>   {:swagger {:ui   "/swagger-ui"
>  :spec "/swagger.json"
>  :data {:info {:version "1.0.0"
>:title   "Title"
>   ...)
>
> However, I don't want swagger to be included in my production build. What 
> is the best way to disable swagger in production?
>
> Best,
> Brjánn Ljótsson
>

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

2019-02-17 Thread James Gatannah
Oops, yes. I typoed the file name.

On Sun, Feb 17, 2019 at 9:26 AM Daniel  wrote:
>
> Weird. Also I thought your file name would need an underscore.
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> 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/COrsNoavQqI/unsubscribe.
> To unsubscribe from this group and all its topics, 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: Silly ns question

2019-02-16 Thread James Gatannah
I haven't messed with it extensively, but it works from the REPL.

On Sat, Feb 16, 2019 at 5:35 AM Matching Socks  wrote:
>
> Haha!  (Can .shared.connection-test be require'd by another ns?)
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> 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/COrsNoavQqI/unsubscribe.
> To unsubscribe from this group and all its topics, 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.


Silly ns question

2019-02-15 Thread James Gatannah
I'm using cider 0.18.0 (which is sweet) and emacs.

I just created a new buffer inside a new directory, and it generated the 
preliminary ns form for me (also sweet).

The path to the file under my source directory is 
"shared/connection-test.cljc".

The symbol of the ns that it generated is ".shared.connection-test".

I haven't seen that leading dot before. My first reaction was "That can't 
be legal." But, so far, the compiler doesn't seem to mind.

Does anyone have a pointer to docs that explain what's going on?

Thanks,
James

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

2018-05-26 Thread James Gatannah


On Friday, May 25, 2018 at 7:40:12 AM UTC-5, Sonny To wrote:
>
> Hi James,
> I'm trying to access the local bindings of the closure like it is an object
> (.-x bar) should give  1. I can use a defrecord for this but I want to use 
> regular functions and no macro magic
>

This isn't quite what you're asking for, but one approach to what records 
actually do would be to return a map of closures that include accessors for 
the state. (Disclaimer: I'm totally doing this off the top of my head in 
the google groups web interface, without even checking that the parentheses 
are balanced) One example would be:

(defn build-incrementer

  [x]

 {:inc (fn [] (inc x))
  :dec (fn [] (dec x))
  :status (fn [] x)})

Is that close to what you wanted?

Regards,
James
 

>
> On Friday, May 25, 2018 at 9:01:22 AM UTC+3, James Gatannah wrote:
>
>> On Thursday, May 24, 2018 at 1:22:42 PM UTC-5, Sonny To wrote:
>>>
>>> (defn foo[]
>>>  (let [x  1]
>>>(fn []  
>>>  (+ x 1)
>>> )
>>>  )
>>>
>>> (def bar  (foo))
>>>
>>> Is there a way to get the value of x from closure bar?
>>>
>>
>> I may be describing this incorrectly.
>>
>> You're creating a top-level var named bar.
>>
>> You're calling the function foo, and associating the value it returns to 
>> that var bar.
>>
>> foo's return value happens to be a function that looks like it should be 
>> a counter. Except that, in clojure, it isn't.
>>
>> This vaguely looks like an approach to lexical closures that I vaguely 
>> remember from scheme textbooks (and Paul Graham essays).
>>
>> What are you really trying to do?
>>
>

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

2018-05-25 Thread James Gatannah
On Thursday, May 24, 2018 at 1:22:42 PM UTC-5, Sonny To wrote:
>
> (defn foo[]
>  (let [x  1]
>(fn []  
>  (+ x 1)
> )
>  )
>
> (def bar  (foo))
>
> Is there a way to get the value of x from closure bar?
>

I may be describing this incorrectly.

You're creating a top-level var named bar.

You're calling the function foo, and associating the value it returns to 
that var bar.

foo's return value happens to be a function that looks like it should be a 
counter. Except that, in clojure, it isn't.

This vaguely looks like an approach to lexical closures that I vaguely 
remember from scheme textbooks (and Paul Graham essays).

What are you really trying to do?

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


Question about tightly couple spec interactions

2018-03-29 Thread James Gatannah
Background:

I'm in the process of translating a fairly low-level and messy C
networking library. The original involves lots of bit-twiddling and
global variables.

My first pass (which has been in the "real soon now" state for months
now...in hind-sight, I have some regrets about starting this at all,
much less trying to go straight from C to clojure) tried to stick
fairly close to the original as I figured out what it was doing.

I also used this project as an excuse to start learning about spec.
Right now, I'm basically just using it to document parameters and
return values. I've started doing a little generative testing, but
that part's just icing, really.

I wound up with some uncomfortably large top-level maps. So I have
specs like ::server/state, ::client/state, and ::ioloop/state. Those
in turn contain maps like ::log/state and ::flow-control/state.

There's nothing really exciting/surprising about any of that. There
are a couple of places where the tree gets 3 or 4 layers deep, but it
doesn't seem awful.

In my original version, I basically just passed the top-level state
maps around everywhere. A function takes that as one of its
parameters, and it probably returns the same thing where 1 or 2 of the
values have been updated.

Now I think I want to get more specific about the spec for each of
those functions so I have a better feel for what each is doing.

And I almost feel like I'm dealing with java checked exceptions.

Say I have (-> x foo bar baz qux), and qux is the hairy part that
actually uses all the complicated values (and there are also plenty of
byte-arrays, just to make life really interesting) stored in x.

The details don't matter, but just to make the problem a little more concrete:

foo, bar, and baz have their own hairiness. In the specific scenario
that I'm looking at right now, foo is the boundary-function event
handler that pulls byte buffers off the network socket, bar is the
function that decides how to handle each incoming packet, baz is the
function that handles this particular packet type, and then qux is the
part that opens the encryption box that contains the actual payload.

I decided last night to extend some ongoing refactoring to qux. It now
uses a new key that I recently introduced. Except that I don't seem to
have added it to the top-level state map that I'm passing around
everywhere. In disgust, I started dabbling with the idea of being
explicit about which keys it actually needs.

In order to make that work, it seems like I need to update the specs
for baz and bar to specify their exact parameters/return values. And
possibly exactly which members of the top-level state I expect to
change. So when the spec for one changes, it trickles up to everything
that calls it.

I wouldn't mind too terribly much making them as tightly coupled as
this implies. They already are, really, and they're all so specialized
that they really don't make any sense in isolation. I really just
broke them into smaller pieces out of a single gigantic main()
function for the sake of my own sanity.

And this is strictly internal. The library interface is just a
function/callback thing to read/write.

How do other people approach the sort of big-picture problem I'm describing?

Thanks in advance,
James

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

2018-03-03 Thread James Gatannah
In case anyone was wondering, it looks like this is probably a known issue:

https://dev.clojure.org/jira/browse/CLJ-2079

On Wednesday, February 28, 2018 at 12:05:31 AM UTC-6, James Gatannah wrote:
>
>
>
> On Tuesday, February 27, 2018 at 12:45:26 AM UTC-6, Didier wrote:
>>
>> Don't fully understand what you are doing,
>>
>
> (Slightly) bigger picture, I have a pair of functions that 
> serialize/deserialize maps where the values are mostly fixed-length byte 
> arrays.
>
> I want to verify that they round-trip correctly.
>
> This specific example is about two of those fields which really have the 
> same spec. I'm trying to define this in a way that's similar to a C typedef 
> (or possibly just something like using OOP inheritance for the sake of 
> documentation):
>
> (s/def ::extension ...)
> (s/def ::server-extension ::extension)
> (s/def ::client-extension ::extension)
>
> I'm doing this in an attempt to trying to reduce my nesting levels.
>
> This is what the weird subject is about: I'm trying to take advantage of 
> the transitive property of specs.
>
>  
>
>> but when you run test.check, it seems to not always be generating random 
>> sample, it'll grow the samples. When you run sample, it'll always start 
>> back from the beginning. 
>>
>
>> You can see that by running:
>>
>> (sgen/sample (s/gen ::test) 100)
>>
>> See how the generated samples are getting longer and longer?
>>
>
> Now instead try running this 10 times:
> (sgen/sample (s/gen ::test) 10)
>
> And notice how you always get the same short samples?
>
>  
>
> (I'm sorry about the quote mangling).
>
> Since I have to have a specific length, I'm specifying that as a parameter 
> to sgen/vector.
>
> This part of it works. I can run s/sample on my generator and validate its 
> output against the spec without any trouble.
>
> Actually, if I define the ::extension spec using with-gen, it also looks 
> as though it works (I just ran across this, so haven't tested it 
> thoroughly). But then my library has a runtime dependency on test.check. 
> That's not the end of the world, but it's a definite downside.
>
> I haven't been able to find real documentation covering the arguments to 
> s/gen. But it looks as though I can pass in a map of 0-arity functions to 
> override the different generators. The keys to that map override specs 
> being generated. I can't remember now where I found this, but it can't be 
> totally undocumented. I haven't studied the source code thoroughly enough 
> to have picked out that sort of detail.
>
> So:
>
> (s/gen (s/keys :req [::server-extension
>  ::client-extension])
>{::server-extension #(gen/fmap byte-array (gen/vector (gen/choose 
> -128 127) extension-length))
> ::client-extension #(gen/fmap byte-array (gen/vector (gen/choose 
> -128 127) extension-length))})
>
>
> calls the function in the value associated with each key to override the 
> generator for that spec.
>
> This is the part that seems to only work sometimes.
>
> When I extend this to include all the keys in the full spec, these are the 
> only two that have problems. They're also the only ones that are directly 
> defined as another spec definition. (Which is why I'm pointing my finger at 
> my attempt to use the "transitive" property, though that could totally be a 
> red herring).
>
> When I run this inside deftest, it seems fine. Really, that's all I need. 
> But I'd really like to understand the seemingly non-deterministic failures.
>
> I wrote a function called manual-check that takes that generator and calls 
> sgen/sample on it.
>
> When I call that function directly from the REPL, it very nearly always 
> fails.
>
> When I call it 40 times in a reduce inside deftest, I haven't seen it fail 
> yet.
>
> * While I was writing this, I stumbled across another piece that seems 
> like an interesting clue:
>
> If I override the generator for ::extension rather than the individual 
> specs that I've defined transitively, it seems to start working.
>
> i.e. 
>
> (s/gen (s/keys :req [::server-extension
>  ::client-extension])
>{::extension #(gen/fmap byte-array (gen/vector (gen/choose -128 
> 127) extension-length))})
>  
> seems to work.
>
> It's still less than ideal, in case I ever want to change the underlying 
> spec that's the "base" definition, since I'll have to remember to change 
> the base generator. But I really shouldn't have this sort of thing 
> scattered around everywhere. Especially since it's most interesting inside 
> deftest anyway, where both appr

Re: Transitive spec generation

2018-02-27 Thread James Gatannah


On Tuesday, February 27, 2018 at 12:45:26 AM UTC-6, Didier wrote:
>
> Don't fully understand what you are doing,
>

(Slightly) bigger picture, I have a pair of functions that 
serialize/deserialize maps where the values are mostly fixed-length byte 
arrays.

I want to verify that they round-trip correctly.

This specific example is about two of those fields which really have the 
same spec. I'm trying to define this in a way that's similar to a C typedef 
(or possibly just something like using OOP inheritance for the sake of 
documentation):

(s/def ::extension ...)
(s/def ::server-extension ::extension)
(s/def ::client-extension ::extension)

I'm doing this in an attempt to trying to reduce my nesting levels.

This is what the weird subject is about: I'm trying to take advantage of 
the transitive property of specs.

 

> but when you run test.check, it seems to not always be generating random 
> sample, it'll grow the samples. When you run sample, it'll always start 
> back from the beginning. 
>

> You can see that by running:
>
> (sgen/sample (s/gen ::test) 100)
>
> See how the generated samples are getting longer and longer?
>

Now instead try running this 10 times:
(sgen/sample (s/gen ::test) 10)

And notice how you always get the same short samples?

 

(I'm sorry about the quote mangling).

Since I have to have a specific length, I'm specifying that as a parameter 
to sgen/vector.

This part of it works. I can run s/sample on my generator and validate its 
output against the spec without any trouble.

Actually, if I define the ::extension spec using with-gen, it also looks as 
though it works (I just ran across this, so haven't tested it thoroughly). 
But then my library has a runtime dependency on test.check. That's not the 
end of the world, but it's a definite downside.

I haven't been able to find real documentation covering the arguments to 
s/gen. But it looks as though I can pass in a map of 0-arity functions to 
override the different generators. The keys to that map override specs 
being generated. I can't remember now where I found this, but it can't be 
totally undocumented. I haven't studied the source code thoroughly enough 
to have picked out that sort of detail.

So:

(s/gen (s/keys :req [::server-extension
 ::client-extension])
   {::server-extension #(gen/fmap byte-array (gen/vector (gen/choose 
-128 127) extension-length))
::client-extension #(gen/fmap byte-array (gen/vector (gen/choose 
-128 127) extension-length))})


calls the function in the value associated with each key to override the 
generator for that spec.

This is the part that seems to only work sometimes.

When I extend this to include all the keys in the full spec, these are the 
only two that have problems. They're also the only ones that are directly 
defined as another spec definition. (Which is why I'm pointing my finger at 
my attempt to use the "transitive" property, though that could totally be a 
red herring).

When I run this inside deftest, it seems fine. Really, that's all I need. 
But I'd really like to understand the seemingly non-deterministic failures.

I wrote a function called manual-check that takes that generator and calls 
sgen/sample on it.

When I call that function directly from the REPL, it very nearly always 
fails.

When I call it 40 times in a reduce inside deftest, I haven't seen it fail 
yet.

* While I was writing this, I stumbled across another piece that seems like 
an interesting clue:

If I override the generator for ::extension rather than the individual 
specs that I've defined transitively, it seems to start working.

i.e. 

(s/gen (s/keys :req [::server-extension
 ::client-extension])
   {::extension #(gen/fmap byte-array (gen/vector (gen/choose -128 127) 
extension-length))})
 
seems to work.

It's still less than ideal, in case I ever want to change the underlying 
spec that's the "base" definition, since I'll have to remember to change 
the base generator. But I really shouldn't have this sort of thing 
scattered around everywhere. Especially since it's most interesting inside 
deftest anyway, where both approaches always seem to work (I haven't tested 
this out thoroughly yet either).

My current hypothesis is that there's something about the deftest macro 
that interacts with test.check in a way that makes gen more capable in 
terms of resolving which spec I actually mean/want to override. I know 
(based on digging through internals) that it calls something (I think it's 
named specize) that resolves the spec's name. Then it has to use that 
name/those names in the overriding map parameter to pick out the 
appropriate function to call to get the generator.

I'm very skeptical, but could that possibly hold water?

Thank you to anyone who actually took the time to read this!

 

>
>
> On Monday, 26 February 2018 21:39:09 UTC-8, James Ga

Re: Transitive spec generation

2018-02-26 Thread James Gatannah
Fairly minimalist example available 
at https://gist.github.com/jimrthy/21851c52a8cd6b04a31ed08b1d0a7f04

When I call gen/sample from inside a unit test, it seems to pass with 
flying colors.

When I directly eval the gen/sample form or call (manual-check) from the 
REPL (I checked both CIDER and the boot CLI, just in case), I usually get 
the "Couldn't satisfy such-that predicate after 100 tries."

To be a little more specific about this:

Calling (manual-check) failed 49/50 times.

Calling (transitive-indirect) passed 50 times in a row. If you haven't 
bothered looking at the gist, each of those calls (manual-check) 40 times.

I was quite surprised by this. Does anyone have any suggestions about why 
wrapping the call in a unit test might help it succeed more often?

If I just call gen/sample on the generator I'm trying to use, followed by 
s/valid? for one of the specs I'm trying to generate, it seems fine. I 
haven't dug into the source here (and I'm not positive what all's going on 
inside the spec.gen namespace), but I thought that's what gen/generate does 
when you define a custom generator for your spec.

Except that isn't really what I'm doing.

I'm trying to avoid adding extra runtime dependencies on a library like 
tools.check, so I'm trying to do this with overrides in the test namespaces 
to try to limit the extra dependencies to test time.

Could that be where I'm breaking core assumptions that don't seem to cause 
trouble for anyone else?

Thanks,
James



On Sunday, February 25, 2018 at 6:45:39 PM UTC-6, James Gatannah wrote:
>
> I have a spec for an array of 16 bytes:
>
> (s/def ::extension (s/and bytes?
>#(= (count %) 16))
>
> Then I have a couple of other specs that are really just renaming it:
>
> (s/def ::client-extension ::extension)
> (s/def ::server-extension ::extension)
>
> I started doing some refactoring today, and the definitions wound up 
> needing to move to a different namespace.
>
> So now the original definitions have changed to
>
> (s/def ::client-extension ::refactored/client-extension)
>
> I also started dabbling with generators, and came up with this:
>
> (gen/generate (s/gen ::client-extension
>   {::client-extension #(gen/fmap 
> byte-array (gen/vector (gen/choose -128 127) 16)}))
>
> When I define things this way, I get a "Couldn't satisfy such-that 
> predicate after 100 tries." exception a little more than half the time.
>
> If I rearrange things so that either
> a) The refactored namespace defines the spec directly
> or
> b) I change my generator override to specify the top-level spec that the 
> others are copying
>
> i.e.
> a) would mean changing the refactored ns such that I have
> (s/def ::client-extension (s/and bytes?
>  #(= (count %) 16))
>
> b) changing the generator to
> (gen/generate (s/gen ::client-extension
>   {::refactored/extension #(gen/fmap 
> byte-array (gen/vector (gen/choose -128 127) 16)}))
>
> it seems to fail (with the same problem) about 1 time in 5.
>
> I haven't seen it fail yet if I undo my refactoring and move the spec back 
> to the original location.
>
> I haven't collected any sorts of real numbers on this, much less tried to 
> make enough test runs to collect a statistically significant sample. I know 
> the next real steps are to put together a minimalist example.
>
> But before I do that, I figured it might be asking whether anyone sees 
> anything obviously wrong in what I'm trying to do, or whether there's a 
> better way to do it.
>
> Thanks in advance,
> James
>
>

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


Transitive spec generation

2018-02-25 Thread James Gatannah
I have a spec for an array of 16 bytes:

(s/def ::extension (s/and bytes?
   #(= (count %) 16))

Then I have a couple of other specs that are really just renaming it:

(s/def ::client-extension ::extension)
(s/def ::server-extension ::extension)

I started doing some refactoring today, and the definitions wound up 
needing to move to a different namespace.

So now the original definitions have changed to

(s/def ::client-extension ::refactored/client-extension)

I also started dabbling with generators, and came up with this:

(gen/generate (s/gen ::client-extension
  {::client-extension #(gen/fmap byte-array 
(gen/vector (gen/choose -128 127) 16)}))

When I define things this way, I get a "Couldn't satisfy such-that 
predicate after 100 tries." exception a little more than half the time.

If I rearrange things so that either
a) The refactored namespace defines the spec directly
or
b) I change my generator override to specify the top-level spec that the 
others are copying

i.e.
a) would mean changing the refactored ns such that I have
(s/def ::client-extension (s/and bytes?
 #(= (count %) 16))

b) changing the generator to
(gen/generate (s/gen ::client-extension
  {::refactored/extension #(gen/fmap 
byte-array (gen/vector (gen/choose -128 127) 16)}))

it seems to fail (with the same problem) about 1 time in 5.

I haven't seen it fail yet if I undo my refactoring and move the spec back 
to the original location.

I haven't collected any sorts of real numbers on this, much less tried to 
make enough test runs to collect a statistically significant sample. I know 
the next real steps are to put together a minimalist example.

But before I do that, I figured it might be asking whether anyone sees 
anything obviously wrong in what I'm trying to do, or whether there's a 
better way to do it.

Thanks in advance,
James

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


Re: Best Practices for Accessing Data Files That May Be Bundled?

2018-02-06 Thread James Gatannah
At first glance, it seems like you probably 
want http://clojuredocs.org/clojure.core/ns-resolve


On Tuesday, February 6, 2018 at 2:38:06 PM UTC-6, Randy J. Ray wrote:
>
> First, some brief background/context: I've been playing around with 
> Clojure for a while, mostly just doing Project Euler problems. I'm taking 
> the "Algorithms Specialization" from Coursera, and decided to do all the 
> programming assignments in Clojure as a way of tackling some larger, deeper 
> problems. But overall, my understanding of Clojure overall is still fairly 
> mild.
>
> What I want to do, is write some scaffolding around the weekly programming 
> tasks that automates the execution of the user-contributed test-cases. I'd 
> like to be able to add a new form to be tested in a single place (e.g., the 
> project's core.clj file) and have a re-compile be able to find out that the 
> new namespace is now in place, locate the test-files, and execute the form 
> with each test-input.
>
> I'm pretty sure I can handle locating the test files as long as they're on 
> the file system (I'm looking at the fs package for walking around the file 
> system). But is there a way to (semi-)transparently handle the data files 
> being resources within the JAR, as well?
>
> Also, how would I take a pair of strings (namespace and form-name, 
> respectively) and turn that into the callable function? For example, if my 
> set of desired test-forms were a simple nested list:
>
> (("algorithms.class1.week1.karatsuba-mult" "karatsuba-mult")
>  ("algorithms.class1.week2.count-inv" "count-inv")
>  ...)
>
> (Currently, the last ns element is the same as the function-name to call, 
> but some of these will have multiple implementations that I'll want to time 
> for comparison, so this won't always be the case.)
>
> So, for the first "test", I want to turn 
> ("algorithms.class1.week1.karatsuba-mult" 
> "karatsuba-mult") into a binding that will call 
> algorithms.class1.week1.karatsuba-mult/karatsuba-mult when used as a 
> function. I know how to do this in other languages (my strongest is Perl, 
> but don't hold that against me!), just not in Clojure.
>
> The interface of all tests is the same-- they take the name of the input 
> file as a single input, and return a string as a result (I have 
> result-files in the same dirs as the input files, for comparison. I just 
> need to be able to iterate over the forms to test, and the test-cases for 
> each form.
>
> (I say "I just need", but I'll probably be back with more questions after 
> I get these answered...)
>
> Randy
> -- 
> Randy J. Ray - randy...@gmail.com  - twitter.com/rjray
> Silicon Valley Scale Modelers: http://www.svsm.org
> San Jose, CA
>

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

2018-01-07 Thread James Gatannah


On Thursday, January 4, 2018 at 5:51:27 PM UTC-6, Ben Kovitz wrote:
>
>
> Well! So far, Specter appears to have taken the "path map" idea that I'd 
> been toying with to its ultimate logical conclusion—far better than I could 
> ever do it. Nathan Marz even says that needing to manipulate tricky graphs 
> "forced" him to come up with Specter. If I understand it correctly, Specter 
> would even allow me to map these peculiar port graphs to simplicial graphs 
> without adding any performance overhead.
>
> It looks like I'd need to write a custom navigator or two. I haven't yet 
> found a good tutorial for getting beyond the most elementary concepts of 
> Specter, though. Can you recommend one?
>

FWIW, I think https://leanpub.com/specter looks extremely interesting. (Or 
it may be awful...I haven't had a chance to read it yet, much less work 
through the exercises).

Regards,
James


> --
> Ben Kovitz
> http://pages.iu.edu/~bkovitz/
>
>

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

2017-12-31 Thread James Gatannah
Disclaimer: I once spent 3-4 weeks studying Vert.x's design philosophy and 
architecture. So I'm hardly an expert.

On Saturday, December 30, 2017 at 9:31:47 AM UTC-6, Feuer Au wrote:
>
> Hmm
> yes it is almost an absolute requirement since we have already invested a 
> lot in Java, Kotlin, Javascript and other languages based on Vert.x
>

I think there's a very important open question here: *what* are you 
actually using Vert.x for?
 

> and for Clojure & Haskell are pretty new candidates for us, we need to 
> find a way to persuade our programmers to use these languages
>
and Vert.x is almost the only way to persuade our lovely programmers to 
> give it a try
>
 

> If we dont use Vert.x, those guys may resist to try a new language since 
> they need to get used to many new softwares e.g. maven -> leiningen
> some times people may not like changes^_^ 
>

It's been my experience that, if you have to persuade the programmers to 
use clojure, they probably aren't going to approach it correctly.

They'll try to write it the same way they'd write java. Then they'll decide 
that it's awful because the startup time is too slow, the syntax is too 
weird, and the immutable data structures add a lot of overhead for no real 
benefit.

Now, if you have someone on the team who's already realized that there are 
a ton of benefits (like stability in production, much faster development 
time, fewer bugs, less code to maintain, and general developer happiness 
all come to mind), then allowing them to show the others the benefits is a 
great option.

But someone on the team really needs to already  understand that this *is* 
a better way.

>  

> Now, building on what other people have already written:

If you have a bunch of separate stand-alone microservices that are using 
vert.x to communicate, there's no reason you couldn't write one in clojure. 
Just call the Vert.x pieces the way you would any other Java library. I 
don't know how much effort would be involved in getting it to play nicely 
with the actual Vert.x ecosystem. It's been a while since I looked at this, 
but I remember that one of the main selling points was the ability to spin 
verticles up and down on demand.

That sort of thing really isn't clojure's strength. It's really meant to be 
part of a process that runs for months or years. You don't have to use it 
that way, of course, and I bet plenty of others on this list are not. But, 
if you need something that automatically scales up pretty much instantly 
when demand increases, then clojure may not be your best bet.

And, if you don't, then why are you using Vert.x?

For me, trying to use Vert.x with clojure was incredibly frustrating. In a 
lot of ways, it felt like they're trying to solve the same basic problems 
in two totally different ways. 

One of clojure's main selling points is sane multi-threading. Using that 
involves fighting the Vert.x ecosystem, which is at least partially based 
on the premise that multi-threading is sheer evil and should really be 
avoided. I never really into this, because I barely scratched the surface, 
and it seemed like a really nasty can of worms to unleash.

As others have said, a huge chunk of what Vert.x provides is already baked 
into clojure. But the different approaches really aren't compatible. So 
you'll be fighting either the language or the library on some pretty 
fundamental decisions.

The one useful thing I could find that Vert.x provides out of the box that 
clojure doesn't is the pub/sub messaging. That turned our architecture into 
spaghetti, so I wouldn't call it a win.

Then, yeah, there's the codegen thing which is the part you're really 
asking about.

Why would anyone use an external codegen tool for a lisp? You already have 
[arguably] the best codegen tool the world has run across baked into the 
language, in the form of macros.

If I really had to use Vert.x (and I was working in a polyglot environment 
where this was an option), I'd just write stand-alone clojure microservices 
that used Vert.x as a communications library. Then I'd point out how much 
time/energy is being wasted on the java/kotlin portions.

BTW, your devs can still use maven instead of leiningen/boot. That's 
usually just an example of using old, comfortable approaches instead of 
embracing what's new and different. Depending on how your project(s) is/are 
set up, it might actually make sense (though I strongly suspect that boot 
would be a better option).

Regards,
James
 

>
> On Friday, December 29, 2017 at 9:11:34 PM UTC+8, Gary Verhaegen wrote:
>>
>> Is vert.x an absolute (external) requirement, or is that a tool you want 
>> to use to achieve some goal? If the latter, maybe there are other tools in 
>> the Clojure ecosystem that you could use instead?
>>
>> On 29 December 2017 at 13:49, Toby Crawley  wrote:
>>
>>> The short answer is no, there is no Clojure support for Vert.x 3 that I 
>>> know of.
>>>
>>> The longer answer: I wrote the 

Re: Clojure for beginners

2017-12-06 Thread James Gatannah
This isn't in the same league as any of those books, or the anything 
recommended by anyone else. And you probably already know everything it has 
to teach. But it seems worth mentioning.

I threw this together a couple of years ago:

https://github.com/jimrthy/clojure-introduction

It's really meant to be something you open in your editor and then used 
with its REPL integration to get a feel for the high-level overview.

If you don't have an editor set up with REPL integration, stop everything 
else and get that working. That's one of the major advantages that lisps 
have over almost any other language. If you try to approach this the way 
you'd write code in, say, python or java, you're going to be sad.

On Wednesday, December 6, 2017 at 5:24:22 PM UTC-6, Clojure beginner wrote:
>
> Hi all 
> I heard about Clojure a week ago and have a new assignment at work to 
> learn, develope and deploy to production. I haven't developed in 2 years. 
> Programming background is: mainframe and informatica. I have bought 5 
> books: and Clojure programming, Clojure for brave and true, Clojure in 
> action, programming Clojure, the joy of clojure. I have also been on the 
> main Clojure website. It's been a week and I still don't understand the 
> meat and potatoes. Any recommendations where I can get a walk through of it 
> with real examples. 

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

2017-10-13 Thread James Gatannah
It's been a couple of years, but (from what I remember) it works great.

Immutant (or maybe it's wildfly?) has an option to deploy "exploded .WAR 
files." 

I'm very fuzzy on the details, but it seems like the basic choices were 
either:
1) deploy an uberwar with AOT (advantage: faster startup time)
2) deploy the exploded version, which was really the source tree. This 
approach let you update the .clj files on the fly.

We had problems with the AOT version. I think they stemmed from library 
version conflicts, but it's been long enough that I can't swear to it.

On Friday, October 13, 2017 at 3:13:24 PM UTC-5, Andy Fingerhut wrote:
>
> I haven't deployed an application written in Clojure to a server as a WAR 
> file before, so can't speak from experience, but I am sure others here 
> probably can.  Hey, others, have you deployed a Clojure application via a 
> WAR file without using AOT compilation, with only Clojure source code 
> packaged in the WAR file?  Is that something that works?
>
> Andy
>
> On Fri, Oct 13, 2017 at 11:05 AM, Damien Mattei  > wrote:
>
>> but i am in this situation, i wrote application in Scheme (Kawa,Bigloo) 
>> ,LisP that ran on an apache tomcat server, the application is deplyed in 
>> war files , they are precompiled ,with Kawa or Bigloo Scheme, and also use 
>> regular Java class compiled with Java8.
>> They never ran in REPL ,all the test and debug must be done on the host 
>> that run tomcat web server in Java 8, here is the site : 
>> https://sidonie.oca.eu/  
>>
>> On Friday, October 13, 2017 at 7:37:08 PM UTC+2, Andy Fingerhut wrote:
>>>
>>> Just a note that at the top of the documentation page you mention, it 
>>> says: "Clojure compiles all code you load on-the-fly into JVM bytecode, 
>>> but sometimes it is advantageous to compile ahead-of-time (AOT)."
>>>
>>> I would venture an estimate that most people who use Clojure do so 
>>> without using AOT compilation.  Many would advocate against using AOT 
>>> compilation, unless you are in a particular situation that requires it.
>>>
>>> Andy
>>>
>>> On Fri, Oct 13, 2017 at 10:13 AM, Damien Mattei  
>>> wrote:
>>>
 i did not have , i just follow the tutorial:
 https://clojure.org/reference/compilation
 i made the file but still the same problem:

 [mattei@moita ~]$ export CLASSPATH=.:./clojure/examples
 [mattei@moita ~]$ clojure
 Clojure 1.5.1
 user=> (compile 'clojure.examples.hello)
 FileNotFoundException Could not locate 
 clojure/examples/hello__init.class or clojure/examples/hello.clj on 
 classpath:   clojure.lang.RT.load (RT.java:443)
 user=> ^C[mattei@moita ~]$ 

 [mattei@moita ~]$ cat clojure/examples/hello.clj 
 (ns clojure.examples.hello
 (:gen-class))

 (defn -main
   [greetee]
   (println (str "Hello " greetee "!")))

 On Friday, October 13, 2017 at 4:48:40 PM UTC+2, James Reeves wrote:
>
> Maybe this is a dumb question, but do you have a file 
> "clojure/examples/hello.clj" on the classpath? Since that's what the 
> exception is complaining about.
>
> On 13 October 2017 at 15:09, Damien Mattei  
> wrote:
>
>> hello,
>>
>> i'm new to clojure, just installed it on a CentOS box,
>>
>> and try to compile the code below from tutorial, but it does not 
>> work, i searched a lot before posting, no answer... i do not want to use 
>> leiningen at this stage,later perheaps...
>>
>> just want to compile and run
>>
>> user=> (ns clojure.examples.hello
>> (:gen-class))
>> nil
>> clojure.examples.hello=>
>> clojure.examples.hello=> (defn -main
>>   [greetee]
>>   (println (str "Hello " greetee "!")))
>> #'clojure.examples.hello/-main
>> clojure.examples.hello=> (compile 'clojure.examples.hello)
>> FileNotFoundException Could not locate 
>> clojure/examples/hello__init.class or clojure/examples/hello.clj on 
>> classpath:   clojure.lang.RT.load (RT.java:443)
>>
>> help greatly appreciated (because i'm just one step to leave Clojure 
>> and continue using  Kawa or Bigloo i already use or dive into ABCL , but 
>> Clojure has a so good reputation, i cannot imagine being sticked here by 
>> a 
>> simple hello world!)
>>
>> damien
>>
>> -- 
>> 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.

Re: hello world question !!!

2017-10-13 Thread James Gatannah
This is really "just" a +1 for using Leiningen.

TL;DR: Just start with `lein new app hello-world` and get an editor 
integrated with your REPL quickly. Come back to these sorts of things 
later, if/when you still think they're worthwhile.

I came to clojure from the python/c++ world, with just enough common lisp 
to know that I really wanted to understand how this all works.

And just enough java to know that I never wanted to learn about CLASSPATH.

This sort of thing kept me from giving clojure a serious chance for at 
least a year or two. The only reason I kept trying was that I kept hearing 
such good things about it from people who seemed like they'd put in enough 
time and effort to have good, solid opinions.

Leiningen was the secret sauce that finally let me quit worrying about the 
java nonsense that I just didn't want to care about so I could start poking 
away at the language to see if I could find ways to bend it to my will.

Both of those attitudes were wrong. The "java nonsense" is one (many?) of 
the best parts, though it took me a long time to realize that (and lots of 
it *are* hard to swallow). And it was more a matter of me learning a better 
way to program than any amount of getting clojure to work the way I 
wanted/expected.

I think it's a little sad that setting up a toy project is this painful. 
Then again, clojure really isn't *for* toy projects.

Regards,
James

On Friday, October 13, 2017 at 4:06:12 PM UTC-5, Damien Mattei wrote:
>
> @james
> i also try to set the CLASSPATH at src but it does noot work, i will try 
> Leiningen monday
> Regards,
>
> Damien
>
> On Friday, October 13, 2017 at 9:12:55 PM UTC+2, James Reeves wrote:
>>
>> The docstring for compile 
>> 
>>  
>> says that "The source for the lib must be in a proper
>> classpath-relative directory", so unfortunately you can't just create the 
>> namespace in the REPL and compile it from there. The tutorial on the 
>> Clojure site doesn't make that as clear as it could be.
>>
>> In your revised example, you're setting the classpath incorrectly. The 
>> classpath should contain the root of your file tree. For example, if you 
>> have the file path "src/clojure/examples/hello.clj", then the classpath 
>> should be set to "src".
>>
>> I'm not sure how the "clojure" script you're running works, but you might 
>> find Leiningen to be a better starting point. In Clojure 1.9, an official 
>> "clj" script is going to be introduced, which might make this process 
>> easier. Until then, Leiningen is probably the safer bet.
>>
>> On 13 October 2017 at 18:13, Damien Mattei  wrote:
>>
>>> i did not have , i just follow the tutorial:
>>> https://clojure.org/reference/compilation
>>> i made the file but still the same problem:
>>>
>>> [mattei@moita ~]$ export CLASSPATH=.:./clojure/examples
>>> [mattei@moita ~]$ clojure
>>> Clojure 1.5.1
>>> user=> (compile 'clojure.examples.hello)
>>> FileNotFoundException Could not locate 
>>> clojure/examples/hello__init.class or clojure/examples/hello.clj on 
>>> classpath:   clojure.lang.RT.load (RT.java:443)
>>> user=> ^C[mattei@moita ~]$ 
>>>
>>> [mattei@moita ~]$ cat clojure/examples/hello.clj 
>>> (ns clojure.examples.hello
>>> (:gen-class))
>>>
>>> (defn -main
>>>   [greetee]
>>>   (println (str "Hello " greetee "!")))
>>>
>>> On Friday, October 13, 2017 at 4:48:40 PM UTC+2, James Reeves wrote:

 Maybe this is a dumb question, but do you have a file 
 "clojure/examples/hello.clj" on the classpath? Since that's what the 
 exception is complaining about.

 On 13 October 2017 at 15:09, Damien Mattei  wrote:

> hello,
>
> i'm new to clojure, just installed it on a CentOS box,
>
> and try to compile the code below from tutorial, but it does not work, 
> i searched a lot before posting, no answer... i do not want to use 
> leiningen at this stage,later perheaps...
>
> just want to compile and run
>
> user=> (ns clojure.examples.hello
> (:gen-class))
> nil
> clojure.examples.hello=>
> clojure.examples.hello=> (defn -main
>   [greetee]
>   (println (str "Hello " greetee "!")))
> #'clojure.examples.hello/-main
> clojure.examples.hello=> (compile 'clojure.examples.hello)
> FileNotFoundException Could not locate 
> clojure/examples/hello__init.class or clojure/examples/hello.clj on 
> classpath:   clojure.lang.RT.load (RT.java:443)
>
> help greatly appreciated (because i'm just one step to leave Clojure 
> and continue using  Kawa or Bigloo i already use or dive into ABCL , but 
> Clojure has a so good reputation, i cannot imagine being sticked here by 
> a 
> simple hello world!)
>
> damien
>
> -- 
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this 

Re: Sum types in Clojure? Better to represent as tagged records or as variant vectors?

2017-09-28 Thread James Gatannah
I'm late to this party, and maybe this discussion has already gone on too 
long. If so, I'm sorry for dredging it back up.

But I'm curious about where Tim was going with this, because I feel like I 
might be missing out on a great idea:

On Tuesday, August 29, 2017 at 9:12:33 AM UTC-5, Tim Gilbert wrote:
>
> I've used tagged unions to represent lookup identifiers for variant types 
> and found them to be pleasant to work with. I think part of the reason they 
> don't seem useful in the context of this discussion is that many of the 
> examples given have not actually been variants. For example, in [:image/file 
> "/images/image" :jpeg], every value will have those three data elements, 
> and for {:status :response :result val}, every value will have both of 
> those fields, and their values will be the same type. The identifiers I was 
> working with were in heterogenous collections, so I might have [:image/ref 
> 45] or [:user/name "bob"] or [:project/element "project-slug" 435].
>

I'm trying to match this up with my personal experience, and I think that's 
probably lacking.

Based on Jeanine's talk, I almost think that the real context here is 
language design. I got the impression that we could probably also gain 
benefits in network protocol design. (Someone mentioned this earlier in 
terms of REST and HTTP, but I think there are probably broader 
implications).

I'm generally in favor of the "just stick it into a map" approach. But I'd 
love to hear from people with "That didn't work out well" experience. 
Assuming there are any.

Thanks,

James


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

2017-08-04 Thread James Gatannah
Just to be fair: I didn't dig into the other posts in that series to try to 
figure out where he was going.

So I could be completely and totally off-base on this.

My first reaction was "This is the point behind core.async."

My second reaction was "Why not just use an atom and (add-watch)?"

Then I read his disclaimer that add-watch was still in alpha. March 2013? 
According to 
https://jafingerhut.github.io/clojure-benchmarks-results/Clojure-version-history.html,
 
clojure was up to 1.5 at that point.

Yeah, OK. I can see that still being an alpha feature at that point.

But my third (and, for now, final) reaction was "Why not just supply a 
callback?"

Think 1 is (hopefully) going to finish at some point in time in the future.

It's nice (in theory) to be able to say "Stop processing here until some 
other thread toggles this flag."

And then just resume processing when that flag is toggled.

I've spent the past couple of years fighting with variations on this. We 
keep running into weird issues where t, u, v, x, y, and z run practically 
instantaneously, but w had this weird hiccup that blocked everything for 3 
seconds. And no one can explain why.

I think every book I've ever read about implementing scheme is built around 
this idea. You set up a Kontinuation to restore the call stack and resume 
control when some condition is met.

But, honestly, is it really that complex to just hand over a callback?

Sure, that callback might do something with core.async or manifold (my 
experience with both has been great!), or trigger off a bunch of fireworks. 
Or stick the latest response message onto a queue for something else to 
process later.

But the part that calls that should neither know/care. It got a new message 
that gives it a reason to trigger something. It's a big, nasty, ugly, thing 
that's going to involve a bunch of side-effects. Trigger them and be done.

It scares me that I just wrote that.

But I think I'm in pretty good company here.

1. Get some message that tells you side-effects need to happen
2. Build a seq of side-effects that have to happen
3. Call something like (reduce) across that seq to actually make them happen

The actual mechanism behind it all (promise, future, async/chan, 
manifold/stream, etc) is an implementation detail.

On Wednesday, August 2, 2017 at 4:09:04 PM UTC-5, lawrence...@gmail.com 
wrote:
>
> I stumbled across this old post by Tomasz Nurkiewicz:
>
> http://www.nurkiewicz.com/2013/03/promises-and-futures-in-clojure.html
>
> He writes: 
>
> "And here is where the greatest disappointment arrives: neither future 
>  nor promise 
>  in Clojure 
> supports listening for completion/failure asynchronously. The API is pretty 
> much equivalent to very limited java.util.concurrent.Future 
> .
>  
> We can create future, cancel it 
> , check 
> whether it is realized? (resolved) 
>  and block 
> waiting for a value. Just like Future in Java, as a matter of fact the 
> result of future function even implements java.util.concurrent.Future. 
> As much as I love Clojure concurrency primitives like STM and agents, 
> futures feel a bit underdeveloped. Lack of event-driven, asynchronous 
> callbacks that are invoked whenever futures completes (notice that 
> add-watch  
> doesn't 
> work futures - and is still in alpha) greatly reduces the usefulness of a 
> future object. "
>
> That was written in 2013. I think since then the community has found other 
> ways to achieve the same goals? I'm curious what patterns have become 
> common? Would it be correct to say that for most of the use cases where one 
> would otherwise want a notification of completion on a Future, people 
> nowadays instead use something like core.async or a library such as 
> Manifold? 
>
>
>
>
>
>
>
>
>

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

2017-07-26 Thread James Gatannah
I feel your pain. I don't have an answer, but the basic point convinced me 
to write this: 
http://gatannahfiles.blogspot.com/2017/07/moving-away-from-guard-rails.html


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


Re: Clojure resume tips?

2017-03-23 Thread James Gatannah
To get back on-target, I think you should highlight 1 or maybe 2 of your 
github repos and go flesh them out.

I had high hopes for both click-time-fun and cljs-game, but wasn't sure 
what to try or where to start. Working demos are pretty magical, and, 
honestly, incredibly rare.

https://github.com/noffle/art-of-readme has some advice that I've been 
planning to take to heart for a while now about how to help other people 
understand what your projects are about.

That probably won't help your resume get through the original HR screen, 
but it can definitely make interviewers stand up and take notice.

Good luck,
James


On Thursday, March 23, 2017 at 12:10:30 PM UTC-5, Jason Basanese wrote:
>
> Attached is a fairly bad resume that I am using. Any tips on how I might 
> change it to appeal to more places that are looking for functional 
> developers?
>

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

2017-03-23 Thread James Gatannah


On Thursday, March 23, 2017 at 2:00:28 PM UTC-5, puzzler wrote:
>
> On Thu, Mar 23, 2017 at 11:24 AM, Luke Burton  > wrote:
>
 

> Insightful post about a lot of things related to hiring, but I have to 
> take exception with this very last point.  Recently, a friend of mine 
> sought out a data science position in the Seattle area.  Each prospective 
> employer gave him a take-home assignment that required 30-40 work hours to 
> complete.  Some of the assignments were real problems the company was 
> facing, so he was effectively being asked to do free consulting work for 
> each company.  This is a horrible, burdensome interview practice and it 
> would be dreadful if it became the norm in the software industry. 
> Suggesting that someone offer to do a take-home project may make sense in 
> specific cases for an inexperienced candidate, but I fear it starts our 
> industry down the slippery slope.
>

It's not quite on-topic, since this is a post-resume story.

But once upon a time I worked at a company where a fairly senior candidate 
was asked about whatever real-world problem the interviewer was working on 
at the time. I think it was a relaxed "So, how would you approach this 
particular scenario?" big-picture kind of question.

We didn't hire him.

He sent us a bill for an hour of consulting.

The legal department told us to pay it and never, ever, under any 
circumstances, ask any question that could be remotely construed as 
relevant to our actual business needs.

Personally, I enjoy the little "Spend a couple of hours knocking this out" 
challenges, as long as I don't get graded on criteria that wasn't mentioned 
up front ("Our internal style guide, which you've never seen, dictates that 
you must do X"). But I'm at the point where I'd rather point people to 
github so we can talk about real projects that actually have serious 
time/thought investments.

And, on the flip side, I'd rather look at what a candidate's done there, 
even if it does take more time/effort on the hiring side than seeing how 
they approach a cookie-cutter project.

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

2016-11-16 Thread James Gatannah
Thank you, Alex.

Both for the feedback about what I'm doing wrong and for a fix that looks 
simple and obvious.

Regards,
James

On Sunday, November 13, 2016 at 9:57:55 AM UTC-6, James Gatannah wrote:
>
> One of my system boundary data structures is particularly ugly.  It 
> involves things like JNI classes wrapping native socket libraries, go 
> loops, and higher-order functions that I can use to plug in message 
> dispatchers.
>
> I'm in the process of translating it from schema to spec. So far, the 
> process has been very educational.
>
> I've reached a point where calling (s/valid? ::foo x) returns false, but 
> (s/explain ::foo x) returns nil.
>
> Is this a bug in spec? Or am I misinterpreting the docstrings?
>
> (Narrowing it down enough to identify/fix my actual problem is one thing. 
> Getting something that's easily/obviously reproducible is going to be more 
> difficult, just because the problem spans at least 3-4 different github 
> repos).
>
> Thanks,
> James
>  
>

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

2016-11-16 Thread James Gatannah
Congrats!

On Monday, November 14, 2016 at 9:09:01 PM UTC-6, Nicolas Modrzyk wrote:
>
> Hi Clojure people,
>
> So after one year and 23 days, (that would be 388 days) the IT book I was 
> working on with Makoto (merci!) finally got published!
>
> It has been a long battle with many late nights to get it out, tough 
> deadlines and never-ending reviews, but thanks to some skilled people at 
> Packt, thank you Sachin, Pranav (and not forgetting Nikhil, you got it all 
> started!) (http://packtpub.com/ 
> )
>  
> it is finally there in all its 635 pages glory ;)
>
> (PACK) 
> https://www.packtpub.com/application-development/clojure-programming-cookbook
>
> (AMAZON) http://a.co/3c9ckbp 
>
> The book while also presenting Clojure language centric topics, wants to 
> be slightly more focused around using Clojure at work and is bringing tons 
> and tons of working examples for every day usage. Along its (long!) 10 
> chapters, the book goes through many various topics but tries to keep each 
> topic easy to follow, with fun and useful recipes for great projects and 
> various creative ideas.
>
> The book may sometimes be too simple to many of the members of this 
> mailing list, but we hope the book contribute to grow the Clojure community 
> by sharing useful (and battled) Clojure code and stories.
>
> This is out now ! Enjoy!
> Nicolas & Makoto, all the way from Japan
>

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

2016-11-14 Thread James Gatannah
Ticket filed: http://dev.clojure.org/jira/browse/CLJ-2057

Thanks!

On Sun, Nov 13, 2016 at 3:36 PM, Alex Miller  wrote:
> Any case where valid? returns false and explain-data returns nil is a bug.
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> 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/1gOBPLk5wpg/unsubscribe.
> To unsubscribe from this group and all its topics, 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: s/valid? vs. s/explain

2016-11-13 Thread James Gatannah
s/explain doesn't produce any sort of error/output that I can see.

s/explain-data returns nil.

s/explain-str returns the last few lines printed by the function being
exercised. Maybe it captures output from the final test run?


On Sun, Nov 13, 2016 at 10:22 AM, Josh Tilles <j...@signafire.com> wrote:
> Just going on memory at the moment, but I’m pretty sure `s/explain` just
> writes to `*out*` (and thus always returns `nil`). You probably want
> `s/explain-data` or `s/explain-str`.
>
> -Josh
>
> On Sun, Nov 13, 2016 at 10:58 AM James Gatannah <james.gatan...@gmail.com>
> wrote:
>>
>> One of my system boundary data structures is particularly ugly.  It
>> involves things like JNI classes wrapping native socket libraries, go loops,
>> and higher-order functions that I can use to plug in message dispatchers.
>>
>> I'm in the process of translating it from schema to spec. So far, the
>> process has been very educational.
>>
>> I've reached a point where calling (s/valid? ::foo x) returns false, but
>> (s/explain ::foo x) returns nil.
>>
>> Is this a bug in spec? Or am I misinterpreting the docstrings?
>>
>> (Narrowing it down enough to identify/fix my actual problem is one thing.
>> Getting something that's easily/obviously reproducible is going to be more
>> difficult, just because the problem spans at least 3-4 different github
>> repos).
>>
>> Thanks,
>> James
>>
>>
>> --
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to clojure@googlegroups.com
>> Note that posts from new members are moderated - please be patient with
>> your first post.
>> To unsubscribe from this group, send email to
>> clojure+unsubscr...@googlegroups.com
>> For more options, visit this group at
>> http://groups.google.com/group/clojure?hl=en
>> ---
>> You received this message because you are subscribed to the Google Groups
>> "Clojure" group.
>> To unsubscribe from 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/1gOBPLk5wpg/unsubscribe.
> To unsubscribe from this group and all its topics, 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: s/valid? vs. s/explain

2016-11-13 Thread James Gatannah
Turns out I was wrong about the minimal use case.

This particular problem was just an fdef that was missing a :ret spec.

That seems like a bug in s/explain,  but I think it's a tossup whether
the bug's in the docstring or the implementation.

And I'm not entirely convinced that it's a bug at all. But it's
strange enough to seem worth mentioning/explaining.

Thanks again,
James



On Sun, Nov 13, 2016 at 9:57 AM, James Gatannah
<james.gatan...@gmail.com> wrote:
> One of my system boundary data structures is particularly ugly.  It involves
> things like JNI classes wrapping native socket libraries, go loops, and
> higher-order functions that I can use to plug in message dispatchers.
>
> I'm in the process of translating it from schema to spec. So far, the
> process has been very educational.
>
> I've reached a point where calling (s/valid? ::foo x) returns false, but
> (s/explain ::foo x) returns nil.
>
> Is this a bug in spec? Or am I misinterpreting the docstrings?
>
> (Narrowing it down enough to identify/fix my actual problem is one thing.
> Getting something that's easily/obviously reproducible is going to be more
> difficult, just because the problem spans at least 3-4 different github
> repos).
>
> Thanks,
> James
>
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> 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/1gOBPLk5wpg/unsubscribe.
> To unsubscribe from this group and all its topics, 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.


s/valid? vs. s/explain

2016-11-13 Thread James Gatannah
One of my system boundary data structures is particularly ugly.  It 
involves things like JNI classes wrapping native socket libraries, go 
loops, and higher-order functions that I can use to plug in message 
dispatchers.

I'm in the process of translating it from schema to spec. So far, the 
process has been very educational.

I've reached a point where calling (s/valid? ::foo x) returns false, but 
(s/explain ::foo x) returns nil.

Is this a bug in spec? Or am I misinterpreting the docstrings?

(Narrowing it down enough to identify/fix my actual problem is one thing. 
Getting something that's easily/obviously reproducible is going to be more 
difficult, just because the problem spans at least 3-4 different github 
repos).

Thanks,
James
 

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

2016-10-17 Thread James Gatannah


On Saturday, October 15, 2016 at 10:17:15 PM UTC-5, Josh Tilles wrote:
>
> I’ve got a couple questions for Alex Miller and/or the other Cognitect 
> folks.
>

That isn't me. I'm just chiming in from the peanut gallery. Must of my 
"experience" so far stems from converting
my toy projects from prismatic schema to spec.

>
>1. *Are single-segment namespaces still “bad” when it comes to 
>registering specs under qualified keywords?*
>In the past, single-segment namespaces have been discouraged in the 
>Clojure community—both because of Java interop concerns and because of the 
>possibility of name-collision when combining projects. However, many of 
> the 
>spec examples I’ve seen have demonstrated registering specs under keywords 
>qualified by a single-segment namespace. For example, the guide’s 
>section on multi-spec  
>defines :search/url and :error/message. Is that because 
>namespace-qualifiers of specs shouldn’t be under the same constraints as 
>namespaces used to organize code?
>
> This part of the question interests me a lot.

I've found myself defining a lot of specs in, say, the 
com.foo.project.schemas namespace.

This used to be extremely convenient, due to ns aliases.

I think the docs say that I should be able to set up the same kind of basic 
aliasing so that I can
just refer to those specs as (for example) :c.f.p.s/whatever. But I haven't 
been able to actually 
get that to work yet.

I've found myself with a lot of definitions that look like (apologies for 
the formatting/whitespace):

(s/def ::socket-description (s/keys :opt [::client-keys
  ::server-key]
:req [::ctx
  
:com.jimrthy.cljeromq.common/direction
  ::port
  ::sock-type
  
:com.jimrthy.cljeromq.common/socket
  :com.jimrthy.cljeromq.core/url]))

That isn't *too* bad. But this sort of thing gets annoying when I'm nesting 
these things into other namespaces. Especially from the REPL, which is 
lisp's strongest selling point (to me).

I'm willing to bet that I've just missed a talk somewhere about how this is 
supposed to work. Or maybe I just need to keep working on getting my head 
wrapped around these changes.

I don't want to hijack your thread. This was more of a "Me too! This is 
why...I think" sort of thing.. 




>1. I’m *guessing* not; it seems more likely that the single-segment 
>namespaces have been used only to keep the code snippets straightforward 
>and focused on spec, and that “real” code would alias (e.g.) 
>my-company.my-project.search as search before defining a ::search/url 
>spec.
>
>
> Thank you for your help. I really appreciate it.
>

Again, me too! Thanks,
James 

>
> Best,
> Josh
>

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

2016-10-17 Thread James Gatannah
Sweet! And thanks!

I've been trying to find the time to learn enough boot to write this for 
myself.

On Saturday, October 15, 2016 at 8:28:58 AM UTC-5, Borkdude wrote:
>
> Only a few lines of code, but it does the job:
>
> https://github.com/borkdude/boot-bundle
>
> This library lets you define a set of dependencies by a keyword. Details 
> in the README.
>
> I found it especially useful in a multi-project repo where we use a lot of 
> the same dependencies in each project. 
> It's also possible to share your personal bundle via Clojars and use it in 
> your personal projects.
>

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

2016-10-12 Thread James Gatannah


On Thursday, October 6, 2016 at 4:39:43 PM UTC-5, Xman wrote:
>
> It's been many years of postponing learning programming, because I 
> considered the popular languages of that time not right.
>

It's been my experience that there are no "right languages." They all have 
major flaws. No matter what, when you really dig into
one, you'll hit "I really wish I could..." itches.

Any lisp, by its nature, makes those itches easier to scratch. But there's 
always something. That's part of what makes this such a fascinating and 
exciting field of knowledge.

 

> It took me nearly 3 years to learn and build a website using another stack 
> (I wont advertise here), 
>

Congratulations!

Having built something puts you far ahead of most people. It doesn't matter 
how you did it. The fact that you did is something to be proud of.


 

> and without having much previous knowledge in programming.
>

I think the old Nike slogan fits well here: just do it.
 

>  I have not deployed the website yet.
> I would like to know if Clojure is a great option to make websites ?
>

I think that others have addressed this particular question very well.

I think your subject question was more interesting (though others have also 
done a great job addressing it):

> Should I switch to Clojure after 3 years of learning another full stack ?

This is the sort of question that you will always have to answer for 
yourself.

Are there good reasons for learning clojure?

Absolutely.

Are there good reasons for learning any other technology that's also been 
mentioned in this thread?

Absolutely.

Are any of those reasons good enough for you to dedicate your valuable time 
to learning them?

No one but you can make that decision. Or, really, even know what your 
pros/cons are.

I think it's probably safe for me to recommend that you shouldn't translate 
your existing
site/app to a new technology until/unless the current one has proved that 
it really won't
work. And, even then, there's a good chance you could find someone to help 
you figure
out how to make it work well in whatever language you started with.

(It would probably be stronger/lighter/faster/more ductile/less tough if 
you'd written it it clojure
in the first place, but working code beats "probably" every time).
 

>
> I found out that there are new features on the web that Clojure is better 
> for, but I don't use those features in the present.
>

Are you sure about that?

There are a lot of really nice features that have been built into clojure. 
Most useful programs in other languages have to find ways to work around 
them.

If your website works fine, then there probably isn't a good reason to 
switch it over.

You can do that while also learning clojure. It's perfectly fine (and, 
honestly, pretty good) to be multi-lingual.

If that's your cup of tea, of course. If learning one programming language 
was all you care about, that's perfectly fine!

But, honestly, it sounds to me like you're poking around at the idea of 
learning another. Which is pretty
cool too. Actually, it's a lot of fun. If you're into that sort of thing, 
it can turn into a good career.

But maybe you're past the whole "career" thing and just looking for ways to 
amuse yourself as an alternative to
doing crossword puzzles now that you're retired.

If you're interested in the craft of programming, clojure really is a good 
one to learn.

Then again, so are languages like python and ruby and C# (and a slew of 
others).

Take your pick.

These days, C and javascript are the 900 pound gorillas. If you want to get 
into nitty-gritty, or you're doing something very simple,
they're good choices. I personally think there's more black voodoo magic 
there than craft, but black voodoo magic has its place
too.


 

> When I choose to learn a language I decide by myself, and after listening 
> to a video talk, it gives me reasons to think that its better.
>

I hate to go to absolutes, but there's very rarely a blanket "better" in 
any aspect of engineering. Listening to a talk can
be great, but...that's honestly just the marketing pitch.

This gets into personal motivations, so it doesn't really have any place in 
a technical discussion list. But that's really what
the talks are all about.

Do the ideas resonate enough with you to convince you to dedicate the time 
that it takes to learn a language?

It took years for clojure to convince me to make a serious investment in it.

Maybe it never will for you. Again: there's nothing wrong with that.

 

> I want to learn the language and "frameworks" (or how to create the 
> architecture) much quicker than previous attempt.
>

This is up to you.

Odds are, it should be faster.

But that depends on how much difference you're trying to manage.

Personally, I've never been able to make sense out of perl.

I know people who use it to do things that seem magical to me. So I keep 
trying to find time to do the same.

But, really, this is up to you.

A second programming 

Strange tooling interaction bug(?)

2016-10-01 Thread James Gatannah
I recently decided to try out devcards. I got an error because my
ancient java version is no longer supported. I've been meaning to
upgrade that dev environment, so I went ahead and bumped it from
ubuntu 14.04 to 16.04.

Once that was finished, I went back to my experimental devcards
project to try again.

`lein check` ran fine, but `lein repl` led to a stack trace caused by
"java.lang.IllegalArgumentException: Malformed assignment, expecting
(set! target val)"

The problem happened when it tried to compile
/tmp/form-init${long-number}.clj:1:7567.

Trying to google for that error just led me to the basic compiler
code. Something is trying to call the set! special form without two
arguments.

OK, fine. I'd started from a figwheel project template and tweaked
some things like dependency versions (the biggest change was switching
clojure from 1.8.0 to 1.9.0-alpha12). So I generated a fresh
plain-jane vanilla `lein new devcards foo` project. It looks like this
was just updated today, so I may be comparing apples to oranges.

Except that had the same problem.

So I grabbed the file in /tmp/ to examine. There aren't many calls to set!.

The one it's complaining about is
`(set! *print-length* 50 do (clojure.core/require (quote
whidbey.repl)) (whidbey.repl/init! {:whidbey-options "from my
profiles.clj"}))`

In ~/.lein/profiles.clj, under user, I have a :repl-options key which
has the value {:nrepl-middleware []}. (That needs to go away,
obviously).

Then there's a :whidbey key, with the values that were injected into
that broken (set!) call.

The "problem line" is inside the project.clj that was generated by the
devcards/figwheel templates:

 :profiles {:dev {:repl-options {:init (set! *print-length* 50)}}}

If I just delete that option, the REPL starts fine. I haven't done any
experimentation beyond that point.

Does this seem extremely odd to anyone else? And does anyone have any
thoughts about what the real underlying problem might be? Or even
suggestions about useful experiments I could try to narrow the problem
down?

Thanks,
James

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


Re: why is it so annoying to run clojure code

2016-06-15 Thread James Gatannah
It was (thoughtfully and politely) pointed out that I came across as smug 
here.

I'm very sorry about that. I plead exhaustion.

I use python for most of my day job. I was trying to convey how much more
painful its workflow is for me, now that I've embraced "the lisp way" for my
personal projects (I have a toddler...I don't have time to spend on all the 
things that most of the computer industry never even questions).

I meant to go back and edit this to replace "you" with examples of how *I* 
do
these things wrong. I hit Send instead of saving to a draft until this 
morning.

There is a learning curve, and it's a serious change in your point of view. 
But it
really is totally worth it.

Respectfully and apologetically,
James

On Wednesday, June 15, 2016 at 1:02:55 AM UTC-5, James Gatannah wrote:
>
> I *totally* understand your (and pretty much every other responder's) 
> frustration.
>
> You're approaching it wrong.
>
> Most python/ruby programmers get this wrong, also. It's OK. I did this 
> wrong for
> *years* in lots of different languages. (I blame my C++ background for how 
> long
> it's taking this to sink in for me).
>
> One of the keys to "getting" lisp is to embrace the REPL. Start your 
> environment
> up. And let it run. It isn't a living, breathing entity, but it's easy to 
> forget that after
> a short while.
>
> Python's interactive shell covers the same idea. I think ruby has IRB to 
> do the
> same sort of thing. But those are just kind-a sort-a "See? We can do the 
> same
> thing lisp does" wannabes.
>
> I don't want to trash talk ruby or python. They're both great languages 
> for what
> they do.
>
> But they're designed for solving different, easier problems. And they're 
> built for
> coping with those problems in ways that are horribly more complicated.
>
> I came to clojure from a python/common lisp background (and I came to them
> from a C++ background). I spent years hating everything different about 
> it, 
> and I was totally wrong.
>
> Long startup time? Totally worth it. I go through it a few times when I 
> get my
> basic system defined. (People have already recommended Stuart Sierra's
> Component architecture in this thread, haven't they?)
>
> And then my entire system is defined and works. I don't ever need to 
> restart
> until I bring in a new dependency.
>
> When I work in python, I have to restart everything under the sun every 
> time
> I screw up the arguments to a printf.
>
> Immutable data structures? This is the paydirt, darling. I thought that 
> this was
> the most horrible part of clojure, and I wasted reams of imagination 
> trying to
> figure out ways around it.
>
> And I was wrong.
>
> Unless you're writing an OS kernel, you should probably be using immutable
> data structures. Even if you're genius enough to track all the ways that 
> your
> mutable data structure could possibly be mangled, the next person to come
> along and deal with it won't be as smart as you.
>
> That "next person" is usually you 6 months in the future. Don't screw 
> yourself
> over.
>
> And then there's the JVM.
>
> I used to think I was safer from hackers because the JVM gets hacked
> 20,000 times a day and "my" platform *never* got hacked.
>
> Then someone pointed out that the JVM gets attacked 20 bazillion times a
> second, whereas "my" platform would never get attacked until/unless I
> actually created something successful on it.
>
> Just learn how to use lein and/or boot. It *is* annoying, but a good
> investment.
>
>
> On Thursday, June 9, 2016 at 11:08:39 AM UTC-5, Jiacai Liu wrote:
>>
>> I  started learning clojure recently, and I am annoyed at the way to run 
>> it (aka. lein run). why clojure script can't be run like python,ruby or 
>> scala, like python .py
>>
>

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


Re: why is it so annoying to run clojure code

2016-06-15 Thread James Gatannah
I *totally* understand your (and pretty much every other responder's) 
frustration.

You're approaching it wrong.

Most python/ruby programmers get this wrong, also. It's OK. I did this 
wrong for
*years* in lots of different languages. (I blame my C++ background for how 
long
it's taking this to sink in for me).

One of the keys to "getting" lisp is to embrace the REPL. Start your 
environment
up. And let it run. It isn't a living, breathing entity, but it's easy to 
forget that after
a short while.

Python's interactive shell covers the same idea. I think ruby has IRB to do 
the
same sort of thing. But those are just kind-a sort-a "See? We can do the 
same
thing lisp does" wannabes.

I don't want to trash talk ruby or python. They're both great languages for 
what
they do.

But they're designed for solving different, easier problems. And they're 
built for
coping with those problems in ways that are horribly more complicated.

I came to clojure from a python/common lisp background (and I came to them
from a C++ background). I spent years hating everything different about it, 
and I was totally wrong.

Long startup time? Totally worth it. I go through it a few times when I get 
my
basic system defined. (People have already recommended Stuart Sierra's
Component architecture in this thread, haven't they?)

And then my entire system is defined and works. I don't ever need to restart
until I bring in a new dependency.

When I work in python, I have to restart everything under the sun every time
I screw up the arguments to a printf.

Immutable data structures? This is the paydirt, darling. I thought that 
this was
the most horrible part of clojure, and I wasted reams of imagination trying 
to
figure out ways around it.

And I was wrong.

Unless you're writing an OS kernel, you should probably be using immutable
data structures. Even if you're genius enough to track all the ways that 
your
mutable data structure could possibly be mangled, the next person to come
along and deal with it won't be as smart as you.

That "next person" is usually you 6 months in the future. Don't screw 
yourself
over.

And then there's the JVM.

I used to think I was safer from hackers because the JVM gets hacked
20,000 times a day and "my" platform *never* got hacked.

Then someone pointed out that the JVM gets attacked 20 bazillion times a
second, whereas "my" platform would never get attacked until/unless I
actually created something successful on it.

Just learn how to use lein and/or boot. It *is* annoying, but a good
investment.


On Thursday, June 9, 2016 at 11:08:39 AM UTC-5, Jiacai Liu wrote:
>
> I  started learning clojure recently, and I am annoyed at the way to run 
> it (aka. lein run). why clojure script can't be run like python,ruby or 
> scala, like python .py
>

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

2015-08-05 Thread James Gatannah
 layers to get us closer to the 
database.

I'm absolutely positive that it would not be desirable.

My database connection consists of data structures that I put onto and 
read
from a message queue.

This system is about as far from functional purity as you can possibly get.

It's quite possible that the database guys at the very bottom of the stack 
are
using exactly the kind of global connections that were originally suggested.

The difference is that, even if they are (and I certainly hope not!), I 
can't touch
them. When (and it's never if) a hacker gets control over the front-end 
web
server, that's just the first layer of defense.

Regards,
James

 


 James Gatannah writes: 

  On Thursday, July 30, 2015 at 7:44:31 PM UTC-5, J. Pablo Fernández 
 wrote: 
  
  Hello Clojurians, 
  
  I found passing around the database connection to each function that 
 uses 
  it very error prone when you are using transactions as passing the 
 wrong 
  one could mean a query runs outside the transaction when in the source 
 code 
  it is inside the with-db-transaction function. 
  
  
  I'll go ahead and make the point that it's error-prone for different 
  reasons. 
  
  Pretty much by definition, that database connection is a system 
 boundary. 
  It's all about something that's *way* more complex than random global 
 state 
  changes inside your program. This is a thing that interacts with the 
  outside world, with all the nastiness that implies. 
  
  Everything that everyone else has already written about this approach is 
  true, but I don't think they've gone far enough. 
  
  Even if you pass that database connection around as a parameter 
 everywhere, 
  you're talking about throwing away a huge part of the benefit of using a 
  functional language. 
  
  Isolate your side-effects. 
  
  Think of a castle. You have a moat surrounding it, and a few gates that 
 you 
  use to allow your peasants to enter/exit. This particular gate opens up 
 to 
  a swamp full of alligators. 
  
  Your approach amounts to letting the gators wander around loose. 
  
  Passing the connection around to each function in the call chain is like 
  tying a ribbon around the gator's neck and hoping you can use that as a 
  leash. 
  
  You can use either approach to great effect. If you're really, really 
 good. 
  And so is everyone else on your team (you did mention a 200 KLOC 
 project). 
  
  One of the main benefits to functional programming is that admitting you 
  aren't really, really good is incredibly liberating. I don't have the 
  time/energy to dedicate to trying to maintain this sort of code. (Yes, I 
  spent lots of time recently thinking about how java was designed for 
 very 
  average programmers, but it really takes much better programmers than a 
  functional language to actually write correct programs). Even if I were 
  that good...I'd rather be focused on the problems that make my customers 
  happy. 
  
  I'm going to appeal to authority here for the right 
  answer: http://prog21.dadgum.com/23.html (in my defense, it's a great 
  blog). Have your web response handler (which is another system 
  boundary...this one is next to an active volcano populated by 
  fire-breathing dragons) build up a list of all the nasty side-effects 
 that 
  will eventually have to happen. 
  
  Don't just isolate your side-effects. Quarantine those suckers as if 
 each 
  and every one means you're dealing with the most diabolical hacker you 
 can 
  imagine. 

 -- 
 Sent with my mu4e 


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

2015-08-05 Thread James Gatannah


On Monday, August 3, 2015 at 10:21:09 PM UTC-5, Dmitri wrote:

 My understanding is that the problem is actually caused by the stateless 
 nature of the functions.


You're talking about database interactions. By definition, those are not 
stateless. The trick is to isolate this statefulness as much as possible. 
Expanding it just compounds the problem. 

 

 Since the function accepts the connection as a parameter it's up to the 
 user of the function to ensure that it's passed the correct connection.


That depends on what you mean by user of the function. If I'm working on 
the web server front-end, I shouldn't have any idea about the database 
connection. I should describe what I
want to happen. If I have any concept that multiple databases are involved 
(I shouldn't, but abstractions leak), then, yes, I have to specify which 
one I mean. This isn't
complicated.

It's up to the person writing the database back-end code (also possibly me, 
if we're talking about a start-up, but then we aren't talking about the 200 
KLOC scenario) to turn that
description into the side-effects.

 

 Every functional solution presented in this thread suffers from this same 
 fundamental problem that the function is not aware of the context it's 
 being run in.


That isn't a problem: it's a feature.

It doesn't matter what language or programming paradigm you're using in 
this context. This cuts across problem domains and architectures.

The actual database interaction code should be as brain-dead simple (not 
easy) and bullet-proof as you can possibly make it. And it should be as
isolated from the front-end code as you can get away with making it.

That isn't a right answer. But it's a good rule of thumb. And you should 
have very hefty reservations (and very good reasons) about violating it.

Respectfully,
James

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

2015-08-02 Thread James Gatannah


On Thursday, July 30, 2015 at 7:44:31 PM UTC-5, J. Pablo Fernández wrote:

 Hello Clojurians,

 I found passing around the database connection to each function that uses 
 it very error prone when you are using transactions as passing the wrong 
 one could mean a query runs outside the transaction when in the source code 
 it is inside the with-db-transaction function.


I'll go ahead and make the point that it's error-prone for different 
reasons.

Pretty much by definition, that database connection is a system boundary. 
It's all about something that's *way* more complex than random global state 
changes inside your program. This is a thing that interacts with the 
outside world, with all the nastiness that implies.

Everything that everyone else has already written about this approach is 
true, but I don't think they've gone far enough.

Even if you pass that database connection around as a parameter everywhere, 
you're talking about throwing away a huge part of the benefit of using a 
functional language.

Isolate your side-effects.

Think of a castle. You have a moat surrounding it, and a few gates that you 
use to allow your peasants to enter/exit. This particular gate opens up to 
a swamp full of alligators.

Your approach amounts to letting the gators wander around loose.

Passing the connection around to each function in the call chain is like 
tying a ribbon around the gator's neck and hoping you can use that as a 
leash.

You can use either approach to great effect. If you're really, really good. 
And so is everyone else on your team (you did mention a 200 KLOC project).

One of the main benefits to functional programming is that admitting you 
aren't really, really good is incredibly liberating. I don't have the 
time/energy to dedicate to trying to maintain this sort of code. (Yes, I 
spent lots of time recently thinking about how java was designed for very 
average programmers, but it really takes much better programmers than a 
functional language to actually write correct programs). Even if I were 
that good...I'd rather be focused on the problems that make my customers 
happy.

I'm going to appeal to authority here for the right 
answer: http://prog21.dadgum.com/23.html (in my defense, it's a great 
blog). Have your web response handler (which is another system 
boundary...this one is next to an active volcano populated by 
fire-breathing dragons) build up a list of all the nasty side-effects that 
will eventually have to happen.

Don't just isolate your side-effects. Quarantine those suckers as if each 
and every one means you're dealing with the most diabolical hacker you can 
imagine.

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

2015-03-17 Thread James Gatannah

On Thursday, March 12, 2015 at 10:16:10 AM UTC-5, Stuart Sierra wrote:

 On Wednesday, March 11, 2015, Colin Yates wrote:

 Nested systems don't really work.


FWIW, we've been using something that smells an awful lot like nested
systems for months now. I never realized we weren't supposed to.

Maybe we just got lucky?

- James

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


shutdown-agents without agents

2014-05-11 Thread James Gatannah
I apologize if this is just useless noise. It's after midnight on
Sunday, I need to get to bed, and I know I'll totally forget about
this if I don't make the scenario public.

This is on clojure 1.5.1. CentOS 6.5 (virtual guest running on a
Citrix Xen Server host, probably also running CentOS), and 64-bit
OpenJDK 1.7.0_55.

I've spent most of this weekend trying to figure out why my `lein
repl` client was exiting when I tried to run a command after
tools.namespace/refresh.

I'm using Stuart Sierra's Workflow Reloaded, so the actual interaction
looked something like (apologies in advance...I'm typing this in
manually rather than copy/pasting):

user= (reset)
...blah...
Success!
user= anything
SocketException: The transport's socket appears to have lost its
connection to the nREPL server
   clojure.tools.nrepl.transport/bencode/fn--4287/fn--4288 (transport.clj:95)
   clojure.tools.nrepl.transpart/bencode/fn--4287 (transport.clj: 95)
   clojure.tools.nrepl.transpart/fn-transport/fn--4261 (transport.clj:42)
   clojure.core/binding-conveyor-fn/fn--4107 (core.clj:1836)
   java.util.concurrent.FutureTask.run (FutureTask.java:262)
   java.util.concurrent.ThreadPoolExecutor.runWorker
(ThreadPoolExecutor.java:1145)
   java.util.concurrent.ThreadPoolExecutor$Worker.run
(ThreadPoolExecutor.java:615)
   java.lang.Thread.run (Thread.java:744)
Bye for now!

And I think I might have just managed to get a fairly minimalist
scenario (though it still may be tied into the details of the
libraries I'm loading in project.clj, or some such).

If I use lein to start a REPL at the command prompt and immediately
call (shutdown-agents), I get this same unhandled exception after the
next form I enter.

I'm not sure where to go with this one, or even if I should. I guess I
really should just start with an empty default project.clj and add in
libraries (if needed) until I can reproduce the problem. Except that
google makes it look like no one else has ever had the same problem.
So that might be a complete and total waste of time.

Does anyone have any opinions about whether this is worth pursuing?

Thanks,
James

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

2014-01-20 Thread James Gatannah


On Sunday, January 19, 2014 12:48:36 PM UTC-6, Brian Craft wrote:

 That helps, thanks. It's still unclear to me that this is important enough 
 to worry about. What application or service is hindered by string encoding 
 a date in JSON? An example would really help. It's not compelling to assert 
 or imagine some hypothetical application that benefits from knowing a field 
 is a date without having any other knowledge of it. I would guess that 
 cases where this matters are vanishingly few.


This isn't dates, but it's along the same lines:

I'm working on the central hub of a communications distributor/router/thing 
which has to deal with a wide range of diverse clients that each speak 
whatever format was the most expedient for whoever wrote that piece. The 
closest thing that we have to a standard is we mostly want to use JSON.

A huge chunk of our messages include UUIDs. This left me with two real 
options:
1. Special case every incoming message, based on what I know about the 
sender, and convert the fields that I know are supposed to represent a UUID 
(based on extremely informal verbal specs) as a message is read
2. Take the generic, weakly coupled approach: pass every incoming message 
through a parser that converts every value string into a UUID (if that 
conversion is possible).

The pain here could be alleviated with a formalized schema, but we're 
working too fast and furious for that. We tossed out the last one of those 
we had almost 2 months ago.

Dates really present the same challenge, but everything that's using those 
is tied to a relational database. So there, at least, we're forced to stick 
to something fairly standardized. (Though I *do* have another conversion 
function for converting those messages, which tends to change about once a 
week when some other developer decides to change column names...but that's 
a different story).

FWIW,
James




 On Sunday, January 19, 2014 9:03:53 AM UTC-8, jonah wrote:

 I read these self-describing, extensible points in the context of EDN, 
 which has a syntax/wire format for some types- maps, strings, etc- and also 
 has an extensibility syntax:

 #myapp/Person {:first Fred :last Mertz}

 These tagged elements are extensions because they allow values of types 
 not known to EDN to be included in the stream, and are self-describing in 
 two senses:

 * if a wire format reader does know how to create a myapp/Person{}, that 
 blob of data contains all the information needed to do so
 * if a wire format reader doesn't known how to create a myapp/Person, it 
 can still read past this particular element in the stream, because tags 
 have a defined envelope, so a reader can figure out where data comprising 
 this element ends

 The JSON example is mostly about the extensibility attribute. JSON's 
 format natively supports some types (like strings) but not others (like 
 dates), and for those others, JSON's format does not include a way to 
 bucket or envelope data comprising those unknown types. So JSON is not 
 extensible. 

 The google example is mostly about the self-describing attribute, and 
 to my mind is more accurately framed as a statement about the Internet as a 
 whole. Hypothetically, if all data exchange occurred using data formats 
 whose details were private arrangements between writers and readers- for 
 instance, all servers only spoke ProtocolBuffers and used a different 
 schema for each client- there would be no Internet at all, much less a 
 google who as a third party is able to broadly read and understand data 
 made available by servers. (Or, to your point, any ability to parse 
 anything useful from a server data stream by clients lacking knowledge of 
 the schema would be at best be inferential and heuristic- possible, but 
 infeasible on a large scale.)

 With all that said- my read is that Rich bundled those two points 
 together in the JSON date example- JSON doesn't have an extensibility 
 syntax to support dates, but people still have to transmit dates over JSON, 
 so how do they do that? One way is by adopting a  convention, which in 
 some ways is better than an out of band schema, because, as you say, a 
 convention gives a reader additional information to heuristically interpret 
 the stream, but in other ways is worse because it isn't consistent- some 
 people will want date fields to look like dateModified, others will want 
 modifiedDate, and others use modificationDatetime.

 So in a broad sense, it is not desirable to use a data format that does 
 not include an extensibility capability which itself is self-describing, 
 because a format that lacks extensibility creates a combinatorial explosion 
 in conventions to convey values not known to the format, and extensions 
 that are not self-describing require out of band agreements between readers 
 and writers that can preclude the scalable third-party interoperability 
 that is so important to the Internet. 

 Hope that helps.


 On Sat, Jan 18, 2014 at 6:08 

Re: Confusing ArityExceptions from macros

2013-10-23 Thread James Gatannah
Oh, nice! I've been wondering what this error means for at least a month 
now.

Thanks,
James


On Thursday, October 17, 2013 1:14:21 PM UTC-5, Alex Coventry wrote:

 If you've ever had a confusing 
 ArityExceptionhttp://clojure-log.n01se.net/date/2013-10-16.html#19:37 while 
 working with macros, the reason may be that 
 clojure.lang.Compiler.macroexpand1 rethrows any 
 ArityExceptionshttps://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L6475it
  catches from a call to a macro, in order to reduce the number of 
 arguments reported.  This messes up the stack, potentially destroying 
 information about where the ArityException occurred if it did not occur 
 from the call to the macro itself.  For instance:

 user (do (defn inner [] (assoc)) (defmacro f [] (inner)) (f))
 ArityException Wrong number of args (-2) passed to: core$assoc 
  clojure.lang.Compiler.macroexpand1 (Compiler.java:6488)
 user (use 'clojure.repl) (pst)
 nil
 ArityException Wrong number of args (-2) passed to: core$assoc
 clojure.lang.Compiler.macroexpand1 (Compiler.java:6488)
 clojure.lang.Compiler.macroexpand (Compiler.java:6544)
 clojure.lang.Compiler.eval (Compiler.java:6618)
 clojure.lang.Compiler.eval (Compiler.java:6624)
 clojure.lang.Compiler.eval (Compiler.java:6597)
 clojure.core/eval (core.clj:2864)
 clojure.main/repl/read-eval-print--6596/fn--6599 (main.clj:260)
 clojure.main/repl/read-eval-print--6596 (main.clj:260)
 clojure.main/repl/fn--6605 (main.clj:278)
 clojure.main/repl (main.clj:278)
 clojure.tools.nrepl.middleware.interruptible-eval/evaluate/fn--1251 
 (interruptible_eval.clj:56)
 clojure.core/apply (core.clj:617)
 nil
 user 


 Note that the call to inner is not in the stack trace, and the number of 
 arguments to it have been reduced by 2, leading to a nonsensical result in 
 this case.

 The patch at http://dev.clojure.org/jira/browse/CLJ-1279 fixes this bug. 
  Might save you some time, if you're developing macros.

 Best regards,
 Alex


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