| 
| 
 | Вопрос # 4 817/ вопрос открыт / | 
 |  Здравствуйте!ок. хочу получить возможность работать со вложенными открытыми массивами, вроде такого:
 [ 'a', ['b','c'], ['d',['e','f'],'g'], 'h' ]
 при этом желательно, чтобы это был массив array of const
 
 
 собственно вопросы возникли по статье:
 http://www.delphisources.ru/pages/fa..._of_const.html
 Приложение:Переключить в обычный режим  type    ArrayOfConst  = array of TVarRec;    TArrayOfConst = array [ 0 .. High (WORD) div SizeOf (TVarRec) - 1 ] of TVarRec;    PArrayOfConst = ^TArrayOfConst; function PArrayOfConstMerge (anArgs1, anArgs2: array of const) : PArrayOfConst;var    I      : WORD;    Index  : WORD;    Length : WORD;begin    Result := NIL;    try        Length := 0;        if ( High (anArgs1) >= 0 ) then            Length := Length + High (anArgs1) - Low (anArgs1) +1;        if ( High (anArgs2) >= 0 ) then            Length := Length + High (anArgs2) - Low (anArgs2) +1;        if ( Length > 0 ) then        begin            Result := AllocMem ( Length * SizeOf (TVarRec) );            Index := 0;            for I := Low (anArgs1) to High (anArgs1) do            begin                Result^ [Index] := anArgs1 [i];                Inc (Index);            end;            for I := Low (anArgs2) to High (anArgs2) do            begin                Result^ [Index] := anArgs2 [i];                Inc (Index);            end;        end;    except        Result := NIL;    end;end; function ArrayOfConstMerge (anArgs1, anArgs2: array of const) : ArrayOfConst;var    I      : WORD;    Index  : WORD;    Length : WORD;begin    Result := NIL;    try        Length := 0;        if ( High (anArgs1) >= 0 ) then            Length := Length + High (anArgs1) - Low (anArgs1) +1;        if ( High (anArgs2) >= 0 ) then            Length := Length + High (anArgs2) - Low (anArgs2) +1;        if ( Length > 0 ) then        begin            SetLength (Result,Length);            Index := 0;            for I := Low (anArgs1) to High (anArgs1) do            begin                Result [Index] := anArgs1 [i];                Inc (Index);            end;            for I := Low (anArgs2) to High (anArgs2) do            begin                Result [Index] := anArgs2 [i];                Inc (Index);            end;        end;    except        Result := NIL;    end;end; function PointerToArrayOfConst (anArgs: array of const) : PArrayOfConst;var    I      : WORD;    Index  : WORD;    Length : WORD;begin    Result := NIL;    try        Length := 0;        if ( High (anArgs) >= 0 ) then            Length := Length + High (anArgs) - Low (anArgs) +1;        if ( Length > 0 ) then        begin            Result := AllocMem ( Length * SizeOf (TVarRec) );            Index := 0;            for I := Low (anArgs) to High (anArgs) do            begin                Result^ [Index] := anArgs [i];                Inc (Index);            end;        end;    except        Result := NIL;    end;end;   function f1 (anArgs: array of const) : String;var    I : Integer;begin    Result := '';    for I := Low (anArgs) to High (anArgs) do        Result := Format ('%s:%s',[ Result, ParamToStr (anArgs [i]) ]);end; function f2 (anArgs: array of const) : String;begin    Result := f1 ( ArrayOfConstMerge (anArgs,['test','testtest','yo-ho','hi-hi','laaa']) );end; function arrays (anArgs: array of const) : String;var    I : Integer;    P : PArrayOfConst;begin    Result := '';    for I := Low (anArgs) to High (anArgs) do    begin        P := ParamToPointer (anArgs [i]);        if Assigned (P) then            Result := Format ('%s;%s',[ Result, f1 ( PointerToArrayOfConst (P) ) ])        else            Result := Format ('%s;%s',[ Result, ParamToStr (anArgs [i]) ]);    end;end; s := arrays ( [ 'a', _const (['hello','world','test1']), 1, _const (['test2','test3']), _const ([])
] );  ;a;:hello:world:test1;1;:test2:test3;0   function _const (anArgs: PArrayOfConst) : ArrayOfConst;var    ArrayOfConstCallAlias : procedure (var Result: ArrayOfConst; var anArgs: TVarRec; High: WORD);    I                     : WORD;    A                     : ArrayOfConst;     procedure ArrayOfConstCall (var Result: ArrayOfConst; anArgs: array of const);    var        I      : WORD;        Index  : WORD;        Length : WORD;    begin        Result := NIL;        try            Length := 0;            if ( High (anArgs) >= 0 ) then                Length := Length + High (anArgs) - Low (anArgs) +1;            if ( Length > 0 ) then            begin                SetLength (Result,Length);                Index := 0;                for I := Low (anArgs) to High (anArgs) do                begin                    Result [Index] := anArgs [i];                    Inc (Index);                end;            end;        except            Result := NIL;        end;    end; begin    Result := NIL;    try        @ArrayOfConstCallAlias := @ArrayOfConstCall;        I := 0;        while ( I < H ) do        begin            ArrayOfConstCallAlias ( A, anArgs^ [i], SizeOf (anArgs) div SizeOf (TVarRec) );            if ( I = 0 ) then                Result := A            else                Result := ArrayOfConstMerge (Result,A);            Inc (I);        end;    except        Result := NIL;    end;end;
|  |   Вопрос задал: mirt.steelwater (статус: Посетитель)Вопрос отправлен: 14 декабря 2010, 09:55
 Состояние вопроса: открыт, ответов: 0.
 |  
 Мини-форум вопросаВсего сообщений: 8; последнее сообщение — 16 декабря 2010, 13:20; участников в обсуждении: 2. 
|   | Вадим К (статус: Академик), 14 декабря 2010, 10:36 [#1]:хочется массивы произвольной вложенности? p.s. ссылка на в вопросе битая.
 Галочка "подтверждения прочтения" - вселенское зло. |  
|   | mirt.steelwater (статус: Посетитель), 14 декабря 2010, 12:18 [#2]:да, произвольной вложенности ссылка побилась видимо(
 я частично реализовал эту задачу вот так:
 
 function _const (anArgs: array of const) : ArrayOfConst;
var
    I      : WORD;
    Index  : WORD;
    Length : WORD;
begin
    Length := 0;
    if ( High (anArgs) >= 0 ) then
        Length := Length + High (anArgs) - Low (anArgs) +1;
    if ( Length > 0 ) then
    begin
        SetLength (Result,Length);
        Index := 0;
        for I := Low (anArgs) to High (anArgs) do
        begin
            Result [Index] := anArgs [I];
            Inc (Index);
        end;
    end;
end;
 
function ParamToArrayOfConst (const aValue: TVarRec) : ArrayOfConst;
begin
    Result := _const([]);
    with aValue do
    try
        case VType of
            vtPointer: Result := VPointer;
        end;
    except
        Result := _const([]);
    end;
end;и теперь могу обходить массив вот так:
 
 function arrays (anArgs: array of const) : String;
var
    I : WORD;
    A : ArrayOfConst;
begin
    Result := '';
    for I := Low (anArgs) to High (anArgs) do
    begin
        A := ParamToArrayOfConst (anArgs [I]);
        if Assigned (A) then
        begin
            if ( I <= Low (anArgs) ) then
                Result := arrays (A)
            else
                Result := Format ('%s, %s',[ Result, arrays (A) ]);
        end
        else if ( I <= Low (anArgs) ) then
            Result := ParamToStr (anArgs [I])
        else
            Result := Format ('%s, %s',[ Result, ParamToStr (anArgs [I]) ]);
    end;
    Result := Format ('[%s]',[Result]);
end;
 
caption := arrays ([ 'a', _const(['test1']), 'b', _const(['test2','test3']), 'c', Pointer(TForm), NIL, self,
_const(['test4','test5','test6',  _const(['A','B','C']), 'test7' ]), 'hello', 3.14159265 ]);все работает, но возникает исключение, которое нельзя корректно обработать, если я передам Pointer (Form1) , например - процедуры пытается получить в этом случае из указателя массив и все плохо заканчиваетсяⒶ свобода сопротивление солидарность |  
|   | mirt.steelwater (статус: Посетитель), 14 декабря 2010, 12:35 [#3]:забыл описание функции 
 function ParamToStr (const aValue: TVarRec) : String;
begin
    Result := '';
    with aValue do
    try
        case VType of
            vtInteger:    Result := IntToStr (VInteger);
            vtBoolean:    Result := BooleanToStr (VBoolean);
            vtChar:       Result := VChar;
            vtExtended:   Result := FloatToStr (VExtended^);
            vtString:     Result := VString^;
            vtPointer:    Result := IntToStr ( Longint (VPointer) );
            vtPChar:      Result := StrPas (VPChar);
            vtObject:     Result := VObject.ClassName;
            vtClass:      Result := VClass.ClassName;
            vtAnsiString: Result := String (VAnsiString);
            vtWideChar:   Result := Char (VWideChar);
            vtPWideChar:  Result := WideCharToString (VPWideChar);
            vtWideString: Result := WideCharToString (VWideString);
            vtCurrency:   Result := FloatToStr (VCurrency^);
            vtInt64:      Result := IntToStr (VInt64^);
            vtVariant:    Result := VVariant^;
        end;
    except
        Result := '';
    end;
end;Ⓐ свобода сопротивление солидарность |  
|   | Вадим К (статус: Академик), 14 декабря 2010, 12:47 [#4]:Я правильно понимаю, хочется сделать фактически питоновские типы? 
 
 Цитата: если я передам Pointer (Form1) , например - процедуры пытается получить в этом случае из указателя массив и все плохо заканчивается логично. указатель не хранит информацию о типе. Варианты решения:
 - специфицировать, что произвольные указатели нельзя передавать. А в коде сделать try except, который просто будет возвращаться с процедуры или вообще закрывать программу, выдав отладочные сообщения.
 - построить костыли и попытаться научиться угадывать тип указателя (и получить самые феерические ошибки)
 - помещать в массив данные специального типа - variant
 - помещать в массив данные своего типа. если делфи старше 2005-2007, то можно даже написать специальные методы, что бы сделать работу прозрачной.
 - устроится на работу в Embracadero и поправить багу в компиляторе
  - перейти на другой язык программирования
   Галочка "подтверждения прочтения" - вселенское зло. |  
|   | mirt.steelwater (статус: Посетитель), 14 декабря 2010, 15:56 [#5]:спасибо  я отел вначале использовать типизированные указатели, но array of const четко содержит ссылку именно на такой вариант TVarRec - с нетипизированным указателем.
 вариант с обработкой ошибки меня бы устроил, я собственно, и думал так сделать:
 
     try
        ...
    except
        Result := _const([]);
    end;в ряде случаев там возникают ошибки, которые покидают блок except - вероятно все из-за того же Acces Violation - можно ли как-нибудь хранить в указателе его тип и читать его на низком уровне? как-то это ведь работает с типизированными указателями дельфи?однако
 Ⓐ свобода сопротивление солидарность |  
|   | Вадим К (статус: Академик), 14 декабря 2010, 17:19 [#6]:указатель на то и указатель, что там только 4 байта данных - только адрес. Поэтому наверно придется заводить ассоциативный массив для указателей и помнить их тип. Но кому это нужно. Делфи в целом не различает указателей. Основная работа проводиться ещё на уровне компиляции. Галочка "подтверждения прочтения" - вселенское зло. |  
|   | mirt.steelwater (статус: Посетитель), 16 декабря 2010, 13:03 [#7]:>>Я правильно понимаю, хочется сделать фактически питоновские типы? 
 да
   Ⓐ свобода сопротивление солидарность |  
|   | Вадим К (статус: Академик), 16 декабря 2010, 13:20 [#8]:Это очень плохая практика - писать в одном языке методами другого. Нужно просто искать правильный путь реализации идеи. А для этого иногда нужно менять алгоритмы и мировоззрение. 
 Говоря по простому - "со своим чайником в Тулу не едут
  " Галочка "подтверждения прочтения" - вселенское зло. |  Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте. |