On Tue, Mar 15, 2011 at 16:08, Eric Merritt <[email protected]> wrote:
> On Tue, Mar 15, 2011 at 03:30:50PM +0100, Torben Hoffmann wrote:
> >
> > Dictionary1 = ec_gb_trees:new().
> > Dictionary2 = ec_dict:new().
> >
> > NewDictionary1 = Dictionary1:put(SomeKey, SomeValue).
> > NewDictionary2 = Dictionary2:put(SomeKey, SomeValue).
>
> > You have lost me a bit here... how would the Dictionary1 hold both a
> > module name and a value?
>
> Its a parameterized type. ec_gb_trees:new would return the
> parameterized type. I guess I can't expect you to see whats in my head
> lol, I forget about that sometimes.
>
We have not had enough beers together to see inside each others heads... ;-)
>
> So because of limitations in parameterized types. There are two
> modules for each type. A non prameterized module used for construction
> and a parameterized module that actually provides the
> impementation. So ec_gb_trees would look like (off the top of my head,
> uncompiled and un tested).
>
> ,----
> | -module(ec_gb_trees).
> |
> | -export([new/0]).
> |
> | -spec new() -> ec_dictionary:dictionary().
> | new() ->
> | ec_gb_trees_impl:new(gb_trees:new()).
> `----
>
> then ec_gb_trees_impl would look something like
>
> ,----
> | -module(ec_gb_trees_impl, [Data]).
> |
> | -behaviour(ec_dictionary).
> |
> | -export([get/1, put/2, ...]).
> |
> |
> | .....
> `----
>
That looks like a lot of labour, but let's look at the implementations and
their merits before passing judgement.
>
>
> > In this case it wouldn't matter what the concrete implementation of
> > dictionary is, as long as it implemented the ec_dictionary
> interface.
> >
> > I have some utilities that check that a particular module implements
> > an interface, but in general you just have to trust that that the
> > caller is passing you the right value. Of course, thats pretty
> normal
> > in erlang.
> >
> > Trust it at runtime but test the hell out of it and run dialyzer like
> > crazy.
>
> Exactly.
>
> >
> > Well, isn't that a matter of how many layers of indirection you want?
>
> What do you mean?
>
I was rambling about how many layers one wants to put around the thing -
nothing more.
Enough talk - from now on we will let actual code decide.
>
> > My approach adds the thinnest indirection layer by having everything
> in
> > the same module.
> > I like that sort of thing since it makes debugging extremely easy.
> > Another bonus of coding it so directly as I did is that if you run
> xref on
> > the module it will actually figure out what is going on! I have done
> some
> > code where the module was a parameter and that puts a real stick in
> the
> > wheel of xref.
>
> I agree on all points. However, the inability for folks to extend it
> in thier systems is just a killer for a generalized library. Using
> this approach I haven't found a way around that.
>
The extension problem is why I am now fund of your behaviour based solution!
>
> > Another thing is dialyzer - I am not quite sure that it handles
> > parameterized modules very well, so I would experiment with that
> before
> > playing more with those things...
>
> I am not sure either. I think the tools in general support it much
> better then they used to. However, it is certainly worth testing to
> see where dialyzer might fall down..
>
> >
> > The testing should not be all that affected by the chosen
> implementation
> > so I am up for a bit of fun!
>
> sweet!
>
> >
> > There is one major problem, I think, critical fault in this. That is
> you
> > must know all the possible implementations at the time you are
> coding
> > the are coding the interface. I think this is a killer for a set of
> > types. I believe that client developers need the ability to
> implement
> > the interface after the creation of the interface for it to be
> > useful.
>
> >
> > My first implementation used a similar approach. Though it auto
> called
> > the function in the module defined by base. So your size looked
> > something like
> >
> > size(#my_map{base = Moule , content=C}) -> Module:size(C).
> >
> > It retained the ability to be extended at run time, but still
> required
> > that a wrapper be defined to implement the interface. I was coding a
> > wrapper for assoc lists as a test when I realized I had just
> > reinvented parametrized modules.
> >
> > Hmmmm, I am not quite sure that I see the issue here - could you show
> me a
> > bit of your code?
> >
> > My approach has - as you point out - the drawback that you have to
> extend
> > it every time you need a new base module.
> > This you have to weigh up against benefit of giving xref, dialyzer et
> al
> > an easier job.
> >
> > Using your behaviour based solution one could let new return something
> > like #my_map{} above and then let a generic wrapper module handle the
> > operations on the data:
> >
> > Dict1 = ec_dict:new().
> > Dict2= gen_dict:add(1,Dict1).
> >
> > or you could - and probably should - change the instantiation to:
> >
> > Dict1 = gen_dict:new(dict). %% pick implementation at this point.
> > Dict2= gen_dict:add(1,Dict1).
>
> Thats true, and doable. In this model I like that approach a lot. and
> we would retain the tools compatabliity at the expense of a bit of
> indirection.
>
> > This might be a more Erlangish way of doing it since it uses a
> behaviour
> > as restriction for the mapping modules and it wraps the indirection
> with a
> > simple data structure. (It does make xref unhappy I guess, but
> dialyzer
> > should be a happy trooper at this point.)
>
> I don't think it would affect xref for the user. For the type
> developer it would, but we would want to ensure good tests there
> anyway. In this model the user matters more.
>
Agreed.
>
> > This might be exactly the same as using parameterized modules, so it
> would
> > require an experiment to judge what is the cleaner way of doing it.
> >
> > I would say that the solution that keeps most of the analysis tools
> happy
> > is the one to go with. I have not used the tools with parameterized
> > modules so I have no clue if it makes it a mess or not.
>
> Hmm, then it could be that my original approach is best. I have some
> decent examples of that approach already. Let me send them to the list
> and get some feedback.
>
Looking forward to that!
Cheers,
Torben
--
http://www.linkedin.com/in/torbenhoffmann
--
You received this message because you are subscribed to the Google Groups
"erlware-dev" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/erlware-dev?hl=en.