Function innerhalb einer Function?
Übersicht

PhillipKBetreff: Function innerhalb einer Function? |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Heyho!
Ich habe schön öfters mal etwas gesehen, was ich nicht ganz nachvollziehen konnte. Hier mal Pseudocode: BlitzMax: [AUSKLAPPEN] Function Irgendwas:Int(Zahl1:Int, Zahl2:Int) Wieso macht man soetwas? Eine minifunktion innerhalb einer funktion deklarieren? Der logikhalber ist die Funktion 'Addiere' nur innerhalb von 'Irgendwas' aufrufbar. Aber wieso trägt man an dieser stelle nicht direkt den code ein? Ist das wie eine Art sprungmarke zu verstehen? Klar, jetzt wo ich weiß, das das möglich ist, kann es teilweise schon sinn ergeben. Aber manchmal sehe ich das ganze auch bei 'nur' einem aufruf. Hat das sonstige vorteile, die ich grade nicht erahne? Wie siehts mit den geschwindigkeiten aus? Geschieht im programm hinterher wirklich ein 'sprung' in die funktion oder ersetzt der compiler das durch die eigentliche funktion, die dahinter steht? Fragen über fragen ![]() Gruß, Phillipk ![]() |
||
![]() |
M0rgenstern |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hey.
Ich hab das jetzt mal ausgetestet weil ich mir nicht vorstellen konnte, dass der compiler das überhaupt mitmacht. Tut er aber. Führ mal meinen Code so wie er ist aus und dann sorg dafür, dass der Code, der momentan auskommentiert ist (3. letzte Zeile), auch mit ausgeführt wird. Dann siehst du den Sinn der Sache. BlitzMax: [AUSKLAPPEN] SuperStrict Der Sinn ist folgender: Der Scope der Funktion Addiere(a:int, b:int) liegt nur innerhalb der Funktion Me(). Damit kann man Funktionen kurzzeitib überschreiben. Beispiel: Du hast eine Funktion die dir irgendeine Zahl berechnet. Diese Funktion macht das aber normalerweise nur mit Integern und gibt diese auch nur zurück. Du brauchst diese Funktion ganz oft in deinem Programm, also ist sie nötig. Jetzt brauchst du diese Funktion in einer einzigen anderen Funktion aber mit genaueren Ergebnissen, also mit Floats. Anstatt eine neue Funktion extern anzulegen kannst du in dieser einen Funktion die andere Funktion überschreiben. Dann wird nur dort mit Floats gerechnet und überall sonst weiterhin mit Integern. Ich hoffe, ich habe mich einigermaßen verständlich ausgedrückt. Lg, M0rgenstern |
||
PhillipK |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Mhh. Kurzeitiges "überschreiben" - klingt auch nach etwas.
Spontan fällt mir in meiner jetzigen programmierlaufbahn zwar nichts ein, wo das von nöten gewesen wäre (nur das dauerhafte überschreiben von zb blitzmax internem Print *g*).. Nun frag ich mich allerdings, warum ich dann in dieser einen funktion, wo ich dieses eine mal etwas anderes brauche, dann trotzdem den selben namen wählen sollte? Wenn ich jetzt 50x pro schleifendurchlauf die funktion 'Addiere' brauche, welche nur 2 parameter braucht und einmal die funktion 'Addiere' brauche, welche 3 parameter schluckt.. (so als beispiel). Warum nenne ich dann Addiere mit 3 parametern nicht einfach Addiere3P ? Das einzige was ich mir jetzt ungetestet vorstellen kann: Ich habe 4 funktionen: Test1, Test2, Addiere und MacheEtwas() Test1 und Test2 rufen beide MacheEtwas() auf, worin addiere ausgeführt wird. allerdings hat Test2 Addiere() überladen -> Führt MacheEtwas() nun die "Globale" addiere-funktion aus, oder die Addiere funktion aus dem scope von Test2? Edit: Habs grade nachgebaut, nein, klappt nicht ^^ Nunja, über die sinnigkeit lässt sich streiten. Was mich persöhnlich noch interessiert ist, was der compiler an dieser stelle tut. Das ganze habe ich zwar schon öfters gesehen, aber gewundert hats mich zuerst in diesem Worklog Dort steht beschrieben, wie die Abfrage ob die maus innerhalb des Hexagons liegt, geschrieben wurde. Samt beispielcode. Darin sieht es wirklich so aus, das diese Funktion-in-funktions-deklarierung nur für kurzlebigen gebrauch gedacht ist. Nunja. Was macht der compiler? wenn er tatsächlich die selbe zeit benötigt, wie bei einem normalen funktionsaufruf, würde ich es vermeiden. Wenn er allerdings diese kurzlebige funktion direkt wie eine Const zb mit den werten etc ersetz (dh ohne sprung arbeitet), dann werde ich mir diesen stil wohl angewöhnen :> |
||
- Zuletzt bearbeitet von PhillipK am Di, Jul 26, 2011 11:24, insgesamt einmal bearbeitet
![]() |
FireballFlame |
![]() Antworten mit Zitat ![]() |
---|---|---|
M0rgenstern hat Folgendes geschrieben: Du hast eine Funktion die dir irgendeine Zahl berechnet. Diese Funktion macht das aber normalerweise nur mit Integern und gibt diese auch nur zurück. Du brauchst diese Funktion ganz oft in deinem Programm, also ist sie nötig. Jetzt brauchst du diese Funktion in einer einzigen anderen Funktion aber mit genaueren Ergebnissen, also mit Floats.
Anstatt eine neue Funktion extern anzulegen kannst du in dieser einen Funktion die andere Funktion überschreiben. Dann wird nur dort mit Floats gerechnet und überall sonst weiterhin mit Integern. Das halte ich für keine so gute Idee. Wenn die neue Funktion fast das gleiche macht wie die alte (sonst sollte man sie anders nennen), sollte man sie auch neben der alten deklarieren. Auch zwecks Wiederverwertbarkeit: wenn man die Int-Variante so oft braucht, kann man doch kaum wissen, dass man die Float-Variante nie wieder benötigt, oder? Ich würde eher sagen, man benutzt es für sehr spezifische Funktionen, die wirklich nur innerhalb der anderen Funktion Sinn ergeben (kommt selten vor). Selbst wenn man sie dann nur einmal aufruft, kann es zumindest den Code übersichtlicher machen. PhillipK hat Folgendes geschrieben: Test1 und Test2 rufen beide MacheEtwas() auf, worin addiere ausgeführt wird.
allerdings hat Test2 Addiere() überladen -> Führt MacheEtwas() nun die "Globale" addiere-funktion aus, oder die Addiere funktion aus dem scope von Test2? Die globale. Die 2. Addiere-Funktion gibt es ja schließlich nur in Test2, MacheEtwas kennt die nicht. |
||
PC: Intel Core i7 @ 4x2.93GHz | 6 GB RAM | Nvidia GeForce GT 440 | Desktop 2x1280x1024px | Windows 7 Professional 64bit
Laptop: Intel Core i7 @ 4x2.00GHz | 8 GB RAM | Nvidia GeForce GT 540M | Desktop 1366x768px | Windows 7 Home Premium 64bit |
- Zuletzt bearbeitet von FireballFlame am Di, Jul 26, 2011 15:39, insgesamt 2-mal bearbeitet
![]() |
M0rgenstern |
![]() Antworten mit Zitat ![]() |
---|---|---|
@FireballFlame,
Das war irgendwie das einzig logische das mir irgendwie dazu eingefallen ist. Ich wüsste nämlich kein wirkliches Anwendungsbeispiel bei dem man sowas bräuchte. Ich finde das irgendwie ziemlich unnötig ne Funktion in ner Funktion erstellen zu können. Lg, M0rgenstern |
||
![]() |
Midimaster |
![]() Antworten mit Zitat ![]() |
---|---|---|
Das ganze erinnert ein wenig an Public/Privat Deklarierungen von Funktionen in Klassen.
Hier kann ich Funktionen in einer Klasse so abschotten, dass Sie nur innerhalb der Klasse aufgerufen werden können. Das ist bei Klassen schon sehr hilfreich, weil man nach Jahren noch weiß, ob eine bestimmte Funktion Kontakt zur Außenwelt hat, oder beim Überarbeiten der Klasse nach Belieben verändert werden darf: Es gibt ja garantiert keine externe Code-Stelle, die sich auf die Existenz dieser Funktion in der alten Form verlässt. Hier sähe ich auch eine sinnvolle Anwendung für die "Funktion in Funktion" wie ihr sie heute entdeckt habt. |
||
![]() |
FireballFlame |
![]() Antworten mit Zitat ![]() |
---|---|---|
Da man sowas machen kann
BlitzMax: [AUSKLAPPEN] SuperStricthaben sie vielleicht ähnlichen Nutzen wie Lambda Expressions in anderen Sprachen. Von denen hab ich allerdings nicht viel Ahnung, kennt sich hier jemand damit aus? ![]() |
||
PC: Intel Core i7 @ 4x2.93GHz | 6 GB RAM | Nvidia GeForce GT 440 | Desktop 2x1280x1024px | Windows 7 Professional 64bit
Laptop: Intel Core i7 @ 4x2.00GHz | 8 GB RAM | Nvidia GeForce GT 540M | Desktop 1366x768px | Windows 7 Home Premium 64bit |
PhillipK |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
FireballFlame hat Folgendes geschrieben: Da man sowas machen kann
BlitzMax: [AUSKLAPPEN] SuperStricthaben sie vielleicht ähnlichen Nutzen wie Lambda Expressions in anderen Sprachen. Von denen hab ich allerdings nicht viel Ahnung, kennt sich hier jemand damit aus? ![]() Oh gott. Noch viel zu lernen ich hab, ich junger padawan^^ Kann mir jemand gleich noch ein beispiel nennen, wo es sinnvoll ist, einen funktionspointer an eine funktion zu übergeben? (zumal ich nichtmal wusste, das das geht! war schon ganz überrascht, als ich rausfand, das man funktionspointer als field in einem Type ablegen und ausführen kann^^ was enorm if's sparen kann ![]() |
||
![]() |
ZEVSBetreff: Lambda Funktionen |
![]() Antworten mit Zitat ![]() |
---|---|---|
Lambda-Funktionen kenne ich aus JavaScript, wo die eher inflationär verwendet werden. Ein Anwendungsgebiet wären z.B. sog. Event-Listener:
BlitzMax: [AUSKLAPPEN] Type vehicle Ich hoffe mal, das stimmt so (habe keine Ahnung von bMax) |
||
![]() |
FireballFlame |
![]() Antworten mit Zitat ![]() |
---|---|---|
Das Event-System der GUI-Lib wxMax funktioniert z.B. so. Du übergibst das Event, und die Funktion, die es auslösen soll an eine Connect-Funktion, und den Rest erledigt die Lib.
Beispiel: Beim Schließen des Programmfensters soll eine Sicherheitsabfrage kommen: BlitzMax: [AUSKLAPPEN] Function OnClose(Event:wxEvent) Oder stell dir vor, du hast eine Funktion, die z.B. irgendwo ein Array sortieren muss, aber der Sortieralgorithmus soll je nach Anwendungsfall austauschbar sein. Dann kannst du die Sortierfunktion einfach als Parameter übergeben. |
||
PC: Intel Core i7 @ 4x2.93GHz | 6 GB RAM | Nvidia GeForce GT 440 | Desktop 2x1280x1024px | Windows 7 Professional 64bit
Laptop: Intel Core i7 @ 4x2.00GHz | 8 GB RAM | Nvidia GeForce GT 540M | Desktop 1366x768px | Windows 7 Home Premium 64bit |
- Zuletzt bearbeitet von FireballFlame am Di, Jul 26, 2011 12:47, insgesamt 2-mal bearbeitet
![]() |
M0rgenstern |
![]() Antworten mit Zitat ![]() |
---|---|---|
@ ZEVS:
Das ganze sieht genial aus. Aber irgendwie werde ich das Gefühl nicht los, dass das irgendwie doppelts gemoppelt ist. Über die gleiche Funktion nochmal 2 andere Funktionen aufrufen obwohl eine völlig ausreichen würde. Vielleicht ist dein Beispiel auch einfach nur... unpassend. Denn bei dem was du da schreibst sehe ich allerhöchstens mehr Schreibarbeit obwohl man mit weniger den gleichen Effekt erzielen würde. Gibts da vielleicht ein Beispiel, das das besser verdeutlichen würde? Lg, m0rgenstern |
||
![]() |
FireballFlame |
![]() Antworten mit Zitat ![]() |
---|---|---|
M0rgenstern: Hab noch ein simples Beispiel oben reineditiert.
Das Beispiel von ZEVS sieht nur deshalb doppelt gemoppelt aus, weil alles direkt untereinander steht und man den alertDriver-Aufruf ja auch direkt in die Repeat-Schleife einfügen könnte. Wenn aber nun die Schleife schon in einem Modul steht (so wie bei wxMax) geht das nicht, und deshalb übergibt man die selbstgeschriebene alert-Funktion dann als Parameter. |
||
PC: Intel Core i7 @ 4x2.93GHz | 6 GB RAM | Nvidia GeForce GT 440 | Desktop 2x1280x1024px | Windows 7 Professional 64bit
Laptop: Intel Core i7 @ 4x2.00GHz | 8 GB RAM | Nvidia GeForce GT 540M | Desktop 1366x768px | Windows 7 Home Premium 64bit |
- Zuletzt bearbeitet von FireballFlame am Di, Jul 26, 2011 12:55, insgesamt 5-mal bearbeitet
![]() |
ZEVSBetreff: größere Event-Struktur |
![]() Antworten mit Zitat ![]() |
---|---|---|
Mit der Vergrößerung der Event-Struktur könnte das Beispiel etwas mehr Sinn ergeben, auch wenn FireballFlame wohl wesentlich bessere hat:
BlitzMax: [AUSKLAPPEN] Type vehicle Wieder keine Garantie. |
||
PhillipK |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Ich fasse mal zusammen, was ich gelernt habe (ich denke meine frage ist beantwortet^^)
Function innerhalb einer Function kann verschiedene möglichkeiten bringen, der sinn dahinter ist fraglich. Die idee, das ganze wie eine Private funktion anzusehen scheint dabei am sinnigsten, da diese funktion auch nur dort verfügbar ist. Ein beispiel hierfür könnten verschiedene GameLoops sein, mehrere funktionen (TitleScreen(), Credits(), Game()) welche eventuell identische Funktionsnamen besitzen, welche aber alle was anderes bewirken. Beispiel wäre eine Quit() funktion. TitleScreen: Quit beendet das programm ohne nachzufragen, da dies sicher so gewünscht ist. Credits: Das programm warnt davor, das der bisherige spielstand noch nicht gespeichert ist (es hätte nur via AppTerminatate ausgelöst werden können) Game: Quit fragt nach, ob man direkt beenden möchte oder ob man zurück zum TitleScreen möchte. Und funktionspointer als parameter zu übergeben findet seinen sinn zb in EventListener oder in einem Mod (die Netzwerklib die eine gewisse initialisierungsfunktion aufrufen kann, sobald man 'verbunden' ist, kann nichts von meiner Spezifischen initialisierungsfunktion wissen. Diese übergebe ich dann als parameter zum Connect() dazu. ((Wobei das auch wieder ein event wäre, nicht war? OnConnect -> Init() )) ) Alles richtig zusammengefasst? :3 |
||
![]() |
ZEVS |
![]() Antworten mit Zitat ![]() |
---|---|---|
Jawoll!
Dein Beispiel ist korrekt, die Quit()-Funktion macht die Fraglichkeit des Sinns gleichbenannter Funktionen sehr gut deutlich. |
||
![]() |
XeresModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Wenn sich Code wiederholt, schreibt man eine Funktion. Das kann auch in Funktionen selbst der Fall sein, da hilft es der Übersicht (und beim Debuggen!) ungemein, wenn man nochmal eine Sub-Funktion benutzt. Sucht oder berechnet man einen bestimmten Wert, kann man mit Return sofort zurück in die Hauptfunktion springen, ohne komplizierte Konstruktionen zu bauen, die die Rechnung abbrechen.
Klar kann man mehr Geschwindigkeit herausholen, wenn man später alle Funktionsaufrufe durch ihren Code ersetzt (wie Inline-Funktionen in anderen Sprachen) aber mindestens in der Entwicklung benutze ich sie öfters. Funktionspointer sind auch super praktisch, wenn man ich auch nicht ständig damit arbeite: Der eingebauten OnEnd() Funktion z.B. gebe ich immer die "Speicher die Optionen/Daten" Funktion(en) an, und muss mir keine weiteren Gedanken drum machen. Behaltet die Möglichkeiten im Hinterkopf ![]() |
||
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus THERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld) |
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group