2009-05-03 9 views
4

Ich bin sehr neu in SNL/NJ, und frage mich, wie ich folgendes erreichen könnte:Loops in SML/NJ

foo(stuff,counter) 
{ 
    while(counter > 0) 
    { 
    bar(stuff); 
    counter-1; 
    } 
    return; 
} 

So etwas, aber wie kann ich dekrementieren ?:

foo(stuff,counter) = 
    while counter > 0 do bar(stuff) ??? // how do I decrement counter here? 

Antwort

6

In einem funktionalen Programm wird eine veränderbare Variable zu einem Parameter, typischerweise zu einer verschachtelten Hilfsfunktion.

Da in Ihrem Beispiel die zu mutierende Sache bereits ein Parameter ist, wird keine Hilfsfunktion benötigt. Ihr Code wird

fun foo stuff counter = 
    if counter > 0 then 
    (bar stuff 
    ; foo stuff (counter-1) 
    ) 
    else 
    () 

Natürlich ist dieser Code noch ist schrecklich unbedingt ... Der Aufruf bar stuff ausgeführt ist lediglich für Nebeneffekt. Nicht sehr ML-ish.

+1

+1 für den Kommentar entsprechend; Einrückung! – diapir

+0

@diapir: Bah, ich würde -1 für diese Semikolon-Platzierung geben, wenn mir mehr daran liegt als über den Inhalt. – Svante

+0

@Svante: Nicht sicher, was durch meinen Kopf ging, würde ich es tatsächlich geben 0 Aufregung. – diapir

5

Kurze Antwort: Sie nicht. In der funktionalen Programmierung werden Variablen generell nicht verändert, was bedeutet, dass eine Schleife nicht möglich ist. Stattdessen können Sie dasselbe mithilfe der Rekursion implementieren. Da Sie im Allgemeinen keine Nebenwirkungen haben, sind Funktionsaufrufe nur dann sinnvoll, wenn sie Daten zurückgeben. Also Bar (Zeug) ist wahrscheinlich nicht sehr nützlich. Es hat keine Möglichkeit, den Rest der Anwendung zu beeinflussen. In einem funktionalen Programmierstil sollte Ihre bar() - Funktion jedes Mal auf anderen Daten aufgerufen werden und etwas zurückgeben, auf das der Rest der Anwendung zugreifen kann.

(ML hat Nebenwirkungen in bestimmten Fällen zulassen, aber die Dinge einfach zu halten, lassen wir das ignorieren vorerst)

Was genau wollen Sie erreichen? (Was müssen Sie durchlaufen, was machen die Funktionen?

Wenn Sie etwas mehr Details angeben, können wir genauer erklären, wie Sie das Programm schreiben sollten, aber so wie es ist, Ihr Programm einfach nicht Sinn macht, in einem funktionalen Stil.

6

ich mit den anderen Mitwirkenden einig, dass Sie in der Regel Rekursion anstelle von Schleifen und Mutation, dies zu tun in einer funktionalen Sprache verwenden sollen.

Wenn Sie wirklich verwenden Mutation wollten und Schleifen obwohl Sie müssten eine Datenstruktur namens Referenz verwenden, die eine Art "veränderbare Zelle" ist. Sie ordnen die Referenz mit der Funktion ref zu und übergeben ihr den ursprünglichen Inhalt den Inhalt mit dem Operator !. Und Sie setzen neue Inhalte mit dem Operator :=. Also wäre die wörtliche Übersetzung Ihres obigen Codes etwas wie das Folgende. Wie Sie sehen können, ist die Syntax wirklich hässlich und das ist ein weiterer Grund, warum Leute es vermeiden.

fun foo (stuff, counter_start) = 
let 
    val counter = ref counter_start 
in 
    while !counter > 0 do (
    bar stuff; 
    counter := !counter - 1 
) 
end; 
2

Ich weiß nicht, ML, aber das ist etwas ML-ähnlichen Pseudocode:

 
fun foo stuff 0 = return() 
    | foo stuff counter = (bar stuff; foo stuff (counter - 1)) 

Ich weiß nicht, wie zu "Kette" in ML-Befehle; Das Semikolon ist nur ein Platzhalter.

Im Allgemeinen würden Sie nicht Schleife. Ich würde eher die üblichen Funktionen höherer Ordnung erwarten. Wenn Sie sich daran gewöhnen, wird das manuelle Schreiben einer Schleife das Gefühl haben, Assembler zu programmieren.

edit: fester Code

+1

Das ist ziemlich richtig, außer dass Sie die verketteten Befehle in Klammern einschließen müssen, da das Semikolon einen niedrigeren Vorrang als die Funktionsdefinition hat. Ich glaube auch, dass die OP wollte, dass die Aktion 0 mal ausgeführt wird, wenn der Zähler 0 ist, also würden Sie im ersten Fall wahrscheinlich kein "Stangenkram" machen; und gib stattdessen einfach "()" (Einheit) zurück. – newacct

+1

Zu Ihrer Information, Sie müssen das Schlüsselwort return in ml nicht verwenden. Der Rückgabewert einer Funktion ist immer der letzte Ausdruck in der Funktion. – shleim