'Diramazione condizionale - 'GoTo' Kluge ? - pagina 4

 

Anche Java non funziona al di fuori della sua macchina virtuale, lì avrete gli stessi problemi, non potete fare una dll che può essere caricata e chiamata da un programma C.

Se ti piace C# allora ti piacerà anche ObjectPascal (la sicurezza dei tipi, la severità, l'intera filosofia che c'è dietro, eccetto la cosa della VM). Dopo tutto il progettista e capo architetto di C# è la stessa persona che ha creato Turbo-Pascal e Delphi (ObjectPascal) e questo traspare. Per certi aspetti C# è come l'ObjectPascal con una sintassi C (brutta ma oggi alla moda).

Per interfacciarsi direttamente con la macchina e con C-APIs (come è necessario per MetaTrader) e usare ancora un linguaggio potente come C# non ci sono molte alternative a ObjectPascal. Alcuni dicono che il C++ è altrettanto potente (e può ovviamente essere usato anche al posto dell'OP) ma chiaramente non è così elegante, ha molte incongruenze ed è così incline all'errore che solo i veri esperti possono veramente padroneggiarlo.

 
7bit:

.... il ritorno all'interno di una funzione la farà tornare nel luogo da cui la funzione è stata chiamata.

Questa è la distinzione cruciale 7bit: Sto parlando di invocare una funzione completamente diversa, una subroutine o anche codice importato, intere subroutine e/o funzioni FUORI dall'intera funzione corrente. Un esempio concettuale:

Sono in una funzione che si svolge dalla linea 100 alla linea 20, ma voglio invocare qualcosa che cade fuori da questo ambito. Forse una funzione completamente diversa che si trova nelle righe da 50 a 60. <=-Questo non si adatta ai parametri e all'esempio di cui sopra, che è ciò di cui sto chiedendo È un sostituto al 100% del vecchio gosub/return e inoltre la funzione permette di passare valori e restituire valori.

Si possono avere più dichiarazioni di ritorno all'interno della stessa funzione e si può anche uscire dai cicli con break ....

Capito

Ma continuo a sentirmi dire come posso muovermi all'interno dell'ambito di una specifica funzione, cosa che capisco. Ma questo NON è affatto quello che sto chiedendo e che ho dichiarato all'inizio di tutto questo.

Per quanto riguarda le 'eccezioni', immagino che possiate chiamarle così se volete. Come ho detto, sto cercando di trovare un 'work around' per aggiungere e utilizzare la funzionalità di funzioni come: GoTo, GoSub (al di fuori della funzione CURRENT) ecc. che non esiste come funzione direttamente in MQL4. Dalle vostre risposte, la maggior parte di voi conosce e comprende queste distinzioni di programmazione, ma non sta affrontando la vera domanda posta.

 

FourX:

Sono in una funzione che si svolge dalla linea 100 alla linea 20, ma voglio invocare qualcosa che cade fuori da questo ambito. Forse una funzione completamente diversa che si trova nelle linee 50 - 60.
Create una funzione separata che contenga il codice dalle linee 50 - 60, poi potrete invocarla da qualsiasi altra funzione in cui vi troviate in qualsiasi momento.
 

considera questo:

void foo(){
  int x;
  int y;
  y = 33;
  x = 42;
  .LABELFOO
  print(x);
  return;
}

void bar(){
  int x;
  z = 5;
  GOTO .LABELFOO
}

void main(){ //<-- program starts here
  foo();
  bar();
}

Ora cosa succederà? Cominciamo con main(), spiegherò tutti i passi durante l'esecuzione (i commenti sono in verde, le istruzioni sono in nero):

  • (siamo alla prima riga di main())
  • spingiamo l'indirizzo di ritorno sullo stack (ha bisogno di 4 byte), questo è l'indirizzo dove continuerà una volta che la chiamata a pippo() sarà finita (abbiamo bisogno di ricordare questo in modo che sapremo in seguito dove tornare)
  • saltare alla prima riga di pippo()
  • spingere 4 byte sullo stack per fare spazio alla variabile locale x
  • spingere 4 byte sullo stack per fare spazio alla variabile locale y
  • (il nostro stack è ora alto 12 byte)
  • scrivere il valore lungo 33 nei byte 0,1,2,3 (contati dalla cima dello stack)
  • scrivere il valore lungo 42 nei byte 4,5,6,7 (contati dalla cima dello stack)
  • stampare il valore lungo che si trova nei byte 4,5,6,7 (contati dalla cima dello stack)
  • pop 4 byte dalla pila e dimenticarli (y esce dallo scope)
  • pop 4 byte dalla pila e dimenticarli (x esce dallo scopo)
  • pop 4 byte dallo stack, questo è ora l'indirizzo da cui siamo venuti quando abbiamo chiamato foo(), l'indirizzo di ritorno, saltate a questo indirizzo
  • (ora siamo di nuovo in main() alla linea successiva, quella con bar())
  • spingiamo l'indirizzo di ritorno (4 byte) sullo stack
  • saltare alla prima riga di bar()
  • spingiamo 4 byte (variabile locale x) sullo stack
  • (il nostro stack è ora alto 8 byte)
  • scrivere il valore lungo 5 nei byte 0,1,2,3 (contati dalla cima dello stack)
  • saltare all'etichetta .LABELFOO
  • (ora osservate attentamente come tutto va terribilmente male da qui in poi. Sappiamo già cosa faranno tutte le linee seguenti perché l'ho spiegato sopra, fanno esattamente le stesse cose di prima, si comportano tutte come se avessero a disposizione i primi 12 byte dello stack. Ma lo stack ha solo 8 byte questa volta! La prossima linea si aspetta una variabile nella posizione 4,5,6,7 dalla cima dello stack, ora vediamo cosa succede, ecco la linea con il print)
  • stampa il valore lungo che si trova nei byte 4,5,6,7 (contati dalla cima dello stack)
  • (ops? questo non è il nostro x, questo è il valore di ritorno, lo stack è alto solo 8 byte questa volta, sta stampando un numero totalmente senza senso)
  • pop 4 byte dallo stack e dimenticarli (questo sarebbe "y esce dallo scope" ma non è y, è in realtà la x dell'altra funzione)
  • togliete 4 byte dallo stack e dimenticateli (questo sarebbe "x esce dallo scope" ma non è x, abbiamo appena buttato via l'indirizzo di ritorno!)
  • (lo stack è vuoto ora!)
  • pop 4 byte dallo stack per ottenere l'indirizzo di ritorno -> crash!

La funzione pippo ha bisogno di uno stack frame locale di 8 byte più l'indirizzo di ritorno e la funzione bar di soli 4 byte più l'indirizzo di ritorno. Le loro dichiarazioni di ritorno hanno già questo incorporato dal compilatore in fase di compilazione, essi pop quantità diverse di byte dallo stack, non è possibile utilizzare un ritorno per fare il lavoro dell'altro, ognuno funziona solo per la funzione per cui è stato compilato.

Questi vecchi linguaggi che avevano GOTO in tutto il programma non avevano scope di variabili locali e l'unica cosa che dovevi fare bene era far coincidere il numero di GOSUB e RETURN per essere uguali, tutti i loro ritorni facevano solo il pop dell'indirizzo di ritorno e nient'altro, tutti i ritorni si comportavano esattamente allo stesso modo. Ma ora abbiamo un sacco di "GOSUB" di dimensioni diverse (ognuno spinge quantità diverse sullo stack) e anche molti ritorni diversi che popano quantità diverse dallo stack. E abbiamo variabili locali sullo stack. Questo non può funzionare, non importa quali cose folli si cerchi di costruire nel compilatore.

Si potrebbe teoricamente fare il GOTO all'interno della *stessa* funzione (e alcuni linguaggi lo permettono) ma non potete mostrarmi un pezzo di codice in cui questo porterebbe effettivamente ad un codice più elegante, più facile da capire e più manutenibile di una corretta programmazione strutturata. Tutto ciò che farebbe è produrre un orribile casino. Nessuno ha bisogno di questo, quindi non è implementato.

 

Tutti sappiamo già che MQL4 non ha funzioni native come un GoTo o un 'GoSub -=> ReturnFromGoSub'. Non c'è dubbio su questo. Questo si è trasformato in ripetute spiegazioni ed esempi del fatto che MQL4 non ha tali funzioni native. Non c'è discussione. Questo non è il tema di questo thread e non lo è mai stato. Quindi possiamo per favore smettere di discutere su ciò che già sappiamo e su cui siamo d'accordo?

Sappiamo che queste sono funzioni valide in altri linguaggi di programmazione e possono essere molto utili.

Lo scopo di tutto questo è scoprire se possiamo simularle e utilizzarle con ciò che è disponibile in MQL4?

Per esempio, una valida funzione di completamento del secondo caso nella prima frase di'GoSub -=> ReturnFromGoSub ' sarebbe: Tornare al punto del programma in cui il GoSub è stato chiamato e restituire i valori dal GoSub al punto di chiamata nel programma.

 
FourX:

Per esempio, un valido completamento di funzione del secondo caso nella prima frase di'GoSub -=> ReturnFromGoSub ' sarebbe: Tornare al punto del programma in cui il GoSub è stato chiamato e restituire i valori dal GoSub al punto di chiamata nel programma.


Ti è stato detto più volte che quella che stai descrivendo è una funzione personalizzata... perché non riesci ad accettarlo? per favore fai un esempio, con pseudocodice, del perché una funzione personalizzata!= Gosub + Return
 

FourX:

'GoSub -=> ReturnFromGoSub ' sarebbe per: Tornare al punto del programma in cui il GoSub è stato chiamato e restituire i valori dal GoSub al punto chiamante nel programma.

double subtract_two_numbers(double a, double b){
  Print("will now calculate ", a, " minus ", b);
  return(a - b);                                 // <---- THIS IS YOUR RETURN
}

int start(){                                     // <---- PROGRAM STARTS HERE
  double s;
  double d;

  s = subtract_two_numbers(Ask, Bid);            // <---- THIS IS YOUR GOSUB
  d = subtract_two_numbers(Close[0], Open[0]);   // <---- THIS IS YOUR GOSUB

  Print("the spread is ", s);
  Print("price moved ", d, " since the open");
}                                                // <---- PROGRAM ENDS HERE
Ecco i vostri GOSUB e RETURN, integrati nel linguaggio mql4, anche con il passaggio di argomenti e valori di ritorno che non era possibile nemmeno nel Commodore-BASIC o in qualsiasi altro antico e storpio linguaggio con cui cercate costantemente di paragonarlo. Dove siete stati negli ultimi 30 anni?
 

FourX se stai imparando mql4 mentre la tua mente è ancora in BBC Basic pensa a defproc e proc e dimentica GoTo e GoSub.

Ho avuto un BBC micro nei primi anni '80 ....ahhhh mi ricordo ancora le gioie di cercare di far caricare i programmi dal suo lettore di cassette :( scrivevamo programmi in BBC Basic

 
SDC:

FourX se stai imparando mql4 mentre la tua mente è ancora in BBC Basic pensa a defproc e proc e dimentica GoTo e GoSub.

Ho avuto un BBC micro nei primi anni '80 ....ahhhh mi ricordo ancora le gioie di cercare di far caricare i programmi dal suo lettore di cassette :( scrivevamo programmi in BBC Basic

LOL . . . Avevo un Acorn Electron . . . quando era caldo non leggeva le cose dal nastro che avevo scritto quando era freddo e viceversa . . . quelli erano tempi. ;-)
 
RaptorUK:
LOL . . . Avevo un Acorn Electron . . . quando era caldo non leggeva le cose dal nastro che avevo scritto quando era freddo e viceversa . . . quelli erano giorni. ;-)

Sì, erano proprio quei giorni:) torcere un cacciavite piegato su quella piccola vite vicino alle testine del nastro mentre si sbatteva ripetutamente sul lato di essa haha