Recent

Author Topic: Syntax proposals  (Read 13102 times)

damieiro

  • Full Member
  • ***
  • Posts: 200
Re: Syntax proposals
« Reply #15 on: December 19, 2018, 10:32:21 am »
Well, some answers (INMHO) in order:

@Martin_fr: Yes, you're right with the nil. But it's a compiler option, it could be nil as default and no side effect. A class var not created could start by default with nil, so no boilerplate coding with that. Same as being zeroed when calling the constructor (why there and not in declaration?). Or using other definition, if the pointer is invalid(if have a internal valid/assigned field than can be checked), then use the constructor.
The idea behind was not to use (in my way of thinking...) a counterintuitive sintax like
MyClass:=TMyClass.Create (<args>); 
And use more simple MyClass.Create and leave the use of MyClass.Create as a method only if MyClass is not a valid reference.
It enforces that a class is constructed by their own type as default and forces the sentences like MyClass:=TDifferentClass.Create as being explicitally typed and not using the "sugar" declaration.

Other option is that If one declares a Class var like
MyClass:TMyClass;
The declaration of TMyClass Automatically does the getmen (init instance) unless explicitally declaring not doing it. So the .create will be only a init method. Why not this aproach?. This avoids the duality of a constructor method called as a newinstance and init if called as TMyclass.create and as a method if called as myclass.create method.

Option 3 sees what you say, so includes in var declaration a specific getmen.

And even, i'm sure some would appreciate some like a HEAP object. (what is what i try to mimic in class) and not having all the new and deference/reference  boiler plating (^) and no TObject reference :D

Code: Pascal  [Select][+][-]
  1. type
  2.   TTest = HEAP object //not stack one, managed object like Ansistring
  3.   private
  4.     { private declarations }
  5.   public
  6.     { public declarations }
  7.   end;
  8.  
  9. Var
  10.   TestObject:TTest; {in heap, zeroed and with valid reference/pointed}
  11.  

On the other hand.. The FreeAndNil...

Well, it's a tough question :D. I think the option to nil the pointer should be up to the programmer and FreeAndNil masks it, but i think too that all pointers (at declaration time) should start as nil. And the validity/invalidity/assigned of the pointer being a different field and starting as unassigned.

Aplying this to classes, i think all class declaration (like pointers) should be starting as nil, but pascal does let it to the programmer. I do not know what is gained when i type
Code: Pascal  [Select][+][-]
  1. Var
  2.  myPointer:pointer;
And myPointer is not nil by declaration. I must declare this.
Code: Pascal  [Select][+][-]
  1. Var
  2.  myPointer:pointer=nil;

But with managed types, nil is the default. (like AnsiString);

If i asked what i should choose for pointer types (i take class as pointer types)
and choose between these options;

Option 1: nil is not default

Code: Pascal  [Select][+][-]
  1. Var
  2.   NilPointer:pointer=nil;
  3.   NonilPointer:pointer;

Option 2: nil is default
Code: Pascal  [Select][+][-]
  1. Var
  2.   NilPointer:pointer;
  3.   NoNilPointer:pointer=TakeStupidCurrentMemInvalidPossiblyNonNilValue;

I choose 2. I never used and invalid (and possibly) non nil pointer for anything...

So for coherence, i will do all the things the same. All starting pointers to nil...? Ok, all to nil.

Not to nil? well, none to nil (so ansistring starting with anyvalue to point);

We should difference between nil/nor nil valid/not valid?, well, a nil pointer and a valid field in the pointer internals. But i think we have different strategies into the basis of the compiler with nil pointers/classes. :) I would prefer same behaviour (all nil or non nil, field of valid or not field..)
And my personal option is that a pointer defaults to a nil and unasigned by declaration, and then the programmer's choice to assign subsecuents nils and/or validity..
« Last Edit: December 19, 2018, 03:23:50 pm by damieiro »

damieiro

  • Full Member
  • ***
  • Posts: 200
Re: Syntax proposals
« Reply #16 on: December 19, 2018, 12:26:59 pm »
Related question: Scope.

FreeAndNil i think is not good for Scope view. My first option would be that a Object would be declared by their own Var statemente and freed when out of the scope. If we populate too much the stack or prefer heap, then, go for heap -> the heap object i put as a idea.

FreeAndNil is done probably when you need to test the pointer outside the scope. Then, by design, that variable should go to a broader scope (being more general). More general (not necessary global) variables are bad patterns, but can their proper uses like system ones. I'm actually doing classes to mimic pointers with internal pointer an validity check and some other utilities. I think there is confussion between a valid reference and no nil pointer. Not the same as we know. And this extends to the class model.

Well, these are my thoughs, "on the fly".

A simple question: why in TObject are not defined somekind of method like FreeThenNil instead of the system utility of FreeAndNil? (well i do not understand fully the logic of using freethennil... but i do not know why not integrate in TObject) -> And well, i know that self is like a internal const parameter and self:=nil is not possible... But it's like syntax.. it could be like a var parameter and not a reference, for example and a class could be "nilled" inside it :D. In constructor, self is returned as value (you can do a self:=nil in constructor and it returns nil :D which is tricky). Or if wanted to deal with previous code, make a var access to class pointer like varself, so you can access the pointer inside the class (more fire, but freeandnil implementation is a bit tricky for not having these previous facilities).
« Last Edit: December 19, 2018, 03:08:35 pm by damieiro »

damieiro

  • Full Member
  • ***
  • Posts: 200
Re: Syntax proposals
« Reply #17 on: December 19, 2018, 12:48:08 pm »
@Handoko
Quote
If Assigned(TheObject) then PerformChecking;

The problem is the variable TheObject is a reusable variable and the object inside is generated and freed on other part of the code. Using assigned(TheObject) can't really detect if the object already freed. That's why I used FreeAndNil

That's more on syntax as i said. If i read correctly the doc, assigned checks if pointer is nil or not. So the assigned and adresing is the same thing. And, INMHO, this is not true. A freed pointer should return false to assigned and not being nil unless explicity put to nil. Or, if not validity field, then no assigned function that causes confusion :D. So, INMHO, putting it to nil and check the nil the hard way is better thant confusing functions.

I think that is more clear (by its current meaning) this
Code: Pascal  [Select][+][-]
  1. If TheObject<>nil then PerformChecking;

than this, (is more verbose -- i love verbose --, but confusing meaning)
Code: Pascal  [Select][+][-]
  1. If Assigned(TheObject) then PerformChecking;


« Last Edit: December 19, 2018, 03:09:26 pm by damieiro »

damieiro

  • Full Member
  • ***
  • Posts: 200
Re: Syntax proposals
« Reply #18 on: December 19, 2018, 03:00:54 pm »
@Markov:
Quote
Most importantly, the syntax

Code: Pascal  [Select][+][-]
  1.     XXX.Create
  2.  
already has well defined functionality in FPC and Delphi. Namely, call the constructor only on an already allocated and zeroed block of memory. (e.g. bulk memory instantiation)

I propose an extended syntax with the idea of being backward compatible.

With the new syntax if XXX is not nil, behaves exactly the same (call the method XXX.Create).
And if XXX=nil and "create" is a constructor (to difference from a procedure) then it will do new instance and call constructor as XXX:=TXXX.Create (actually, will do a crash, so i think it does better than older ways or at least no harm in previous code).
The main change is that compiler would need default a class declaration as nil like Ansistring.
But for existing code this nil default doesn't hit, because no default value is expected;

I think (from a syntax point of view) that XXX:=TXXX.Create should be used less and only for making XXX objects of TXXX declared type with a different TYYY class. (XXX:=TYYY.Create has more sense INMHO);
And it has a good "sugar" syntax and simmetry  (xxx.create, xxx.free :D)


« Last Edit: December 20, 2018, 07:53:10 pm by damieiro »

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11453
  • FPC developer.
Re: Syntax proposals
« Reply #19 on: December 19, 2018, 06:57:31 pm »
IMHO these are all incompatible and pointless. I think we need to slowly stop adding redundant syntax, and maybe even remove old ones (like objfpc)

Leledumbo

  • Hero Member
  • *****
  • Posts: 8757
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: Syntax proposals
« Reply #20 on: December 20, 2018, 05:03:02 am »
and maybe even remove old ones (like objfpc)
So long as one time automatic migrator is provided, I'm fine to go mode delphi all the way.

damieiro

  • Full Member
  • ***
  • Posts: 200
Re: Syntax proposals
« Reply #21 on: December 20, 2018, 04:43:18 pm »
@Markov
Quote
IMHO these are all incompatible and pointless. I think we need to slowly stop adding redundant syntax, and maybe even remove old ones (like objfpc)

Could you explain more?, please. What are all of these especially incompatible or pointless and why? (knowing the reasons would help me to rewrite or understood why the proposal is not good).
Is a Heap Object bad idea? (not implemented)

I agree that redundant syntax must be removed/deprecated. But i think that Actual Syntax should be rethinked. I do not understand why (unless for backward compatibility that should be a book to keep, but not to write new code) we are having two object models (object, and class).

I think that sintax should be intuitive and should go that way. If i would define a syntax with no legacy code before, i would prefer a XXX.Create, for example. Compatibility is good. But it shouldn't stop to evolve the sintax or we will be caged by old syntax. Better a compiler directive to Eat the Old, then we should go for type the New. Well, it's my philosophy. I really love Free pascal, but i think we are making excess of "boilerplating code".

How much weight backward compatibility vs evolving syntax? And, most important (INMHO), what kind (and feel/look) of the syntax is desired? Where the compiler manages and where not?. I see that actually are a hybrid solution in the compiler. Managed tipes vs non managed. But an ansistring is managed, but a class, not, which is a higher level abstraction (a class can contain an ansistring...). :?.

Well, i know that my above thoughs are light-thinking. These, probably, can have lot of errors, but i wish that what i'm saying were taken from a light-hearted perspective. I really love pascal, but i have a feeling of being trapped in tp and delphi and embarcadero and not in the fp own way.


Quote again:
Quote
, and maybe even remove old ones (like objfpc)
do you mean remove classes or other things?




« Last Edit: December 20, 2018, 05:16:02 pm by damieiro »

Thaddy

  • Hero Member
  • *****
  • Posts: 14373
  • Sensorship about opinions does not belong here.
Re: Syntax proposals
« Reply #22 on: December 20, 2018, 05:03:22 pm »
@Markov
Well, i know that my above thoughs are light-thinking.
Yes. E.g. how do you destroy/free an object created without a reference? THINK some more.

I also do not totally agree with Marco (anymore that is, usually we agree) since mode objfpc syntax has distinctly other features than mode Delphi as PascalDragon a.k.a. Sven pointed out to me and I
 subsequently used in some of my example code on this forum this week regarding generics. (const dynamic arrays)
Using objfpc syntax I could reduce a huge number of lines of code to something very elegant and concise. I am not a fan, but the plain truth is that it has merit regarding some syntactical elements.

An overhaul would be good though.
« Last Edit: December 20, 2018, 05:11:01 pm by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

damieiro

  • Full Member
  • ***
  • Posts: 200
Re: Syntax proposals
« Reply #23 on: December 20, 2018, 05:18:12 pm »
Quote
Yes. E.g. how do you destroy/free an object created without a reference? THINK some more.

Please, could you put an example?. I think i do not pretend to say that, but it can be possible :?

« Last Edit: December 20, 2018, 05:28:54 pm by damieiro »

Thaddy

  • Hero Member
  • *****
  • Posts: 14373
  • Sensorship about opinions does not belong here.
Re: Syntax proposals
« Reply #24 on: December 20, 2018, 05:26:56 pm »
Code: Pascal  [Select][+][-]
  1.  XXX.Create
Where and how can you free it?

(btw it is possible once smartpointers are introduced, which I already showed in some other posts, doesn't mean it is a good thing )
See http://forum.lazarus.freepascal.org/index.php/topic,43143.msg301579.html#msg301579
« Last Edit: December 20, 2018, 05:32:08 pm by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

damieiro

  • Full Member
  • ***
  • Posts: 200
Re: Syntax proposals
« Reply #25 on: December 20, 2018, 05:32:51 pm »
Quote
XXX.Create
Where and how can you free it?

Ok, as usual. Code example:

Code: Pascal  [Select][+][-]
  1. Var
  2.   Myclass: TMyClass; {XXX=MyClass}
  3. begin
  4.   Myclass.Create; {replaces MyClass:=TMyClass.Create, compiler knows that MyClass is Tmyclass}
  5.   { do things... }
  6.   MyClass.Free;
  7. end.
  8.  

MyClass is referenced. I think i have explained it badly :(

Note: About smartpointing. I were posting about the very basis of syntax and going for simplicity/simetry. With simplicity, then one can go for complexity  O:D

« Last Edit: December 20, 2018, 06:00:02 pm by damieiro »

Thaddy

  • Hero Member
  • *****
  • Posts: 14373
  • Sensorship about opinions does not belong here.
Re: Syntax proposals
« Reply #26 on: December 20, 2018, 05:47:22 pm »
No: myclass is not referenced. This is silly code. Better examine e.g. my smartpointer code on how it CAN be done.
What you propose, allocation at declaration,  - if possible - would eat memory and does not allow for several instances of the same class... which is quite common... THINK!  :D
(I am encouraging you, not discouraging you!!)
« Last Edit: December 20, 2018, 05:49:32 pm by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

damieiro

  • Full Member
  • ***
  • Posts: 200
Re: Syntax proposals
« Reply #27 on: December 20, 2018, 06:12:54 pm »
Quote
No: myclass is not referenced. This is silly code. Better examine e.g. my smartpointer code on how it CAN be done.
What you propose, allocation at declaration,  - if possible - would eat memory and does not allow for several instances of the same class... which is quite common... THINK!  :D
(I am encouraging you, not discouraging you!!)

I'm trying to understand you. Currently i do not understand you well. I know what a smartpointer is, but i'm working it on a sintactic level (ie. transform one line on semantic equivalence). If i understand you, with smart pointers, that sintaxis wouldn't work, but i do not understand why (for me is a neutral replacement)

I think i do not say allocation at declaration in the last example. Only a syntax transformation of already existing one, that allocates on .Create, not in var declaration (i propose, also, a declaration allocation option like managed types if wanted, but not this case). MyClass is a pointer. Until not done MyClass.Create, there is no allocation in memory.

could you give me a link to your code implementation to learn it and possibly i could understand you?.

note: thanks for the kind response


« Last Edit: December 20, 2018, 08:50:46 pm by damieiro »

CCRDude

  • Hero Member
  • *****
  • Posts: 600
Re: Syntax proposals
« Reply #28 on: December 20, 2018, 06:18:26 pm »
I thought about something I often use when I first read that suggestion a few posts ago, let me give you a standard usage case broken down to be simple:
Code: [Select]
var
   mi: TMenuItem;
   sl: TStringList;
   i: integer;
begin
   sl := TStringList.Create;
   try
      sl.Add('Hello');
      sl.Add('World');
      for i := 0 to Pred(sl.Count) do begin
         mi := TMenuItem.Create(mainMenu.Items);
         mi.Caption := sl[i];
         mainMenu.Items.Add(mi);
      end;
   finally
      sl.Free;
   end;
end;
In your syntax, this would be:
Code: [Select]
      for i := 0 to Pred(sl.Count) do begin
         mi.Create(mainMenu.Items);
         mi.Caption := sl[i];
         mainMenu.Items.Add(mi);
      end;

Since "mi" is already initialized from the first loop passing, the second one would not create a new menu item, but change the caption of the first, and adds it a second time. To make this work, you would have to write:

Code: [Select]
      for i := 0 to Pred(sl.Count) do begin
         mi := nil;
         mi.Create(mainMenu.Items);
         mi.Caption := sl[i];
         mainMenu.Items.Add(mi);
      end;

So instead of simplifying things, this would need additional effort and introduces new possible reasons for errors.

And this type of re-use of a var is quite common in many cases of importing data, for example. Think about just any type of list you would try to fill.
« Last Edit: December 20, 2018, 06:20:55 pm by CCRDude »

damieiro

  • Full Member
  • ***
  • Posts: 200
Re: Syntax proposals
« Reply #29 on: December 20, 2018, 06:40:14 pm »
Ok, i see. Thanks for the example. You are right. (@Thaddy: That was the kind of things you tried to explain above?)

I thought that as a backward compatible addon. Not as a replacement. If used as replacement, then it would happen what you see. And it's a common use, and yes, it makes the proposal useless.

If used as a replacement (which i would prefer), i would substitute
MyClass:=TMyClass.Create; allways as MyClass.Create;

The main issue here is that XXX.create would never be a method call. Which, INMHO i prefer. INMHO i would prefer a init/reinit separate if needed (example, if a window, better a resize method than a create again).

I do not see as desirable calling the constructor two times (one as an alloc and other as a reinit that could do some undesirable memory alloc for other classes).
Is there any practical use of a constructor as a method except descendant objects constructor code that could be enforced?.

But this could impact in legacy code and break backward compatibility unless new compiler directives. But it's my way of thinking. What we like? Actual way or other way? I do not like actual sintax because i feel counterintuitive, with some polisemy (that i agravated with my first proposal to gain intuitive coding) and allowing constructor calls as methods...

But yes... you show me that there is not perfect solution :(

Nowadays, My preferred sintactic construction would be this (if not having to maintain a constructor as method call):

Code: Pascal  [Select][+][-]
  1.    for i := 0 to Pred(sl.Count) do
  2.      begin
  3.         { mi := nil; not needed,
  4.            mi.Create (mainMenu.Item); full replacement of
  5.            mi := TMenuItem.Create(mainMenu.Items);}
  6.  
  7.          mi.Create(mainMenu.Items);
  8.          mi.Caption := sl[i];
  9.          mainMenu.Items.Add(mi);
  10.       end;

PD: What i have learn up to this post is that syntax change would surely need break backward compatibility at some point ...
« Last Edit: December 20, 2018, 08:38:12 pm by damieiro »

 

TinyPortal © 2005-2018