2017-05-04 4 views
1

Ich habe lua zu lernen und kann nicht scheinen, eine einfache Implementierung dieser binären Baum Arbeit zu machen ...lua nicht zu ändern Argumente Funktion

function createTree(tree, max) 
    if max > 0 then 
     tree = {data = max, left = {}, right = {}} 
     createTree(tree.left, max - 1) 
     createTree(tree.right, max - 1) 
    end 
end 

function printTree(tree) 
    if tree then 
     print(tree.data) 
     printTree(tree.left) 
     printTree(tree.right) 
    end 
end 

tree = {} 
createTree(tree, 3) 
printTree(tree) 

das Programm nur nil nach der Ausführung. Ich habe im Internet gesucht, um zu verstehen, wie Argumentübergabe in Lua funktioniert (wenn es durch Verweis oder nach Wert ist) und herausgefunden, dass einige Typen durch Verweis (wie Tabellen und Funktionen) übergeben werden, während andere nach Wert übergeben werden. Dennoch habe ich die globale Variable "tree" als Tabelle definiert, bevor ich sie an die "createTree" -Funktion übergeben habe, und ich habe sogar "left" und "right" für denselben Zweck als leere Tabellen innerhalb von "createTree" initialisiert. Was mache ich falsch?

Antwort

1

Es ist sicher zu denken, dass in den meisten Fällen lua Argumente nach Wert übergibt. Aber für jedes Objekt außer einer Zahl (Zahlen sind eigentlich keine Objekte) ist der "Wert" tatsächlich ein Zeiger auf das Objekt.

Wenn Sie etwas tun, wie a={1,2,3} oder b="asda" die Werte auf der rechten Seite sind irgendwo dynamisch zugewiesen und a und b nur Adressen von Personen erhalten. Wenn Sie also passieren wird a auf die Funktion fun(a), der Zeiger auf eine neue Variable in Funktion kopiert, aber die a selbst ist nicht betroffen:

function fun(p) 
    --p stores address of the same object, but `p` is not `a` 
    p[1]=3--by using the address you can 
    p[4]=1--alter the contents of the object 
    p[2]=nil--this will be seen outside 

    q={} 
    p={}--here you assign address of another object to the pointer 
    p=q--(here too) 
end 

Funktionen auch durch Zeiger auf ihnen dargestellt sind, können Sie debug Bibliothek verwenden um mit dem function object zu basteln (zB upvalues ​​ändern), kann dies Auswirkungen darauf haben, wie die Funktion ausgeführt wird, aber Sie können nicht mehr ändern, wohin externe Referenzen zeigen.

Zeichenketten sind unveränderliche Objekte, Sie können sie weitergeben, es gibt eine Bibliothek, die für sie zuständig ist, aber alle Funktionen in dieser Bibliothek geben eine neue Zeichenkette zurück. Also einmal, wieder externe Variable b von b="asda" wäre nicht betroffen, wenn Sie versuchten, etwas mit "asda" string innerhalb der Funktion zu tun.

+0

Ihre Antwort war sehr klar und ließ mich meinen Fehler verstehen. Im Grunde war mein Missverständnis, dass "Objekt" Variablen (wie Strings und Tabellen) von REFERENCE übergeben wurden, aber ich verstehe jetzt, dass sie durch Zeiger dargestellt und nach Wert übergeben werden. Dies macht es so, dass eine Funktion Daten ändern kann, auf die sie zeigen, aber nicht die Adresse der Zeiger selbst (wie bei der Übergabe von Zeigern nach Wert an C/C++ - Funktionen, wenn ich richtig verstanden habe). Die anderen Antworten brachten mich dieser Schlussfolgerung nahe, aber es war deine, die alle Zweifel vernichtete. Vielen Dank :) – Dincio

5

In Lua werden Argumente nach Wert übergeben. Die Zuweisung zu einem Argument ändert nicht die ursprüngliche Variable.

Try this:

function createTree(max) 
    if max == 0 then 
     return nil 
    else 
     return {data = max, left = createTree(max-1), right = createTree(max-1)} 
    end 
end 
+0

Ich gebe zu, dass dies nicht die Antwort war, die mich dazu brachte, meinen Fehler zu verstehen, aber es war immer noch hilfreich zu sehen, wie Sie diesen Baum erstellt haben. Ich hätte nie daran gedacht, es so zu machen; und es ist noch einfacher und eleganter als das, was ich mir ausgedacht habe, also trotzdem danke! Aber würde Ihre Version die Tail-Rekursion nicht nutzen? – Dincio

6

Es ist wahrscheinlich notwendig, nicht durch eine neue Tabelle zu initialisieren, sondern nur seine Werte zu setzen.

function createTree(tree, max) 
    if max > 0 then 
     tree.data = max 
     tree.left = {} 
     tree.right = {} 
     createTree(tree.left, max - 1) 
     createTree(tree.right, max - 1) 
    end 
end 
+0

Während diese Antwort mir nahe brachte, das Problem zu verstehen, war es nicht vollständig. Danke jedenfalls, die Informationen zur Verfügung stellend, um mein Problem zu umgehen :) – Dincio