ByRef auf Variablen/Arrays ohne Funktion?

  • Hallo,

    ich suche nach einer Möglichkeit, Variablen/Arrays zu referenzieren (wie in PHP mittels &=). Sozusagen in jedem Scriptteil, wie es auch bei einem Funktionsaufrunf möglich ist (aber eben ohne Funktionsaufruf).

    Geht das in Autoit? Ich habe die Hilfe durchkämmt und auch Google konnte mir nur einen (unbeantworteten) Post im Autoit.com zeigen.

    Danke
    jwka

  • Nein, keine globale Variable, sondern eine Referenz halt. Das ist im Prinzip ein Verweis auf einen tatsächlich bestehenden Speicherbereich (allerdings kein Pointer sondern, wenn man so will, ein Datentopf mit mehreren Namen).

    Die Referenz ermöglicht es, Dinge besser zu kapseln (und z.B. auch über Namespaces hinweg gemeinsame Datenbereiche zu nutzen). Weiters können so z.B. Teile von Arrays "überlappen" ohne, dass man die Daten doppelt hält und jeweils doppelt schreiben muss.

    Wenn man z.B. die Debugging Sachen der AutoIt UDFs ansieht, dann stellt man fest, dass wegen (scheinbar) fehlender Referenzen (und um die Parameterliste für einen Aufruf nicht noch länger zu machen) Globale Variablen definiert werden, damit Funktionen Werte in den entsprechenden (globalen) Variablen ändern können.

    Das wäre mit einer Referenz leichter zu machen: Der Nutzer könnte eigene Variablen anlegen und die Namen "übergeben", während die Funktionen dann eine Referenz bilden und intern mit eigenen Bezeichnern weiter machen.

    Das ginge dann auch z.B. Abschnittsweise für Code-Bestandteile, die man - aus welchen Gründen auch immer - nicht in eine Funktion schieben will.

    Man kann mit Referenzen auch sehr schön Array-Inhalte "Mappen", indem man die Referenz entsprechend verschiebt. Bei Globalen Variablen muss man dazu dann umspeichern, ggf. mehrfach.

    jwka

  • Danke für die Info. Ich habe das fast befürchtet, wollte aber sicher gehen, dass ich nicht in ein paar Monaten sagen muss "mist, hätte ich mal nachgefragt".

    Ich nutze die ByRef Sachen gerade in PHP sehr exzessiv. Schade, dass Autoit da nicht kann.

    Bei der Gelegenheit eine Frage an die Pro's:

    Sind "Assoziative Arrays" (Arrays mit "Strings" als Indices)in der Diskussion?

    Danke & Grüße
    jwka

  • Assoziative Arrays lassen sich in AutoIt sehr gut über das Scripting.Dictionary-COM-Objekt nutzen:

    Beispiel zur Verwendung des Scripting.Dictionary-Objektes
    [autoit]

    ;//// Dictionary Erstellen ///////////
    $oDict = ObjCreate("Scripting.Dictionary")

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;//// Einträge hinzufügen ///////////
    $oDict.add ("Berlin", 3395189)
    $oDict.add ("Hamburg", 1743627)
    $oDict.add ("München", 1259677)
    ; alternativ: (bringt keinen Fehler wenn Schlüssel schon existiert)
    $oDict("Köln") = 983347
    $oDict("Dresden") = 517052
    ;Beispiel hier: Einwohnerzahl wird der jeweiligen Stadt zugeordnet.

    [/autoit] [autoit][/autoit] [autoit]

    ;//// Anzahl der Elemente bestimmen ///////////
    MsgBox(0,"Anzahl Elemente in Dictionary", $oDict.Count)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;//// Überprüft ob ein Element vorhanden ist ///////////
    If $oDict.Exists ("Bonn") Then MsgBox(0, "", "Bonn ist eingetragen") ;Bonn ist im Bsp. nicht enthalten

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;//// Löscht ein Element aus dem Dictionary ///////////
    $oDict.remove ("München")

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;//// Elemente aufrufen ///////////
    ConsoleWrite("Einwohner(Berlin): " & $oDict("Berlin") & @CRLF)
    ConsoleWrite("Einwohner(Dresden): " & $oDict("Dresden") & @CRLF & @CRLF)

    [/autoit] [autoit][/autoit] [autoit]

    ;//// alle Schlüssel durchgehen ///////////
    For $k in $oDict.Keys
    ConsoleWrite("Einwohner(" & $k & "): " & $oDict($k) & @CRLF)
    Next
    ;/// Alle Werte statt Schlüssel erreicht man mit $oDict.Items ////

    [/autoit] [autoit][/autoit] [autoit]

    ;//// Leert das Dictionary ///////////
    $oDict.RemoveAll

    [/autoit]


    [...] wegen fehlender Referenzen [...] Globale Variablen definiert werden, damit Funktionen Werte in den entsprechenden (globalen) Variablen ändern können.
    Das wäre mit einer Referenz leichter zu machen: Der Nutzer könnte eigene Variablen anlegen und die Namen "übergeben", während die Funktionen dann eine Referenz bilden und intern mit eigenen Bezeichnern weiter machen.

    Sicherlich verstehe ich noch nicht ganz was du wirklich meinst aber exakt das was du eben beschrieben hast macht doch das Schlüsselwort ByRef für Parameter von Funktionen.
    Ich habe noch nichts mit PHP gemacht.
    Vielleicht könntest du ein kleines Minimalbeispiel posten damit ich vielleicht eher sehe wie dies gemeint ist?

    Einmal editiert, zuletzt von AspirinJunkie (8. November 2011 um 11:16)

  • i2c: Danke, sehr wertvoller Hinweis. Werde mir das genauer ansehen.

    @Aspirin: zu Referenzen:
    Du hast zwei Variable, die den Inhalt "teilen". Änderst Du die eine, so ändert sich auch die andere. das ganze dann noch in der Möglichkeit, Referenzen auszutauschen gibt tolle Ergebnisse.

    Beispiel: Du hast Eine Anwendung, in der Du gerne bestimmte Daten mehrfach verwenden möchtest, aber, z.B. eben wegen sonst unhandlichen Parameterstrukturen gerne "konsolidieren willst.

    Nehmen wir mal an, Du hast ein zentrales LOG, das als Array $Log geführt wird. Deine Funktion, die in das Log schreiben soll, hat ein anderer Gebaut und der "verlängert" je Logeintrag das Array $Debug.

    Du schreibt nun einfach $Debug &= $LOG

    Damit schreibt die Funktion automatisch in Dein Array $Log.

    Oder Du möchtest "Untermengen" bilden:

    $Fulldata['Subdata'] &= $A

    Alles, was Du in $A machst, landet (auch) im Array $Fulldata, aber im Array-Element "Subdata".

    Ich nutze sowas z.B. um ALLE benutzten Variablen (oder ein Teilset davon) via Array in eine andere Scriptinstanz zu schaufeln, ohne irgend eine Iteration zu brauchen.Dazu stelle ich schlicht eine Referenz von Array zu Variablen / Arrays her und gut ist. Und da ich fast nur mit Arrays arbeite, ist der Aufwand sogar noch geringer, weil ich i.d.R. mit 5-6 Referenzen zu recht komme.

    jwka

    • Offizieller Beitrag

    Sind "Assoziative Arrays" (Arrays mit "Strings" als Indices)in der Diskussion?


    Ob die Dev's in dieser Richtung überlegen, weiß ich nicht.
    Da viele unserer Forennuntzer am Anfang mit Arrays wenig am Hut haben, hatte ich mal eine Kombination aus Array und Struktur erstellt, die es ermöglicht über den String auf die Daten zuzugreifen. Das ist aber für größere Datenmengen etwas zeitlastig, da das Lesen/Schreiben in Strukturen doch länger dauert als bei einem direkten Arrayzugriff. Andererseits lassen sich hiermit (im Gegensatz zu den anderen existierenden Modellen) einem Schlüssel mehrere Werte zuordnen, also die Abbildung eines 2D-Arrays mit mehreren Spalten.

  • Nehmen wir mal an, Du hast ein zentrales LOG, das als Array $Log geführt wird. Deine Funktion, die in das Log schreiben soll, hat ein anderer Gebaut und der "verlängert" je Logeintrag das Array $Debug.
    Du schreibt nun einfach $Debug &= $LOG
    Damit schreibt die Funktion automatisch in Dein Array $Log.

    Ich bin sicherlich etwas verwirrt weil du als Beispiele immer das Beispiel des Call-By-Reference Verhaltens von Funktionsparametern anbringst.
    Dies ist, wie schon geschrieben, aber ja durchaus mit dem Schlüsselwort ByRef für Funktionsparameter auch mit AutoIt machbar.

    Ich kann mir momentan nur halt nicht so richtig vorstellen was dies außerhalb von Funktionen bringen soll.
    Um ein Referenz auf eine Variable zu erstellen hat der Kontext in dem das geschieht ja schon Vollzugriff auf die zu referenzierende Variable.
    Also kann sie ja auch gleich direkt benutzt werden.
    Da die einzige wirkliche Kapselung in AutoIt die Funktionen sind macht für mich auch nur in diesem Kontext ein ByRef Sinn.
    Dies ist der Punkt den ich noch nicht so richtig verstehe.
    Abgesehen von deinem schönen Beispiel mit der Referenzierung auf eine Untermenge eines Arrays.
    Den Punkt mit den mehreren Skriptinstanzen habe ich auch nicht so recht verstanden.
    Startest du im Skript mehrere Threads (ist in AutoIt nicht möglich) oder startest du das Skript mehrfach was zu prozessübergreifenden Datenaustausch führen würde?