On Fri, 28 May 2010 20:51:10 +0300
Alberto Narduzzi <albertonardu...@yahoo.com> wrote:

> >    i := self.names.indexOf(name);
> >    val := Struct(self.values[i]);
> > raises "got untyped expected Struct". Sure, that's why I'm trying to 
> > cast... Without casting to Struct, the compiler indeed throws "got pointer 
> > expected Struct". I'm very surprised since I already did this.
> 
> in first place, you can omit self within the object's methods, as it's 
> implicitly there.

Right. Just personal preference for expliciteness. (Even if I don't like magic 
names.)

> second, the property Values[] expects a string inside "[]" and not a 
> number, so you may want to use val := Values[name];

No. Sorry, I was not clear enough. Self here is a Struct, and Struct is custom 
class type. Its .values attribute is a TFPList holding objects, which also 
happen to be Struct-s; but they could be any kind of pointed thingies. .names 
is a TStringList. (*)
My issue is I cannot cast a value (thus a struct) back to its Struct type. The 
compiler refuses.
But I can do exactly the same operation, for any reason, with the simpler case 
appended to the previous post.

> third, Values return a string (the rightmost part of the "=" if you read 
> the items property (or directly l[n])), so you cannot cast it to "Struct".

... see above, and the example. It *is* a Struct.

> I think you intend to do something like:
> 
> Var
> MyStruct: Struct;
> MyList: TStringList;
> I: Integer;
> 
> (...)
> 
> MyList := TStringList.Create();
> 
> (...)
> 
> For I := 0 To 10 Do
> Begin
>    MyStruct := Struct.struct(I);
>    MyList.AddObject(Format('struct no. %d', [I]), TObject(MyStruct));
> End;
> 
> {cannot remember whether the casting to TObject is necessary or not, or 
> any syntax error I might have done, because I'm typing it out of my 
> mind, after a year or so I haven't written any pascal code... anyway, I 
> suggest you derive your Struct from TObject. And for a matter of 
> readability, I also suggest you name it TStruct instead of plainly 
> Struct, but this is a matter of taste}
> 
> (...)

Yes, thank you for this example. I will probably do this later. But as of now, 
since I did not now TStringList implements the "associated object" features, I 
use a // TFPList of objects; instead of a TStringList's .Object attribute. hope 
it's clear. It's exactly the same scheme, in fact, and I doubt there is any 
loss & again at using the one or the other.

> you can now retrieve the objects you added with:
> 
> For I := 0 To Pred(MyList.ItemsCount) Do
> Begin
>    MyStruct := Struct(MyList.Objects[I]);

This is precisely what the compiler refuses in my case. To be fully explicite, 
the above translates in my case (since both container and the values are 
structs):
    MyStructValue := Struct.(StructContainer.values[I]);

>    ...do whatever you like with your struct variable here...
> End;
> 
> If you need to retrieve your objects using the "names" you need to do 
> something like:
> 
> I := MyList.IndexOfName("struct no. 6");
> If(I >= 0)
>    MyStruct := Struct(MyList.Objects[I]);

Yes, this is the code you commented on top of this post:
> >    i := self.names.indexOf(name);
> >    val := Struct(self.values[i]);

> bear in mind that free-ing MyList does not free the instances of Struct 
> you have created and inserted; so you need to do it manually, in another 
> for-cycle, for example...
> 
> For I := 0 To Pred(MyList.ItemsCount) Do
> Begin
>    MyStruct := Struct(MyList.Objects[I]);
>    MyStruct.Free;
> End;

Yes, thank you for this warning. And, believe it or not, this is precisely in 
the destructor that the compiler refuses my casting. The reason there is no 
test. The whole .free methoid reads (untested since the compiler blocks):

destructor Struct.free;
{ Free values before freeing the structure itself. }
var i        : Integer;
    val      : Struct;
begin
    self.names.destroy;
    for i:=0 to self.count-1 do begin
        val := Struct(self.values[i]);
        val.free;
        val := nil;
    end;
    self.values.destroy;
    inherited;          // useless???
end;

> Or you can descend from TStringList (don't know if this is the best 
> thing you could do, but...), and add a property ObjectValues, with a 
> proper Getter and Setter expecting a string instead of an integer; like:

No, this does not match my case. I'd rather have a linked list for names since 
it is only traversed, to find the index of a value (so the method could follow 
pointers, instead of computing them like for an array).
But I keep the code below, thank you, as an example or property implementation 
(haven't written any yet).

> property ObjectValues[const AName:String]: TObject Read GetObjectValue 
> write SetObjectValue;
> 
> Function TMyStringList.GetObjectValue(const AName:String):TObject;
> Var I:Integer;
> Begin
>    Result := Nil;
>    I := IndexOfName(AName);
>    If (I >= 0) Then
>      Result := Objects[I];
> End;
> 
> Procedure TMyStringList.SetObjectValue(const AName:String; AObject:TObject);
> Var I:Integer;
> Begin
>    I := IndexOfName(AName);
>    If (I >= 0) Then
>      Objects[I] := AObject;
> End;
> 
> 
> As I said, take all this with a grain of salt, as I may have written 
> mistakes and/or forgot something.
> 
> Just my 2c, hope this helps.

Thank you very much.

Denis

(*) Struct is in fact the root type of an OO type system. It should be called 
"Unit" but for any reason the compiler also refuses this name ;-) The OO 
framework is to be written "in itself", meaning the model only uses its own 
features to define itself. There is a name for this kind of reflexivity. It is 
the reason why the content of a Struct is structs. Looks like a joke... Later, 
even the names will be (instances of a subtype of) Struct.
I don't know where this path leads (PascaLisp?), but I'm sure I want to follow 
it :-)
________________________________

vit esse estrany ☣

spir.wikidot.com
_______________________________________________
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply via email to