Entwined STM V1.0

2013-08-18 Thread Ivan Koblik
Hi All,

Almost 4 years ago I developed STM with semantic concurrency control for my
project at CERN. Main feature of this STM is the TransactionalMap that lets
you merge concurrent changes. Library is heavily tested and is very stable.
It has been used in production for the past 2 years.

Recently I released it on GitHub:
http://entwined.koblik.ch (will redirect to
https://github.com/CERN-BE/Entwined-STM)

Since Entwined STM was designed to be used from Java I wrote a simple
facade for it in Clojure that you can load with

(require '[cern.entwined.core :as stm])

Entwined STM operates on a memory with a fixed structure, meaning that you
have to define what and how many collections you want to have in your STM
and this can't be changed after construction. To construct memory with 1
transactional map and 1 transactional queue run this:

(def memory (stm/create-memory :map (stm/create-map) :queue
(stm/create-queue)))

It's impossible to access transactional entities outside of a transaction,
to run a transaction you can use intrans macro

(stm/intrans memory data (- data :map (.put :key1 value1)) true)

(stm/intrans memory data (- data :map (.get :key1))) ;- value1

First line puts [:key1 value1] pair into the map. True at the end of the
body tells the memory to commit this transaction. intrans will initiate
commit if body returns truthy value. Second line just shows that the change
has been committed.

A couple more words on the implementation: I used HashMap to implement the
TransactionalMap, I copy the backing map for every transaction which may be
expensive for some scenarios. Obvious solution would be to use Clojure's
persistent map. Commits are eventually serialized and protected with a
single lock. If you take a look at the Java source you'll see that
Transaction interface has a second method committed that is called when
commit is being done. I use this method to write to the hardware knowing
that execution order of committed callbacks is the same as the commit order.

I would greatly appreciate any feedback and suggestions. If you have any
questions don't hesitate to ask here or email me directly. Documentation is
still somewhat lacking and I'd be interested to know which parts of it
should be improved first.

Cheers,
Ivan.

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


Re: Entwined STM V1.0

2013-08-18 Thread Hussein B.
Great ! Congratulations!

How it does compare with Clojure's builtin STM?

Thanks.

On Sunday, August 18, 2013 10:24:48 AM UTC+2, Ivan Koblik wrote:

 Hi All,

 Almost 4 years ago I developed STM with semantic concurrency control for 
 my project at CERN. Main feature of this STM is the TransactionalMap that 
 lets you merge concurrent changes. Library is heavily tested and is very 
 stable. It has been used in production for the past 2 years.

 Recently I released it on GitHub:
 http://entwined.koblik.ch (will redirect to 
 https://github.com/CERN-BE/Entwined-STM)

 Since Entwined STM was designed to be used from Java I wrote a simple 
 facade for it in Clojure that you can load with 

 (require '[cern.entwined.core :as stm])

 Entwined STM operates on a memory with a fixed structure, meaning that you 
 have to define what and how many collections you want to have in your STM 
 and this can't be changed after construction. To construct memory with 1 
 transactional map and 1 transactional queue run this:

 (def memory (stm/create-memory :map (stm/create-map) :queue 
 (stm/create-queue)))

 It's impossible to access transactional entities outside of a transaction, 
 to run a transaction you can use intrans macro

 (stm/intrans memory data (- data :map (.put :key1 value1)) true)

 (stm/intrans memory data (- data :map (.get :key1))) ;- value1

 First line puts [:key1 value1] pair into the map. True at the end of the 
 body tells the memory to commit this transaction. intrans will initiate 
 commit if body returns truthy value. Second line just shows that the change 
 has been committed.

 A couple more words on the implementation: I used HashMap to implement the 
 TransactionalMap, I copy the backing map for every transaction which may be 
 expensive for some scenarios. Obvious solution would be to use Clojure's 
 persistent map. Commits are eventually serialized and protected with a 
 single lock. If you take a look at the Java source you'll see that 
 Transaction interface has a second method committed that is called when 
 commit is being done. I use this method to write to the hardware knowing 
 that execution order of committed callbacks is the same as the commit order.

 I would greatly appreciate any feedback and suggestions. If you have any 
 questions don't hesitate to ask here or email me directly. Documentation is 
 still somewhat lacking and I'd be interested to know which parts of it 
 should be improved first.

 Cheers,
 Ivan.
  

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


Re: Model validation - exceptions as side-effects?

2013-08-18 Thread Leonardo Borges
On 18/08/2013 2:00 PM, Alexandr Kurilin a...@kurilin.net wrote:


 I'd love to know your expert opinion on this, since you wrote Bouncer: say
 you're in the situation I listed above, where you don't care about nice
 error handling, you just want to give the caller a 400 if the input is
 incorrect. Would you still go the route where the validator function
 returns a list of errors? My concern is that now I have to have additional
 checks in place in my controller for whether the model save returned a list
 of errors, which will regardless ultimately result in a 400 status code.


Hi Alexandr,

I see your point now and I completely agree your API should leak as little
as possible, but no less.

By that I mean your API should try and help it users - as Christian pointed
out.

To me, the types of information you would not want leaked are: database
names, table names, server host names, software versions etc.

Validation errors on the other hand are, in my opinion, crucial when using
an API. It's very frustrating to make a request to an API I'm learning and
get a 400 back that tells me nothing about what went wrong - making me go
read the docs - so the information you're trying to hide would still be
available - only in a different medium.

In regards to your question though, about how to handle the validations if
you don't care about the actual messages, I'd approach it in one of two
ways - this is assuming bouncer as the validation library:

The first one is the same as before but highlighting you don't care about
the validation results:
(defn my-fn [my-map]
  (match (validate my-map)
  [nil original-map] (send-400)
  [_ original-map] (save original-map)))
;; bouncer returns nil as the first element of the vector if the validation
is successful



For the second one, I'll use the function 'valid?' , also from bouncer,
which simply returns a boolean - it's meant for the cases where you don't
care about the messages:

(defn my-fn [my-map]
  (if (valid? my-map)
  (save original-map)
  (send-400)))

I hope this is helpful - but I'd encourage you to think about the scenarios
where sending back validation errors could be helpful for your API clients



 Thanks!

 (BTW, your blog is great, great content)


Thank you for the kind words :)

Cheers,
Leonardo Borges

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


Re: Entwined STM V1.0

2013-08-18 Thread dennis zhuang
That's really cool.
Do you have any performance benchmark between TransactionalMap and
java.util.concurrent.ConcurrentHashMap?  When should i use these
collections instead of java.util.concurrent.* collections?




2013/8/18 Ivan Koblik ivankob...@gmail.com

 Hi All,

 Almost 4 years ago I developed STM with semantic concurrency control for
 my project at CERN. Main feature of this STM is the TransactionalMap that
 lets you merge concurrent changes. Library is heavily tested and is very
 stable. It has been used in production for the past 2 years.

 Recently I released it on GitHub:
 http://entwined.koblik.ch (will redirect to
 https://github.com/CERN-BE/Entwined-STM)

 Since Entwined STM was designed to be used from Java I wrote a simple
 facade for it in Clojure that you can load with

 (require '[cern.entwined.core :as stm])

 Entwined STM operates on a memory with a fixed structure, meaning that you
 have to define what and how many collections you want to have in your STM
 and this can't be changed after construction. To construct memory with 1
 transactional map and 1 transactional queue run this:

 (def memory (stm/create-memory :map (stm/create-map) :queue
 (stm/create-queue)))

 It's impossible to access transactional entities outside of a transaction,
 to run a transaction you can use intrans macro

 (stm/intrans memory data (- data :map (.put :key1 value1)) true)

 (stm/intrans memory data (- data :map (.get :key1))) ;- value1

 First line puts [:key1 value1] pair into the map. True at the end of the
 body tells the memory to commit this transaction. intrans will initiate
 commit if body returns truthy value. Second line just shows that the change
 has been committed.

 A couple more words on the implementation: I used HashMap to implement the
 TransactionalMap, I copy the backing map for every transaction which may be
 expensive for some scenarios. Obvious solution would be to use Clojure's
 persistent map. Commits are eventually serialized and protected with a
 single lock. If you take a look at the Java source you'll see that
 Transaction interface has a second method committed that is called when
 commit is being done. I use this method to write to the hardware knowing
 that execution order of committed callbacks is the same as the commit order.

 I would greatly appreciate any feedback and suggestions. If you have any
 questions don't hesitate to ask here or email me directly. Documentation is
 still somewhat lacking and I'd be interested to know which parts of it
 should be improved first.

 Cheers,
 Ivan.

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




-- 
庄晓丹
Email:killme2...@gmail.com xzhu...@avos.com
Site:   http://fnil.net
Twitter:  @killme2008

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


Re: vec to map with consolidated vals

2013-08-18 Thread Timo Mihaljov
On 17.08.2013 08:40, David Chelimsky wrote:
 Which led me to this:
 
 (defn to-consolidated-map [parts]
   (apply merge-with + (map (partial apply hash-map) parts)))

This is exactly what I came up with after reading your first message.
Apparently Jay Fields took the same approach. I think it's fair to say
that this is the idiomatic solution, now that three people have come to
the same result independently. :)

-- 
Timo

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


Re: core.async - handling nils

2013-08-18 Thread Mikera
If you use a singleton sentinel value that is generated privately within 
the core.async implementation, then the sentinel isn't really a regular 
value in the sense that it can be created by regular user code.

nil, on the other hand, gets used very frequently as a value in regular 
Clojure code.

That's a key reason IMHO why it's better to use a sentinel as a closed 
channel indicator than nil.

On Sunday, 18 August 2013 09:43:34 UTC+8, Ben wrote:

 A sentinel value also prevents channels from being able to send/receive 
 arbitrary values, without further wrapping.

 Sent from my iPhone

 On Aug 17, 2013, at 5:48 PM, Mikera mike.r.an...@gmail.com javascript: 
 wrote:

 My overall sense is that the convenience of using if-let directly in a few 
 use cases doesn't justify making channels fall short of being able to send 
 arbitrary values (nil specifically, and clearly boolean false can cause 
 some problems too). 

 I think it would be a much better design to have a sentinel value and a 
 couple of specialised functions or macros that can detect  / interact with 
 it appropriately. With a sentinel value the key part of your if-recv code 
 could just be something like:

 `(let [~name (! ~port)]
   (if (end-of-stream? ~name)
 ~else
 ~then


 I can see that wrappers for nil values could also work, but that seems to 
 be a more complex solution (and also potentially with more overhead) than a 
 sentinel value


 On Saturday, 17 August 2013 07:50:06 UTC+8, Brandon Bloom wrote:

 I ran into the other half of this problem: If you expect nils to signify 
 closed channels, then you can't leverage the logically false nature of nil 
 without excluding explicit boolean false values. Given the pleasant syntax 
 of if-let / ! pairs, I reworked my early experiments to use if-recv 
 which is defined as follows:

 (defmacro if-recv
   Reads from port, binding to name. Evaluates the then block if the
   read was successful. Evaluates the else block if the port was closed.
   ([[name port :as binding] then]
`(if-recv ~binding ~then nil))
   ([[name port] then else]
`(let [~name (! ~port)]
   (if (nil? ~name)
 ~else
 ~then


 I've considered some alternative core.async designs, such as an 
 additional done sentinel value, or a pair of quote/unquote operators (see 
 reduced), but nothing seems as simple as just avoiding booleans and nils, 
 as annoying as that is. I'd be curious to here what Rich  team 
 considered and how they're thinking about it. However, my expectation is 
 that the nil approach won't change, since it's pretty much good enough.

 On Thursday, August 15, 2013 10:44:48 PM UTC-4, Mikera wrote:

 Hi all,

 I'm experimenting with core.async. Most of it is exceptionally good, but 
 bit I'm finding it *very* inconvenient that nil can't be sent over 
 channels. In particular, you can't pipe arbitrary Clojure sequences through 
 channels (since sequences can contain nils). 

 I see this as a pretty big design flaw given the ubiquity of sequences 
 in Clojure code - it appears to imply that you can't easily compose 
 channels with generic sequence-handling code without some pretty ugly 
 special-case handling.

 Am I missing something? Is this a real problem for others too? 

 If it is a design flaw, can it be fixed before the API gets locked down?

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



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


Re: Entwined STM V1.0

2013-08-18 Thread Ivan Koblik
Thank you! Great question.

I couldn't devise a way to merge concurrent changes in a HashMap using 
Clojure's STM. A while ago I discussed it with Christophe Grand and he had 
his own idea about how to fix it: [1] and [2]. IIRC Christophe's solution 
may see a conflict even if there's no real conflict due to stochastic 
nature of the implementation.

I had this use case in my project that functions as a reservation system, I 
needed a way to add a record into the Map saying that a given device has 
been reserved by a given user. Since I didn't know all the devices in 
advance I needed a way to detect conflicts even if Key/Value pair is added 
for the first time or when it is removed completely.

[1] http://clj-me.cgrand.net/2011/10/06/a-world-in-a-ref/
[2] http://clj-me.cgrand.net/2012/09/21/follow-up-a-world-in-a-ref/


On Sunday, August 18, 2013 12:42:23 PM UTC+2, Hussein B. wrote:

 Great ! Congratulations!

 How it does compare with Clojure's builtin STM?

 Thanks.

 On Sunday, August 18, 2013 10:24:48 AM UTC+2, Ivan Koblik wrote:

 Hi All,

 Almost 4 years ago I developed STM with semantic concurrency control for 
 my project at CERN. Main feature of this STM is the TransactionalMap that 
 lets you merge concurrent changes. Library is heavily tested and is very 
 stable. It has been used in production for the past 2 years.

 Recently I released it on GitHub:
 http://entwined.koblik.ch (will redirect to 
 https://github.com/CERN-BE/Entwined-STM)

 Since Entwined STM was designed to be used from Java I wrote a simple 
 facade for it in Clojure that you can load with 

 (require '[cern.entwined.core :as stm])

 Entwined STM operates on a memory with a fixed structure, meaning that 
 you have to define what and how many collections you want to have in your 
 STM and this can't be changed after construction. To construct memory with 
 1 transactional map and 1 transactional queue run this:

 (def memory (stm/create-memory :map (stm/create-map) :queue 
 (stm/create-queue)))

 It's impossible to access transactional entities outside of a 
 transaction, to run a transaction you can use intrans macro

 (stm/intrans memory data (- data :map (.put :key1 value1)) true)

 (stm/intrans memory data (- data :map (.get :key1))) ;- value1

 First line puts [:key1 value1] pair into the map. True at the end of 
 the body tells the memory to commit this transaction. intrans will initiate 
 commit if body returns truthy value. Second line just shows that the change 
 has been committed.

 A couple more words on the implementation: I used HashMap to implement 
 the TransactionalMap, I copy the backing map for every transaction which 
 may be expensive for some scenarios. Obvious solution would be to use 
 Clojure's persistent map. Commits are eventually serialized and protected 
 with a single lock. If you take a look at the Java source you'll see that 
 Transaction interface has a second method committed that is called when 
 commit is being done. I use this method to write to the hardware knowing 
 that execution order of committed callbacks is the same as the commit order.

 I would greatly appreciate any feedback and suggestions. If you have any 
 questions don't hesitate to ask here or email me directly. Documentation is 
 still somewhat lacking and I'd be interested to know which parts of it 
 should be improved first.

 Cheers,
 Ivan.
  


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


Re: Entwined STM V1.0

2013-08-18 Thread Ivan Koblik
I'll come back to you with the benchmarks, so far I haven't done any. I 
have an impression that ConcurrentHashMap will outperform TransactionalMap 
in most cases, but there may be cases when different keys end up in the 
same bucket in the ConcurrentHashMap and that is where TransactionalMap may 
be faster.

To answering your second question: I would use STM only when there's a need 
to perform a series of coordinated actions. To read a key/value pair and 
depending on the value update some other transactional entity.

For example if I expand on the example posted here:
https://github.com/CERN-BE/Entwined-STM/blob/master/src/test/java/cern/entwined/demo/clojure_examples.clj

I can write a function that would access map and the queue in the same 
transaction:

(defn add-user-and-queue-update!
  Adds user and schedules initial update only if it's a new user.
  [id user update-fn]
  (intrans memory _
(when-not (get-user id)
  (add-user id name)
  (schedule-task update-fn

Transactions in Entwined are composable and in the example above I create 
outer transaction that uses API from the example namespace to check for a 
condition and only if it is true preform some action. If user is added 
concurrently than this transaction is restarted and no action is performed.

On Sunday, August 18, 2013 1:01:53 PM UTC+2, dennis wrote:

 That's really cool.
 Do you have any performance benchmark between TransactionalMap and 
 java.util.concurrent.ConcurrentHashMap?  When should i use these 
 collections instead of java.util.concurrent.* collections? 




 2013/8/18 Ivan Koblik ivank...@gmail.com javascript:

 Hi All,

 Almost 4 years ago I developed STM with semantic concurrency control for 
 my project at CERN. Main feature of this STM is the TransactionalMap that 
 lets you merge concurrent changes. Library is heavily tested and is very 
 stable. It has been used in production for the past 2 years.

 Recently I released it on GitHub:
 http://entwined.koblik.ch (will redirect to 
 https://github.com/CERN-BE/Entwined-STM)

 Since Entwined STM was designed to be used from Java I wrote a simple 
 facade for it in Clojure that you can load with 

 (require '[cern.entwined.core :as stm])

 Entwined STM operates on a memory with a fixed structure, meaning that 
 you have to define what and how many collections you want to have in your 
 STM and this can't be changed after construction. To construct memory with 
 1 transactional map and 1 transactional queue run this:

 (def memory (stm/create-memory :map (stm/create-map) :queue 
 (stm/create-queue)))

 It's impossible to access transactional entities outside of a 
 transaction, to run a transaction you can use intrans macro

 (stm/intrans memory data (- data :map (.put :key1 value1)) true)

 (stm/intrans memory data (- data :map (.get :key1))) ;- value1

 First line puts [:key1 value1] pair into the map. True at the end of 
 the body tells the memory to commit this transaction. intrans will initiate 
 commit if body returns truthy value. Second line just shows that the change 
 has been committed.

 A couple more words on the implementation: I used HashMap to implement 
 the TransactionalMap, I copy the backing map for every transaction which 
 may be expensive for some scenarios. Obvious solution would be to use 
 Clojure's persistent map. Commits are eventually serialized and protected 
 with a single lock. If you take a look at the Java source you'll see that 
 Transaction interface has a second method committed that is called when 
 commit is being done. I use this method to write to the hardware knowing 
 that execution order of committed callbacks is the same as the commit order.

 I would greatly appreciate any feedback and suggestions. If you have any 
 questions don't hesitate to ask here or email me directly. Documentation is 
 still somewhat lacking and I'd be interested to know which parts of it 
 should be improved first.

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




 -- 
 庄晓丹 
 Email:killm...@gmail.com javascript: xzh...@avos.comjavascript:
 Site:   http://fnil.net
 Twitter:  @killme2008


 

-- 
-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to 

Help to morph this imperative snippet into a functional one

2013-08-18 Thread Hussein B.
Hi!

Would you please help me transforming this imperative code into functional 
one?

The code is a typical snippet in imperative style. A lot of mutations that 
I don't even know how to start morphing it to Clojure.

class Container {
  MapString, Container children;
  String letter;
  ListString value;
}

void insert(Container container, String letters, String value) {
  
  for (int i = 0; i  letters.length; i++) {

String letter = new String(letters.chatAt[i]);

if (container.children.get(letter) != null) {
  container = container.children.get(letter);
} else {
  MapContainer childContainer = new HashMap();
  container.children.put(letter, childContainer);
  container = container.children.get(letter);
}

   if (i == letters.length() - 1) {
 container.values.add(value);
 break;
   }

} 


Thanks for help and time.

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


Re: Current state of the art in Web deployment?

2013-08-18 Thread Norman Richards
On Sat, Aug 17, 2013 at 3:52 PM, John Jacobsen eigenhom...@gmail.comwrote:

 So, what do all y'all do?  What is a good lightweight but robust way to
 get a fairly simple Compojure/Ring app backed by Datomic facing the outside
 world?  Not too worried about massive scalability at this point; simplicity
 will be a plus (am worried that e.g. Immutant / JBoss are too heavyweight).


If simplicity is the goal, then Immutant makes things pretty extremely easy
while giving you some infrastructure to build on going forward.

Our non-immutant deployment uses a custom jetty startup along with an
uberjar build.  Doing the uberjar lets us not worry about dependency
resolution at deploy time, but that's really it.  (I don't know if lein has
some other mechanism for fixing dependencies or if the recommendation is to
run your own internal caching maven proxy)

Other than that, mechanically our deploy is not significantly different
from a lein ring server, so maybe you can explain what your concerns with
that are?

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


Re: Help to morph this imperative snippet into a functional one

2013-08-18 Thread Chris Ford
Can you explain what the code is supposed to do in English? Java is a
little hard to read. :-)

Are you doing Huffman coding or similar?


On 18 August 2013 16:51, Hussein B. hubaghd...@gmail.com wrote:

 Hi!

 Would you please help me transforming this imperative code into functional
 one?

 The code is a typical snippet in imperative style. A lot of mutations that
 I don't even know how to start morphing it to Clojure.

 class Container {
   MapString, Container children;
   String letter;
   ListString value;
 }

 void insert(Container container, String letters, String value) {

   for (int i = 0; i  letters.length; i++) {

 String letter = new String(letters.chatAt[i]);

 if (container.children.get(letter) != null) {
   container = container.children.get(letter);
 } else {
   MapContainer childContainer = new HashMap();
   container.children.put(letter, childContainer);
   container = container.children.get(letter);
 }

if (i == letters.length() - 1) {
  container.values.add(value);
  break;
}

 }


 Thanks for help and time.

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


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


Re: Help to morph this imperative snippet into a functional one

2013-08-18 Thread Hussein B.
It might be Huffman coding but I don't know Hoffman coding in depth, so I 
can't be precise. :)

But any way, it is a snippet written in an imperative style that I'm trying 
to transfer into a functional one.

The amount of mutation and the if statements are blocking me from doing it 
in Clojure.


On Sunday, August 18, 2013 4:27:43 PM UTC+2, Chris Ford wrote:

 Can you explain what the code is supposed to do in English? Java is a 
 little hard to read. :-)

 Are you doing Huffman coding or similar?


 On 18 August 2013 16:51, Hussein B. hubag...@gmail.com javascript:wrote:

 Hi!

 Would you please help me transforming this imperative code into 
 functional one?

 The code is a typical snippet in imperative style. A lot of mutations 
 that I don't even know how to start morphing it to Clojure.

 class Container {
   MapString, Container children;
   String letter;
   ListString value;
 }

 void insert(Container container, String letters, String value) {
   
   for (int i = 0; i  letters.length; i++) {

 String letter = new String(letters.chatAt[i]);

 if (container.children.get(letter) != null) {
   container = container.children.get(letter);
 } else {
   MapContainer childContainer = new HashMap();
   container.children.put(letter, childContainer);
   container = container.children.get(letter);
 }

if (i == letters.length() - 1) {
  container.values.add(value);
  break;
}

 } 


 Thanks for help and time.

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




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


Re: Help to morph this imperative snippet into a functional one

2013-08-18 Thread Chris Ford
This is close, though it only permits values at leaves and stores the
values in the reverse order. Depending on what you need, this might be
sufficient:

(defn insert [container letters value]
  (update-in container letters #(conj % value)))

e.g. (- {} (insert foo 3) (insert foo 4) (insert bar 7))

If you do need values at non-leaf notes, you just need a slightly more
sophisticated representation.


On 18 August 2013 17:38, Hussein B. hubaghd...@gmail.com wrote:

 It might be Huffman coding but I don't know Hoffman coding in depth, so I
 can't be precise. :)

 But any way, it is a snippet written in an imperative style that I'm
 trying to transfer into a functional one.

 The amount of mutation and the if statements are blocking me from doing it
 in Clojure.


 On Sunday, August 18, 2013 4:27:43 PM UTC+2, Chris Ford wrote:

 Can you explain what the code is supposed to do in English? Java is a
 little hard to read. :-)

 Are you doing Huffman coding or similar?


 On 18 August 2013 16:51, Hussein B. hubag...@gmail.com wrote:

 Hi!

 Would you please help me transforming this imperative code into
 functional one?

 The code is a typical snippet in imperative style. A lot of mutations
 that I don't even know how to start morphing it to Clojure.

 class Container {
   MapString, Container children;
   String letter;
   ListString value;
 }

 void insert(Container container, String letters, String value) {

   for (int i = 0; i  letters.length; i++) {

 String letter = new String(letters.chatAt[i]);

 if (container.children.get(**letter) != null) {
   container = container.children.get(letter)**;
 } else {
   MapContainer childContainer = new HashMap();
   container.children.put(letter, childContainer);
   container = container.children.get(letter)**;
 }

if (i == letters.length() - 1) {
  container.values.add(value);
  break;
}

 }


 Thanks for help and time.

 --
 --
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clo...@googlegroups.com

 Note that posts from new members are moderated - please be patient with
 your first post.
 To unsubscribe from this group, send email to
 clojure+u...@**googlegroups.com

 For more options, visit this group at
 http://groups.google.com/**group/clojure?hl=enhttp://groups.google.com/group/clojure?hl=en
 ---
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send
 an email to clojure+u...@**googlegroups.com.

 For more options, visit 
 https://groups.google.com/**groups/opt_outhttps://groups.google.com/groups/opt_out
 .


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


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


Re: Help to morph this imperative snippet into a functional one

2013-08-18 Thread Chris Ford
Here's a version that allows values to be anywhere in the tree:

(defn insert [[container values] [letter  letters] value]
  (if letter
[(update-in container [letter] #(insert % letters value)) values]
[container (conj values value)]))

e.g. (- [{} []] (insert foo 4) (insert f 5) (insert bar 8))


On 18 August 2013 18:03, Chris Ford christophertf...@gmail.com wrote:

 This is close, though it only permits values at leaves and stores the
 values in the reverse order. Depending on what you need, this might be
 sufficient:

 (defn insert [container letters value]
   (update-in container letters #(conj % value)))

 e.g. (- {} (insert foo 3) (insert foo 4) (insert bar 7))

 If you do need values at non-leaf notes, you just need a slightly more
 sophisticated representation.


 On 18 August 2013 17:38, Hussein B. hubaghd...@gmail.com wrote:

 It might be Huffman coding but I don't know Hoffman coding in depth, so I
 can't be precise. :)

 But any way, it is a snippet written in an imperative style that I'm
 trying to transfer into a functional one.

 The amount of mutation and the if statements are blocking me from doing
 it in Clojure.


 On Sunday, August 18, 2013 4:27:43 PM UTC+2, Chris Ford wrote:

 Can you explain what the code is supposed to do in English? Java is a
 little hard to read. :-)

 Are you doing Huffman coding or similar?


  On 18 August 2013 16:51, Hussein B. hubag...@gmail.com wrote:

  Hi!

 Would you please help me transforming this imperative code into
 functional one?

 The code is a typical snippet in imperative style. A lot of mutations
 that I don't even know how to start morphing it to Clojure.

 class Container {
   MapString, Container children;
   String letter;
   ListString value;
 }

 void insert(Container container, String letters, String value) {

   for (int i = 0; i  letters.length; i++) {

 String letter = new String(letters.chatAt[i]);

 if (container.children.get(**letter) != null) {
   container = container.children.get(letter)**;
 } else {
   MapContainer childContainer = new HashMap();
   container.children.put(letter, childContainer);
   container = container.children.get(letter)**;
 }

if (i == letters.length() - 1) {
  container.values.add(value);
  break;
}

 }


 Thanks for help and time.

 --
 --
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clo...@googlegroups.com

 Note that posts from new members are moderated - please be patient with
 your first post.
 To unsubscribe from this group, send email to
 clojure+u...@**googlegroups.com

 For more options, visit this group at
 http://groups.google.com/**group/clojure?hl=enhttp://groups.google.com/group/clojure?hl=en
 ---
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send
 an email to clojure+u...@**googlegroups.com.

 For more options, visit 
 https://groups.google.com/**groups/opt_outhttps://groups.google.com/groups/opt_out
 .


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




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


Re: Current state of the art in Web deployment?

2013-08-18 Thread John Jacobsen
Many thanks to everyone who replied about deploying a Web server to production. 
 Specific replies:

On Aug 17, 2013, at 6:51 PM, Mark Mandel mark.man...@gmail.com wrote:

 
 On Sun, Aug 18, 2013 at 6:52 AM, John Jacobsen eigenhom...@gmail.com wrote:
 After some prototyping and development, we are now getting to the stage 
 where lein run and a Jetty server running from -main aren't going to cut 
 it.
 
 At the risk of asking a dumb question, but being quite new to Clojure, I 
 don't mind - why do you say they won't cut it?

On Aug 18, 2013, at 9:25 AM, Norman Richards o...@nostacktrace.com wrote:

 Other than that, mechanically our deploy is not significantly different from 
 a lein ring server, so maybe you can explain what your concerns with that are?

My main concern was just the need to ssh into the server and run leiningen in 
the background, as opposed to setting up a real server which starts at boot 
time.  I'm OK w/ wrapping 'lein ring server-headless' with Apache/Nginx, if 
there are no known issues w/ that approach.


On Aug 17, 2013, at 4:52 PM, Ray Miller r...@1729.org.uk wrote:

 One option is simply to write an upstart script that invokes 'lein
 ring server-headless' and sit an apache or nginx proxy in front of it.
 That's how my website is currently running. Alternatively, you could
 deploy your application as a war to tomcat or jetty.
 
 The upstart configuration, which is installed to /etc/init/cms.conf,
 can be found here: https://gist.github.com/ray1729/6258845

That's very helpful -- can you be a little more specific about what you mean by 
sit an apache or nginx proxy in front of it?  It looks like your example is 
self-contained (need Clojure/lein + upstart, and that's it).

Thanks again everyone.

John



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


Comparing of 2 words

2013-08-18 Thread Christian Sperandio
Hi,

I wrote a set of functions to compare 2 words managing the keyboard 
mistakes. The common mistakes are insertion, deletion, substitution or 
inversion.

It can be useful for searching name, product reference, city 

For example, if you want to let 2 errors in an input, you can do:

;; a name 
(candidates? hickey hikey 3)
 -- true

(candidates? hickey hitchock 3)
 -- false

;; a city
(candidates? montrouge monrouge 3)
  -- true

;; a brand
(candidates? google googel 3)
  -- true

I used lazy sequence to avoid compare the words completely if they' re very 
different. Thus,
(candidates? hickey jobs 3)
  -- returns false when the third error is found.

The code is on gist:
https://gist.github.com/chrix75/6262565


Christian

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


Re: Current state of the art in Web deployment?

2013-08-18 Thread Steven Degutis
I don't think there is a such thing as a real server. Any process that
listens on a TCP port and talks HTTP is a legitimate server, regardless of
when or how it's started up.

Upstart is a fine way to run your server and make sure it's restarted if it
dies. It's not hacky or unconventional, in fact it's probably the best way.

Sitting nginx in front of something usually goes like this: You make your
server process listen on some port, but only accepting connections from
localhost. Then you make nginx listen on port 80 directly from the
internet, and when it receives a request, it forwards it to your server via
that internal port on localhost, and returns the results. This extra layer
of abstraction gives you a lot of power and flexibility. Of course, you
could get fancier than just using localhost, and you might even want
several servers running at once, not just one, and round-robin requests to
them. But this is the basic idea. And it's the same no matter what language
your server is written in, as long as it knows how to talk HTTP over TCP.

-Steven


On Sun, Aug 18, 2013 at 11:21 AM, John Jacobsen eigenhom...@gmail.comwrote:

 Many thanks to everyone who replied about deploying a Web server to
 production.  Specific replies:

 On Aug 17, 2013, at 6:51 PM, Mark Mandel mark.man...@gmail.com wrote:

 
  On Sun, Aug 18, 2013 at 6:52 AM, John Jacobsen eigenhom...@gmail.com
 wrote:
  After some prototyping and development, we are now getting to the stage
 where lein run and a Jetty server running from -main aren't going to cut
 it.
 
  At the risk of asking a dumb question, but being quite new to Clojure, I
 don't mind - why do you say they won't cut it?

 On Aug 18, 2013, at 9:25 AM, Norman Richards o...@nostacktrace.com wrote:

  Other than that, mechanically our deploy is not significantly different
 from a lein ring server, so maybe you can explain what your concerns with
 that are?

 My main concern was just the need to ssh into the server and run leiningen
 in the background, as opposed to setting up a real server which starts at
 boot time.  I'm OK w/ wrapping 'lein ring server-headless' with
 Apache/Nginx, if there are no known issues w/ that approach.


 On Aug 17, 2013, at 4:52 PM, Ray Miller r...@1729.org.uk wrote:

  One option is simply to write an upstart script that invokes 'lein
  ring server-headless' and sit an apache or nginx proxy in front of it.
  That's how my website is currently running. Alternatively, you could
  deploy your application as a war to tomcat or jetty.
 
  The upstart configuration, which is installed to /etc/init/cms.conf,
  can be found here: https://gist.github.com/ray1729/6258845

 That's very helpful -- can you be a little more specific about what you
 mean by sit an apache or nginx proxy in front of it?  It looks like your
 example is self-contained (need Clojure/lein + upstart, and that's it).

 Thanks again everyone.

 John



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


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


ANN Langohr documentation updates

2013-08-18 Thread Michael Klishin
I'm happy to announce that Langohr [1] documentation is being actively
worked on again. There's already one full new guide available [2],
that covers RabbitMQ extensions and how to use them from Clojure.

At least two more guides (TLS/SSL support and Durability) are in the works
and will be published in a few days.

If you use or in the process of evaluating Langohr, take a look at [2]. It
covers
quite a few nice features RabbitMQ provides.

1. http://clojurerabbitmq.info
2. http://clojurerabbitmq.info/articles/extensions.html
-- 
MK

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

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


Re: Current state of the art in Web deployment?

2013-08-18 Thread Sean Corfield
On Sun, Aug 18, 2013 at 9:21 AM, John Jacobsen eigenhom...@gmail.com wrote:
 My main concern was just the need to ssh into the server and run leiningen in 
 the background, as opposed to setting up a real server which starts at boot 
 time.  I'm OK w/ wrapping 'lein ring server-headless' with Apache/Nginx, if 
 there are no known issues w/ that approach.

We have a number of processes that we kick off via lein-daemon. We
have a standard shell script that mimics standard 'service' operations
(start, stop, status, restart) and wraps 'lein daemon ...' commands,
and we just symlink it into /etc/init.d to create service files so our
processes launch at server startup, and we can stop/start them as
needed around deploys.
-- 
Sean A Corfield -- (904) 302-SEAN
An Architect's View -- http://corfield.org/
World Singles, LLC. -- http://worldsingles.com/

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

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


Revisiting forward-chaining rules in Clojure

2013-08-18 Thread Ryan Brush
Perhaps the best aspect of Clojure is how it can adopt the best ideas from 
other domains to concisely solve problems, as we've seen with core.logic, 
core.async and other libraries. I recently came across a problem domain 
that is easily expressed in forward-chaining rules, and found Clojure to be 
a powerful way to solve it. 

While working through this problem space I started to suspect there is a 
more general need for forward-chaining rules in Clojure to complement 
core.logic and other libraries. So as a side project I implemented a raw 
but working engine to do so. I'm posting here to share a draft of this 
engine, its major design goals, and to ask for input on how we should 
approach forward-chaining rules in Clojure in general.

The rationale and some examples are on the github page for this 
enginehttps://github.com/rbrush/clara-rules, 
which I've tentatively named Clara. The state of the code isn't where it 
needs to be yet; I've been learning the intricacies of Rete and discovering 
better ways to solve problems along the way, and some of that is reflected 
in the code base. However, the major pieces of design and functionality are 
in place, so I'd like to get input on those. 

The idea is to draw a bit from Jess and Lisa, with the Java interop 
strength of Drools, but the advantages and idioms available in Clojure. The 
major goals are:

   - Focus on problem spaces naturally expressed as forward-chaining rules. 
   Data-driven needs like eventing, data validation, or application of 
   arbitrary business rules fit here. 
   - Embrace immutability. The rule engine's working memory is a persistent 
   Clojure data structure that can participate in transactions. All changes 
   produce a new working memory that shares state with the previous.
   - Rule constraints and actions are simply Clojure s-expressions.
   - First-class Java interoperability and APIs. This should be an 
   alternative to Jess or Drools from Java-land.
   - Usable either as a library to simplify Clojure code, or as a DSL to 
   externalize business logic.
   - Working memory facts are typically (but not exclusively) Clojure 
   records or Java objects following the Java Bean conventions.
   - Support the major advantages of existing rules systems, such as 
   explainability of why a rule fired and automatic truth maintenance.
   - Collections of facts can be reasoned with using accumulators similar 
   to Jess or Drools. These accumulators leverage the reducers API and are 
   transparently parallelized.
   - The working memory is independent of the logic flow, and can be 
   replaced with a distributed processing system. A prototype that uses 
   Storm https://github.com/rbrush/clara-storm to apply rules to a stream 
   of incoming events already exists.

I'd love to hear thoughts on a couple questions:

What else would you want from a forward-chaining rules engine in Clojure?
What design changes would you make, given the above criteria and examples 
on github?

All thoughts are appreciated!

-Ryan

https://github.com/rbrush/clara-rules
https://github.com/rbrush/clara-examples
https://github.com/rbrush/clara-storm

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


Re: Current state of the art in Web deployment?

2013-08-18 Thread Ray Miller
On 18 August 2013 17:21, John Jacobsen eigenhom...@gmail.com wrote:

 On Aug 17, 2013, at 4:52 PM, Ray Miller r...@1729.org.uk wrote:

 One option is simply to write an upstart script that invokes 'lein
 ring server-headless' and sit an apache or nginx proxy in front of it.
 That's how my website is currently running. Alternatively, you could
 deploy your application as a war to tomcat or jetty.

 The upstart configuration, which is installed to /etc/init/cms.conf,
 can be found here: https://gist.github.com/ray1729/6258845

 That's very helpful -- can you be a little more specific about what you mean 
 by sit an apache or nginx proxy in front of it?  It looks like your example 
 is self-contained (need Clojure/lein + upstart, and that's it).

The Ring server is listening on localhost (port 3000 by default). I've
set up an apache reverse proxy that routes requests to the Compojure
application. This gives a bit more flexibility e.g. if you have other
services on the same machine, or want apache to serve static content
directly.

Ray.

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


Re: vec to map with consolidated vals

2013-08-18 Thread Ray Miller
On 18 August 2013 12:31, Timo Mihaljov t...@mihaljov.info wrote:
 On 17.08.2013 08:40, David Chelimsky wrote:
 Which led me to this:

 (defn to-consolidated-map [parts]
   (apply merge-with + (map (partial apply hash-map) parts)))

 This is exactly what I came up with after reading your first message.
 Apparently Jay Fields took the same approach. I think it's fair to say
 that this is the idiomatic solution, now that three people have come to
 the same result independently. :)

For the record, I don't like this approach at all. You're creating
temporary hash-map's just so you can use the core merge-with function.
I prefer to reduce with a custom accumulator function (I think someone
already posted something along these lines):

(defn accumulate-keys [xs] (reduce (fn [accum [k v]] (assoc accum k (+
v (get accum k 0 {} xs))

Mostly a matter of taste, of course.

Ray.

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


Re: Current state of the art in Web deployment?

2013-08-18 Thread James Henderson
Hi John,

Building on Ray's answer to use Upstart, I've recently started using a 
Git-based deployment method that essentially uses a Git post-receive hook 
to re-deploy the application with a simple git push.

To set-up, create a bare repo and a working tree on the deploy host, and 
the relevant Upstart job. We then deploy using *`git push 
deployhost:path/to/deploy-repo.git master:deploy`*. When a push is received 
on the deploy branch, the hook on the remote repo updates the working tree, 
and restarts the Upstart job. (I use SystemD services in place of Upstart 
when I get the choice - IMO it beats Upstart hands-down, but that's an 
aside!)

I've put the post-receive hook at 
https://gist.github.com/james-henderson/6263386 - hope this helps!

Regards,

James

On Sunday, 18 August 2013 17:21:22 UTC+1, John Jacobsen wrote:

 Many thanks to everyone who replied about deploying a Web server to 
 production.  Specific replies: 

 On Aug 17, 2013, at 6:51 PM, Mark Mandel mark@gmail.com javascript: 
 wrote: 

  
  On Sun, Aug 18, 2013 at 6:52 AM, John Jacobsen 
  eigen...@gmail.comjavascript: 
 wrote: 
  After some prototyping and development, we are now getting to the stage 
 where lein run and a Jetty server running from -main aren't going to cut 
 it. 
  
  At the risk of asking a dumb question, but being quite new to Clojure, I 
 don't mind - why do you say they won't cut it? 

 On Aug 18, 2013, at 9:25 AM, Norman Richards 
 o...@nostacktrace.comjavascript: 
 wrote: 

  Other than that, mechanically our deploy is not significantly different 
 from a lein ring server, so maybe you can explain what your concerns with 
 that are? 

 My main concern was just the need to ssh into the server and run leiningen 
 in the background, as opposed to setting up a real server which starts at 
 boot time.  I'm OK w/ wrapping 'lein ring server-headless' with 
 Apache/Nginx, if there are no known issues w/ that approach. 


 On Aug 17, 2013, at 4:52 PM, Ray Miller r...@1729.org.uk javascript: 
 wrote: 

  One option is simply to write an upstart script that invokes 'lein 
  ring server-headless' and sit an apache or nginx proxy in front of it. 
  That's how my website is currently running. Alternatively, you could 
  deploy your application as a war to tomcat or jetty. 
  
  The upstart configuration, which is installed to /etc/init/cms.conf, 
  can be found here: https://gist.github.com/ray1729/6258845 

 That's very helpful -- can you be a little more specific about what you 
 mean by sit an apache or nginx proxy in front of it?  It looks like your 
 example is self-contained (need Clojure/lein + upstart, and that's it). 

 Thanks again everyone. 

 John 





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


Re: Revisiting forward-chaining rules in Clojure

2013-08-18 Thread Shantanu Kumar
Thanks for posting. I will certainly explore this.

Did you look at Mimir? https://github.com/hraberg/mimir Could you outline 
how is Clara's approach different from Mimir?

Shantanu

On Sunday, 18 August 2013 23:46:14 UTC+5:30, Ryan Brush wrote:

 Perhaps the best aspect of Clojure is how it can adopt the best ideas from 
 other domains to concisely solve problems, as we've seen with core.logic, 
 core.async and other libraries. I recently came across a problem domain 
 that is easily expressed in forward-chaining rules, and found Clojure to be 
 a powerful way to solve it. 

 While working through this problem space I started to suspect there is a 
 more general need for forward-chaining rules in Clojure to complement 
 core.logic and other libraries. So as a side project I implemented a raw 
 but working engine to do so. I'm posting here to share a draft of this 
 engine, its major design goals, and to ask for input on how we should 
 approach forward-chaining rules in Clojure in general.

 The rationale and some examples are on the github page for this 
 enginehttps://github.com/rbrush/clara-rules, 
 which I've tentatively named Clara. The state of the code isn't where it 
 needs to be yet; I've been learning the intricacies of Rete and discovering 
 better ways to solve problems along the way, and some of that is reflected 
 in the code base. However, the major pieces of design and functionality are 
 in place, so I'd like to get input on those. 

 The idea is to draw a bit from Jess and Lisa, with the Java interop 
 strength of Drools, but the advantages and idioms available in Clojure. The 
 major goals are:

- Focus on problem spaces naturally expressed as forward-chaining 
rules. Data-driven needs like eventing, data validation, or application of 
arbitrary business rules fit here. 
- Embrace immutability. The rule engine's working memory is a 
persistent Clojure data structure that can participate in transactions. 
 All 
changes produce a new working memory that shares state with the previous.
- Rule constraints and actions are simply Clojure s-expressions.
- First-class Java interoperability and APIs. This should be an 
alternative to Jess or Drools from Java-land.
- Usable either as a library to simplify Clojure code, or as a DSL to 
externalize business logic.
- Working memory facts are typically (but not exclusively) Clojure 
records or Java objects following the Java Bean conventions.
- Support the major advantages of existing rules systems, such as 
explainability of why a rule fired and automatic truth maintenance.
- Collections of facts can be reasoned with using accumulators similar 
to Jess or Drools. These accumulators leverage the reducers API and are 
transparently parallelized.
- The working memory is independent of the logic flow, and can be 
replaced with a distributed processing system. A prototype that uses 
Storm https://github.com/rbrush/clara-storm to apply rules to a 
stream of incoming events already exists.

 I'd love to hear thoughts on a couple questions:

 What else would you want from a forward-chaining rules engine in Clojure?
 What design changes would you make, given the above criteria and examples 
 on github?

 All thoughts are appreciated!

 -Ryan

 https://github.com/rbrush/clara-rules
 https://github.com/rbrush/clara-examples
 https://github.com/rbrush/clara-storm



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


Re: Revisiting forward-chaining rules in Clojure

2013-08-18 Thread Ryan Brush
Shantanu,

I appreciate it. I did look at Mimir, but had some different objectives, 
and therefore tradeoffs, and didn't see a straightforward way to reconcile 
them. 

First, I wanted to use existing data models in the rules as is -- be it 
Clojure records, Java Beans, or other structures. Drools has a number of 
drawbacks, but has success in Java-land largely because it interoperates 
with existing models so well. A pure Clojure solution with strong interop 
could offer a number of advantages over existing engines. In fairness, I 
have yet to add first-class Java support, but the same structure that uses 
Clojure records right now will be extended to seamlessly use 
JavaBeans-style classes.

Second, I have a broader goal of executing rules against arbitrarily large 
data sets in a distributed system, and there are semantic and structural 
tradeoffs to make that happen. For instance, the underlying working memory 
is a separate subsystem in Clara, and all join operations are hash-based 
and structured in such a way that they need not be performed in the same 
process. The clara-storm project is a very raw proof-of-concept of 
distributing rules across a cluster, but we should be able to layer it on 
top of other infrastructures as well, such as Hadoop (although that's 
another, involved conversation in itself.) At this point I'm more focused 
on getting the core system correct and useful on its own, doing enough to 
ensure this will be scalable in the future. 

There are a number of other distinctions that could probably be reconciled 
with Mimir's approach, such as the use of Jess- or Drools-like Accumulators 
to reason over collections of objects. To be honest I didn't look closely 
on how that could be done given some of the above differences.

Thanks!

-Ryan

On Sunday, August 18, 2013 2:54:32 PM UTC-5, Shantanu Kumar wrote:

 Thanks for posting. I will certainly explore this.

 Did you look at Mimir? https://github.com/hraberg/mimir Could you outline 
 how is Clara's approach different from Mimir?

 Shantanu

 On Sunday, 18 August 2013 23:46:14 UTC+5:30, Ryan Brush wrote:

 Perhaps the best aspect of Clojure is how it can adopt the best ideas 
 from other domains to concisely solve problems, as we've seen with 
 core.logic, core.async and other libraries. I recently came across a 
 problem domain that is easily expressed in forward-chaining rules, and 
 found Clojure to be a powerful way to solve it. 

 While working through this problem space I started to suspect there is a 
 more general need for forward-chaining rules in Clojure to complement 
 core.logic and other libraries. So as a side project I implemented a raw 
 but working engine to do so. I'm posting here to share a draft of this 
 engine, its major design goals, and to ask for input on how we should 
 approach forward-chaining rules in Clojure in general.

 The rationale and some examples are on the github page for this 
 enginehttps://github.com/rbrush/clara-rules, 
 which I've tentatively named Clara. The state of the code isn't where it 
 needs to be yet; I've been learning the intricacies of Rete and discovering 
 better ways to solve problems along the way, and some of that is reflected 
 in the code base. However, the major pieces of design and functionality are 
 in place, so I'd like to get input on those. 

 The idea is to draw a bit from Jess and Lisa, with the Java interop 
 strength of Drools, but the advantages and idioms available in Clojure. The 
 major goals are:

- Focus on problem spaces naturally expressed as forward-chaining 
rules. Data-driven needs like eventing, data validation, or application 
 of 
arbitrary business rules fit here. 
- Embrace immutability. The rule engine's working memory is a 
persistent Clojure data structure that can participate in transactions. 
 All 
changes produce a new working memory that shares state with the previous.
- Rule constraints and actions are simply Clojure s-expressions.
- First-class Java interoperability and APIs. This should be an 
alternative to Jess or Drools from Java-land.
- Usable either as a library to simplify Clojure code, or as a DSL to 
externalize business logic.
- Working memory facts are typically (but not exclusively) Clojure 
records or Java objects following the Java Bean conventions.
- Support the major advantages of existing rules systems, such as 
explainability of why a rule fired and automatic truth maintenance.
- Collections of facts can be reasoned with using accumulators 
similar to Jess or Drools. These accumulators leverage the reducers API 
 and 
are transparently parallelized.
- The working memory is independent of the logic flow, and can be 
replaced with a distributed processing system. A prototype that uses 
Storm https://github.com/rbrush/clara-storm to apply rules to a 
stream of incoming events already exists.

 I'd love to hear thoughts on a couple 

lein-undertow-adapter

2013-08-18 Thread Alexander Solovyov
I was looking at techempower benchmarks [1] and noticed that fastest (by
their measurements) Java HTTP server - Undertow - had no Ring adapter. I
felt like it and wrote one just for fun:

https://github.com/piranha/ring-undertow-adapter

Installation and usage is pretty standard, put

[ring-undertow-adapter 0.1.0]

in your :dependencies and then you can require it:

(require '[ring.adapter.undertow :refer [run-undertow]])

It's fairly simple - that's my first experience in writing a wrapper for
Java library and it was an interesting road to walk - no support for
websockets or any other async stuff or client. I guess that could be added
(or made as a separate library), but right now it's just a Ring adapter.

It's certainly faster than Jetty or Netty, and is on par with HTTP-Kit.
Enjoy, if you feel like it.


[1]: www.techempower.com/benchmarks/

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


[ANN] clj-time 0.6.0 released - some API deprecations

2013-08-18 Thread Sean Corfield
What:
A Clojure wrapper for Joda Time

Where:
https://github.com/clj-time/clj-time

Details:
An API cleanup that deprecates several inconsistent / abbreviated
names and introduces preferred replacements. Deprecated API will
remain under 0.7.0 so you will have plenty of time to update your
code.

Thanx:
https://github.com/michaelklishin/
https://github.com/bitemyapp/ aka callen on #clojure freenode
-- 
Sean A Corfield -- (904) 302-SEAN
An Architect's View -- http://corfield.org/
World Singles, LLC. -- http://worldsingles.com/

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

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


Re: What's your preference, partial or closures?

2013-08-18 Thread Mikera
I prefer to use closures / higher order functions that return a function. 
Reasons:
- You typically get much better performance by returning a closure. 
partial uses apply, which adds a lot of overhead
- It can result in cleaner user code (partials require a bit of mental 
decoding, and you can give the closure-returning function a good, specific 
name)

On naming, I like to use the er suffix to imply that the return value is 
a function that will perform the relevant task. e.g.

(defn incrementer [value]
  (fn [x] (+ x value)))

((incrementer 3) 10)
= 13

On Saturday, 17 August 2013 06:00:30 UTC+8, nodename wrote:

 (defn newgrid 

   [m initialize qi qj]... 


 and then (let [init (partial newgrid m initialize)]... 


 Or else: 


 (defn newgrid 

   [m initialize] 

   (fn [qi qj]... 


 and then (let [init (newgrid m initialize)]... 


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


Re: What's your preference, partial or closures?

2013-08-18 Thread Chris Allen
Am I crazy or does this scream macro?

On Saturday, August 17, 2013 6:02:03 PM UTC-7, Sean Corfield wrote:

 On Sat, Aug 17, 2013 at 5:43 PM, yair yair...@gmail.com javascript: 
 wrote: 
  What do you mean by currying in this context?  Is there a way to do this 
 in 
  clojure apart from using partial? 

 (defn some-func 
   ([a b c] (process a b c)) 
   ([a b]   (fn [c] (some-func a b c))) 
   ([a] (fn ([b] (fn [c] (some-func a b c))) 
([b c] (some-func a b c) 

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

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


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


Re: What's your preference, partial or closures?

2013-08-18 Thread Sean Corfield
You're crazy :)

On Sun, Aug 18, 2013 at 9:04 PM, Chris Allen callen.2...@gmail.com wrote:
 Am I crazy or does this scream macro?

 On Saturday, August 17, 2013 6:02:03 PM UTC-7, Sean Corfield wrote:

 On Sat, Aug 17, 2013 at 5:43 PM, yair yair...@gmail.com wrote:
  What do you mean by currying in this context?  Is there a way to do this
  in
  clojure apart from using partial?

 (defn some-func
   ([a b c] (process a b c))
   ([a b]   (fn [c] (some-func a b c)))
   ([a] (fn ([b] (fn [c] (some-func a b c)))
([b c] (some-func a b c)

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

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

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



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

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

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


Re: Revisiting forward-chaining rules in Clojure

2013-08-18 Thread Alan Moore
On Sunday, August 18, 2013 1:41:56 PM UTC-7, Ryan Brush wrote:

 Shantanu,

 I appreciate it. I did look at Mimir, but had some different objectives, 
 and therefore tradeoffs, and didn't see a straightforward way to reconcile 
 them. 

 First, I wanted to use existing data models in the rules as is -- be it 
 Clojure records, Java Beans, or other structures. Drools has a number of 
 drawbacks, but has success in Java-land largely because it interoperates 
 with existing models so well. A pure Clojure solution with strong interop 
 could offer a number of advantages over existing engines. In fairness, I 
 have yet to add first-class Java support, but the same structure that uses 
 Clojure records right now will be extended to seamlessly use 
 JavaBeans-style classes.

 Second, I have a broader goal of executing rules against arbitrarily large 
 data sets in a distributed system, and there are semantic and structural 
 tradeoffs to make that happen. For instance, the underlying working memory 
 is a separate subsystem in Clara, and all join operations are hash-based 
 and structured in such a way that they need not be performed in the same 
 process. The clara-storm project is a very raw proof-of-concept of 
 distributing rules across a cluster, but we should be able to layer it on 
 top of other infrastructures as well, such as Hadoop (although that's 
 another, involved conversation in itself.) At this point I'm more focused 
 on getting the core system correct and useful on its own, doing enough to 
 ensure this will be scalable in the future. 



I have been working on a similar approach - only using datomic as the 
working memory. At one point I briefly considered putting the rete nodes 
into datomic but quickly realized that wasn't a good idea.

The datomic datalog engine is very impressive. I wondered if using that in 
combination with datomic's tx-report-queue API might be worth looking into 
- instead of running full queries there could be incremental or persistent 
queries that yield tuples matching the datalog expressions in a lazy 
fashion.

 


 There are a number of other distinctions that could probably be reconciled 
 with Mimir's approach, such as the use of Jess- or Drools-like Accumulators 
 to reason over collections of objects. To be honest I didn't look closely 
 on how that could be done given some of the above differences.



Let me know if you need help. It looks like you are farther along than I 
am. I agree that clojure is a great medium for a rules engine... I was 
looking at trying to leverage a lot of the existing match/logic/unification 
libraries as much as possible but it looks like your engine doesn't rely on 
them except for core.reducers.
 
You asked about what features I would like to see - does Clara work in the 
browser/cljs? I haven't tried it yet - do you know any reason why it 
wouldn't?

Alan



 Thanks!

 -Ryan

 On Sunday, August 18, 2013 2:54:32 PM UTC-5, Shantanu Kumar wrote:

 Thanks for posting. I will certainly explore this.

 Did you look at Mimir? https://github.com/hraberg/mimir Could you 
 outline how is Clara's approach different from Mimir?

 Shantanu

 On Sunday, 18 August 2013 23:46:14 UTC+5:30, Ryan Brush wrote:

 Perhaps the best aspect of Clojure is how it can adopt the best ideas 
 from other domains to concisely solve problems, as we've seen with 
 core.logic, core.async and other libraries. I recently came across a 
 problem domain that is easily expressed in forward-chaining rules, and 
 found Clojure to be a powerful way to solve it. 

 While working through this problem space I started to suspect there is a 
 more general need for forward-chaining rules in Clojure to complement 
 core.logic and other libraries. So as a side project I implemented a raw 
 but working engine to do so. I'm posting here to share a draft of this 
 engine, its major design goals, and to ask for input on how we should 
 approach forward-chaining rules in Clojure in general.

 The rationale and some examples are on the github page for this 
 enginehttps://github.com/rbrush/clara-rules, 
 which I've tentatively named Clara. The state of the code isn't where it 
 needs to be yet; I've been learning the intricacies of Rete and discovering 
 better ways to solve problems along the way, and some of that is reflected 
 in the code base. However, the major pieces of design and functionality are 
 in place, so I'd like to get input on those. 

 The idea is to draw a bit from Jess and Lisa, with the Java interop 
 strength of Drools, but the advantages and idioms available in Clojure. The 
 major goals are:

- Focus on problem spaces naturally expressed as forward-chaining 
rules. Data-driven needs like eventing, data validation, or application 
 of 
arbitrary business rules fit here. 
- Embrace immutability. The rule engine's working memory is a 
persistent Clojure data structure that can participate in transactions. 
 All 
changes produce a new 

Re: Revisiting forward-chaining rules in Clojure

2013-08-18 Thread Ryan Brush
The idea of Datomic as an approach to scalable working memory is 
interesting. I haven't looked at the mechanics of doing this, but it seems 
possible since Clara aims to separate the working memory system from the 
rule logic and Rete network.  Also, the approach I've taken here aligns 
with Datomic's ideals of persistent data structures. I think having 
multiple working memory implementations makes sense -- the approaches for 
dealing with distributed event streams, local business logic, and 
incremental queries over large, long-lived memory likely call for different 
infrastructures. Datomic seems like a possible candidate to fill at least 
one of those roles. The problems I've been working on haven't (yet) 
required persisting the working memory, so my focus has been on in-memory 
models to this point.

As for help on this project, it would be welcome! Right now the code is 
rough and the documentation nearly absent, but I plan on addressing that in 
the coming weeks. I am starting to track bugs and enhancements on Github 
for this project in the interest of transparency and collaboration. If 
there's a particular item of interest, feel free to log or claim an issue 
on the project.

Regarding ClojureScript: I believe it should be straightforward to get this 
running in ClojureScript, but I haven't attempted it. There is a small 
amount of logic specific to the JVM -- the mechanism for identifying the 
fields that exist in a fact used in the working memory -- but that could be 
factored out ad a ClojureScript alternative made available. I logged an 
issue to track that: https://github.com/rbrush/clara-rules/issues/4

On Sunday, August 18, 2013 11:51:46 PM UTC-5, Alan Moore wrote:

 On Sunday, August 18, 2013 1:41:56 PM UTC-7, Ryan Brush wrote:

 Shantanu,

 I appreciate it. I did look at Mimir, but had some different objectives, 
 and therefore tradeoffs, and didn't see a straightforward way to reconcile 
 them. 

 First, I wanted to use existing data models in the rules as is -- be it 
 Clojure records, Java Beans, or other structures. Drools has a number of 
 drawbacks, but has success in Java-land largely because it interoperates 
 with existing models so well. A pure Clojure solution with strong interop 
 could offer a number of advantages over existing engines. In fairness, I 
 have yet to add first-class Java support, but the same structure that uses 
 Clojure records right now will be extended to seamlessly use 
 JavaBeans-style classes.

 Second, I have a broader goal of executing rules against arbitrarily 
 large data sets in a distributed system, and there are semantic and 
 structural tradeoffs to make that happen. For instance, the underlying 
 working memory is a separate subsystem in Clara, and all join operations 
 are hash-based and structured in such a way that they need not be performed 
 in the same process. The clara-storm project is a very raw proof-of-concept 
 of distributing rules across a cluster, but we should be able to layer it 
 on top of other infrastructures as well, such as Hadoop (although that's 
 another, involved conversation in itself.) At this point I'm more focused 
 on getting the core system correct and useful on its own, doing enough to 
 ensure this will be scalable in the future. 



 I have been working on a similar approach - only using datomic as the 
 working memory. At one point I briefly considered putting the rete nodes 
 into datomic but quickly realized that wasn't a good idea.

 The datomic datalog engine is very impressive. I wondered if using that in 
 combination with datomic's tx-report-queue API might be worth looking into 
 - instead of running full queries there could be incremental or 
 persistent queries that yield tuples matching the datalog expressions in 
 a lazy fashion.

  


 There are a number of other distinctions that could probably be 
 reconciled with Mimir's approach, such as the use of Jess- or Drools-like 
 Accumulators to reason over collections of objects. To be honest I didn't 
 look closely on how that could be done given some of the above differences.



 Let me know if you need help. It looks like you are farther along than I 
 am. I agree that clojure is a great medium for a rules engine... I was 
 looking at trying to leverage a lot of the existing match/logic/unification 
 libraries as much as possible but it looks like your engine doesn't rely on 
 them except for core.reducers.
  
 You asked about what features I would like to see - does Clara work in the 
 browser/cljs? I haven't tried it yet - do you know any reason why it 
 wouldn't?

 Alan



 Thanks!

 -Ryan

 On Sunday, August 18, 2013 2:54:32 PM UTC-5, Shantanu Kumar wrote:

 Thanks for posting. I will certainly explore this.

 Did you look at Mimir? https://github.com/hraberg/mimir Could you 
 outline how is Clara's approach different from Mimir?

 Shantanu

 On Sunday, 18 August 2013 23:46:14 UTC+5:30, Ryan Brush wrote:

 Perhaps the best aspect of Clojure