Sugestões para a sintaxe MQL

Alexey Navoykov  

Decidi criar tal tópico, porque de acordo com minhas observações, o desenvolvimento da sintaxe do MQL estagnou por muito tempo, não consigo ver nenhuma melhoria da linguagem nos últimos anos. Não sei se os desenvolvedores vão trabalhar no MQL, mas muitas das características estão muito ausentes, algumas das quais são criticamente necessárias.

Neste tópico decidi compilar uma lista dos meus principais pedidos. Primeiro vou dar minha lista, talvez alguém acrescente algo mais, e depois talvez os desenvolvedores se juntem e expressem seus pontos de vista, seria bom.

Esta lista eu coloco em ordem de importância (como eu a vejo), mas não em ordem de minhas prioridades pessoais. Isto é, colocar primeiro as coisas mais fundamentais e indispensáveis para a linguagem. Tomar a funcionalidade C++ e C# como referência


1. Trabalhando com tipos: typedef, decltype, auto

Esta é na verdade uma funcionalidade básica, pelo menos os dois primeiros especificadores. As operações de nomeação e de tipo hopping são criadas não só pela conveniência, mas também pela confiabilidade e flexibilidade do código. Se você definir um valor fixo em tipos concretos de variáveis utilizadas em diferentes lugares, você terá problemas quando precisar mudar qualquer um dos tipos.

Muitos de vocês aqui já estão familiarizados com o typedef, mas infelizmente ele ainda é um cepo que só funciona com indicadores de função. Quanto ao decltype, deixe-me esclarecer para aqueles que não estão familiarizados com ele: ele retorna o tipo de expressão passada a ele como argumento, permitindo flexibilidade para definir tipos de variáveis ou funções com base em outros tipos:

int a=100;
//...
decltype(a) b= a;

Seja usando typedef:

typedef int type;
type a= 100;
type b = a;
Ou, por exemplo, no caso de tipos longos e complexos (por exemplo, ClassA< ClassB< ClassC,ClassD< ClassE>>>) - aqui é uma dádiva de Deus para embrulhá-lo em typedef

Em C#, usa-se o uso em vez de datilografar.

A única coisa possível é a variante crocante da definição do tipo através da definição que está repleta de alguns problemas.


2. Namespaces: namespace

Este tópico já foi discutido recentemente. Para mim é realmente estranho porque ainda não foi implementado, porque é uma característica obrigatória da linguagem. Especialmente considerando a tendência para o desenvolvimento comunitário, codobase e de grupos. Neste caso, o problema da correspondência de nomes torna-se muito relevante.

Eles citaram um exemplo de que mesmo quando o nome de uma variável local dentro de alguma função é idêntico ao nome de um tipo definido em outro arquivo, o compilador irá gerar um erro. É um ultraje.

Em geral, é errado ter tudo em uma pilha em um só espaço.


Sem ela, os tiposdefinidos pelo usuário são inerentemente incompletos e a flexibilidade é grandemente reduzida.
Suponha que você tenha criado uma estrutura DATETIME que armazena a hora, e você quer poder usá-la como data/hora, passando-a para todas as funções que aceitam data/hora, assim como usá-la em expressões com data/hora.
Normalmente isto é feito de forma simples: sobrecarregue o construtor e a declaração de fundição com o tipo correspondente, e você obtém total compatibilidade de nossa estrutura com este tipo:

struct DATETIME
{
  DATETIME(datetime time) { ... }
  operator datetime() const { return ...; }
};

Mas na MQL, ao invés disso, é necessário criar um método separado para_datetime() e escrever sua chamada em todos os lugares. Ou a chamada da função alvo de DATETIME & tipo deve ser sobrecarregada, o que também não aumenta o conforto e a flexibilidade.


4. Múltiplas interfaces... Bem, já houve muitos rumores e conversas sobre isso (lembro-me que há três anos eles escreveram no serviço -desk que o trabalho está em andamento), mas está se arrastando... Se é que está acontecendo.



5. Osuporte de interfaces para estruturas é necessário para o trabalho unificado com o OOP. Atualmente, muitas vezes temos que fazer muletas.

Esta funcionalidade poderia ser implementada de duas maneiras: ou como em C# - via embalagem/desembalagem (boxe), ou de forma mais flexível - criando uma alavanca dinâmica para a estrutura ligada a um descritor de objeto dinâmico que contém a estrutura - seria mais eficiente, além de que você poderia criar indicadores para estruturas e outros tipos de dados, o que aumentaria a flexibilidade.


6. Possibilidade de passar as estruturas por valor, o que é importante ao passar as pequenas estruturas (DATETIME do exemplo acima), o que permitiria conversões flexíveis em vôo de um tipo para outro, se o construtor da estrutura suportar este tipo. Não há tal flexibilidade na transferência por referência, embora se forem implementadas interfaces para estruturas, ela se tornará menos relevante.


7. Possibilidade de especificar os parâmetros numéricos do modelo:

template<int N>
struct A
{
  char a[N];
};

A<100> a;
template<int N>
void f(int &arr[][N]) {  }

void start()
{
  int a[][5];
  f(a);
}

Quanto ao segundo exemplo, na MQL4 você pode passar sem ele, pois ali as funções aceitam matrizes de qualquer dimensão. E na MQL5, tudo é muito mais complicado com arrays multidimensionais.


8. Especialização de modelos (implementação separada para tipos específicos).

Exemplo de função:
struct A
{
  double _value;
 
  template<typename T>
   T      ToType() { return (T)round(_value); }  
  template<>
   double ToType() { return _value; }
  template<>
   float  ToType() { return (float)_value; }
  template<>
   string ToType() { return DoubleToString(_value, 2); }
};

void f(A& a) { Print(a.ToType<string>()); }

Exemplo com uma classe:
template<typename T>
struct CArrayBase    // Базовый класс массива
{
  T _data[];
  int Size()          { return ArraySize(_data); }
  T operator[](int i) { return _data[i]; }
};

template<typename T>
struct CArray : CArrayBase<T> { };  // Основной класс массива

template<>
struct CArray<double> : CArrayBase<double>  // Специализация класса для массива double
{
  double Sum() { double sum=0;  for (int i=0; i<Size(); i++) sum+=_data[i];  return sum; } 
}; 

template<typename T>
struct CArray<T*> : CArrayBase<T*>  // Специализация класса для массива указателей
{
  void DeleteObjects() { for (int i=0; i<Size(); i++) { delete _data[i]; _data[i]=NULL; } }    
};

void start()
{
  CArray<double> arr1;
  arr1.Sum();  

  class A { };
  
  CArray<A*> arr2;
  arr2.DeleteObjects();
}



E assim por diante, as pequenas coisas:


9. A possibilidade de fundir (explícita ou implícita) uma série de ponteiros para uma série de ponteiros de base. No antigo edifício isto funcionava, e era muito conveniente:

interface I { };
class A : I { };

void f(I* &Array[]) {  }

void Main(A* &array[]) { f(array); }

Agora temos que recopiar a matriz em uma nova, e depois novamente, desperdiçar esforços.

10. fundição de referência de objeto:(tipo&)objeto

Isto é necessário para poder passar um objeto referenciado a uma função. O exemplo seguinte exige que um objeto da classe B seja escrito em um arquivo como um objeto da classe base A, mas isto não pode ser feito agora, uma função intermediária deve ser criada ou o objeto deve ser copiado para um novo objeto.

struct A { int a; };

struct B : A { int b; };

B b;

void main()
{
  int h= FileOpen("MyFile",FILE_BIN|FILE_WRITE);
  FileWriteStruct(h, (A&)b);  // '&' - unexpected token
  FileClose(h); 
}


11. Inicializar arrays e estruturas não apenas com constantes, mas com quaisquer expressões. Isto reduz e simplifica significativamente o código em tais casos:

void f(int a, int b, int c, int d, int e, int f)
{
  int arr[]= { a, b, c, d, e, f };
 //......
}


12. Possibilidade de lançar explicitamente um ponteiro para um valor numérico.

Agora é possível obter um valor numérico somente através da conversão para uma forma textual, o que mata toda a idéia.

13. Definição dos parâmetros padrão do modelo

template<typename T>
struct DefaultConstructor { static T* New() { return new T; } };

template<typename T, typename TConstructor=DefaultConstructor<T>>
struct A
{
  T* data;
  A() { data= TConstructor::New(); }
 ~A() { delete data; }
};

class B { };

A<B> a;
Georgiy Merts  

Na minha opinião, muito poucas pessoas precisam de tudo isso.

A julgar pelo código em Kodobase - 95% dos usuários usam muito pouco OOP. E dos 5% restantes da maioria - todas estas características são pouco utilizadas. Certamente, elas são agradáveis e até podem ser úteis, mas não há grande necessidade em todas essas melhorias, na minha opinião.

Alexey Navoykov  
Georgiy Merts:

Na minha opinião, muito poucas pessoas precisam de tudo isso.

A julgar pelo código em Kodobase - 95% dos usuários usam muito mal o OOP. E dos 5% restantes, a maioria deles não usa muito estas características. É claro que são agradáveis e podem até mesmo ser úteis, mas em minha opinião não há grande necessidade em todas essas melhorias.

Sim, eu entendo, mas além do kodobase existem o Freelance e o Market, e a MQ deve estar interessada na qualidade dos produtos. E a qualidade da linguagem afeta a qualidade e a velocidade do desenvolvimento e da depuração de uma forma ou de outra.

Se falando em porcentagens como esta, então por que a MQL5 foi criada em primeiro lugar? Ainda estaríamos sentados na antiga MQL4 hardcore onde a OOP ou qualquer outra coisa não é necessária... 99% dos usuários estavam satisfeitos com isso )

Talvez os programadores normais não vão para a MQL precisamente porque ainda é uma linguagem incompleta.

Koldun Zloy  
Alexey Navoykov:

Decidi criar tal tópico, pois de acordo com minhas observações, o desenvolvimento da sintaxe MQL tem estado estagnado por muito tempo, sem melhorias na linguagem nos últimos anos. Não sei se os desenvolvedores vão trabalhar mais na MQL, mas faltam muitas características, algumas das quais são extremamente necessárias.

Neste tópico decidi compilar uma lista dos meus principais pedidos. Primeiro vou dar minha lista, talvez alguém acrescente algo mais, e depois talvez os desenvolvedores se juntem e compartilhem sua visão, seria bom.

Esta lista eu coloco em ordem de importância (como eu a vejo), mas não em ordem de minhas prioridades pessoais. Isto é, colocar primeiro as coisas mais fundamentais e indispensáveis para a linguagem. Tomar a funcionalidade C++ e C# como referência


1. Trabalhando com tipos: typedef, decltype, auto

Esta é na verdade uma funcionalidade básica, pelo menos os dois primeiros especificadores. As operações de nomeação e de tipo hopping são criadas não só pela conveniência, mas também pela confiabilidade e flexibilidade do código. Se você definir um valor fixo em tipos concretos de variáveis utilizadas em diferentes lugares, você terá problemas quando precisar mudar qualquer um dos tipos.

Muitos de vocês aqui já estão familiarizados com o typedef, mas infelizmente ele ainda é um cepo que só funciona com indicadores de função. Quanto ao decltype, deixe-me esclarecer para aqueles que não estão familiarizados com ele: ele retorna o tipo de expressão passada a ele como argumento, permitindo flexibilidade para definir tipos de variáveis ou funções com base em outros tipos:

Seja usando typedef:

Ou, por exemplo, no caso de tipos longos e complexos (por exemplo, ClassA< ClassB< ClassC,ClassD< ClassE>>>) - aqui é uma dádiva de Deus para embrulhá-lo em typedef

Em C#, usa-se o uso em vez de datilografar.

A única coisa possível é a variante crocante da definição do tipo através da definição que está repleta de alguns problemas.


2. Namespaces: namespace

Este tópico já foi discutido recentemente. Para mim é realmente estranho porque ainda não foi implementado, porque é uma característica obrigatória da linguagem. Especialmente considerando a tendência para o desenvolvimento comunitário, codobase e de grupos. Neste caso, o problema da correspondência de nomes torna-se muito relevante.

Eles citaram um exemplo de que mesmo quando o nome de uma variável local dentro de alguma função é idêntico ao nome de um tipo definido em outro arquivo, o compilador irá gerar um erro. É um ultraje.

Em geral, é errado ter tudo em uma pilha em um só espaço.


Sem ela, os tiposdefinidos pelo usuário são inerentemente incompletos e a flexibilidade é grandemente reduzida.
Suponha que você tenha criado uma estrutura DATETIME que armazena a hora, e você quer poder usá-la como data/hora, passando-a para todas as funções que aceitam data/hora, assim como usá-la em expressões com data/hora.
Normalmente isto é feito de forma simples: sobrecarregue o construtor e a declaração de fundição com o tipo correspondente, e você obtém total compatibilidade de nossa estrutura com este tipo:

Mas na MQL, ao invés disso, é necessário criar um método separado para_datetime() e escrever sua chamada em todos os lugares. Ou a chamada da função alvo de DATETIME & tipo deve ser sobrecarregada, o que também não aumenta o conforto e a flexibilidade.


4. Múltiplas interfaces... Bem, já houve muitos rumores e conversas sobre isso (lembro-me que há três anos eles escreveram no serviço -desk que o trabalho está em andamento), mas está se arrastando... Se é que está acontecendo.



5. Osuporte de interfaces para estruturas é necessário para o trabalho unificado com o OOP. Atualmente, muitas vezes temos que fazer muletas.

Esta funcionalidade poderia ser implementada de duas maneiras: ou como em C# - via embalagem/desembalagem (boxe), ou de forma mais flexível - criando uma alavanca dinâmica para a estrutura ligada a um descritor de objeto dinâmico que contém a estrutura - seria mais eficiente, além de que você poderia criar indicadores para estruturas e outros tipos de dados, o que aumentaria a flexibilidade.


6. Possibilidade de passar as estruturas por valor, o que é importante ao passar as pequenas estruturas (DATETIME do exemplo acima), o que permitiria conversões flexíveis em vôo de um tipo para outro, se o construtor da estrutura suportar este tipo. Ao transferir por referência, não há tal flexibilidade. Embora se forem implementadas interfaces para estruturas, ela se tornará menos relevante.


7. Possibilidade de especificar os parâmetros numéricos do modelo:

Quanto ao segundo exemplo, na MQL4 você pode passar sem ele, pois ali as funções aceitam matrizes de qualquer dimensão. E na MQL5, tudo é muito mais complicado com arrays multidimensionais.


8. Especialização de modelos (implementação separada para tipos específicos).

Exemplo de função:

Exemplo com uma classe:



E assim por diante, as pequenas coisas:


9. A possibilidade de fundir (explícita ou implícita) uma série de ponteiros para uma série de ponteiros de base. No antigo edifício isto funcionava, e era muito conveniente:

Agora temos que recopiar a matriz em uma nova, e depois novamente, desperdiçar esforços.

10. fundição de referência de objeto:(tipo&)objeto

Isto é necessário para poder passar um objeto referenciado a uma função. O exemplo seguinte exige que um objeto da classe B seja escrito em um arquivo como um objeto da classe base A, mas isto não pode ser feito agora, uma função intermediária deve ser criada ou o objeto deve ser copiado para um novo objeto.


11. Inicializar arrays e estruturas não apenas com constantes, mas com quaisquer expressões. Isto reduz e simplifica significativamente o código em tais casos:


12. Possibilidade de lançar explicitamente um ponteiro para um valor numérico.

Agora é possível obter um valor numérico somente através da conversão para uma forma textual, o que mata toda a idéia.

13. Definição dos parâmetros padrão do modelo

Eu apoio.

Koldun Zloy  
Georgiy Merts:

Na minha opinião, um número muito pequeno de pessoas precisa de tudo isso.

A julgar pelo código em Kodobase - 95% dos usuários usam muito pouco OOP. E dos 5% restantes, todos esses recursos são pouco utilizados. É claro que elas são boas e podem até ser úteis, mas não há grande necessidade de todas essas melhorias, na minha opinião.

Este pequeno número de pessoas pode escrever bibliotecas que todos utilizarão.

Koldun Zloy  

14. Permitir a passagem de um objeto temporário se o argumento da função for uma referência constante.

template< typename Type >
struct complex
{
   Type Re;
   Type Im;
   
   complex() : Re(), Im(){}
   complex( Type re, Type im ) : Re(re), Im(im){}
};

template< typename Type >
void Func( const Type& val )
{
}

void OnStart()
{
   Func( 5.0 );
   
   complex< double > C( 1.0, 5.0 );
   Func( C );
   
   Func( complex< double >( 2.0, 4.0 ) );
}

15. a palavra-chave "amigo".

Para algumas classes, querem dar acesso aos membros particulares, a uma classe particular, mas não a todos.

template< typename Type >
class Matrix;

template< typename Type >
class MatrixData
{
   friend class Matrix< Type >;
   
   int mRefCount;
   int mRows;
   int mColumns;
   
   Type mArray[];
   
public:
   MatrixData();
   MatrixData( int rows, int cols );
};

template< typename Type >
class matrix
{
   MatrixData< Type >* mData;
   
public:
        Matrix();
        Matrix( int rows, int cols );
};

16. anular uma variável ao chamar explicitamente o construtor para tipos embutidos

Isto vem a calhar nos modelos.

   double x;         // Не инициализирована
   double y();       // Инициализирована нулём
   double z = 5.0;   // Инициализирована 5.0
secret  
Eles nem sequer têm placas de sinalização) o que poderia ser mais fundamental)
Alexey Volchanskiy  
Alexey Navoykov:

Decidi criar tal tópico, porque, de acordo com minha observação, o desenvolvimento da sintaxe MQL estagnou por muito tempo, nenhuma melhoria na linguagem foi feita durante os últimos anos. Não sei se os desenvolvedores vão trabalhar em MQL, mas muitas características estão faltando, algumas delas são extremamente necessárias.

Neste tópico decidi compilar os principais desejos, primeiro vou dar minha lista, talvez alguém acrescente algo mais. E depois talvez os desenvolvedores se conectem e expressem sua visão, seria ótimo.

************

Esperar uma proibição, não é permitido criticar as escrituras :)

PS: As melhorias foram, não tão globais, mas houve

Alexey Volchanskiy  
secret:
Eles não têm nem mesmo indicadores) o que poderia ser mais fundamental)

Não haverá nenhum, o idioma é gerenciado, embora sem GC

Sharp também os tem apenas em modo inseguro.

Alexey Volchanskiy  
Alexey Navoykov:

Sim, eu entendo, mas além do kodobase existem o Freelance e o Market, e a MQ deve estar interessada na qualidade dos produtos. E a qualidade da linguagem afeta a qualidade e a velocidade do desenvolvimento e da depuração de uma forma ou de outra.

Se falando em porcentagens como esta, então por que a MQL5 foi criada em primeiro lugar? Ainda estaríamos sentados na antiga MQL4 hardcore onde a OOP ou qualquer outra coisa não é necessária... 99% dos usuários estavam satisfeitos com isso )

Talvez os programadores normais não vão para a MQL porque ainda é uma linguagem incompleta.

Kodobase é um lixo de 95%. Não tenho visto novas versões do MT5 há muito tempo. Renat, eu me lembro, prometeu algo global no novo lançamento.

Alexey Navoykov  
Alexey Volchanskiy:

PS: Houve melhorias, não tão globais, mas houve

A última coisa que me lembro foi de um operador de cópia implícita permitindo copiar objetos dinâmicos, mas isso não é nada, especialmente porque muito tempo se passou desde então.

Razão: