'Условное ветвление - "GoTo" Kluge ? - страница 4

 

Java также не работает вне своей виртуальной машины, там у вас будут те же проблемы, вы не сможете сделать dll, которая может быть загружена и вызвана из программы на C.

Если вам нравится C#, то вам также понравится ObjectPascal (безопасность типов, строгость, вся философия, лежащая в его основе, за исключением VM). В конце концов, разработчик и главный архитектор C# - тот же человек, который когда-то создал Turbo-Pascal и Delphi (ObjectPascal), и это просвечивает. В некоторых отношениях C# похож на ObjectPascal с (уродливым, но сегодня модным) синтаксисом C.

Для взаимодействия непосредственно с машиной и с C-API (как это необходимо для MetaTrader) и при этом с использованием такого мощного языка, как C#, альтернатив ObjectPascal не так много. Некоторые говорят, что C++ не менее мощный язык (и, конечно, может использоваться вместо OP), но он явно не так элегантен, имеет много несоответствий и настолько склонен к ошибкам, что только настоящие эксперты могут по-настоящему овладеть им.

 
7bit:

.... возврат внутри функции заставит ее вернуться в то место, откуда была вызвана функция.

Это решающее различие, 7bit: Я говорю о вызове совершенно другой функции, подпрограммы или даже импортированного кода, целых подпрограмм и/или функций ВНЕ всей текущей функции. Концептуальный пример:

Я нахожусь в функции, которая выполняется со строки 100 по строку 20, но я хочу вызвать что-то, что находится за пределами этой области. Возможно, совершенно другую функцию, которая находится в строках с 50 по 60. <=-Это не соответствует параметрам и примеру выше, о чем я и спрашиваю. Это 100% замена старого gosub/return и, кроме того, функция позволяет передавать значения и возвращать значения.

Вы можете иметь несколько операторов возврата в одной функции, а также вы можете выходить из циклов с помощью break .... .

Понятно

Но мне продолжают рассказывать о том, как я могу перемещаться в пределах области видимости конкретной функции, что я понимаю. Но это совсем не то, о чем я спрашиваю , и это было сказано в самом начале всего этого.

Что касается "исключений", то я думаю, вы можете называть их так, если хотите. Как я уже сказал, я пытаюсь найти "обходной путь" для добавления и использования функциональности таких функций, как: GoTo, GoSub (вне функции CURRENT) и т.д., которые не существуют как функции непосредственно в MQL4. Судя по вашим ответам, большинство из вас знают и понимают эти различия в программировании, но не отвечают на заданный вопрос.

 

FourX:

Я нахожусь в функции, которая выполняется со строки 100 по строку 20, но я хочу вызвать что-то, что находится за пределами этой области. Возможно, совершенно другую функцию, которая находится в строках с 50 по 60.
Создайте отдельную функцию, содержащую код из строк 50-60, тогда вы сможете вызвать ее из любой другой функции, в которой находитесь, в любое время.
 

подумайте об этом:

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();
}

Что теперь произойдет? Начнем с main(), я объясню все шаги во время выполнения (комментарии выделены зеленым цве том, инструкции - черным):

  • (мы находимся на первой строке в main())
  • занести адрес возврата в стек (нужно 4 байта), это адрес, по которому будет продолжаться работа после завершения вызова foo() (нам нужно запомнить это, чтобы потом знать, куда возвращаться)
  • перейти к первой строке foo()
  • занести 4 байта в стек, чтобы освободить место для локальной переменной x
  • занесите 4 байта в стек, чтобы освободить место для локальной переменной y
  • (наш стек теперь имеет высоту 12 байт)
  • записать длинное значение 33 в байты 0,1,2,3 (считая от вершины стека)
  • записать длинное значение 42 в байты 4,5,6,7 (считая от вершины стека)
  • выведите длинное значение, которое находится в байтах 4,5,6,7 (считая от вершины стека)
  • извлечь 4 байта из стека и забыть о них (y выходит из области видимости)
  • извлечь 4 байта из стека и забыть их (x выходит за пределы области видимости)
  • вытащите 4 байта из стека, теперь это адрес, с которого мы пришли при вызове foo(), адрес возврата, перейдите по этому адресу
  • (теперь мы вернулись в main() на следующую строку, ту, где есть bar())
  • заталкиваем адрес возврата (4 байта) в стек
    .
  • перейдите к первой строке bar()
  • заталкиваем 4 байта (локальная переменная x) в стек
  • (наш стек теперь имеет высоту 8 байт)
  • запишите длинное значение 5 в байты 0,1,2,3 (считая от вершины стека)
  • переходим к метке .LABELFOO
  • (Теперь внимательно проследите, как все идет ужасно неправильно. Мы уже знаем, что будут делать все следующие строки, потому что я объяснил это выше, они делают точно такие же вещи, как и раньше, они все ведут себя так, как будто в их распоряжении 12 верхних байт стека. Но в стеке на этот раз только 8 байт! Следующая строка ожидает переменную в позиции 4,5,6,7 от вершины стека, теперь посмотрим, что произойдет, вот строка с print)
  • вывести длинное значение, которое находится в байтах 4,5,6,7 (считая от вершины стека).
  • (упс? это не наш x, это возвращаемое значение, стек на этот раз имеет высоту всего 8 байт, он печатает совершенно бессмысленное число)
  • вытащить 4 байта из стека и забыть их (это было бы "y выходит за пределы области видимости", но это не y, а x из другой функции)
  • вытащить 4 байта из стека и забыть их (это было бы "x выходит из области видимости", но это не x, мы только что выбросили адрес возврата!)
  • (стек теперь пуст!)
  • вытащить 4 байта из стека, чтобы получить адрес возврата -> крах!

Вы видите это? Функции foo нужен локальный стек размером 8 байт плюс адрес возврата, а функции bar - только 4 байта плюс адрес возврата. Их операторы возврата уже встроены компилятором во время компиляции, они вынимают разное количество байт из стека, вы не можете использовать один возврат для выполнения работы другого, каждый работает только для той функции, для которой он был скомпилирован.

Эти старые языки, которые имели GOTO во всей программе, не имели локальной области видимости переменных, и единственное, что вы должны были сделать правильно, это подобрать одинаковое количество GOSUB и RETURN, все их возвраты только выводили адрес возврата и ничего больше, все возвраты вели себя одинаково. Но теперь у нас есть много разных по размеру "GOSUB" (каждый из которых заталкивает в стек разные суммы), а также много разных возвратов, которые забирают из стека разные суммы. И у нас есть локальные переменные в стеке. Это просто не может работать, независимо от того, какие безумные вещи вы пытаетесь встроить в компилятор.

Теоретически вы можете использовать GOTO внутри *одной и той же* функции (и некоторые языки позволяют это), но вы не можете показать мне ни одного куска кода, где это действительно привело бы к более элегантному, более легкому для понимания и более удобному в обслуживании коду, чем правильное структурированное программирование. Все, что это может сделать, это создать ужасный беспорядок. Это никому не нужно, поэтому это не реализовано.

 

Все мы уже знаем, что в MQL4 нет таких нативных функций, как GoTo ИЛИ 'GoSub -=> ReturnFromGoSub'. С этим не поспоришь. Теперь это превратилось в многократные объяснения и примеры того, что в MQL4 нет таких родных функций. Тут спора нет. Эта тема не об этом и никогда не была. Так что, пожалуйста, мы можем прекратить спорить о том, что мы уже знаем и с чем согласны?

Мы знаем, что эти функции работают в других языках программирования и могут быть очень полезны.

Весь смысл этой темы заключается в том, чтобы выяснить, можем ли мы смоделировать и использовать их с тем, что доступно в MQL4?

Например, допустимой функцией завершения второго случая в первом предложении'GoSub -=> ReturnFromGoSub ' будет: Вернуться в точку программы, в которой был вызван GoSub, и вернуть значения из GoSub в вызывающую точку программы.

 
FourX:

Например, правильным завершением функции во втором случае в первом предложении'GoSub -=> ReturnFromGoSub ' будет: Вернуться в точку программы, в которой был вызван GoSub, и вернуть значения из GoSub в вызывающую точку программы.


Вам неоднократно говорили, что то, что вы описываете, является пользовательской функцией... почему вы не можете принять это? Пожалуйста, приведите пример, с псевдокодом, почему пользовательская функция!= Gosub + Return
 

FourX:

'GoSub -=> ReturnFromGoSub ' будет означать: Вернуться в точку программы, в которой был вызван GoSub, и вернуть значения из GoSub в вызывающую точку программы.

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
Вот вам и GOSUB и RETURN, встроенные прямо в язык mql4, даже с передачей аргументов и возвращаемых значений, что было невозможно даже в Commodore-BASIC или любом другом древнем и убогом языке, с которым вы постоянно пытаетесь его сравнивать. Где вы были в течение последних 30 лет?
 

FourX, если вы изучаете mql4, пока ваш разум все еще находится в BBC Basic, думайте о defproc и proc и забудьте GoTo и GoSub.

У меня был BBC micro в начале 80-х ....ahhhh я до сих пор помню радость от попыток заставить программы загружаться с его кассетного накопителя :( мы писали программы на BBC Basic

 
SDC:

FourX, если вы изучаете mql4, пока ваш разум все еще находится в BBC Basic, думайте о defproc и proc и забудьте GoTo и GoSub.

У меня был BBC micro в начале 80-х ....ahhhh я до сих пор помню радость от попыток заставить программы загружаться с его кассетного накопителя :( мы писали программы на BBC Basic

LOL . . . У меня был Acorn Electron ... когда было жарко, он не читал материал с ленты, который я записал, когда было холодно, и наоборот ... вот это были времена. ;-)
 
RaptorUK:
LOL . . . У меня был Acorn Electron ... когда он был горячим, он не читал материал с ленты, который я записал, когда он был холодным, и наоборот ... вот это были дни. ;-)

Да, это были те времена :) крутил согнутой отверткой тот маленький винтик возле головки кассеты, одновременно повторяя удары по его боковой стороне хаха
Причина обращения: