Recent

Author Topic: types as parameters  (Read 6940 times)

ptrAux

  • Newbie
  • Posts: 1
types as parameters
« on: July 31, 2015, 05:03:02 am »
How do that: (sorry, I speak spanish)

Hola, necesito saber como se hace para pasar un tipo (TYPE) como parámetro.
A modo de ejemplo, dejo el pseudocódigo.
Primero defino un par de registros nodoA y nodoB con sus tipos y los respectivos ptr para crearlos dinámicamente.



type
    ptrNodoA = ^nodoA;
    nodoA = record
        datoInt: integer;
        datochar: char;
    end;

    ptrNodoB = ^nodoB;
    nodoB = record
        datoInt: integer;
        datochar: char;
    end;

SIN USAR OBJETOS - SIN USAR OBJETOS - SIN USAR OBJETOS:
------------------------------------------------------------------------------------------
Lo que pretendo es hacer un creador genérico de instancias usando new() de Pascal, donde necesito conocer el tipo del registro para hacer el cast y acceder a los campos.
Sería más o menos así:

                                                                                   I need pass the TYPE  in tipoNodo
procedure crearNodo(var p:pointer, d:char; tipoNodo:TYPE?????); << cómo pasar tipo o referencia de tipo ???
begin
    new(tipoNodo(p));
    tipoNodo(p).datoint := 0;
    tipoNodo(p).datochar := d;
end;

var
    nA: ptrNodoA;
    nB: ptrNodoB;
    p: pointer;

begin
    crearNodo(p, 'A', ptrNodoA); << ??? how to pass TYPE or reference ???
    nA := ptrnodoA(p)
    crearNodo(p, 'B', ptrNodoB);  << ??? how to pass TYPE or reference ???
    nB := ptrnodoB(p)
end.

¿Cómo se hace para pasarle a tipoNodo un valor que es un tipo, o la referencia de un tipo?
¿How does one tipoNodo happen to a value that is a type or reference type? (google trad)


Gracias por tu molestia.
« Last Edit: July 31, 2015, 05:43:09 am by ptrAux »

Basile B.

  • Guest
Re: types as parameters
« Reply #1 on: July 31, 2015, 05:31:07 am »
Lo que tu necesitas es los genericos functions. Pero son no existan en ObjFPC Pascal. Tambien nota que tu exemplo no esta bien porque los dos tipos estan los mismos.

cdbc

  • Hero Member
  • *****
  • Posts: 1026
    • http://www.cdbc.dk
Re: types as parameters
« Reply #2 on: July 31, 2015, 05:52:01 am »
Hi
"Use the source Luke"  :)
Code: [Select]
Application.CreateForm(TfmMain, fmMain);Follow this and investigate.... Then tweak to your purpose ... maybe, I don't speak that much spanish  ;) Anyway, it's the "Factory pattern" in play.
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE5 -> FPC 3.2.2 -> Lazarus 2.2.6 up until Jan 2024 from then on it's: KDE5/QT5 -> FPC 3.3.1 -> Lazarus 3.0

bylaardt

  • Sr. Member
  • ****
  • Posts: 309
Re: types as parameters
« Reply #3 on: July 31, 2015, 06:14:18 am »
y por qué "class" no es aplicable?

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: types as parameters
« Reply #4 on: July 31, 2015, 07:05:13 am »
you ask, we deliver :-)

Code: [Select]
program record_type;
{$MODE OBJFPC}{$H+}
Uses
  TypInfo;

type
    ptrNodoA = ^nodoA;
    nodoA = record
        datoInt: integer;
        datochar: char;
    end;

    ptrNodoB = ^nodoB;
    nodoB = record
        datoInt: integer;
        datochar: char;
    end;
   

procedure crearNodo(var p:pointer; d:char; tipoNodo: pTypeInfo); // << cómo pasar tipo o referencia de tipo ???
begin
    case tiponodo^.name of

      'ptrNodoA' :
      begin       
        new(ptrNodoA(p));
        ptrNodoA(p)^.datoint  := 0;
        ptrNodoA(p)^.datochar := #0;       
      end;

      'ptrNodoB' :
      begin
        new(ptrNodoB(p));
        ptrNodoB(p)^.datoint  := 0;
        ptrNodoB(p)^.datochar := #0;             
      end;

    end;
end;

var
    nA: ptrNodoA;
    nB: ptrNodoB;
    p: pointer;

begin
    crearNodo(p, 'A', typeinfo(ptrNodoA)); //<< ??? how to pass TYPE or reference ???
    nA := ptrnodoA(p);
    crearNodo(p, 'B', typeinfo(ptrNodoB));  //<< ??? how to pass TYPE or reference ???
    nB := ptrnodoB(p);

  // do something with nA and nB

  // and in the end don't forget to free the memory again
  Dispose(nA);
  Dispose(nB);
end.

But, i highly doubt the sense of it all.
a) The records are exactly identical, as correctly noted by BBasile
b) Memory isn't freed
c) Note how OT wants to use a single procedure to create different record types

In regards to point c), my code exactly shows how redundant it is to use this approach as you would need to distinguish between record type, any which way you put it. Using generics only hides the symptom as the code would be generated.

Might it perhaps be OT wants to create an array of exactly the same record types (but does not exactly knows how to) ?

In case the record types do need to differ (and their differences in size are eventually small) you could use an alternative form of record definition:

Code: [Select]
Type
  TMyRec = record
  case LongInt of
   0     : (field1: longint; field 2: char);
   1     : (field1: longint; field 2: word);
   n+1 : (blah blah);
  end;

And you should be able to access all fields, no matter the names -> you would use those names that matches the type of recrod you actually want. There is even a better way making the case from an actual field.

Classes might be overkill (but so are all other solutions ). But, components ... really cdbc ?

Sorry for the English, i really am not able to speak/write even a single word of Spanish.

Edit:
Added comment at bottom of code and added disposing of the allocated memory.
« Last Edit: July 31, 2015, 07:28:49 am by molly »

Basile B.

  • Guest
Re: types as parameters
« Reply #5 on: July 31, 2015, 11:51:09 am »
Code: [Select]
type
  RunTimeTypeHint = (T1,T2,T3);

  TT1 = record
  end;
  TT2 = record
  end;
  TT3 = record
  end;

  PTT1 = ^TT1;
  PTT2 = ^TT2;
  PTT3 = ^TT3;

function newTT(Type: RunTimeTypeHint ): pointer;
begin
  case RunTimeTypeHint of
    T1: result := new(PTT1);
    T2: result := new(PTT2);
    T3: result := new(PTT3);
  end; 
end;

Actually even with generics you would need some modern Delphi generic features to make compile time branches depending on the generic type.
In D, a language I particularly like, it works fine since years...

Code: [Select]
struct T1{this(A...)(A a){}}
struct T2{this(A...)(A a){}}
struct T3{this(A...)(A a){}}
 
T* newT(T, A...)(A a)
{
    static if (is(T == T1))
    {return new T1(a);}
    else static if (is(T == T2))
    {return new T2(a);}
    else static if (is(T == T3))
    {return new T3(a);}
}

"T" is the parameter of the template newT.
"static if" is a compile-time branch.
"A" is a parameter pack, so it's possible to pass what you want and use them as you want in each compile-time branch...because the struct members may have different type for example.

If only ObjFPC pascal dialect was as advanced with templates...

cdbc

  • Hero Member
  • *****
  • Posts: 1026
    • http://www.cdbc.dk
Re: types as parameters
« Reply #6 on: July 31, 2015, 01:33:27 pm »
Hi
Sorry guys, I didn't mean components !!!!!!!!!!!!!!!!
Looked at his code tried to understand what he was trying to do, but I lack alot of spanish, but it looked to me as if he needed the factory pattern, thus the best example around TApplication.... I meant the principle............. I'll just get out of your way now.
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE5 -> FPC 3.2.2 -> Lazarus 2.2.6 up until Jan 2024 from then on it's: KDE5/QT5 -> FPC 3.3.1 -> Lazarus 3.0

Basile B.

  • Guest
Re: types as parameters
« Reply #7 on: July 31, 2015, 02:06:12 pm »
but it looked to me as if he needed the factory pattern

no. Remember that he said:

Quote
SIN USAR OBJETOS - SIN USAR OBJETOS - SIN USAR OBJETOS:
------------------------------------------------------------------------------------------

which means "Without using Object - Without using Object - Without using Object"...
So show me show how you make a factory for records... :P

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: types as parameters
« Reply #8 on: July 31, 2015, 04:00:23 pm »
That would be possible with advanced records, so don't get too excited by screwing a noob.
It would be pointless, yes, but possible since it can contain a constructor.

He just doesn't understand these matters yet.
Specialize a type, not a var.

Basile B.

  • Guest
Re: types as parameters
« Reply #9 on: July 31, 2015, 04:15:02 pm »
That would be possible with advanced records, so don't get too excited by screwing a noob.
It would be pointless, yes, but possible since it can contain a constructor.

He just doesn't understand these matters yet.
I'm not excited by screwing a noob.
My only interest was to show that D is a language with which you don't have to discuss about the problem he has. The way he want to follow is standard. It just works like that. It's made for that.

In Pascal it's a PITA, people gotta give him some workarounds, some tricks, etc. It's not made for that. It's clear. We cannot give him the immediate way to dot it because this way doesn't exist. Period.

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: types as parameters
« Reply #10 on: July 31, 2015, 07:21:27 pm »
thats true for fpc too just ignore the last parameter the type and create overloaded procedures with the same name one for each type you want. Even simpler than D a bit more verbose though. eg
Code: [Select]
type
    ptrNodoA = ^nodoA;
    nodoA = record
        datoInt: integer;
        datochar: char;
    end;

    ptrNodoB = ^nodoB;
    nodoB = record
        datoInt: integer;
        datochar: char;
    end;

procedure crearNodo(var p:ptrNodoA, d:char);overload; //<< cómo pasar tipo o referencia de tipo ???
begin
    new(p);
    p^.datoint := 0;
    p^.datochar := d;
end;
procedure crearNodo(var p:ptrNodoB, d:char);overload; //<< cómo pasar tipo o referencia de tipo ???
begin
    new(p);
    p^.datoint := 0;
    p^.datochar := d;
end;

and call it like this
Code: [Select]
var
    nA: ptrNodoA;
    nB: ptrNodoB;
    p: pointer;

begin
    crearNodo(na, 'A');
    crearNodo(nB, 'B');
end.

the end result is better in my opinion.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: types as parameters
« Reply #11 on: July 31, 2015, 07:59:30 pm »
That would be possible with advanced records, so don't get too excited by screwing a noob.
Actually i was unable to make any sense of things using advanced records, and would not stay at the least close to the original code from OT.

There is no intention (at least on my part) to screw with any-one here.

Actually i thought about BBasile's solution as that would perhaps be more clean.

Quote
It would be pointless, yes, but possible since it can contain a constructor.

The point of my post was to show that Pascal is a typed language, and as such the records cannot be created the way OT envisioned.

OT obviously intended to have a common procedure for creating different types of records, while that is very hard (if not impossible) to do in a strongly typed language as Pascal.

Inheritance could help a little there (depending of what OT had in mind exactly), but as we all know advanced records don't have support for inheritance, while objects and classes do. Thereby, classes can be identified and worked with more easily while records don't have any provision to handle them in the same way.

I don't consider using typeinfo a good solution, but that was besides the point i was trying to make.

There will always be the code duplication, and i can't fix that. I'm only able to show OT that it's there.

See also taaz's example.

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: types as parameters
« Reply #12 on: July 31, 2015, 08:19:43 pm »
Hi
Sorry guys, I didn't mean components !!!!!!!!!!!!!!!!
Looked at his code tried to understand what he was trying to do, but I lack alot of spanish, but it looked to me as if he needed the factory pattern, thus the best example around TApplication.... I meant the principle............. I'll just get out of your way now.

Please don't feel too objected, because if you understand how Pascal works then one is able to figure out what you meant.

The problem is that there is a big distance between components and records (or in your suggested case it would come to classes) and their design patterns, and i'm assuming OT is new to the game.

The latter would make it very difficult, if not impossible for him/her to figure out what exactly you meant by your remark.

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: types as parameters
« Reply #13 on: July 31, 2015, 08:39:05 pm »
To answer the original question: use a class and a class reference and not a record.

Class types are not even discussed : declare as  "class off '. There you go, way before D. Fully acceptable as parameter and it is the type itself, not an instance.

Records just work another way, slightly different, and as of now need rtti, but anything can be expressed as a class reference and a class and frankly that is what D does under the hood.

And somebody needs to upgrade his information about the factory pattern: that can be implemented in many ways, not only how it is usually done in LCL. (Actually, I really doubt any understanding of any pattern except being capable of producing working code)

« Last Edit: July 31, 2015, 08:41:58 pm by Thaddy »
Specialize a type, not a var.

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: types as parameters
« Reply #14 on: July 31, 2015, 09:03:22 pm »
To answer the original question: use a class and a class reference and not a record.
I rather wait on feedback from OT, or at least until is clear what exactly the idea is behind the code he/she presented as it's ambiguous now.

Using classes/classtypes is not the issue, it's just another way of hiding things, although it does permits you to use a generic creation procedure in a bit more fashionable matter.

Quote
Records just work another way, slightly different, and as of now need rtti, but anything can be expressed as a class reference and a class and frankly that is what D does under the hood.
Regarding the latter, does that mean that for every little tidbit we must do similar in order to accomplish the same things ?

I rather favour having a solution that's more close to what OT had in mind. But of course we can disagree on that matter :-)

Quote
(Actually, I really doubt any understanding of any pattern except being capable of producing working code)
The message behind that last paragraph completely eluded me, sorry.

 

TinyPortal © 2005-2018