4

Haskell lets you define functions like thrice, which accepts an element of type a and returns a list of the element repeated three times, for any data type a.

thrice :: a -> [a]
thrice x = [x, x, x]

Does Free Pascal allow type variables? If not, is there another way to do this in Free Pascal?

gawi
  • 13,940
  • 7
  • 42
  • 78
mcandre
  • 22,868
  • 20
  • 88
  • 147
  • Free Pascal has type variables in its generics (comparable to C++ templates). –  Oct 17 '11 at 20:27
  • How do I use Free Pascal's built-in generic types? Google only returns forum threads. – mcandre Oct 17 '11 at 20:37
  • See monadic's answer for the Wiki page. Alternatively, you might want to turn to the compiler's [documentation](http://www.freepascal.org/docs.var), or actually the [relevant chapter in the language reference](http://www.freepascal.org/docs-html/ref/refch8.html). –  Oct 17 '11 at 20:41
  • 1
    Again, the docs only say how to create generic types. I want to know how to use Free Pascal's built-in generic types in a function like `thrice`. – mcandre Oct 17 '11 at 20:45

3 Answers3

3

As a haskell person who doesn't know Pascal, this appears to be a similar thing. Sorry for not being able to expand.

http://wiki.freepascal.org/Generics

alternative
  • 12,703
  • 5
  • 41
  • 41
1

Unfortunately FreePascal currently has only generic classes, not generic functions. Though, your goal can still be achieved, albeit a little awkwardly. You need to define a new class to encapsulate your operation:

unit Thrice;

interface

type

generic ThriceCalculator<A> = class
public
  class function Calculate(x: A): array of A;
  // We define it as a class function to avoid having to create an object when 
  // using Calculate. Similar to C++'s static member functions.
end;

implementation

function ThriceCalculator.Calculate(x: A): array of A;
begin
  SetLength(Result, 3);
  Result[0]:= x;
  Result[1]:= x;
  Result[2]:= x;
end;

end.

Now, unfortunately when you want to use this class with any specific type, you need to specialize it:

type

  IntegerThrice = specialize ThriceCalculator<Integer>;

Only then you can use it as:

myArray:= IntegerThrice.Calculate(10);

As you see, Pascal is not the way to go for generic programming yet.

cyco130
  • 4,654
  • 25
  • 34
  • Thrice is just one example. Would you have to create special classes for `FourTimes`? `FiveTimes`? etc. etc. – mcandre Nov 01 '11 at 07:20
  • You can create an `NTimes` function and take an integer argument `N`. – cyco130 Nov 01 '11 at 07:31
  • 1
    @mcandre: there are roughly two options. Create one class for "functions that are polymorphic in one variable without constraints", and add every function there, or create a class for each function. It is also possible to combine this (e.g. the `NTimes` class). In any case, the choice between the two is a trade-off between clutter and ease of extension. –  Nov 01 '11 at 11:28
  • @Tinctorius: Yes. +1 for "putting the functions in the same generic class" idea. – cyco130 Nov 01 '11 at 14:03
0

...answering from the future.

FreePascal has support for generic functions and procedures outside of classes.

Here's code that shows how you could implement Thrice as a special case of Times to also illustrate your ask about "FourTimes, FiveTimes, etc.".

The code includes a couple of examples using different types (integer, string, record):

{$mode objfpc}

program Thrice;

uses sysutils;

type
   TPerson = record
      First: String;
      Age: Integer;
   end;

   generic TArray<T> = array of T;

var
   aNumber: integer;
   aWord: String;
   
   thePerson: TPerson;
   aPerson: TPerson;

generic function TimesFn<T, RT>(thing: T; times: Integer): RT;
var i: integer;
begin
   setLength(Result, times);
   for i:= 0 to times-1 do
      Result[i] := thing;      
end;
  
generic function ThriceFn<T, RT>(thing: T): RT;
begin
   Result := specialize TimesFn<T, RT>(thing, 3);
end;


begin
   { Thrice examples }
   
   for aNumber in specialize ThriceFn<Integer, specialize TArray<Integer>>(45) do
                                                  writeln(aNumber);   

   for aWord in specialize ThriceFn<String, specialize TArray<String>>('a word') do
                                                writeln(aWord);

   thePerson.First := 'Adam';
   thePerson.Age := 23;

   for aPerson in specialize ThriceFn<TPerson, specialize TArray<TPerson>>(thePerson) do
                                                   writeln(format('First: %s; Age: %d', [aPerson.First, aPerson.Age]));

   { Times example } 
   for aNumber in specialize TimesFn<Integer, specialize TArray<Integer>>(24, 10) do
                                                 writeln(aNumber);
end.
   
Joubert Nel
  • 3,154
  • 3
  • 26
  • 24