[fpc-pascal] Better usage of "with"

Ryan Joseph ryan at thealchemistguild.com
Thu Jun 14 11:44:40 CEST 2018



> On Jun 14, 2018, at 4:25 PM, Sven Barth via fpc-pascal <fpc-pascal at lists.freepascal.org> wrote:
> 
> omething like that only leads to confusion. Pascal is a rather explicit language so manually declaring a Position property inside TDoor would be more in the spirit of the language. 
> 
> A possible alternative would be generic type helpers, like this (just an example, not working code):

That’s probably the best available solution but more verbose than “with” in records. JB also hinted at how templates could be used to hack up something and I think this is what had in mind. :) The idea of “with” inside records is so interesting because it basically mimics inheritance without going full class. Now that I’ve seen it it feels like a natural extension of how data should be able to be laid out.

Something I tried was using properties like this but it didn’t work. Is that something properties could do? It feels like they should be able to reach into records fields that since everything is known to the property as time of declaration.

property Position: TVec2D read entity^.position;

> 
> === code beging ===
> 
> type
>   generic TEntityUserHelper<T> = type helper for T
>   private
>     function GetPosition: TVec2D; inline;
>     procedure SetPosition(constref aValue: TVec2D); inline;
>   public
>     property Position: TVec2D read GetPosition write SetPosition;
>   end;
> 
> function TEntityUserHelper.GetPosition: TVec2D;
> begin
>   Result := Self.Entity^.Position;
> end;
> 
> procedure TEntityUserHelper.SetPosition(constref aValue: TVec2D);
> begin
>   Self.Entity^.Position := aValue;
> end;
> 
> type
>   TDoor = record
>     Entity: PEntity;
>     State: Boolean;
>   end;
>   TDoorHelper = specialize TEntityUserHelper<TDoor>;
> 
> var
>   door: TDoor;
> begin
>   // init door
>   door.Position := Vec2D(21, 42);
> end;
> 
> === code end ===
> 
> 
> 
> // works with function parameters also.
> // this is almost like a class helper or at very least mimics “self” in methods.
> 
> procedure OpenDoor(with var door: TDoor);
> begin
>         state := true; // with imports door namespace into entire function scope
> end;
> 
> The declaration of the function (in the interface section) would need to contain the "with" as all parameters have to match (and its only that parts are removed from the definition (default parameters, modifiers), but not the other way around) and thus the declaration would "spill" information about the function while not needing to. 
> And again I think that as an expressive language the explicit usage of a "with" block is better than something like this. Please also not that there are people out there that advocate *against* the usage of "with" at all as it is likely to introduce bugs with it. 

I don’t follow the syntax issue in the first paragraph or understand why it’s a problem to have with in both the interface and implementation (var is that way after all).

A with block does the same thing but putting in the parameters basically mimics what classes do with methods, i.e. a hidden “self” which is the first parameter and hidden in the scope. It’s such a common pattern for procedural API’s where the first param is a pointer to the member data that it makes sense to be part of the language imo.

The reason Jonathan Blow suggested this is to get out of OOP designs when really all you want is the syntactic sugar of not typing door^.xxx all the time, which is reason enough to make a class in some people minds. He’s using c++ though so he has no fallback like “with" in Pascal and even so wrapping entire functions in with .. do is not as nice as his idea.

Regards,
	Ryan Joseph




More information about the fpc-pascal mailing list