Recent

Author Topic: Can I somehow set priority of undecidable routines?  (Read 2772 times)

jollytall

  • Sr. Member
  • ****
  • Posts: 380
Can I somehow set priority of undecidable routines?
« on: January 22, 2023, 01:59:30 pm »
I have two identical name, similar parameter list routines. In some cases it is obvious which one to call, but sometimes not. Is it possible to set a priority somehow?

Example:
Code: Pascal  [Select][+][-]
  1. procedure a(const x: array of integer);
  2.   begin
  3.   // do something with the array
  4.   end;
  5. procedure a(const x: array of string);
  6.   begin
  7.   // do something with the array
  8.   end;
  9. type
  10.   tas = array of string;
  11. var
  12.   v1: array of string;
  13.   v2: tas;
  14. begin
  15. a([12,23]); // works
  16. a(['a','b']); // works
  17. v1 := [];
  18. a(v1); // works
  19. v2 := [];
  20. a(v2); // works
  21. a([]); // this does not compile as it cannot decide which one to call. Here I would need the priority. Anyway, as the array is empty I do nothing,
  22.        // so I do not really care.
  23.  
  24. // I also tried a typecast like thing, to avoid creating a variable as shown in the above examples
  25. a(tas([])); // but this also gives a compile error
  26. end;
  27.  

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12715
  • FPC developer.
Re: Can I somehow set priority of undecidable routines?
« Reply #1 on: January 22, 2023, 02:01:46 pm »
No. The only thing I can imagine to try is to add a typecast. But that probably hinders the ease of use that you use overloading for in the first place.

alpine

  • Hero Member
  • *****
  • Posts: 1412
Re: Can I somehow set priority of undecidable routines?
« Reply #2 on: January 22, 2023, 02:25:13 pm »
What can be expected if you impose two ambiguities on top of each other?

The first ambiguity you introduce on purpose (overloading).
The second is the FPC ambiguous syntax for open array, const array, and set, which can be resolved only by a context.

Why a([])? If you pass a variable parameter it can be easily resolved by it's type.

"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

jollytall

  • Sr. Member
  • ****
  • Posts: 380
Re: Can I somehow set priority of undecidable routines?
« Reply #3 on: January 22, 2023, 05:14:50 pm »
Thanks,

No. The only thing I can imagine to try is to add a typecast. But that probably hinders the ease of use that you use overloading for in the first place.
Typecast is not ideal, but doable. I tried to do it in the last line, but that is a compile error. How could I do that?

Why a([])? If you pass a variable parameter it can be easily resolved by it's type.
I have a general purpose routine that can be called with parameters not known in advance. Even the parameters can be different types (but at one time all of them are only this or that, not mixed). Sometimes there are no parameters at all to pass. One option is of course would be to create yet another overloaded version with no parameter. The problem that I already have many overloaded versions and if I remove this parameter from the parameter list then it conflicts with another overloaded version when another parameter is skipped.

I can do workarounds (give different names, put the parameters (especially if empty) into a variable before, etc.), just I though if there is a more elegant way (like it would be a compiler option or so) then I could do that.

alpine

  • Hero Member
  • *****
  • Posts: 1412
Re: Can I somehow set priority of undecidable routines?
« Reply #4 on: January 22, 2023, 09:08:01 pm »
I'm sorry, but I still don't get it. In a statically typed Pascal how you can confuse the compiler except of giving it an ambiguous syntax (namely [])? As you said a([]); then will do nothing which can then be reduced (in source) to empty statement (;)?
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

jamie

  • Hero Member
  • *****
  • Posts: 7601
Re: Can I somehow set priority of undecidable routines?
« Reply #5 on: January 22, 2023, 09:29:13 pm »
What really makes me wonder here is the fact that you can use a function with an array of const, thus pass whatever you want to a single function and determine the type within once the code lands there.


The only true wisdom is knowing you know nothing

balazsszekely

  • Guest
Re: Can I somehow set priority of undecidable routines?
« Reply #6 on: January 22, 2023, 09:43:58 pm »
Maybe this:
Code: Pascal  [Select][+][-]
  1. uses
  2.   {$IFDEF UNIX}
  3.   cthreads,
  4.   {$ENDIF}
  5.   Classes
  6.   { you can add units after this };
  7.  
  8. type
  9.   tas = array of string;
  10.  
  11. procedure a(const x: array of integer);
  12. begin
  13.   // do something with the array
  14. end;
  15.  
  16. procedure a(const x: tas = nil);
  17. begin
  18.   // do something with the array
  19. end;
  20.  
  21.  
  22. var
  23.   v1: array of string;
  24.   v2: tas;
  25.  
  26. begin
  27. a([12,23]); // works
  28. a(['a','b']); // works
  29. v1 := [];
  30. a(v1); // works
  31. v2 := [];
  32. a(v2); // works
  33.  
  34. a([]); //works
  35. a();  //works
  36.  
  37. end.    

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12715
  • FPC developer.
Re: Can I somehow set priority of undecidable routines?
« Reply #7 on: January 22, 2023, 09:44:20 pm »
Thanks,

No. The only thing I can imagine to try is to add a typecast. But that probably hinders the ease of use that you use overloading for in the first place.
Typecast is not ideal, but doable. I tried to do it in the last line, but that is a compile error. How could I do that?

I never tested it, just something to try.

uses types; // contains tstringdynarray = array of string

a(tstringdynarray([]); or so

TRon

  • Hero Member
  • *****
  • Posts: 4377
Re: Can I somehow set priority of undecidable routines?
« Reply #8 on: January 22, 2023, 09:56:51 pm »
@marcov:
If i understood correctly then OP already did something like that (line 25). It won't work and imho is a bug.

For an empty array you can try:
Code: Pascal  [Select][+][-]
  1. type
  2.   tai = array of integer;
  3.   tas = array of string;
  4.  
  5. ...
  6.  
  7.   a(tas.create);
  8.   a(tai.create);
  9.  

But I am personally more in favour of GetMem's solution.
« Last Edit: January 22, 2023, 10:00:04 pm by TRon »
Today is tomorrow's yesterday.

TRon

  • Hero Member
  • *****
  • Posts: 4377
Re: Can I somehow set priority of undecidable routines?
« Reply #9 on: January 22, 2023, 10:17:07 pm »
What really makes me wonder here is the fact that you can use a function with an array of const, thus pass whatever you want to a single function and determine the type within once the code lands there.
See https://www.freepascal.org/docs-html/ref/refsu69.html

That is, unless you meant something else with your statement.
« Last Edit: January 22, 2023, 10:19:00 pm by TRon »
Today is tomorrow's yesterday.

jamie

  • Hero Member
  • *****
  • Posts: 7601
Re: Can I somehow set priority of undecidable routines?
« Reply #10 on: January 22, 2023, 10:33:40 pm »
What really makes me wonder here is the fact that you can use a function with an array of const, thus pass whatever you want to a single function and determine the type within once the code lands there.
See https://www.freepascal.org/docs-html/ref/refsu69.html

That is, unless you meant something else with your statement.

Exactly, captain!
The only true wisdom is knowing you know nothing

jollytall

  • Sr. Member
  • ****
  • Posts: 380
Re: Can I somehow set priority of undecidable routines?
« Reply #11 on: January 23, 2023, 10:25:36 am »
Maybe this:
Thanks, that is a very good thought. I am afraid I cannot use it, as the real world is much more complicated than the example I showed (I have more parameters after with no default value), but will see if I can do something with it.

What really makes me wonder here is the fact that you can use a function with an array of const, thus pass whatever you want to a single function and determine the type within once the code lands there.
a) I did not think of it
b) in my real world situation one of the two cases is an array of strings and the other is an array of records and if I know well records cannot be passed as untyped array of const parameter.

However now I found something not thought before, and almost works:
Code: Pascal  [Select][+][-]
  1. program simple;
  2.  
  3. uses
  4. SysUtils;
  5.  
  6. type
  7.   integers = array of integer;
  8.   strings = array of string;
  9.  
  10. procedure a(const x: integers);
  11.   begin
  12.   writeln('In integers');
  13.   end;
  14. procedure a(const x: array of string);
  15.   begin
  16.   Writeln('In strings');
  17.   end;
  18. var
  19.   v1: strings;
  20. begin
  21. a([12,23]); // calls the integers - CORRECT
  22. a(['a','b']); // calls the strings - CORRECT
  23. v1 := [];
  24. a(v1); // calls the strings - CORRECT
  25. a([]); // calls the strings - HERE IT DECIDES FOR THE "array of..." VERSION
  26. a(strings([])); // calls the integers - ERROR, THE TYPECAST DOES NOT WORK LIKE THIS
  27. Sleep(500);
  28. end.
  29.  

As you see, I changed one of the declarations to a pre-defined type (instead of array of integer introduced integers). Then it almost works as intended.
The empty array calls the string version or to be more precise that one with the declaration like "array of something". The last one with the typecast works incorrectly, as it calls the integers (pre-defined) version, although the typecast would be the string version.
If I change the two declarations (to "array of integer" and "strings") then again, the first three will call what it should (obvious choices) the fourth calls the one with the "array of something" version (in this case the integer) and the last one calls the string version, but not because the typecast is strings([]), but because it calls the pre-defined type. Even if I use integers([]) it will call the strings version.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12715
  • FPC developer.
Re: Can I somehow set priority of undecidable routines?
« Reply #12 on: January 23, 2023, 10:28:02 am »
But I am personally more in favour of GetMem's solution.

It is a different solution, as you must pass a dynamic array, and not just some random construct array of strings.

A workaround might also be:

Code: Pascal  [Select][+][-]
  1. x(tas.create([]));

but I don't know anymore if that is 3.2.0+ of trunk+

TRon

  • Hero Member
  • *****
  • Posts: 4377
Re: Can I somehow set priority of undecidable routines?
« Reply #13 on: January 23, 2023, 10:29:15 am »
@jollytall:
I already provided an answer to that. Use .create in you caller routine.

Code: [Select]
a(strings.create);
a(integers.create);

Only required when passing an empty array.

PS: Please prepend t to type declarations and also use both type declarations for your functions.

@marcov
That is at least in 3.2.2 and you can omit the brackets as shown in the example above. I would like to try it on an older version of FPC on this machine but ..... (working on it)  ;)
« Last Edit: January 23, 2023, 10:44:48 am by TRon »
Today is tomorrow's yesterday.

jollytall

  • Sr. Member
  • ****
  • Posts: 380
Re: Can I somehow set priority of undecidable routines?
« Reply #14 on: January 23, 2023, 12:09:20 pm »
@jollytall:
I already provided an answer to that. Use .create in you caller routine.

I try to avoid any special treatment, as the place calling it is generated by a program (for over 1000 cases) and I want to keep them all look alike. This is why the typecast is not ideal either.

PS: Please prepend t to type declarations and also use both type declarations for your functions.

Usually I use t prepend, but as the built in types are integer and not tinteger, etc. and also IIRC integers is actually an existing type definition in one of the standard units, I just followed for this example the simple versions.

If I understand correctly, you suggest to use
Code: Pascal  [Select][+][-]
  1. procedure a(const x: tintegers);
  2. procedure a(const x: tstrings);
but it will not work. If BOTH are pre-defined types then again, the compiler cannot decide which one to call when a([]); is called. The trick is to use one pre-defined one and one array of ... .

 

TinyPortal © 2005-2018