1. I have a matched-rule (Attr2Field) for attributes of classes. In this matched rule, I call a lazy-rule (Attr2Getter) to generate some getters and to add it to the new created class, which owns the new created field

2. The same lazy-rule (Attr2Getter) is now called a second time, for the same source-elment but now from a called-rule. In this called rule I use the return-type of the lazy-rule (Attr2Getter) to generate the getter a second time.

Here some code for a better understanding:

rule Attr2Field{
from source:IN!Attr
to target:OUT!Field( )
do{
thisModule.Attr2Getter(source); --create getter for the also created "owning-class" of this field
}
}
initGetterInInterface(source:IN!Attr, containingTargetClass: OUT!OtherClass){
to ...
do {
-- this source-element is used twice, once in a matched rule and once in a called-rule
containingTargetClass.body <-containingTargetClass.body -> including(thisModule.Attr2Getter(source));
}
}
lazy rule Attr2Getter{
from
from source:Attr
using {
containingSourceClass: IN!Class = source.refImmediateComposite();
containingTargetClass: OUT!OtherClass =thisModule.resolveTemp(containingSourceClass, 'target');
}
to getter:OUT!Method(
containerClass <- containingTargetClass
)
}

Is this use of lazy-rules kind of a hack? Should I better create the needed elements in the called rule itself?

I initially thought, that the created getter will be added twice to the (also created) owning class, but this is not the case.

No, this is not a hack. Lazy rules can be called multiple times, and return new elements every time. If you want "functional" behaviour, whereby the same output is returned every time you provide the same input, you can use unique lazy rules.

Also, the return value of a lazy rule is the return value of just that call, not of all the calls to the rule. Therefore, the owning class contains only one copy of the lazy rule output.