Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation example mistake ? 4.3.1. TList-like properties #425

Closed
mingodad opened this issue Mar 7, 2022 · 10 comments
Closed

Documentation example mistake ? 4.3.1. TList-like properties #425

mingodad opened this issue Mar 7, 2022 · 10 comments

Comments

@mingodad
Copy link

mingodad commented Mar 7, 2022

Going through the documentation it seems that the examples at 4.3.1. TList-like properties has a mistake:

for i := GroupA.Count-1 downto 0 do
    if i and 3=0 then ///!!!!<<<< here it seems that it shoudl be "GroupA[3] = 0" or something similar
      GroupA.Delete(i); // delete integer at index i
@synopse
Copy link
Owner

synopse commented Mar 7, 2022

Hello,
Please use https://synopse.info/forum for such discussion: this is not worth opening a ticket, until a bug is really identified.

This sample is correct. if i and 3=0 then Does make sense: it erases one fourth of the entries, per index. It is the same as if i mod 4=0 - just slightly faster.
In fact, this is what the regression tests do, with no problem.

@synopse synopse closed this as completed Mar 7, 2022
@mingodad
Copy link
Author

mingodad commented Mar 7, 2022

Thank you for your help !
After your answer I made a console application to test it and indeed it works, the problem is that I'm used to C/C++ like laguages and the expression and it's style (spaces without grouping) i and 3=0 seems like comparing two constants and it's result been tested against i with and operator, but in realisty the expression is (i and 3) = 0 or in C/C++ like languages something like (i % 3) == 0.

I did some work in pascal in the past and evaluating using it again with mORMot and I'm not sure if this style of code formatting is a good one for the readability point of view because it seem to induce confusing/wrong interpretation like I did.
Again thank you for your time and dedication !

@synopse
Copy link
Owner

synopse commented Mar 7, 2022

Operator precedence in the pascal language does more sense than in C/C++ for sure.

@mingodad
Copy link
Author

mingodad commented Mar 7, 2022

But a bit of formatting doesn't hurt !

@mingodad
Copy link
Author

mingodad commented Mar 7, 2022

And that we are at the documentation examples I'm trying to build/execute 4.4.1.1. Variant object documents example and it has a variable that is not declared/initialized (although it has ... to denote missing pieces) and as I said before been new again to pascal and mORMot it makes a bit harder to understand/evaluate it through the documentation examples:

var Doc1,Doc2: [TDocVariantData](https://synopse.info/files/html/api-1.18/SynCommons.html#TDOCVARIANTDATA);
 ...
  Doc1.Init; // needed for proper initialization
  assert(Doc1.Kind=dvUndefined);
  Doc1.AddValue('name','John');        // add some properties
  Doc1.AddValue('birthyear',1972);
  assert(Doc1.Kind=dvObject);          // is now identified as an object
  assert(Doc1.Value['name']='John');    // read access to the properties (also as varByRef)
  assert(Doc1.Value['birthyear']=1972);
  assert(Doc1.U['name']='John');        // slightly faster read access
  assert(Doc1.I['birthyear']=1972);
  writeln(Doc1.ToJSON); // will write '{"name":"John","birthyear":1972}'
  Doc1.Value['name'] := 'Jonas';      // update one property
  writeln(Doc1.ToJSON); // will write '{"name":"Jonas","birthyear":1972}'
  Doc2.InitObject(['name','John','birthyear',1972],
///<<<<!!!!<<< here aOptions is undefined
    aOptions+[dvoReturnNullForUnknownProperty]); // initialization from name/value pairs 
///>>>>
  assert(Doc2.Kind=dvObject);
  assert(Doc2.Count=2);
  assert(Doc2.Names[0]='name');
  assert(Doc2.Values[0]='John');
  writeln(Doc2.ToJSON);         // will write '{"name":"John","birthyear":1972}'
  Doc2.Delete('name');
  writeln(Doc2.ToJSON);         // will write '{"birthyear":1972}'
  assert(Doc2.U['name']='');
  assert(Doc2.I['birthyear']=1972);
  Doc2.U['name'] := 'Paul';
  Doc2.I['birthyear'] := 1982;
  writeln(Doc2.ToJSON);         // will write '{"name":"Paul","birthyear":1982}'

Thanks again for your help, time and dedication !

@mingodad
Copy link
Author

mingodad commented Mar 7, 2022

Replacing aOptions+[dvoReturnNullForUnknownProperty] by Doc2.Options+[dvoReturnNullForUnknownProperty] allow it to build/run.

@synopse
Copy link
Owner

synopse commented Mar 7, 2022

Please use our forum for such discussion.

@mingodad
Copy link
Author

mingodad commented Mar 7, 2022

I'm trying to register the forum but it ask for What is the UPPERCASE name of the CURRENT editor of Delphi? (hint: E..O) and as I said I'm new again to Pascal (Freepascal/Delphi) and I don't know it ?

@mingodad
Copy link
Author

mingodad commented Mar 7, 2022

I was going to report this problem with this documetnatio example 4.4.1.3. Variant array documents:

var V1,V2: variant; // stored as any variant
 ...
  V1 := [_Arr](https://synopse.info/files/html/api-1.18/SynCommons.html#_ARR)(['John','Mark','Luke']);
  V2 := [_Obj](https://synopse.info/files/html/api-1.18/SynCommons.html#_OBJ)(['name','John','array',[_Arr](https://synopse.info/files/html/api-1.18/SynCommons.html#_ARR)(['one','two',2.5])]); // as nested array
writeln([VariantSaveJson](https://synopse.info/files/html/api-1.18/SynCommons.html#VARIANTSAVEJSON)(V1));
 writeln(V1);  // implicit conversion from variant into string
 // both commands will write '["John","Mark","Luke"]'
 writeln([VariantSaveJson](https://synopse.info/files/html/api-1.18/SynCommons.html#VARIANTSAVEJSON)(V2));
 writeln(V2);  // implicit conversion from variant into string
 // both commands will write '{"name":"john","array":["one","two",2.5]}'
writeln(V1._Count); // will write 3 i.e. the number of items in the array document
  writeln(V1._Kind);  // will write 2 i.e. ord(dvArray)
  for i := 0 to V1._Count-1 do
    writeln(V1.Value(i),':',V2._(i));    // Value() or _() pseudo-methods
  // will write in the console:
  //  John John
  //  Mark Mark
  //  Luke Luke
  if V1.Exists('John') then             // Exists() pseudo-method
    writeln('John found in array');
  V1.Add('new item');                   // add "new item" to the array
  V1._ := 'another new item';           // add "another new item" to the array
  writeln(V1);          // will write '["John","Mark","Luke","new item","another new item"]'
  V1.Delete(2);
  V1.Delete(1);
  writeln(V1);          // will write '["John","Luke","another new item"]'
program mytlistlikeprop;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}
  cthreads,
  {$ENDIF}
  Classes, SysUtils, CustApp, SynCommons
  { you can add units after this };

type

  { TlistLikeProp }

  TlistLikeProp = class(TCustomApplication)
  protected
    procedure DoRun; override;
  public
    constructor Create(TheOwner: TComponent); override;
    destructor Destroy; override;
    procedure WriteHelp; virtual;
  end;

{ TlistLikeProp }

procedure TlistLikeProp.DoRun;
type
   TGroup = array of integer;
var
  Group: TGroup;
  GroupA: TDynArray;
  i, v: integer;
  ErrorMsg: String;
  bv: Boolean;
  Doc1,Doc2: TDocVariantData;
  var V1,V2: variant; // stored as any variant
begin
  // quick check parameters
  ErrorMsg:=CheckOptions('h', 'help');
  if ErrorMsg<>'' then begin
    ShowException(Exception.Create(ErrorMsg));
    Terminate;
    Exit;
  end;

  // parse parameters
  if HasOption('h', 'help') then begin
    WriteHelp;
    Terminate;
    Exit;
  end;

  { add your program here }
    GroupA.Init(TypeInfo(TGroup),Group); // associate GroupA with Group
    for i := 0 to 1000 do
    begin
      v := i+1000; // need argument passed as a const variable
      GroupA.Add(v);
    end;
    v := 1500;
    if GroupA.IndexOf(v)<0 then // search by content
      Writeln('Error: 1500 not found!');
    for i := GroupA.Count-1 downto 0 do
    begin
      //bv := (i and 3) = 0;
      //Writeln('Loop at ', i, ' value ', bv);
      if (i and 3) = 0 then
        GroupA.Delete(i); // delete integer at index i
    end;

    Doc1.Init; // needed for proper initialization
    assert(Doc1.Kind=dvUndefined);
    Doc1.AddValue('name','John');        // add some properties
    Doc1.AddValue('birthyear',1972);
    assert(Doc1.Kind=dvObject);          // is now identified as an object
    assert(Doc1.Value['name']='John');    // read access to the properties (also as varByRef)
    assert(Doc1.Value['birthyear']=1972);
    assert(Doc1.U['name']='John');        // slightly faster read access
    assert(Doc1.I['birthyear']=1972);
    writeln(Doc1.ToJSON); // will write '{"name":"John","birthyear":1972}'
    Doc1.Value['name'] := 'Jonas';      // update one property
    writeln(Doc1.ToJSON); // will write '{"name":"Jonas","birthyear":1972}'
    Doc2.InitObject(['name','John','birthyear',1972],
      Doc2.Options+[dvoReturnNullForUnknownProperty]); // initialization from name/value pairs
    assert(Doc2.Kind=dvObject);
    assert(Doc2.Count=2);
    assert(Doc2.Names[0]='name');
    assert(Doc2.Values[0]='John');
    writeln(Doc2.ToJSON);         // will write '{"name":"John","birthyear":1972}'
    Doc2.Delete('name');
    writeln(Doc2.ToJSON);         // will write '{"birthyear":1972}'
    assert(Doc2.U['name']='');
    assert(Doc2.I['birthyear']=1972);
    Doc2.U['name'] := 'Paul';
    Doc2.I['birthyear'] := 1982;
    writeln(Doc2.ToJSON);         // will write '{"name":"Paul","birthyear":1982}'

    V1 := _Arr(['John','Mark','Luke']);
    V2 := _Obj(['name','John','array',_Arr(['one','two',2.5])]); // as nested array
    writeln(VariantSaveJson(V1));
    writeln(V1);  // implicit conversion from variant into string
    // both commands will write '["John","Mark","Luke"]'
    writeln(VariantSaveJson(V2));
    writeln(V2);  // implicit conversion from variant into string
    // both commands will write '{"name":"john","array":["one","two",2.5]}'

    writeln(V1._Count); // will write 3 i.e. the number of items in the array document
    writeln(V1._Kind);  // will write 2 i.e. ord(dvArray)
    for i := 0 to V1._Count-1 do
      writeln(V1.Value(i),':',V2._(i));    // Value() or _() pseudo-methods
    // will write in the console:
    //  John John
    //  Mark Mark
    //  Luke Luke
    if V1.Exists('John') then             // Exists() pseudo-method
      writeln('John found in array');
    V1.Add('new item');                   // add "new item" to the array
    V1._ := 'another new item';           // add "another new item" to the array
    writeln(V1);          // will write '["John","Mark","Luke","new item","another new item"]'
    V1.Delete(2);
    V1.Delete(1);
    writeln(V1);          // will write '["John","Luke","another new item"]'

  // stop program loop
  Terminate;
end;

constructor TlistLikeProp.Create(TheOwner: TComponent);
begin
  inherited Create(TheOwner);
  StopOnException:=True;
end;

destructor TlistLikeProp.Destroy;
begin
  inherited Destroy;
end;

procedure TlistLikeProp.WriteHelp;
begin
  { add your help code here }
  writeln('Usage: ', ExeName, ' -h');
end;

var
  Application: TlistLikeProp;
begin
  Application:=TlistLikeProp.Create(nil);
  Application.Title:='myTlistLikeProp';
  Application.Run;
  Application.Free;
end.

Output (Freepascal 3.2):

./tlistlikeprop
{"name":"John","birthyear":1972}
{"name":"Jonas","birthyear":1972}
{"name":"John","birthyear":1972}
{"birthyear":1972}
{"birthyear":1982,"name":"Paul"}
["John","Mark","Luke"]
["John","Mark","Luke"]
{"name":"John","array":["one","two",2.5]}
{"name":"John","array":["one","two",2.5]}
3
2
John:Exception at 000000000051D294: EVariantDispatchError:
No variant method call dispatch.

@synopse
Copy link
Owner

synopse commented Mar 8, 2022

Please use the forum for such discussion.
And put the source code in a separated ready-to-be-downloaded file, e.g. on gist.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants