MQL4 - How to set a "today"-datetime to an extern variable in MQL4 script? - constants

I have an MQL4 script ( a script that runs on MetaTrader4 Terminal platform ) and I need to define an extern variable, named extractionDate of type datetime, so that the user can change its input value before the script starts.
I tried the conventional way to define the variable before the standard script's function start(), but it doesn't work. When I compile I, get the error message
['TimeLocal' - constant expected]
that means MQL4 wants a constant value for the variable. But this isn't my goal. I would like to show as default value the "Today" date, when the script starts and not a fixed predefined date value.
Is it possible to do this or not?
extern datetime extractionDate = TimeLocal();
int start()
{
......
return(0);
}

No, compiler does not allow this directly
Compiler does not allow a way to assign a default value, that is not constant.
It has to know the value, so an attempt to setup / assign an unknown / variable-value as a default one, will yield compilation error.
Yet, how to solve this?
My approach would be to give user instructions and a choice to setup any datetime, or setup a value of -1, which would be translated inside the OnInit() event handler code-block:
void OnInit(){
...
if ( extractionData == -1 ) extractionDate = TimeLocal();
...
}

Related

Issue with passing an int field in as a parameter argument, but all others work perfectlyy how is this even possible?

ScreenShot of CodeCould someone please explain to me how everything works in this script except a simple int counter that I pass in as a parameter? However if I directly pass in the int counter field into the method instead of using/ref. the para, it works just fine, how is this even possible? HELP!
By default parameters you give to the function, are evaluated and its value is passed (eg. not int xy is passed but the value of int xy, so 5).
So if you change the value directly eg. CounterAi -= 1; you are just changing the value you've passed on not the underlying variable. So if you want to use Pass by Reference in these cases you must use out or ref.
If you change a parameter of the passed value however it's value will be changed without needing to use ref or out.
Example:
public void Example1(int myValue) {
// This won't change the actual variable, just the value of the parameter,
// that has been passed
myValue -= 1;
}
public void Example2(ref int myValue) {
// This will change the actual variable,
// it's changing just the value of the parameter again,
// but we're using pass by reference
myValue -= 1;
}
public void Example3(Transform finishLine) {
// This will change the actual variable,
// because it's changing the data within the object,
// that the parameter value refers to.
finishLine.position = flSpts[Random.Range(0, flSpots.Count)].position;
}

How can we put an integer variable into a task string?

Indeed I have a task to read registers:
task read_reg(bit[31:0] reg_addr,bit [0:31] rd_beat...);
The first input parameters is the address of the register that is 32-bit, as you can see. The register addresses are defined through parameters:
parameter int REG_0 = 32'h80440050; //R
So when you call the task to read a register, you can pass over the parameter to the task:
read_reg(REG_0,….);
to read e.g. REG_0.
Now, this is the call of the task that I would like to parametrize more, so I don't want to hardcode the parameter name REG_0 into it but I would like to handle it partly through another variable:
bit [1:0] num=0;
and then instead of hardcoding REG_0 when calling the task, I would like to use the variable "num" for it, so something like:
read_reg(REG_$num$,...)
just I don't know how to handle over the value of num (which is 0 in the above example) into the call of the task.
I hope I managed to give a clearer description now and that someone has an idea how to do it.
There's no way to form an identifier name from a variable. You want an array. You can do
parameter int REG[4] = {32'h80440050, //R
32'h80450050,
...};
read_reg(REG[num],...)
or you could create an associative array
int REG[string] = '{"REG_0":REG_0,"REG_1":REG_1,...};
read_reg(REG[$sformatf("REG_%0d",num)],...);

Problems with Dateish strings

This code (for checking the changed timestamp of the current directory):
my $date = ".".IO.changed.DateTime.yyyy-mm-dd but Dateish;
say $date;
yields the error:
«Ambiguous call to 'gist(Str+{Dateish}: )'; these signatures all match:␤: (Str:D: *%_)␤:(Dateish:D: │ avalenn
| *%_)␤ in block <unit> at <tmp> line 1␤␤»
Without the Dateish mix in, the string is simply 2018-05-12. Using any other kind of Dateish function, like .week-year also yields a different error:
«Str+{Dateish}␤Invocant of method 'Bridge' must be an object instance of type 'Int', not a type │ a3r0
| object of type 'Int'. Did you forget a '.new'?␤ in block <unit> at <tmp> line 1␤␤»
Does it simply mean that you can't mix in a string with Dateish? I've done something similar with hours without a problem.
To answer your question, we should look at that role:
my role Dateish {
has Int $.year;
has Int $.month; # should be int
has Int $.day; # should be int
has Int $.daycount;
has &.formatter;
...
multi method Str(Dateish:D:) {
&!formatter ?? &!formatter(self) !! self!formatter
}
multi method gist(Dateish:D:) { self.Str }
...
}
So, role Dateish has several attributes, and the methods use those attributes to calculate their return values.
When you do $some-string but Dateish, you are not doing anything to initialize the attributes, and thus method calls that use them (potentially indirectly) fail in interesting ways.
How do you get a Dateish object from a DateTime then? Well, DateTime is one, already, or you can coerce to Date if that is what you want:
my $date = ".".IO.changed.DateTime.Date; say $date
You might also try to instantiate a Dateish by supplying all attributes, but I don't see any advantage over just using Date as intended.

How I can to define in UE4 the default values of variables published by UFUNCTION

I have a proeject in C++ with UE4 and I need to know if there is a way to define the default value of C++ variables when I use this function from Blueprints.
UFUNCTION(BlueprintCallable, Category = SirenPlayerCameraManager)
virtual void SwitchCameraTo(ACameraActor* CameraActor, EViewTargetBlendFunction BlendFunc, float BlendTime);
This is my Function, and when I use this Blueprint I want the parameter BlendFunc could have a default value != 0
Yes it is possible
just like in plain C++ you can assign a value for example
UFUNCTION(...)
void F(int x = 0);

How to pass parameters to a Progress program using database field dynamic-based rules?

I have in my database a set of records that concentrates information about my .W's, e.g. window name, parent directory, file name, procedure type (for internal treatments purposes), used to build my main menu. With this data I'm developing a new start procedure for the ERP that I maintain and using the opportunity in order to rewrite some really outdated functions and programs and implement new functionalities. Until now, I hadn't any problems but when I started to develop the .P procedure which will check the database register of a program that was called from the menu of this new start procedure - to check if it needs to receive fixed parameters to be run and its data types - I found a problem that I can't figure out a solution.
In this table, I have stored in one of the fields the parameters needed by the program, each with his correspondent data type. The problem is on how to pass different data types to procedures based only on the stored data. I tried to pre-convert data using a CASE clause and an include to check the parameter field for correct parameter sending but the include doesn't work as I've expected.
My database field is stored as this:
Description | DATATYPE | Content
I've declared some variables and converted properly the stored data into their correct datatype vars.
DEF VAR c-param-exec AS CHAR NO-UNDO EXTENT 9 INIT ?.
DEF VAR i-param-exec AS INT NO-UNDO EXTENT 9 INIT ?.
DEF VAR de-param-exec AS DEC NO-UNDO EXTENT 9 INIT ?.
DEF VAR da-param-exec AS DATE NO-UNDO EXTENT 9 INIT ?.
DEF VAR l-param-exec AS LOG NO-UNDO EXTENT 9 INIT ?.
DEF VAR i-count AS INT NO-UNDO.
blk-count:
DO i-count = 0 TO 8:
IF TRIM(programa.parametro[i-count]) = '' THEN
LEAVE blk-count.
i-count = i-count + 1.
CASE ENTRY(2,programa.parametro[i-count],CHR(1)):
WHEN 'CHARACTER' THEN
c-param-exec[i-count] = ENTRY(3,programa.parametro[i-count],CHR(1)).
WHEN 'INTEGER' THEN
i-param-exec[i-count] = INT(ENTRY(3,programa.parametro[i-count],CHR(1))).
WHEN 'DECIMAL' THEN
de-param-exec[i-count] = DEC(ENTRY(3,programa.parametro[i-count],CHR(1))).
WHEN 'DATE' THEN
da-param-exec[i-count] = DATE(ENTRY(3,programa.parametro[i-count],CHR(1))).
WHEN 'LOGICAL' THEN
l-param-exec[i-count] = (ENTRY(3,programa.parametro[i-count],CHR(1)) = 'yes').
OTHERWISE
c-param-exec[i-count] = ENTRY(3,programa.parametro[i-count],CHR(1)).
END CASE.
END.
Then I tried to run the program using an include to pass parameters (in this example, the program have 3 INPUT parameters).
RUN VALUE(c-prog-exec) ({util\abrePrograma.i 1},
{util\abrePrograma.i 2},
{util\abrePrograma.i 3}).
Here is my abrePrograma.i
/* abrePrograma.i */
(IF ENTRY(2,programa.parametro[{1}],CHR(1)) = 'CHARACTER' THEN c-param-exec[{1}] ELSE
IF ENTRY(2,programa.parametro[{1}],CHR(1)) = 'INTEGER' THEN i-param-exec[{1}] ELSE
IF ENTRY(2,programa.parametro[{1}],CHR(1)) = 'DECIMAL' THEN de-param-exec[{1}] ELSE
IF ENTRY(2,programa.parametro[{1}],CHR(1)) = 'DATE' THEN da-param-exec[{1}] ELSE
IF ENTRY(2,programa.parametro[{1}],CHR(1)) = 'LOGICAL' THEN l-param-exec[{1}] ELSE
c-param-exec[{1}])
If I suppress the 2nd, 3rd, 4th and 5th IF's from the include or use only one data type in all IF's (e.g. only CHAR, only DATE, etc.) the program works properly and executes like a charm but I need to call some old programs, which expects different datatypes in its INPUT parameters and using the programs as described OpenEdge doesn't compile the caller, triggering the error number 223.
---------------------------
Erro (Press HELP to view stack trace)
---------------------------
** Tipos de dados imcompativeis em expressao ou atribuicao. (223)
** Nao entendi a linha 86. (196)
---------------------------
OK Ajuda
---------------------------
Can anyone help me with this ?
Thanks in advance.
Looks as if you're trying to use variable parameter definitions.
Have a look at the "create call" statement in the ABL reference.
http://documentation.progress.com/output/ua/OpenEdge_latest/index.html#page/dvref/call-object-handle.html#wwconnect_header
Sample from the documentation
DEFINE VARIABLE hCall AS HANDLE NO-UNDO.
CREATE CALL hCall.
/* Invoke hello.p non-persistently */
hCall:CALL-NAME = "hello.p".
/* Sets CALL-TYPE to the default */
hCall:CALL-TYPE = PROCEDURE-CALL-TYPE
hCall:NUM-PARAMETERS = 1.
hCall:SET-PARAMETER(1, "CHARACTER", "INPUT", "HELLO WORLD").
hCall:INVOKE.
/* Clean up */
DELETE OBJECT hCall.
The best way to get to the bottom of those kind of preprocessor related issues is to do a compile with preprocess listing followed by a syntax check on the preprocessed file. Once you know where the error is in the resulting preprocessed file you have to find out which include / define caused the code that won't compile .
In procedure editor
compile source.w preprocess source.pp.
Open source.pp in the procedure editor and do syntax check
look at original source to find include or preprocessor construct that resulted in the code that does not compile.
Okay, I am getting a little bit lost (often happens to me with lots of preprocessors) but am I missing that on the way in and out of the database fields you are storing values as characters, right? So when storing a parameter in the database you have to convert it to Char and on the way out of the database you have convert it back to its correct data-type. To not do it one way or the other would cause a type mismatch.
Also, just thinking out loud (without thinking it all the way through) wonder if using OOABL (Object Oriented ABL) depending on if you Release has it available wouldn't make it easier by defining signatures for the different datatypes and then depending on which type of input or output parameter you call it with, it will use the correct signature and correct conversion method.
Something like:
METHOD PUBLIC VOID storeParam(input cParam as char ):
dbfield = cParam.
RETURN.
END METHOD.
METHOD PUBLIC VOID storeParam(input iParam as int ):
dbfield = string(iParam).
RETURN.
END METHOD.
METHOD PUBLIC VOID storeParam(input dParam as date ):
dbfield = string(dParam).
RETURN.
END METHOD.
just a thought.