Ich habe mal just for fun eine DOIF-Version gebastelt, bei der man Perlfunktionen am Ende des DOIF-Definitionsbereichs definieren kann.
Bsp:
define di_test DOIF (convert([sens:temperature]) > 30)(set bla on)
##my perl definitions
sub convert ($)
{
my ($param) = @_;
my $result;
...
return($result);
}
Natürlich kann man auch seine Funktionen in myUtils ablegen, allerdings könnte es vielleicht interessant sein, die gerade benötigte Perlfunktion direkt gleich an der "richtigen" Stelle zu haben.
Bin mir aber nicht sicher, ob diese Möglichkeit Segen oder eher Fluch wäre;)
Verständnisfrage:
Die Perlfunktion existiert dann nur im Kontext dieses einen DOIF-Moduls? Oder ist sie auch für andere DOIFs sicht- und nutzbar (also "wiederverwendbar")?
Das wäre eigentlich nur für den Sonderfall interessant, wenn eine Funktion nur in einem DOIF mehrfach verwendet wird.
Selbst, wenn sie global verfügbar wäre und in mehreren DOIF eingesetzt wird, würde ich die Funktion lieber im Modul myUtils pflegen.
Wenn die Funktion nur einmal im DOIF verwendet wird, könnte sie als Block genau so gut in der eigentlichen Definition stehen.
Es stört ja nicht, wenn DOIF es kann.
@Damian: Jetzt verstehe ich, was das eigentliche Ziel von DOIF ist. Du willst alle zu Perl-Entwicklern machen...
SCNR,
Thorsten
Zitat von: Thorsten Pferdekaemper am 09 März 2017, 11:18:37
@Damian: Jetzt verstehe ich, was das eigentliche Ziel von DOIF ist. Du willst alle zu Perl-Entwicklern machen...
SCNR,
Thorsten
Genau, wo die meisten schon in der Bedingung Perl ohne es zu wissen programmieren, können sie jetzt auch noch den Rest schnell lernen :)
Zum Thema Sichtbarkeit. Ich wüsste jetzt nicht, wie man die Funktion kapseln könnte. Wenn man irgendwo in FHEM eine Funktion definiert, ist sie überall in FHEM bekannt. Das ist meiner Meinung nach gefährlich, weil man damit auch wichtige FHEM-Funktionen umdefinieren kann, ohne es zu merken. Das Problem dürfe auch in myUtils existieren.
Dieser Option könnte bleiben, für Dinge, die DOIF noch nicht kann. Ich hoffe, dass es eher eine Ausnahme ist, als der Regelfall ;)
Könntest Du nicht sowas wie
package DOIF::di_test
reingenerieren? Dann ist das main-Package erst einmal geschützt, aber man kann es immer noch explizit auch woanders verwenden, wenn man unbedingt will und DOIF::di_test::convert aufruft.
Gruß,
Thorsten
Zitat von: Thorsten Pferdekaemper am 09 März 2017, 12:34:33
Könntest Du nicht sowas wie
package DOIF::di_test
reingenerieren? Dann ist das main-Package erst einmal geschützt, aber man kann es immer noch explizit auch woanders verwenden, wenn man unbedingt will und DOIF::di_test::convert aufruft.
Gruß,
Thorsten
Ja, muss ich mir noch mal genau anschauen, denn eine Kapselung im DOIF-Modul wäre mir wichtig.
Ich finde es schon recht ungünstig, dass man in der Kommandozeile z. B. durch {sub CommandSet(){return "bla"}} sich den set-Befehl zerstören kann.
Zitat von: Damian am 09 März 2017, 13:28:52Ich finde es schon recht ungünstig, dass man in der Kommandozeile z. B. durch {sub CommandSet(){return "bla"}} sich den set-Befehl zerstören kann.
Tja, ich glaube, da gibt es eine Art Lemma zur Turing-Vollständigkeit. Es besagt, dass man mit jedem System, das mächtig genug ist, um damit etwas wirklich sinnvolles machen zu können, man automatisch auch irgend etwas kaputt machen kann. ...oder so ähnlich.
Für Dein Beispiel muss man aber schon wissen, dass es so geht und ein bisschen bösartig sein. Es ist unwahrscheinlich, dass das zufällig vorkommt. Da ist ja noch "sudo rm -rf /" wahrscheinlicher...
Disclaimer: Children, don't try this at home...
Gruß,
Thorsten
Ich meine nicht eine böse Absicht, sondern die Tatsache, dass man durch die Definition seiner eigenen Funktion irgendeine bereits existierende FHEM-Funktion umdefiniert ohne es zu bemerken. Ich glaube nicht, dass jemand weiß, welche unzähligen Funktionen es alle in FHEM gibt, oder sich gar der Tatsache bewusst ist, dass er überhaupt etwas umdefinieren kann.
Deswegen sieht man ja in den meisten Beispielen, dass eigene Funktionen irgendeinen Präfix haben. Z.B. in den Moduldateien fangen die Funktionen mit dem Modulnamen an. In 99_myUtils.pm normalerweise mit "myUtils_". Funktionen ohne Präfix darf nur rudolfkoenig.
Gruß,
Thorsten
Könnte man das nicht als Attribut implementieren
define di_test DOIF (MYconvert([sens:temperature]) > 30)(set bla on)
attr di_test MYconvert ($)
{
my ($param) = @_;
my $result;
...
return($result);
}
man könnte dann programmieren, dass alle subs die mit MY beginnen in den eigenen Attributen zu suchen sind. Das ganze wird dann perl analyzeCommand ausgewertet.
Zitat von: igami am 10 März 2017, 07:23:06
Könnte man das nicht als Attribut implementieren
define di_test DOIF (MYconvert([sens:temperature]) > 30)(set bla on)
attr di_test MYconvert ($)
{
my ($param) = @_;
my $result;
...
return($result);
}
man könnte dann programmieren, dass alle subs die mit MY beginnen in den eigenen Attributen zu suchen sind. Das ganze wird dann perl analyzeCommand ausgewertet.
Klar, kann man so was programmieren. Die Frage ist, was besser lesbar wäre.
Zitat von: Damian am 10 März 2017, 10:19:24
Klar, kann man so was programmieren. Die Frage ist, was besser lesbar wäre.
Sollte eher den Hintergrund haben, dass die Funktion dann nur in diesem DOIF verfügbar ist.
Zitat von: igami am 10 März 2017, 12:02:16
Sollte eher den Hintergrund haben, dass die Funktion dann nur in diesem DOIF verfügbar ist.
ja.
Optimal wäre, beliebige Funktionen ohne Namenseinschränkung zu definieren, die nur in der jeweiligen Instanz des DOIF-Moduls sichtbar wären und gleichzeitig auf alle anderen Funktionen, wie bisher, zugreifen zu können.
Z. Zt. weiß ich noch nicht wie man mit package vererben kann und wie man etwas pro Instanz kapseln könnte.
analyzeCommand kapselt Funktionen wohl nicht, siehe mein Beispiel für die
Commandref. Edit: Kommandozeile
https://stackoverflow.com/questions/451521/how-do-i-make-private-functions-in-a-perl-module
my $priv_func1 = sub {
my $self = shift; say 'func1';
};
sub public_sub {
my $self = shift;
$self->$priv_func1(@_);
}
Zitat von: igami am 10 März 2017, 12:45:03
https://stackoverflow.com/questions/451521/how-do-i-make-private-functions-in-a-perl-module
my $priv_func1 = sub {
my $self = shift; say 'func1';
};
sub public_sub {
my $self = shift;
$self->$priv_func1(@_);
}
ok, das ist schon mal ein Ansatz, allerdings müsste ich dann einen Präprozessor wieder bauen. z. Zt. habe ich einfach eval ("Rest hinter der DOIF-Definition") für die Definition der Funktionen aufgerufen.
Zitat von: igami am 10 März 2017, 07:23:06
Könnte man das nicht als Attribut implementieren
attr di_test MYconvert ($)
{
...}
Wobei ich
attr di_test myfuncs MYconvert ($)
{
...}
besser fände.
Ich wollte da nicht zu viel Arbeit investieren, es soll weiterhin in erster Linie ein Modul für nicht Perl-Programmierer sein. Mit einem einfachen eval hat man alle Möglichkeiten offen sich in Perl auszutoben. Was z. B. jetzt schon geht ist:
define di_test DOIF (di_test::convert([sens:temperature]) > 30)(set bla on)
##my perl definitions
package di_test;
sub convert ($)
{
my ($param) = @_;
my $result;
...
return($result);
}
Damit ist die Funktion gekapselt und stört keinen anderen.
Also könnte man ein funktionsloses Perl-Funktionen Sammel-DOIF definieren
define my DOIF ##
##my perl definitions
package my;
sub sub1 ($){...}
sub sub2 ($){...}
sub sub3 ($){...}
...
und in jedem DOIF verwenden mit
my::sub2([device:reading])
?
Zitat von: Ellert am 12 März 2017, 17:23:19
Also könnte man ein funktionsloses Perl-Funktionen Sammel-DOIF definieren
define my DOIF ##
##my perl definitions
package my;
sub sub1 ($){...}
sub sub2 ($){...}
sub sub3 ($){...}
...
und in jedem DOIF verwenden mit
my::sub2([device:reading])
?
ja, all das funktioniert schon mit einem simplen eval. In diesem Teil möchte ich bewusst keinen Einfluss von außen nehmen, deswegen ist es reines Perl mit allem, was dazu gehört.
Ich sehe gerade, dass er zuvor die Bedingung vermisst, das kann ich ihm aber abgewöhnen.
Zitat von: Damian am 12 März 2017, 17:32:59
Ich sehe gerade, dass er zuvor die Bedingung vermisst, das kann ich ihm aber abgewöhnen.
Allerdings kann man so eine Definition genauso in myUtils vornehmen, daher wäre das nichts besonderes.
Besser gefallen hätte mir eine pro DOIF-Instanz gekapselte Definition, bei der man die Funktion im jeweiligen DOIF ohne package-Angabe in der Bedingung nutzen könnte. Was mir aber noch fehlt, ist in dem package der jeweiligen Instanz der Zugriff auf alle restlichen definierten Funktionen in FHEM.