On Aug 12, 6:40 pm, Ryan Hinton <iob...@email.com> wrote:
> Hello, Johan.
>
> I'm a little confused at your restatement of my idea as well as your
> description of your idea.  Let me provide some code fragments to be
> concrete.
>
> class Code:
>     def __init__(..., encode_algorithm=['alg_name', args],
> decode_algorithm=['alg_name', args], ...):
>         # handle encoding algorithm; the real implementation should
> allow just
>         # passing in the name instead of a list containing the name
> and
>         # arguments to initialize the requtesd algorithm
>         enc_alg_name = encode_algorithm[0]
>         if 'generator-matrix' == enc_alg_name:
>             # initialization for generator matrix, may use the
> accompanying arguments
>             ...
>         elif ('none' == enc_alg_name) or None is enc_alg_name:
>             # no encoding provided; when base classes handle the
> encoding
>             # algorithm, they can use this code path or just catch the
>             # exception from the next path
>             self.encoder = lambda ...: raise ValueError('encoding not
> allowed on this Code instance.')
>         else:
>             raise NotImplementedError('requested encoding algorithm %s
> not provided.' % enc_alg_name)
>
>         # similar pattern for decoding algorithm specification
>         ...
>
>     def encode(*args, **kwds):
>         # just delegate the encode requests
>         self.encoder(self, *args, **kwds)
>
>     def decode(*args, **kwds):
>         # similarly delegate the decode requests
>         self.decoder(self, *args, **kwds)
>
> So each Code instance keeps a reference to one callable object each
> for encoding and decoding.  My assumption is that these objects are
> relatively small/cheap.  If lots of space is required (large tables?),
> this information could be cached and shared between encoder/decoder
> objects (i.e. in a singleton with lookup by encode/decode
> parameters).  Or we could provide another __init__ keyword argument to
> provide the encoder/decoder object directly so that multiple code
> instances actually return the same object.  On third thought, these
> two ideas can be combined so the if/elif chain will somehow find the
> same object (at least if the objects are expensive) given the same
> code parameters.  (But why do you need multiple instances of the same
> code?)
>
> I think I see the confusion on rereading your post again.  My idea --
> as described above -- is to create/store a reference to the encoder
> and decoder objects *in the Code constructor*.  They can be omitted
> altogether if encoding/decoding is not required.  Or they can be
> created externally and provided through setters (i.e. set_encoder(),
> set_decoder()).  This also provides a path to change the encoding/
> decoding algorithm at runtime if desired.  Again, expensive
> initialization can be delayed until the first call to encode/decode in
> case a Code subclass specifies default encoder/decoder defaults.
>
> Hope this is clearer. :-)
>
> - Ryan

Ok, so now I understand your idea, and mine is actually not too far
from to yours. I'll demonstrate by commenting yours and amending it
until we arrive at mine :-)

My primary objection is that for object-oriented ideology, I think
that constructors should specify what inherently _defines_ some
object. I don't think that the encoder/decoder algorithms do this for
a code. Therefore, I wouldn't really want them to be in the
constructor. If that is accepted, then the set_en/decoder functions
you suggest should always be used for specifying the algorithms by
user-instantiated objects. But in that case, why does the Code object
even need to bother about these De/Encoder objects? They work
perfectly well on their own. The reason could be the user-friendly
intention of your constructor: put the name-to-algorithm check in your
constructor into a function get_en/decoder in the Code object, which
constructs and returns the specified algorithm, constructed in the
correct way and from the intended class; without the user having to
find out what such a En/Decoder class might be called in the Sage
tree. These are then used for en/decoding. Also, this is a guarantee
to the user, that he is using a correct en/decoder for the code in
question, even if he wants to change algorithm in midstream. This way,
we can scrap the set_en/decoder functions, and in the case that the
user really wants to use a en/decoder that is not intended (e.g.
written by himself), he simply constructs it outside of the Code
object and uses it directly. If it works, it can later be added to
Sage and built into the Code class as a possibility.

A secondary objection is easily amendable: I think it is very
important according to Sage methodology, that the Code objects work
out-of-the-box for both encoding and decoding without the user having
to worry about different algorithms existing. This could of course be
done in your model by replacing the error-throwing with a sensible
default. If we want to amend the above idea, then we could let Code
classes have en/decode() functions which chooses, constructs, caches
and uses a sensible default algorithm. Voilá, and we arrive at my
idea :-)

So, I guess both ideas have the same flexibility and scalability, so
which to use is largely a matter of taste. I still like mine best, but
I gladly listen to arguments against it; I hope we can agree on
something. If you are as confused as it turned out I was when reading
your idea, I can quickly cook up some example-code ;-)


> I think I see the confusion on rereading your post again.  My idea --
> as described above -- is to create/store a reference to the encoder
> and decoder objects *in the Code constructor*.  They can be omitted
> altogether if encoding/decoding is not required.  Or they can be
> created externally and provided through setters (i.e. set_encoder(),
> set_decoder()).  This also provides a path to change the encoding/
> decoding algorithm at runtime if desired.  Again, expensive
> initialization can be delayed until the first call to encode/decode in
> case a Code subclass specifies default encoder/decoder defaults.

I don't think we really have to worry about this much. The intention
is for En/Decoder objects to be constructed only rarely (~once per
code object), and they will almost always be different. Adding checks
for uniqueness will most likely end up adding overhead in the usual
case with only miniscule savings in the rare case. If it turned out
that some en/decodes often seemed to require the same pre-computation,
the singleton caching and checking could be implemented separately for
each such (very rare) case, I think.

Cheers,
Johan

-- 
To post to this group, send an email to sage-devel@googlegroups.com
To unsubscribe from this group, send an email to 
sage-devel+unsubscr...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/sage-devel
URL: http://www.sagemath.org

Reply via email to