Puppet: how can i pass value from inherited class to base class? - puppet

How can I pass value from inherited class to base class using puppet?
You can see below a simplified code for my trials.
class executor::app($base_dir = "/usr/local",
$run_command = undef,
$prefix_naming = undef) {
}
class app1(
$base_dir = ::app1::params::base_dir,
$prefix_naming = "reader",
$run_command = " ") inherits executor::app{
}

OK, for starters lets assume you have these classes in module format. If not, then that should be the first order of business.
Second, avoid inheritance. There is almost always a better way to do it. Especially don't inherit across modules. About the only time I can think it's useful is for defaulting class parameters.
The base_dir on class app1 will not get the default unless the class inherits cea::params::base_dir (leading :: not needed). Again, across modules shouldn't be done. app1::params much better -- or just put in a sane default and eliminate the need to inherit parameters all together.
For your actual question, if you want to get a variable in another class you can just reference it. Keep in mind that puppet doesn't guarantee compile order so you should tell it to evaluate the other class first:
class executor::app {
Class['app1'] -> Class['executor::app']
$other_app_var = $app1::base_dir
}
Or throw this data in hiera and look up the value.

Related

Use Haskell like Prelude modules in a module in raku

I'm writing a drawing package with some parts, and I have operators and data types scattered througout. However I don't want the users to add the corresponding modules every time, since it would be quite messy, for instance I'd have a Point class, a Monoid role and a Style class
in different paths like this
unit module Package::Data::Monoid;
# $?FILE = lib/Package/Data/Monoid.pm6
role Monoid {...}
unit module Package::Data::Point;
# $?FILE = lib/Package/Data/Point.pm6
class Point {...}
unit module Package::Data::Style;
# $?FILE = lib/Package/Data/Style.pm6
class Style {...}
I would like to have a haskell like prelude in lib/Package/Prelude.pm6
with the effect that I can write such scripts
use Package::Prelude;
# I can use Point right away, Style etc...
instead of doing
use Package::Data::Style;
use Package::Data::Point;
use Package::Data::Monoid;
# I can too use point right away, but for users not knowing the
# inner workings it's too overwhelming
I've tried many things:
This version doesn't give me the right effect, I have to type
the whole path to point, i.e., Package::Data::Point...
unit module Package::Prelude;
# $?FILE = lib/Package/Prelude.pm6
use Package::Data::Style;
use Package::Data::Point;
use Package::Data::Monoid;
This version gives me the Point right away, but I get
problems with the operators and so on, also I would just like to
add automatically everything from the exported routines in the mentioned
example packages.
# $?FILE = lib/Package/Prelude.pm6
use Package::Data::Style;
use Package::Data::Point;
use Package::Data::Monoid;
sub EXPORT {
hash <Point> => Point
, <Style> => Style
, <mappend> => &mappend
...
}
Do you people know a better and quick way of getting such a prelude-like
file?
Using EXPORT is in the right direction. The key things to know are:
Imports are lexical
We can use introspection to obtain and access the symbols in the current lexical scope
So the recipe is:
use all the modules inside of EXPORT
Then extract all the imported symbols and return them as the result from EXPORT
As an example, I create a module Foo::Point, including an operator and a class:
unit module Foo::Point;
class Point is export {
has ($.x, $.y);
}
multi infix:<+>(Point $a, Point $b) is export {
Point.new(x => $a.x + $b.x, y => $a.y + $b.y)
}
And, just to demonstrate it can work with multiple modules, also a Foo::Monad:
unit module Foo::Monad;
class Monad is export {
method explain() { say "Just think of a burrito..." }
}
The goal is to make this work:
use Foo::Prelude;
say Point.new(x => 2, y => 4) + Point.new(x => 3, y => 5);
Monad.explain;
Which can be achieved by writing a Foo::Prelude that contains:
sub EXPORT() {
{
use Foo::Point;
use Foo::Monad;
return ::.pairs.grep(*.key ne '$_').Map;
}
}
There's a few oddities in here to explain:
A sub has implicit declarations of $_, $/, and $!. Exporting these would result in a compile-time symbol clash error when the module is use'd. A block only has an implicit $_. Thus we make our life easier with a nested bare block.
The grep is to make sure we don't export our implicitly declared $_ symbol (thanks to the nested block, it's the only one we have to care about).
:: is a way to reference the current scope (etymology: :: is the package separator). ::.pairs thus obtains Pair objects for each symbol in the current scope.
There's a speculated re-export mechanism that may appear in a future Raku language release that would eliminate the need for this bit of boilerplate.

Confused about static class vars in python

Here a little example code:
class A:
staticvar=3;
def foo2(self):
print("------ Foo2")
print("static: "+str(A.staticvar));
print("instance: "+ str(self.staticvar));
class B(A):
def setStaticVar(self, num):
B.staticvar=num;
a=A();
b=B();
a.staticvar=7;
a.foo2();
b.setStaticVar(100);
a.foo2();
b.foo2();
what results in:
------
static: 3
instance: 7 -->correct. Instance var modified
------
static: 3
instance: 7 --> Not correct. Why static var is not 100
------
static: 3
instance: 100 --> Correct, but this value should be shared between A and B
Why is this happening? Shouldn't the static variable be shared between A and B? Why when it is modified in b through b.
From this example it seems, each class has its own static var (not really static from my point of view because there would only be one static var and we have 2, one per class).
Could anyone explain this behaviour?
Cheers.
I suspect what you're running into is an issue of name resolution. When you get B.staticvar, the interpreter fails to find it and falls back on its super classes to try to resolve the name. Upon traversing to A, the interpreter finds staticvar and returns the value.
When you set a value to B.staticvar, however, you get much the same behavior as your "instance" case, where a new property called staticvar is added to B. Now, when it attempts to resolve the property name on B (or instances thereof), it uses this new value without ever falling back to A. In Python, inheriting a class isn't much about sharing its properties, it's about setting a fallback class to resolve names when they aren't defined in your child class (hence why there's no need to explicitly "override" methods, and why you must remember to call super(A).method_name within B.method_name if you want the parent function to be run).
To get the behavior you're asking for, either define setStaticVar in A, and/or change its body to A.staticvar=num

Groovy Spock: is it possible to make "shared" a group of variables?

I have a big group of variables in my spock test. First half of them are objects which need some serious effort to be created, and second one are the constants. I want to mark all these objects with #Shared annotation. But actually may be there is a better and shorter way to evaluate this task?
Placing 20 or 30 similair annotations one after one is not a groovy way, I suppose..
You could have a single context, so one #Shared
class Test extends Specification {
#Shared context = [
one: new One(),
two: new Two()
]
def "Use of context"() {
expect:
context.one.//
context.two.//
}
}

C# Inheritance access confusion

public class ABC
{
}
public class DEF : ABC
{
}
public class Class1
{
ABC abc = new DEF(); //No error
DEF def = new ABC(); //Compile time error
}
Can anyone explain to me this scenario.
and under what circumstances we might use it.
Its because as per the OOD rule you can assign child to parent but you cannot assign parent to child.
//this possible as you re assigning child to parent
ABC abc = new DEF(); //No error
//this is illegal as you are trying to assign child to parent directly
DEF def = new ABC(); //Compile time error
Reconsider your design again or if you want to convert parent object to child than you need method for that conversion directly its not possible to do it as per OOD rules.
Consider real time example relation of Customer and RetailCustomer or Corporatecustomer of bank. Where you can easily say RetailCustomer or CorporateCustomer is Customer, but you cannot say Customer is RetailCustomer or CorporateCustomer because customer can be of any type.
Same goes for relation between Parent Shape Class and Child Rectangle,Circle etc. class.
This is called as Ploymorphism .
As explained in MSDN
At run time, objects of a derived class may be treated as objects of a
base class in places such as method parameters and collections or
arrays. When this occurs, the object's declared type is no longer
identical to its run-time type.
Base classes may define and implement virtual methods, and derived
classes can override them, which means they provide their own
definition and implementation. At run-time, when client code calls the
method, the CLR looks up the run-time type of the object, and invokes
that override of the virtual method. Thus in your source code you can
call a method on a base class, and cause a derived class's version of
the method to be executed.
The answer of for this question is best explained here MSDN Polymorphism
Let's say ABC is Person, while DEF is Student (which is a subclass of Person). You can always treat a Student as a Person, so the assignment to abc (of type Person) of a Student is correct, but you cannot treat a generic Person as Student, so the assignment to def is wrong (for instance, you cannot get the student number of a person which is not a student)

Vala: Pass String as Class

Scenario:
I have x number of classes. Lets say 10; Each class does different UI Functions. When a user loads a file, that extension tells the program the classname to load; but it's in the form of a string.
Is there anyway to pass a string off as a classname? Something to the effect of.
var classname = "Booger";
var nose = new classname(){ //classname really means "Booger"
//Do Operation
}
You can reflect a type by name using var t = Type.from_name(classname);, however, this works on all types, including enums and structs and it might be the type Type.INVALID. You should probably do some checks, like t.is_a(typeof(MyParentClass)).
You can then instantiate a copy using var obj = Object.new(t);. The whole thing would look like:
var classname = "Booger";
var t = Type.from_name(classname);
if (t.is_a(typeof(MyParentClass)))
return Object.new(t);
else
return null;
It's also worth noting that the run-time type names have the namespace prepended, so you might want to do "MyNs" + classname. You can check in either the generated C or doing typeof(MyClass).name().
I've had the same problem as the OP in regards to getting an assertion error against null. If you take a look at the Glib documentation (in C) it mentions you have to register your class by actually specifying the class name first before you can actually use a string representation of your class name.
In other words you have to use your class first BEFORE you can instantiate a copy of your class with Glib.Type.from_name ("ClassName").
You can use your class first by instantiating a class instance or by getting type information for your class.
var type = typeof (MyClass);
var type_from_string = Type.from_name ("MyClass");
Furthermore, when you use Object.new to create a class there are two things you need to be aware of:
1) You need to cast the return value to get your specific class or base class.
var instance_of_my_class = Object.new (type) as MyClass;
2) Constructors for your class will no longer be called (I don't why). You will need to use the GObject style constructor inside your class:
construct {
pizza = 5;
}

Resources