Yes, you are right :-(. I forgot your requirement.

I fear there is no simple solution in this case, as you need to create the 
object with the right type (to get the right size) and, at this moment, you 
don’t have access to the private field. In fact, I’m sure that my first 
solution with a cast doesn’t work if extra fields exists in _ElementA_ (it 
compiles, but will cause problems at runtime).

And I’m not sure that using a macro will change anything: you need to allocate 
in the client module to get the right size and to allocate in the _lib_ module 
to have access to the private field. This is incompatible.

But there are ways to check that _initElement_ is not called several times. For 
instance, you can add a private boolean field _initialized_ in _Element_ which 
is false by default. Then _initElement_ becomes:
    
    
    proc initElement(elem: Element, id: string) =
      if elem.initialized:
        # already initialized: raise some exception
        …
      elem.id = id
      elem.initialized = true
    
    
    Run

Or, if you require that _id_ cannot be the empty string, you no longer need the 
_initialized_ field:
    
    
    proc initElement(elem: Element, id: string) =
      if id.len == 0:
        # id must not be empty: raise some exception.
        …
      if elem.id.len != 0:
        # already initialized: raise some other exception.
        …
      elem.id = id
    
    
    Run

I agree that these are not very elegant solutions. Maybe using a macro to 
initialize could solve the problem in a more elegant way. I can’t say for sure 
as I have not use macros for now. 

Reply via email to