Заметки о тестировании, программировании и прочий "поток сознания", который жалко писать "в стол"
вторник, 28 ноября 2017 г.
воскресенье, 19 ноября 2017 г.
четверг, 16 ноября 2017 г.
Реализация ADT на моих скриптах
Собственно определение аксиоматики ADT:
Определение типа List и операций над ним:
Примеры использования типа List:
(+) http://programmingmindstream.blogspot.ru/2017/11/adt.html?m=1
UNIT ADT.ms.dict USES axiom:CompiledWordWorkerWord axiom:TtfwSuppressNextImmediate axiom:Capture ; //BOOLEAN CompileTime-VAR g_NeedLog true BOOLEAN CompileTime-VAR g_NeedLog false STRING CompileTime-VAR g_Indent '' : :Log ToPrintable if g_NeedLog then ( ToPrintable 'Log: ' SWAP Cat g_Indent SWAP Cat . ) else DROP ; // :Log : :Log: ^@ IN aName ^ IN aLambda if g_NeedLog then begin STRING VAR l_Name aName DO >>> l_Name l_Name ' Enter' Cat :Log TF g_Indent ( g_Indent ' ' Cat >>> g_Indent aLambda DO ) // TF g_Indent l_Name ' Leave' Cat :Log end // g_NeedLog else begin aLambda DO end // g_NeedLog ; // :Log: : OutDelim '----------' . ; // OutDelim : . ToPrintable if g_NeedLog then ( 'Value: ' SWAP Cat ) . ; // . PROCEDURE :Dump WordOrBox IN aValue PROCEDURE :DoDump WordOrBox IN aValue RULES ( aValue pop:Word:IsCapture ) ( aValue Capture:Lambda CodeIterator ==> DumpCodeCall ) //( aValue Capture:Lambda DumpElement ) //() //( aValue DumpElement ) DEFAULT () ; // RULES ; // :DoDump RULES ( g_NeedLog ! ) () ( aValue IsWordBox ) ( aValue pop:WordBox:Boxed :DoDump ) DEFAULT ( aValue :DoDump ) ; // RULES ; // :Dump : :ValueDo WordOrBox IN aValue aValue :Log //aValue :Dump aValue DO DUP :Log ; // :ValueDo : DerefParam IN aValue : DoDeref 'DerefParam' :Log: ( aValue :ValueDo ) ; // DoDeref if ( aValue IsWordBox ) then ( aValue pop:WordBox:Boxed >>> aValue ) RULES ( aValue IsWord ) ( RULES ( aValue pop:Word:IsWordPusher ) DoDeref ( aValue pop:Word:IsBeginLike ) DoDeref ( aValue pop:Word:IsConst ) DoDeref DEFAULT aValue ; // RULES ) DEFAULT aValue ; // RULES ; // DerefParam //MACRO STACK_CHANGING_MACRO codePusher IN aCode aCode pop:Word:CodeIterator .for> DO aCode pop:Word:DecRef ; // codePusher STRING CompileTime-VAR g_CurrentDataName '' TkwCompiledTypedKeyValues ARRAY ItfwWordBox TYPE ADT STACK_CHANGING_MACRO data ^L IN aName ^ IN aCode /*{ @SELF Ctx:SetWordProducerForCompiledClass class::TkwCompiledKeyValues Ctx:SetCompiledClassForCompilingWord 'axiom:operator' Ctx:Parser:PushSymbol aName |N Ctx:Parser:PushSymbol ';' Ctx:Parser:PushSymbol}*/ VAR l_Name aName |N >>> l_Name l_Name >>> g_CurrentDataName //'ANY' Ctx:Parser:PushSymbol 'ADT' Ctx:Parser:PushSymbol //'TkwCompiledTypedKeyValues' Ctx:Parser:PushSymbol //'ARRAY' Ctx:Parser:PushSymbol 'TYPE' Ctx:Parser:PushSymbol l_Name Ctx:Parser:PushSymbol aCode pop:Word:IncRef aCode 'codePusher' Ctx:Parser:PushSymbol ; // data INTEGER CompileTime-VAR g_UnnamedCount 0 IMMEDIATE VOID OPERATOR unnamed 'field' g_UnnamedCount IntToStr + @SELF axiom:DefineVar INC g_UnnamedCount ; // unnamed IMMEDIATE VOID OPERATOR unnamedleft 'field' g_UnnamedCount IntToStr + @SELF axiom:DefineVar INC g_UnnamedCount ; // unnamedleft /*{IMMEDIATE VOID OPERATOR VAR ^L IN aName aName |N @SELF axiom:DefineVar ; // VAR}*/ STACK_CHANGING_MACRO constructorPusher IN aSelf IN aCode IN aName VAR l_Members aCode pop:Word:MembersIterator >>> l_Members VAR l_IsAtomic l_Members .IsEmpty >>> l_IsAtomic aSelf Ctx:SetWordProducerForCompiledClass if l_IsAtomic then begin //class::TkwCompiledKeyValues Ctx:SetCompiledClassForCompilingWord class::TkwCompiledTypedKeyValues Ctx:SetCompiledClassForCompilingWord //class::TkwCompiledKeyValuesWithWordInfo Ctx:SetCompiledClassForCompilingWord g_CurrentDataName Ctx:Parser:PushSymbol end // l_IsAtomic else begin g_CurrentDataName Ctx:Parser:PushSymbol end // l_IsAtomic //( 'INTERFACE' Ctx:Parser:PushSymbol ) 'axiom:operator' Ctx:Parser:PushSymbol aName Ctx:Parser:PushSymbol if ( l_IsAtomic ! ) then begin VAR l_Count 0 >>> l_Count ARRAY VAR l_FieldNames [ l_Members .for> ( IN anItem if ( anItem pop:Word:Producer @ unnamedleft == ) then begin '^@' Ctx:Parser:PushSymbol end // ( anItem pop:Word:Producer @ unnamedleft ) else begin '^' Ctx:Parser:PushSymbol end // ( anItem pop:Word:Producer @ unnamedleft ) 'IN' Ctx:Parser:PushSymbol VAR l_FieldName 'aField' l_Count IntToStr Cat >>> l_FieldName l_FieldName Ctx:Parser:PushSymbol INC l_Count l_FieldName ) // .for> ] >>> l_FieldNames '[' Ctx:Parser:PushSymbol l_FieldNames .for> ( IN anItem anItem Ctx:Parser:PushSymbol 'DerefParam' Ctx:Parser:PushSymbol 'nil' Ctx:Parser:PushSymbol '>>>' Ctx:Parser:PushSymbol anItem Ctx:Parser:PushSymbol ) // .for> ']' Ctx:Parser:PushSymbol /*{ 'KeyValuesCreate:' Ctx:Parser:PushSymbol '(' Ctx:Parser:PushSymbol 'IN' Ctx:Parser:PushSymbol 'aMade' Ctx:Parser:PushSymbol l_FieldNames .for> ( IN anItem 'aMade' Ctx:Parser:PushSymbol '->' Ctx:Parser:PushSymbol anItem 'a' .CutPrefix Ctx:Parser:PushSymbol ':=' Ctx:Parser:PushSymbol '(' Ctx:Parser:PushSymbol anItem Ctx:Parser:PushSymbol 'DerefParam' Ctx:Parser:PushSymbol ')' Ctx:Parser:PushSymbol ) // .for> ')' Ctx:Parser:PushSymbol}*/ '>>>' Ctx:Parser:PushSymbol 'Result' Ctx:Parser:PushSymbol end // ( l_IsAtomic ! ) ';' Ctx:Parser:PushSymbol 0 >>> g_UnnamedCount aCode pop:Word:DecRef ; // constructorPusher //MACRO //PROCEDURE : constructor ^L IN aName ^ IN aCode aCode pop:Word:IncRef 'constructorPusher' Ctx:Parser:PushSymbol @SELF aCode aName |N ; // constructor : .DO? IN aValue : DoDeref '.DO?' :Log: ( aValue :ValueDo ) true ; // DoDeref if ( aValue IsWordBox ) then ( aValue pop:WordBox:Boxed >>> aValue ) RULES ( aValue IsWord ) begin RULES // - проверка на то, что это конструктор, чтобы не звать все подряд ссылки на функции ( aValue pop:Word:IsConst ) begin // - тут вычисляется ссылка на значение DoDeref end // ( aValue pop:Word:IsConst ) ( aValue pop:Word:IsBeginLike ) begin // - чтобы работало ( 1 ) в xs DoDeref end // ( aValue pop:Word:IsBeginLike ) ( aValue pop:Word:IsWordPusher ) begin false ?ASSURE 'Ловушка' aValue DO DO true end // ( aValue pop:Word:IsWordPusher ) ( aValue Is class::TkwCompiledTypedKeyValues ) begin // - тут зовутся нульарные конструкторы ( aValue pop:Word:Producer @ constructor == ) ?ASSURE [ aValue pop:Word:Name ' : ' aValue pop:Word:Producer pop:Word:Name ] //DoDeref aValue false end // ( aValue Is TkwCompiledTypedKeyValues ) ( aValue pop:Word:IsRunner ) begin // - тут зовутся все остальные конструкторы ( aValue pop:Word:Producer @ constructor == ) ?ASSURE [ aValue pop:Word:Name ' : ' aValue pop:Word:Producer pop:Word:Name ] DoDeref end // ( aValue pop:Word:IsRunner ) ( aValue pop:Word:IsCapture ) DoDeref DEFAULT begin //( [ aValue pop:Word:Name ' : ' aValue pop:Word:Producer pop:Word:Name ] strings:Cat Msg ) aValue false end // DEFAULT ; // RULES end // ( aValue IsWord ) DEFAULT begin aValue false end // DEFAULT ; // RULES ; // .DO? INTEGER CompileTime-VAR g_Guard 0 : .getMembers ADT IN aData VAR l_Index if ( aData IsArray ! ) then ( aData DO >>> aData ) //aData Array:Count >>> l_Index 0 >>> l_Index aData //.reverted> .for> ( //DEC l_Index INC g_Guard TRY //if ( g_Guard < 10 ) then //if ( g_Guard < 5 ) then if ( g_Guard < 4 ) then begin .DO? ? begin DUP l_Index aData Array:SetItem end // .DO? end // ( g_Guard < 10 ) FINALLY DEC g_Guard END INC l_Index ) // .for> /*{ aData pop:Word:MembersIterator .reverted> .for> ( IN anItem anItem DO .DO? ) // .for>}*/ ; // .getMembers ARRAY FUNCTION array:CopyWithoutDuplicatedStrings IN anArray RULES ( anArray .IsNil ) [nil] ( anArray Array:SortKey TtfwSortKey::tfw_skString == ) // - типа и так сортированный - не надо ничего копировать anArray DEFAULT ( VAR l_Used Array:MakeStringSorted >>> l_Used VAR l_Copy [] >>> l_Copy VAR l_Empty true >>> l_Empty anArray .filter> .AddToArray?: l_Used .for> ( IN anElement anElement .AddToArray: l_Copy false >>> l_Empty ) // anArray .for> RULES l_Empty [nil] DEFAULT l_Copy ; // RULES ) ; // RULES >>> Result ; // array:CopyWithoutDuplicatedStrings ARRAY FUNCTION TotalMembers VAR l_It nil >>> l_It VAR l_W Context:rWordCompilingNow >>> l_W while ( l_W .NotIsNil ) begin l_W pop:Word:MembersIterator .filter> ( pop:Word:Name 'Result' != ) .join> l_It >>> l_It if ( Ctx:WordDefiningNow l_W == ) then ( nil >>> l_W ) else ( l_W pop:Word:Parent >>> l_W ) end l_It .filter> pop:Word:IsVarLike .filter> ( pop:Word:IsGlobalVar ! ) .map> pop:Word:Name array:CopyWithoutDuplicatedStrings >>> l_It l_It >>> Result ; // TotalMembers MACRO match VAR l_Names [ VAR l_Parser Ctx:Parser >>> l_Parser VAR l_Continue true >>> l_Continue l_Parser pop:Parser:NextToken while l_Continue begin STRING VAR l_Token l_Parser pop:Parser:TokenLongString >>> l_Token if ( l_Token ':' == ) then begin ( false >>> l_Continue ) end // ( l_Token ':' == ) else begin l_Token l_Parser pop:Parser:NextToken end // ( l_Token ':' == ) end // true ] >>> l_Names VAR l_It TotalMembers >>> l_It l_Names .filter> ( l_It SWAP array:HasString ! ) .filter> ( '_' != ) .for> ( IN anItem 'VAR' Ctx:Parser:PushSymbol anItem Ctx:Parser:PushSymbol ) // .for> '.getMembers' Ctx:Parser:PushSymbol l_Names .reverted> .for> ( IN anItem if ( anItem '_' == ) then begin 'DROP' Ctx:Parser:PushSymbol end // ( anItem '_' == ) else begin '>>>' Ctx:Parser:PushSymbol anItem Ctx:Parser:PushSymbol end // ( anItem '_' == ) ) // .for> ; // match WordAliasSafe !( ( : .Check? IN aValue VAR l_Value : DoDeref '.Check?' :Log: ( aValue :ValueDo DUP >>> l_Value ) true ; // DoDeref aValue >>> l_Value RULES ( aValue IsWordBox ) RULES ( l_Value pop:Word:IsCapture ) ( DoDeref if ( ( l_Value IsWordBox ) AND ( l_Value pop:Word:IsCapture ) ) then begin false ?ASSURE 'Ловушка' //'got' Msg DROP // - снимаем true l_Value call.me end // ( l_Value pop:Word:IsCapture ) ) DEFAULT ( aValue false ) ; // RULES ( aValue IsWord ) RULES ( aValue pop:Word:IsWordPusher ) ( aValue :ValueDo MakeCaptureScreen true ) //( aValue :ValueDo MakeCaptureScreen false ) //( aValue false ) ( aValue pop:Word:IsConst ) // Чтобы работало: ^@( aList1 ) :List: ^@( aList2 ) DoDeref ( aValue pop:Word:IsRunner ) // Чтобы работало: ^@( aList1 ) :List: ^@( aList2 ) begin //( aValue pop:Word:Producer @ constructor == ) ?ASSURE // [ aValue pop:Word:Name ' : ' aValue pop:Word:Producer pop:Word:Name ] DoDeref end // ( aValue pop:Word:IsRunner ) DEFAULT ( aValue false ) ; // RULES DEFAULT ( aValue false ) ; // aValue ; // .Check? PROCEDURE .OutCapture ARRAY IN anIt //if ( anIt .NotEmpty ) then begin 'Capture:' Ctx:Parser:PushSymbol '[' Ctx:Parser:PushSymbol anIt .for> ( IN anItem anItem Ctx:Parser:PushSymbol ) // anIt .for> ']' Ctx:Parser:PushSymbol '!(' Ctx:Parser:PushSymbol anIt .for> ( IN anItem 'IN' Ctx:Parser:PushSymbol '_' anItem Cat Ctx:Parser:PushSymbol ) // anIt .for> anIt .for> ( IN anItem ':' Ctx:Parser:PushSymbol anItem Ctx:Parser:PushSymbol STRING VAR l_Item '_' anItem Cat >>> l_Item l_Item Ctx:Parser:PushSymbol '.Check?' Ctx:Parser:PushSymbol '?' Ctx:Parser:PushSymbol '(' Ctx:Parser:PushSymbol 'DUP' Ctx:Parser:PushSymbol '>>>' Ctx:Parser:PushSymbol // - типа перезаписываем значение l_Item Ctx:Parser:PushSymbol ')' Ctx:Parser:PushSymbol ';' Ctx:Parser:PushSymbol ) // anIt .for> end // ( anIt .NotEmpty ) /*{ else begin '!(' Ctx:Parser:PushSymbol end // ( anIt .NotEmpty )}*/ ; // .OutCapture MACRO Cap( TotalMembers .OutCapture ; // Cap( MACRO Cap[ VAR l_Names [ VAR l_Parser Ctx:Parser >>> l_Parser VAR l_Continue true >>> l_Continue l_Parser pop:Parser:NextToken while l_Continue begin STRING VAR l_Token l_Parser pop:Parser:TokenLongString >>> l_Token if ( l_Token '](' == ) then begin ( false >>> l_Continue ) end // ( l_Token ':' == ) else begin l_Token l_Parser pop:Parser:NextToken end // ( l_Token ':' == ) end // true ] >>> l_Names l_Names .OutCapture ; // Cap[ WordAlias ^@[ Cap[ WordAlias ^@( Cap( IMMEDIATE VOID operator def ^L IN aName VAR l_Compiler VAR l_Name aName |N >>> l_Name @ ( IN aCode 'Result' aCode pop:Word:FindMember pop:KeyWord:Word aCode pop:Compiler:AddCodePartRef TtfwSuppressNextImmediate::tfw_sniNo @ pop:Word:SetValue aCode pop:Word:AddCodePart ) // BeforeFinishDefinitionOfNewWord @ ( IN aCode VAR l_KW l_Name aCode pop:Word:CheckWord >>> l_KW @ call.me l_KW pop:KeyWord:SetWord ) // AfterFillCompiledWord .TtfwProcedureEx.Create >>> l_Compiler TRY l_Name Ctx:SetNewWordName @SELF Ctx:SetWordProducerForCompiledClass l_Compiler DO FINALLY l_Compiler Word:DecRef END // TRY..FINALLY ; // def WordAlias Lambda ^@ /*{ : :Call Lambda IN aLambda aLambda DO >>> aLambda RULES ( aLambda pop:Word:IsWordPusher ) ( aLambda DO >>> aLambda aLambda DO ) DEFAULT ( aLambda DO ) ; // RULES ; // :Call}*/ : :CallOn IN aParam Lambda IN aLambdaToCall : :CheckParam IN aParam RULES ( aParam IsWordBox ) RULES ( aParam pop:Word:IsCapture ) ( aParam DO ) DEFAULT aParam ; // RULES DEFAULT aParam ; // RULES ; // :CheckParam /*{ if ( aLambdaToCall pop:Word:IsVarLike ! ) then begin aLambdaToCall pop:Word:Name Msg aLambdaToCall pop:Object:ClassName Msg end }*/ VAR l_Lambda //if ( aLambdaToCall pop:Word:IsVarLike ! ) then // ( aLambdaToCall pop:Object:ClassName Msg ) if ( aLambdaToCall pop:Word:IsVarLike ) then ( aLambdaToCall pop:Word:GetValue >>> l_Lambda ) else ( aLambdaToCall DO >>> l_Lambda ) //if ( aLambdaToCall pop:Word:IsVarLike ! ) then // ( aLambdaToCall pop:Object:ClassName Msg ) RULES ( l_Lambda pop:Word:IsWordPusher ) ( l_Lambda DO >>> l_Lambda //if ( aLambdaToCall pop:Word:IsVarLike ! ) then // ( aLambdaToCall pop:Object:ClassName Msg ) //aLambdaToCall pop:Word:Name Msg //aLambdaToCall pop:Object:ClassName Msg if ( aLambdaToCall pop:Word:IsVarLike ) then begin //l_Lambda Msg l_Lambda MakeCaptureScreen >>> l_Lambda l_Lambda >>>^ aLambdaToCall //'got' Msg end // ( aLambdaToCall pop:Word:IsVarLike ) aParam :CheckParam l_Lambda DO ) DEFAULT ( aParam :CheckParam l_Lambda DO ) ; // RULES ; // :CallOn
Определение типа List и операций над ним:
UNIT ADTList.ms.dict USES ADT.ms.dict ; data List ( //constructor List: ( ANY unnamed List unnamed ) constructor :List: ( ANY unnamedleft List unnamed ) constructor List:[] () ) // List List def List: ^ IN aList1 ^ IN aList2 ^@[ aList1 ]( aList1 ) :List: ^@[ aList2 ]( aList2 ) ; // List: //PROCEDURE : // - чтобы итератор мог на стек значения возвращать, например для преобразования к массиву .List:For: List IN aList ^ IN aLambda RULES ( aList List:[] == ) () DEFAULT begin 'List:ForFor:' :Log: ( VAR l_Continue true >>> l_Continue while l_Continue begin aList match l_Head aList : l_Head aLambda :CallOn if ( aList List:[] == ) then ( false >>> l_Continue ) end // l_Continue ) // 'List:ForFor:' :Log: end // DEFAULT ; // RULES nil >>> aList ; // .List:For: List def .List:Map List IN aList Lambda IN aLambda RULES ( aList List:[] == ) List:[] DEFAULT begin 'List:Map' :Log: ( aList match l_Head l_Tail : ^@[ l_Head aLambda ]( l_Head aLambda :CallOn ) :List: ^@[ l_Tail aLambda ]( l_Tail aLambda call.me ) ) end // DEFAULT ; // RULES ; // .List:Map List def .List:Filter List IN aList Lambda IN aLambda 'List:Filter' :Log: ( VAR l_Cont true >>> l_Cont while l_Cont begin RULES ( aList List:[] == ) ( List:[] false >>> l_Cont ) DEFAULT begin aList match l_Head aList : if ( l_Head aLambda :CallOn ) then begin ^@[ l_Head ]( l_Head ) :List: ^@[ aList aLambda ]( aList aLambda .List:Filter ) false >>> l_Cont end // ( l_Head aLambda :CallOn ) end // DEFAULT ; // RULES end // while l_Cont ) // 'List:Filter' :Log: ; // .List:Filter List def .List:Join List IN aList1 List IN aList2 RULES ( aList1 List:[] == ) aList2 ( aList2 List:[] == ) aList1 DEFAULT begin 'List:Join' :Log: ( aList1 match l_Head l_Tail : ^@[ l_Head ]( l_Head ) :List: ^@[ l_Tail aList2 ]( l_Tail aList2 call.me ) ) end // DEFAULT ; // RULES ; // .List:Join List def .List:Take List IN aList INTEGER IN aCount RULES ( aList List:[] == ) List:[] ( aCount <= 0 ) List:[] DEFAULT begin 'List:Take' :Log: ( aList match l_Head l_Tail : ^@[ l_Head ]( l_Head ) :List: ^@[ l_Tail aCount ]( l_Tail aCount ` - 1 call.me ) ) end // DEFAULT ; // RULES nil >>> aList ; // .List:Take INTEGER def .List:Count List IN aList RULES ( aList List:[] == ) 0 DEFAULT begin 'List:Count' :Log: ( aList match _ l_Tail : 1 ` + ( l_Tail call.me ) //1 l_Tail call.me + ) end // DEFAULT ; // RULES ; // .List:Count List def .Any:ToList ANY IN anItem ^@[ anItem ]( anItem ) :List: List:[] ; // .Any:ToList WordAlias .ItemToList .Any:ToList List def .List:Add List IN aList ANY IN aValue 'List:Add' :Log: ( aList aValue .Any:ToList //^@[ aValue ]( aValue ) :List: List:[] .List:Join ) ; // .List:Add List def xs 'xs' :Log: ( 1 :List: ^@[ ]( xs ( 2 * ) .List:Map ) ) ; // xs List def xs1 'xs1' :Log: ( 1 :List: ^@[ ]( xs1 ( 1 + ) .List:Map ) ) ; // xs1 List def xs2 List:[] ; // xs2 List def xs3 INTEGER IN aStart 'xs3' :Log: ( ^@[ aStart ]( aStart ) :List: ^@[ aStart ]( aStart ` + 1 xs3 ) ) ; // xs3 List def .Array:ToList ARRAY IN anArray List VAR l_List List:[] >>> l_List anArray .for> ( IN anItem l_List anItem .List:Add >>> l_List ) // anArray .for> l_List ; // .Array:ToList WordAlias .ArrayToList .Array:ToList /*{ qsort [] = [] qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ qsort (filter (>= x) xs) }*/ List def .List:Sort List IN aList RULES ( aList List:[] == ) List:[] DEFAULT begin 'List:Sort' :Log: ( aList match l_Head l_Tail : l_Tail ^@[ l_Head ]( l_Head LESS ) .List:Filter .List:Sort l_Head .ItemToList .List:Join l_Tail ^@[ l_Head ]( l_Head SWAP LESS ) .List:Filter //l_Tail ^@[ l_Head ]( l_Head LESS ! ) .List:Filter .List:Sort .List:Join ) end // DEFAULT ; // RULES ; // .List:Sort ARRAY def .List:ToArray List IN aList Capture: [ aList ] ( OBJECT IN aLambda List IN aList aList .List:For: ( aLambda DO ) ) FunctorToIterator ; // .List:ToArray WordAlias .ListToArray .List:ToArray
Примеры использования типа List:
PROGRAM ADT.ms.script USES ADT.ms.dict ; USES ADTList.ms.dict ; Test&Dump ADTTest data MyEnum ( constructor One () constructor Two () constructor Three () ) // MyEnum //MyEnum . One . Two . Three . One One == . Two Two == . Three Three == . One Two == . xs2 . xs 10 .List:Take .ListToArray . //.List:For: . OutDelim xs1 10 .List:Take .ListToArray . //.List:For: . OutDelim xs 10 .List:Take xs 10 .List:Take .List:Join .ListToArray . //.List:For: . OutDelim xs 10 .List:Take xs .List:Join 10 .List:Take .ListToArray . //.List:For: . OutDelim xs //10 //.List:Take // - на самом деле - всё равно есть тут Take или нет // ибо объединяются ДВЕ БЕСКОНЕЧНЫЕ последовательности, а выбирается потом из первой из них xs .List:Join 10 .List:Take .ListToArray . //.List:For: . OutDelim xs ( 4 != ) .List:Filter 10 .List:Take ( 2 != ) .List:Filter .ListToArray . //.List:For: . OutDelim List: 1 List:[] IsOdd .List:Filter .ListToArray . //.List:For: . OutDelim List:[] . OutDelim VAR l_List List: 1 List:[] >>> l_List l_List .ListToArray . //.List:For: . OutDelim List: 1 List: 2 List:[] >>> l_List l_List .ListToArray . //.List:For: . OutDelim List: 1 List: 2 List: 3 List: 4 List: 5 List: 6 List:[] >>> l_List l_List .ListToArray . //.List:For: . OutDelim List: 1 List: 2 List: 3 List: 4 List: 5 List: 6 List:[] .ListToArray . //.List:For: . OutDelim List: 1 List: 2 List: 3 List: 4 List: 5 List: 6 List: 7 List: 8 List: 9 List: 10 List:[] .ListToArray . //.List:For: . OutDelim List: 1 List:[] IsOdd .List:Filter .ListToArray . //.List:For: . OutDelim List: 1 List: 2 List: 3 List: 4 List: 5 List: 6 List: 7 List: 8 List: 9 List: 10 List:[] IsOdd .List:Filter .ListToArray . //.List:For: . OutDelim List: 1 List: 2 List: 3 List: 4 List: 5 List: 6 List: 7 List: 8 List: 9 List: 10 List:[] IsEven .List:Filter .ListToArray . //.List:For: . OutDelim List: 1 List: 2 List: 3 List: 4 List: 5 List: 6 List: 7 List: 8 List: 9 List: 10 List:[] IsEven .List:Filter 3 .List:Take .ListToArray . //.List:For: . OutDelim List: 1 List: 2 List:[] ( 2 * ) .List:Map ( 1 + ) .List:Map .ListToArray . //.List:For: . OutDelim List: 1 List:[] ( 2 * ) .List:Map .ListToArray . //.List:For: . OutDelim List: 1 List: 2 List: 3 List: 4 List: 5 List: 6 List: 7 List: 8 List: 9 List: 10 List:[] ( 2 * ) .List:Map .ListToArray . //.List:For: . OutDelim List: 1 List: 2 List: 3 List: 4 List: 5 List: 6 List: 7 List: 8 List: 9 List: 10 List:[] >>> l_List l_List l_List .List:Join .ListToArray . //.List:For: . OutDelim List: 1 List: 2 List: 3 List: 4 List: 5 List: 6 List: 7 List: 8 List: 9 List: 10 List:[] List: 11 List: 12 List: 13 List: 14 List: 15 List: 16 List: 17 List: 18 List: 19 List: 20 List:[] .List:Join List: 21 List: 22 List: 23 List: 24 List: 25 List: 26 List: 27 List: 28 List: 29 List: 30 List:[] .List:Join >>> l_List l_List l_List .List:Join >>> l_List l_List l_List .List:Join >>> l_List l_List .ListToArray . //.List:For: . OutDelim l_List 5 .List:Take .ListToArray . //.List:For: . OutDelim List: 1 List: 2 List: 3 List: 4 List: 5 List: 6 List: 7 List: 8 List: 9 List: 10 List:[] .List:Count . OutDelim List:[] 1 .List:Add 2 .List:Add 3 .List:Add 4 .List:Add 5 .List:Add .ListToArray . //.List:For: . OutDelim List:[] 'a' .List:Add 'b' .List:Add 'c' .List:Add 'd' .List:Add 'e' .List:Add .ListToArray . //.List:For: . OutDelim List:[] @ + .List:Add @ - .List:Add @ * .List:Add @ / .List:Add .ListToArray . //.List:For: . OutDelim xs 1 .List:Take .ListToArray . //.List:For: . OutDelim xs 20 .List:Take .ListToArray . //.List:For: . OutDelim xs ( 2 * ) .List:Map 20 .List:Take ( 2 * ) .List:Map .ListToArray . //.List:For: . OutDelim xs1 200 .List:Take .ListToArray . //.List:For: . OutDelim 1 xs3 //500 200 .List:Take .ListToArray . //.List:For: . OutDelim 1 xs3 200 .List:Take .ListToArray . //.List:For: . OutDelim ; // ADTTest ADTTest DT1.ms.script USES ADT.ms.dict ; USES ADTList.ms.dict ; Test&Dump ADTTest [ 1 2 3 ] .ArrayToList .ListToArray . OutDelim 1 xs3 IsOdd .List:Filter //10 5001 .List:Take IsOdd .List:Filter IsOdd .List:Filter .ListToArray . //.List:For: . OutDelim [ 1 2 3 ] .ArrayToList .ListToArray . //.List:For: . OutDelim [ 1 2 3 ] .ArrayToList ( 1 LESS ) .List:Filter .ListToArray . //.List:For: . OutDelim [ 1 2 3 ] .ArrayToList .List:Sort .ListToArray . //.List:For: . OutDelim [ 1 2 ] .ArrayToList .List:Sort .ListToArray . //.List:For: . OutDelim [ 2 1 ] .ArrayToList .List:Sort .ListToArray . //.List:For: . OutDelim [ 1 2 3 ] .ArrayToList .List:Sort .ListToArray . //.List:For: . OutDelim [ 3 2 1 ] .ArrayToList .List:Sort .ListToArray . //.List:For: . OutDelim [ 1 2 3 4 5 6 7 8 9 10 ] .ArrayToList .List:Sort .ListToArray . //.List:For: . OutDelim //[ 1 2 3 4 5 6 7 8 9 10 ] [ 8 9 10 2 1 3 20 ] .ArrayToList .List:Sort .ListToArray . //.List:For: . OutDelim 10 .ItemToList .ListToArray . //.List:For: . OutDelim [ 1 2 3 4 5 6 7 8 9 10 ] .ArrayToList .ListToArray . //.List:For: . OutDelim 1 xs3 5001 .List:Take .ListToArray . //.List:For: . OutDelim 1 xs3 IsOdd .List:Filter 5001 .List:Take //IsOdd .List:Filter .ListToArray . //.List:For: . OutDelim ; // ADTTest ADTTest
(+) http://programmingmindstream.blogspot.ru/2017/11/adt.html?m=1
среда, 15 ноября 2017 г.
Offtopic. Байка
#байка
Вспомнилось тут...
Езжу с детьми на каникулы в деревню Лосиное Калужской области.
Детям там нравится.
Когда мы первый раз туда приехали, к нам тут же пришли два местных колдыря. С четвертинкой. И стали звать меня третьим. Ну как же - новые люди из Москвы и "всё такое".
Я вообще-то не злоупотребляю. Здоровье не позволяет. А с детьми на каникулах - так вообще не пью.
Но разве колдырям это объяснишь.
Но тут меня прям "озарило". Просто "Бог нашептал".
Я им говорю - "мужики, я бы рад с вами выпить, но я мол запойный и зашился".
Мол, выпью - помру.
Они на меня посмотрели с сочувствием. "Больной человек".
И больше с этим вопросом не приставали...
Железобетонная "отмазка". И "не обидно".
И вроде не отказал "уважаемым людям"...
Вспомнилось тут...
Езжу с детьми на каникулы в деревню Лосиное Калужской области.
Детям там нравится.
Когда мы первый раз туда приехали, к нам тут же пришли два местных колдыря. С четвертинкой. И стали звать меня третьим. Ну как же - новые люди из Москвы и "всё такое".
Я вообще-то не злоупотребляю. Здоровье не позволяет. А с детьми на каникулах - так вообще не пью.
Но разве колдырям это объяснишь.
Но тут меня прям "озарило". Просто "Бог нашептал".
Я им говорю - "мужики, я бы рад с вами выпить, но я мол запойный и зашился".
Мол, выпью - помру.
Они на меня посмотрели с сочувствием. "Больной человек".
И больше с этим вопросом не приставали...
Железобетонная "отмазка". И "не обидно".
И вроде не отказал "уважаемым людям"...
вторник, 14 ноября 2017 г.
Ещё о ФЯ. Цитата
Цитата:
"
Это - функциональная возможность:
sealed abstract class Either[+A, +B]
final case class Left[+A, +B](value: A) extends Either[A, B]
final case class Right[+A, +B](value: B) extends Either[A, B]
А это - функциональный дух:
data Either a b = Left a | Right b
И добавить нечего...
"
Вот мне тоже Haskell кажется "понятнее", чем Scala.
Хотя я всего "пять минут" с обоими знаком.
"
Это - функциональная возможность:
sealed abstract class Either[+A, +B]
final case class Left[+A, +B](value: A) extends Either[A, B]
final case class Right[+A, +B](value: B) extends Either[A, B]
А это - функциональный дух:
data Either a b = Left a | Right b
И добавить нечего...
"
Вот мне тоже Haskell кажется "понятнее", чем Scala.
Хотя я всего "пять минут" с обоими знаком.
О функциональных языках
Познакомился с Haskell.
Многое оказалось знакомо.
До многого оказывается "сам" давно "дошёл".
Для глубины понимания реализовал маленькое подмножество Haskell на своих скриптах.
Чисто в "образовательных целях".
Не для "промышленного применения". По крайней мере пока.
Очень помогают доки собственно по Haskell. Читаю её и делаю "кальку с примеров".
Упоминания тут:
http://programmingmindstream.blogspot.ru/2017/11/blog-post.html?m=1
Чем дальше реализую, тем больше проникаюсь "духом ФЯ".
"Что-то" в этом есть.
Особено в immutable, ленивости и ADT с patternMatching'ом.
Очень полезный ресурс вот:
https://www.ibm.com/developerworks/ru/library/l-haskell4/index.html
Там очень многое подробно объяснется. Дух и буква ФЯ.
Я там много чего полезного почерпнул. И понял как оно "под капотом" устроено.
Ну и про qsort я уже писал:
http://programmingmindstream.blogspot.ru/2017/11/haskell.html?m=1
На Haskell - qsort реально понятнее, чем на C или Pascal.
Ну и:
http://programmingmindstream.blogspot.ru/2017/11/blog-post_22.html?m=1
(+):
http://programmingmindstream.blogspot.ru/2017/11/haskell_1.html?m=1
http://programmingmindstream.blogspot.ru/2017/11/adt.html?m=1
Многое оказалось знакомо.
До многого оказывается "сам" давно "дошёл".
Для глубины понимания реализовал маленькое подмножество Haskell на своих скриптах.
Чисто в "образовательных целях".
Не для "промышленного применения". По крайней мере пока.
Очень помогают доки собственно по Haskell. Читаю её и делаю "кальку с примеров".
Упоминания тут:
http://programmingmindstream.blogspot.ru/2017/11/blog-post.html?m=1
Чем дальше реализую, тем больше проникаюсь "духом ФЯ".
"Что-то" в этом есть.
Особено в immutable, ленивости и ADT с patternMatching'ом.
Очень полезный ресурс вот:
https://www.ibm.com/developerworks/ru/library/l-haskell4/index.html
Там очень многое подробно объяснется. Дух и буква ФЯ.
Я там много чего полезного почерпнул. И понял как оно "под капотом" устроено.
Ну и про qsort я уже писал:
http://programmingmindstream.blogspot.ru/2017/11/haskell.html?m=1
На Haskell - qsort реально понятнее, чем на C или Pascal.
Ну и:
http://programmingmindstream.blogspot.ru/2017/11/blog-post_22.html?m=1
(+):
http://programmingmindstream.blogspot.ru/2017/11/haskell_1.html?m=1
http://programmingmindstream.blogspot.ru/2017/11/adt.html?m=1
четверг, 2 ноября 2017 г.
Просто так. О тестировании
Я вот что писал:
http://18delphi.blogspot.ru/2013/11/gui_9423.html?m=1
Оно не потеряло актуальности.
Что я хотел написать?
Я очень рад тому, что я следую принципам, которые там описаны.
Более того. Я применяю "почти TDD" в "повседневном программировании".
Я пишу код. И если он не слишком тривиален - пишу к нему тест.
Для меня лично - этот подход, более чем оправдывает себя.
У меня уже скопилась немаленькая база тестов. Многие из тестов написаны на скриптах. На скриптах тесты писать в РАЗЫ удобнее, чем на Delphi. На несколько десятичных порядков.
Потому, что в скриптах и инфраструктура развитее и там есть всякие "вкусности" типа лямбд (замыканий), литераторов, "сборки мусора", препроцессинга кода, и "сравнения с образцом", пост- и пред-условий, генерации эталонов, элементов ФЯ, кеширования значений функций, view от array, типа map и filter, а также rules и прочее и прочее и прочее.
Вот я тут начал делать Haskell-подобные вещи:
http://programmingmindstream.blogspot.ru/2017/11/haskell.html?m=1
http://programmingmindstream.blogspot.ru/2017/10/haskell-vs-count.html?m=1
Параллельно пишу тесты. Очень помогает. Ошибки вылазят "практически сразу".
Пишу "минимальный код" к нему тут же пишу "минимальный тест".
И всё срастается.
Собственно тесты и есть "примеры использования кода". Очень всё просто и логично.
Если какие-то ветки кода - не рабочие, то там пишутся assert'ы и они не покрыты тестами.
Как только assert'ы вылазят - дописываются ветки кода и дописываются "тривиальные тесты".
Всё просто и банально. Как 2*2=5.
Код используется - тестируем. Не используется - ставим assert и не тестируем.
Наткнулись на assert - пишем тест и тестируем.
И так "по кругу".
Просто и банально.
Мне лично - нравится.
Никому ничего в то же время не навязываю.
Ну в общем "ни о чём" написал. Хорошо быть "богатым и здоровым".
С коммунистическим приветом. ;)
p.s. Возможно уже стоит опубликовать машинку для тестирования?
http://18delphi.blogspot.ru/2013/11/gui_9423.html?m=1
Оно не потеряло актуальности.
Что я хотел написать?
Я очень рад тому, что я следую принципам, которые там описаны.
Более того. Я применяю "почти TDD" в "повседневном программировании".
Я пишу код. И если он не слишком тривиален - пишу к нему тест.
Для меня лично - этот подход, более чем оправдывает себя.
У меня уже скопилась немаленькая база тестов. Многие из тестов написаны на скриптах. На скриптах тесты писать в РАЗЫ удобнее, чем на Delphi. На несколько десятичных порядков.
Потому, что в скриптах и инфраструктура развитее и там есть всякие "вкусности" типа лямбд (замыканий), литераторов, "сборки мусора", препроцессинга кода, и "сравнения с образцом", пост- и пред-условий, генерации эталонов, элементов ФЯ, кеширования значений функций, view от array, типа map и filter, а также rules и прочее и прочее и прочее.
Вот я тут начал делать Haskell-подобные вещи:
http://programmingmindstream.blogspot.ru/2017/11/haskell.html?m=1
http://programmingmindstream.blogspot.ru/2017/10/haskell-vs-count.html?m=1
Параллельно пишу тесты. Очень помогает. Ошибки вылазят "практически сразу".
Пишу "минимальный код" к нему тут же пишу "минимальный тест".
И всё срастается.
Собственно тесты и есть "примеры использования кода". Очень всё просто и логично.
Если какие-то ветки кода - не рабочие, то там пишутся assert'ы и они не покрыты тестами.
Как только assert'ы вылазят - дописываются ветки кода и дописываются "тривиальные тесты".
Всё просто и банально. Как 2*2=5.
Код используется - тестируем. Не используется - ставим assert и не тестируем.
Наткнулись на assert - пишем тест и тестируем.
И так "по кругу".
Просто и банально.
Мне лично - нравится.
Никому ничего в то же время не навязываю.
Ну в общем "ни о чём" написал. Хорошо быть "богатым и здоровым".
С коммунистическим приветом. ;)
p.s. Возможно уже стоит опубликовать машинку для тестирования?
Ссылка. ADT
https://ru.m.wikipedia.org/wiki/Алгебраический_тип_данных
Наконец я вроде понял, что это такое...
Там конечно "мудрёно" всё написано. Особенно про pattern-matching.
Всё гораздо проще. Банальное "сравнение кортежей" и сопоставление формальных параметров фактическим.
Я прям готов уже "статью" написать. Типа - "ADT, Haskell, immutable objects и pattern-matching для дебилов из мира императивных языков". Таких как я.
А то блин "морфизм, конструкторы (не такие как в C++), монады/шмонады, хвостовая рекурсия, ленивые вычисления, чанки, функции высшего порядка..."
Всё просто на самом деле объясняется. Для дебилов. Таких как я. Из императивного мира.
Шучу... Куда уж мне сирому...
Даже есть мысли как такое под Delphi устроить.
Не понятно только - надо ли...
Я ведь почему ФЯ "пристально" заинтересовался? А потому, что "понял", что я "двигаюсь в том же направлении". И раз я двигаюсь в том же направлении, то надо посмотреть "как У людей устроено". Посмотрел. Много полезного для себя почерпнул.
Местами даже захотелось попрограммировать на Haskell.
Но это возможно в будущем...
Я уже "очаровывался" языком Objective-C...
Одно могу сказать - "immutable-объекты - это круто!". Даже для императивных языков.
Что интересно... Пока я "въезжал в Haskell" - я нашёл ошибку с "глубокой рекурсией" при освобождении объектов. Которую лет пять не мог найти..
"Американский метод".
"Ищем одну ошибку, находим - другую".
Наконец я вроде понял, что это такое...
Там конечно "мудрёно" всё написано. Особенно про pattern-matching.
Всё гораздо проще. Банальное "сравнение кортежей" и сопоставление формальных параметров фактическим.
Я прям готов уже "статью" написать. Типа - "ADT, Haskell, immutable objects и pattern-matching для дебилов из мира императивных языков". Таких как я.
А то блин "морфизм, конструкторы (не такие как в C++), монады/шмонады, хвостовая рекурсия, ленивые вычисления, чанки, функции высшего порядка..."
Всё просто на самом деле объясняется. Для дебилов. Таких как я. Из императивного мира.
Шучу... Куда уж мне сирому...
Даже есть мысли как такое под Delphi устроить.
Не понятно только - надо ли...
Я ведь почему ФЯ "пристально" заинтересовался? А потому, что "понял", что я "двигаюсь в том же направлении". И раз я двигаюсь в том же направлении, то надо посмотреть "как У людей устроено". Посмотрел. Много полезного для себя почерпнул.
Местами даже захотелось попрограммировать на Haskell.
Но это возможно в будущем...
Я уже "очаровывался" языком Objective-C...
Одно могу сказать - "immutable-объекты - это круто!". Даже для императивных языков.
Что интересно... Пока я "въезжал в Haskell" - я нашёл ошибку с "глубокой рекурсией" при освобождении объектов. Которую лет пять не мог найти..
"Американский метод".
"Ищем одну ошибку, находим - другую".
среда, 1 ноября 2017 г.
Повторю ссылку. "О Haskell по-человечески"
https://www.ohaskell.guide/adt.html
ОЧЕНЬ хорошая книга.
И на самом деле не только про Haskell, но и про ADT вообще.
ОЧЕНЬ хорошая книга.
И на самом деле не только про Haskell, но и про ADT вообще.
Haskell. Вопрос. Сортировка
А как на Haskell реализуется сортировка списка?
Там же вроде нет "рандомного" доступа к элементу. Учитывая наличие map и filter.
Или я чего-то не понимаю?
Интересует конечно не встроенная функция api, а как это написать самому руками. С указанием собственной функции сравнения элементов.
Видимо, вот из этой реалализации очевидно, как передать ф-ю сравнения:
qsort [] = []
qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ qsort (filter (>= x) xs)
так?
Кстати при "детальном рассмотрении" - даже понятнее, чем qsort на императивных языках. Влево отбираем элементы < x, вправо > x, а x - "посерединке". ;) Ясно и просто ;)
РЕАЛЬНО ПОНЯТНЕЕ, чем qsort на Pascal. Я НАКОНЕЦ реально ПОНЯЛ, как qsort работает.
Да. Да. Реально понятнее.
Декларатив.
?
А что такое <- ?
И что такое in ?
Там же вроде нет "рандомного" доступа к элементу. Учитывая наличие map и filter.
Или я чего-то не понимаю?
Интересует конечно не встроенная функция api, а как это написать самому руками. С указанием собственной функции сравнения элементов.
HaskellВыделить код | ||
|
Видимо, вот из этой реалализации очевидно, как передать ф-ю сравнения:
qsort [] = []
qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ qsort (filter (>= x) xs)
так?
Кстати при "детальном рассмотрении" - даже понятнее, чем qsort на императивных языках. Влево отбираем элементы < x, вправо > x, а x - "посерединке". ;) Ясно и просто ;)
РЕАЛЬНО ПОНЯТНЕЕ, чем qsort на Pascal. Я НАКОНЕЦ реально ПОНЯЛ, как qsort работает.
Да. Да. Реально понятнее.
Декларатив.
?
А что такое <- ?
И что такое in ?
Подписаться на:
Сообщения (Atom)