Re: Declarative Data Models

2011-05-04 Thread David Jagoe
Hey Stuart,

On 4 May 2011 00:19, Stuart Sierra the.stuart.sie...@gmail.com wrote:
 No. Clojure template (which I wrote) is a backwards way of doing macros. It
 happens to be useful in clojure.test, but nowhere else.

Thanks that's good to know. While we're on the subject, I'm curious
about cc.apply-macro. Why should it not be used? I got around a
potential use-case by rearranging my macro a bit. Can it have
unintended consequences? It seems like there may be cases where it
would make code easier to understand.


Thanks,
David


 -Stuart S
 clojure.com

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

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


Re: Declarative Data Models

2011-05-04 Thread Stuart Sierra
apply-macro is a bad idea because it evaluates a macro at runtime.  Macros 
are supposed to be evaluated at compile-time, so apply-macro breaks 
assumptions about how macros are supposed to work.  It's basically a back 
door into `eval`, which is considered bad style in Lisp-like languages.

-Stuart Sierra
clojure.com

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

Re: Declarative Data Models

2011-05-03 Thread Stuart Sierra
No. Clojure template (which I wrote) is a backwards way of doing macros. It 
happens to be useful in clojure.test, but nowhere else.

-Stuart S
clojure.com

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

Re: Declarative Data Models

2011-05-02 Thread David Jagoe
Hi Ambrose,

Thanks for the advice. I have already implemented my application using
maps (defstruct) and busy evaluating whether I should switch to
records. I like the idea of using records and protocols to help me to
define strict abstractions and to do easy type dispatch. On the other
hand I can see that they reduce flexibility. I will post some code to
show what I am trying to do...


Cheers,
David

On 30 April 2011 12:39, Ambrose Bonnaire-Sergeant
abonnaireserge...@gmail.com wrote:
 Hi David,
 I can only comment on a subset of your post.
 Records can be cumbersome to work with during early stages of development,
 when
 everything is rather volatile (when isn't it?).
 You might like to try using maps instead. They are easier to work with when
 you are
 working out what properties you need in your records. It's also
 straightforward to convert
 from maps to records.
 Of course there are downsides to this (speed, lack of types) but it can be a
 useful strategy.
 Thanks,
 Ambrose
 On Sat, Apr 30, 2011 at 4:46 PM, David Jagoe davidja...@gmail.com wrote:

 G'day everyone,

 Are there any libraries or projects that are similar to Python Traits
 or Zope Schemas (http://pypi.python.org/pypi/zope.schema) for clojure.
 I am developing a compojure application and there is a lot of
 duplication between areas of the codebase, e.g.

 - Fields listed on the defrecords
 - Fields listed on the public constructor function
 - Fields listed on forms and again on handlers

 So it is a lot of effort to e.g. add a new field to the data model. I
 would like something declarative from which I can generate forms,
 validators etc.


 Cheers,
 David

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


Re: Declarative Data Models

2011-05-02 Thread David Jagoe
Hey Paul,

On 30 April 2011 20:27, Paul deGrandis paul.degran...@gmail.com wrote:
 I'm not exactly sure of your specific use case, but you should take a
 look at clojure.template.  It could be what you're looking for.

 http://clojuredocs.org/clojure_core/clojure.template

Great, I will have a look thanks.

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


Re: Declarative Data Models

2011-05-02 Thread David Jagoe
Hi Everyone,

Background to my problem:

I am developing a compojure application, and there is lots of
duplication in listing field names in my current data model:

(i) in the defstruct
(ii) in the public constructor's argument list
(iii) in the hiccup form fields
(iv) in the compojure argument destructuring
(v) in the handler's argument list

Ideally I would like to declare my data model in one place like this:

(def person-entity
 {:name  {:type String :validator name-validator}
  :id-number {:type String :validator id-number-validator}
  :height{:type Float :default 0.0}
  :weight{:type Float :default 0.0}
  :bmi   {:type Float :internal true}})

And generate everything from there so that it is trivial to add fields
etc. (:internal true just means that this is a calculated field or for
some other reason is not supplied by the user - it is therefore not
needed by the constructor, and will not show up on the edit-person
form).

I have tried to generate the defrecord etc from such a definition and
have battled a bit, so in the interest of making some progress with my
experiment I have tried this instead:

(defn name-validator [val] val)
(defn id-number-validator [val] val)
(defn nil-validator [val] val)

(defrecord Person
  [#^String name
   #^String id-number
   #^Float  height
   #^Float  weight
   #^Float  bmi])

(def person-traits
 {:name  {:validator name-validator}
  :id-number {:validator id-number-validator}
  :height{:default 100.0}
  :weight{:default 100.0}
  :bmi   {:internal true}})

(def person-constructor (make-constructor Person person-traits))
(def person-editor (make-editor Person person-traits))
(def bob (person-constructor {:name Bob :id-number 123}))

;;; I don't really know how bmi is calculated!! Let's pretend it is
weight (kg) / height (cm)
(bob :bmi)
1.0
(bob :id-number)
123

And the person-editor is a snippet of hiccup which has all of the
relevant fields (e.g. text fields by default).

I plan to use flutter validators, and not to use compojure
destructuring (I will have to pull the fields out of the request in
the generated form handlers).

I am looking for advice in the following areas:

(i) Is it possible to generate the (defrecord Person ...) from the
person-entity hash-map that I have shown?

(ii) Is this a totally crazy idea?

(iii) Am I neglecting to see a much simpler way of achieving my core
objective (reduce all of the duplication)?


Thanks very much.


Cheers,
David

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


Re: Declarative Data Models

2011-05-02 Thread craig worrall


On May 2, 8:37 pm, David Jagoe davidja...@gmail.com wrote:

 (i) Is it possible to generate the (defrecord Person ...) from the
 person-entity hash-map that I have shown?

Sure. You may want to have a look at https://gist.github.com/876029
(and associated post to this group) for something somewhat related.

 (ii) Is this a totally crazy idea?

I don't think so. The ability to have a model/schema that can be used
to build forms, codecs and DDL statements etc would be useful to
others
I imagine. Such a mechanism could be used, for example, as input into
Lobos.

 (iii) Am I neglecting to see a much simpler way of achieving my core
 objective (reduce all of the duplication)?

If so, you and me both.

Regards,
Craig

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


Re: Declarative Data Models

2011-05-02 Thread Ken Wesson
On Mon, May 2, 2011 at 6:37 AM, David Jagoe davidja...@gmail.com wrote:
 Hi Everyone,

 Background to my problem:

 I am developing a compojure application, and there is lots of
 duplication in listing field names in my current data model:

 (i) in the defstruct
 (ii) in the public constructor's argument list
 (iii) in the hiccup form fields
 (iv) in the compojure argument destructuring
 (v) in the handler's argument list

 Ideally I would like to declare my data model in one place like this:

 (def person-entity
     {:name      {:type String :validator name-validator}
      :id-number {:type String :validator id-number-validator}
      :height    {:type Float :default 0.0}
      :weight    {:type Float :default 0.0}
      :bmi       {:type Float :internal true}})

 And generate everything from there so that it is trivial to add fields
 etc. (:internal true just means that this is a calculated field or for
 some other reason is not supplied by the user - it is therefore not
 needed by the constructor, and will not show up on the edit-person
 form).

 I have tried to generate the defrecord etc from such a definition and
 have battled a bit, so in the interest of making some progress with my
 experiment I have tried this instead:

 (defn name-validator [val] val)
 (defn id-number-validator [val] val)
 (defn nil-validator [val] val)

 (defrecord Person
  [#^String name
   #^String id-number
   #^Float  height
   #^Float  weight
   #^Float  bmi])

 (def person-traits
     {:name      {:validator name-validator}
      :id-number {:validator id-number-validator}
      :height    {:default 100.0}
      :weight    {:default 100.0}
      :bmi       {:internal true}})

 (def person-constructor (make-constructor Person person-traits))
 (def person-editor (make-editor Person person-traits))
 (def bob (person-constructor {:name Bob :id-number 123}))

 ;;; I don't really know how bmi is calculated!! Let's pretend it is
 weight (kg) / height (cm)
 (bob :bmi)
 1.0
 (bob :id-number)
 123

 And the person-editor is a snippet of hiccup which has all of the
 relevant fields (e.g. text fields by default).

 I plan to use flutter validators, and not to use compojure
 destructuring (I will have to pull the fields out of the request in
 the generated form handlers).

 I am looking for advice in the following areas:

 (i) Is it possible to generate the (defrecord Person ...) from the
 person-entity hash-map that I have shown?

Shoundn't be too hard. Something like

(defn to-rec-field [kword entity-map]
  (let [rf (symbol (name kword))]
(if-let [t (:type (entity-map kword))]
  (with-meta rf {:tag t})
  rf)))

(defmacro defentity [name entity-map]
  (let [fields (fn [ks]
 (map #(to-rec-field % entity-map)
   ks))
optionals (filter #(:default (entity-map %))
(keys entity-map))
optional-subsets (map #(set (drop % (reverse optionals)))
   (range (count optionals)))]
`(do
   (defrecord ~(symbol (str R name))
 ~@(fields (keys entity-map)))
   (defn ~(symbol (str construct- name))
 ~@(map
 (fn [ops]
   (list
 (vec (fields (remove ops (keys entity-map
 (cons
   (symbol (str R name .))
   (map
 #(if (ops %)
(:default (entity-map %))
(to-rec-field % entity-map))
 (keys entity-map)
 optional-subsets))
 (defn ~(symbol (str edit- name))
  ~@(left as an exercise for the reader)

This should (untested) produce a defrecord and arity-overloaded
constructors for the whole argument list and with successively more of
the fields with defaults omitted, starting at the right -- so, for
your person, you'd get constructors for [name id-number height weight
bmi], [name id-number height bmi], and [name id-number bmi].

You probably want it to omit bmi from the argument lists and compute
it -- that will complicate things, something like:


(defmacro defentity [name entity-map]
  (let [fields (fn [ks]
 (map #(to-rec-field % entity-map)
   ks))
default #(:default (entity-map %))
optionals (filter default (keys entity-map))
optional-subsets (map #(set (drop % (reverse optionals)))
   (range (count optionals)))
computer #(:computer (entity-map %))
computed (filter computer (keys entity-map))]
`(do
   (defrecord ~(symbol (str R name))
 ~@(fields (keys entity-map)))
   (defn ~(symbol (str construct- name))
 ~@(map
 (fn [ops]
   (list
 (vec
   (fields
 (remove (concat ops computed)
   (keys entity-map
 `(let ~(vec
  (interleave
(fields 

Re: Declarative Data Models

2011-05-02 Thread Christian Schuhegger
My comment is unrelated to Clojure but related to the general topic of
avoiding redundancy. Please have a look at InfoQ's Dan Haywood's
Domain-Driven Design Using Naked Objects:
http://www.infoq.com/articles/haywood-ddd-no
The book is definitely worth a read!

Naked Object's (now called Apache Isis http://incubator.apache.org/isis/)
whole purpose is to concentrate the domain knowledge (including the
meta data!) in the domain model and thus avoid the typical
redundancies you find across the different application layers.

Here is an answer to one of my questions to their mailing list to find
out how to query their central meta data infrastructure:
http://mail-archives.apache.org/mod_mbox/incubator-isis-dev/201104.mbox/browser

One of my ideas (don't know when and if I will ever come around to
pursue that) would be to create an implementation of that meta data
interface in Clojure. That way the whole feature set of the framework
would be available for developing applications in Clojure.

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


Re: Declarative Data Models

2011-05-02 Thread Christian Schuhegger
Sorry, the link to their mailing list is here:
http://mail-archives.apache.org/mod_mbox/incubator-isis-dev/201104.mbox/BANLkTim+9061Se1mPLK3=wymmj0qkdu...@mail.gmail.com

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


Re: Declarative Data Models

2011-05-02 Thread David Jagoe
On 2 May 2011 14:06, craig worrall craig.worr...@gmail.com wrote:


 On May 2, 8:37 pm, David Jagoe davidja...@gmail.com wrote:

 (i) Is it possible to generate the (defrecord Person ...) from the
 person-entity hash-map that I have shown?

 Sure. You may want to have a look at https://gist.github.com/876029
 (and associated post to this group) for something somewhat related.

Excellent, thanks Craig. That is what I am looking for.

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


Re: Declarative Data Models

2011-05-02 Thread David Jagoe
Hi Ken,

 Shoundn't be too hard. Something like

[snip]

Thanks, looks good. I haven't had a chance to play with the code yet
but it looks like a very good start.


 You probably want it to omit bmi from the argument lists and compute
 it -- that will complicate things, something like:


[snip]

 used with something like

 (defentity person
  {:name      {:type String}
   :id-number {:type Integer}
   :height    {:type Double :default 100.0}
   :weight    {:type Double :default 100.0}
   :bmi       {:type Double :computer (/ weight height)}})

 Note that both the :default and the :computer can be s-expressions
 that just get inserted verbatim as code. The two differences are:

 1. A field with :computer will not ever be a constructor parameter.

 2. The :computer s-expression can refer to any of the fields; the
 :default can only refer to earlier ones and non-optional ones.

 I hope this shows how one might go about constructing a macro to take
 a definition similar to your original person-entity map and turn it
 into a record, constructor function, and possibly other structures.
 For example it could put code in the constructor function to run a
 :validator, if present, on that field, where the :validator throws an
 exception; or to turn a :validator field into a test and throw
 exception clause where the :validator is a boolean expression; etc.

Yes, that is great thanks!


Cheers,
David

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


Declarative Data Models

2011-04-30 Thread David Jagoe
G'day everyone,

Are there any libraries or projects that are similar to Python Traits
or Zope Schemas (http://pypi.python.org/pypi/zope.schema) for clojure.
I am developing a compojure application and there is a lot of
duplication between areas of the codebase, e.g.

- Fields listed on the defrecords
- Fields listed on the public constructor function
- Fields listed on forms and again on handlers

So it is a lot of effort to e.g. add a new field to the data model. I
would like something declarative from which I can generate forms,
validators etc.


Cheers,
David

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


Re: Declarative Data Models

2011-04-30 Thread Ambrose Bonnaire-Sergeant
Hi David,

I can only comment on a subset of your post.

Records can be cumbersome to work with during early stages of development,
when
everything is rather volatile (when isn't it?).

You might like to try using maps instead. They are easier to work with when
you are
working out what properties you need in your records. It's also
straightforward to convert
from maps to records.

Of course there are downsides to this (speed, lack of types) but it can be a
useful strategy.

Thanks,
Ambrose

On Sat, Apr 30, 2011 at 4:46 PM, David Jagoe davidja...@gmail.com wrote:

 G'day everyone,

 Are there any libraries or projects that are similar to Python Traits
 or Zope Schemas (http://pypi.python.org/pypi/zope.schema) for clojure.
 I am developing a compojure application and there is a lot of
 duplication between areas of the codebase, e.g.

 - Fields listed on the defrecords
 - Fields listed on the public constructor function
 - Fields listed on forms and again on handlers

 So it is a lot of effort to e.g. add a new field to the data model. I
 would like something declarative from which I can generate forms,
 validators etc.


 Cheers,
 David

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

Re: Declarative Data Models

2011-04-30 Thread Paul deGrandis
I'm not exactly sure of your specific use case, but you should take a
look at clojure.template.  It could be what you're looking for.

http://clojuredocs.org/clojure_core/clojure.template

Paul


On Apr 30, 3:39 am, Ambrose Bonnaire-Sergeant
abonnaireserge...@gmail.com wrote:
 Hi David,

 I can only comment on a subset of your post.

 Records can be cumbersome to work with during early stages of development,
 when
 everything is rather volatile (when isn't it?).

 You might like to try using maps instead. They are easier to work with when
 you are
 working out what properties you need in your records. It's also
 straightforward to convert
 from maps to records.

 Of course there are downsides to this (speed, lack of types) but it can be a
 useful strategy.

 Thanks,
 Ambrose







 On Sat, Apr 30, 2011 at 4:46 PM, David Jagoe davidja...@gmail.com wrote:
  G'day everyone,

  Are there any libraries or projects that are similar to Python Traits
  or Zope Schemas (http://pypi.python.org/pypi/zope.schema) for clojure.
  I am developing a compojure application and there is a lot of
  duplication between areas of the codebase, e.g.

  - Fields listed on the defrecords
  - Fields listed on the public constructor function
  - Fields listed on forms and again on handlers

  So it is a lot of effort to e.g. add a new field to the data model. I
  would like something declarative from which I can generate forms,
  validators etc.

  Cheers,
  David

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