Autor Zpráva
KryVosa
Profil
V jedné nedodělané hře vytvářím možnost přidávat si vlastní 'mutátory' hry, kterými můžete různé vlastnosti hry upravovat za běhu a/nebo přidávat nové. Implementace v samotné hře vypadá nějak takto:
var functions=
      {
        // ...
        move:function(p, x, y)
        {
          var mut=game.mutator.move.test({functions:functions/*další a další upravovatelné atributy...*/});
          mut=mut||false;
          if(mut.x||mut)player[p].x += x;
          if(mut.y||mut)player[p].y += y;
        },
        // ...
      }
Jak sami vidíte, v případě zavolání funkce move() se provede mutátor, kterému je funkce move() předána a on ji může zavolat, čímž pádem se provede mutátor.... Zároveň však game.mutator.test() může testovat více mutátorů, tudíž nejde přidat 'test zavolání z mutátorů', kterým by se volání stornovalo.¨

Máte-li nějaký nápad, pomocný článek, nebo kritiku kódu, napište, předem děkuji :)
Chamurappi
Profil
Reaguji na KryVosu:
Nejsem si jistý, jestli jsem správně pochopil, v čem spočívá problém, hodně věcí jsem si musel domyslet.

se provede mutátor, kterému je funkce move() předána a on ji může zavolat
Můžeš mu tu funkci nepředat. Respektive předat mu místo functions jiný objekt naplněný vším, co je ve functions, s přepsanou metodou move.
Nebo můžeš do volání předávat i nějaký (s každým voláním rostoucí) výčet volaných funkcí a ověřovat, jestli v něm právě volaná funkce už jednou není.

Nebo by asi šlo mít v move pojmenovanou funkci (tzn. move: function název(p, x, y)) a pak zevnitř přes název.caller zjistit, čím je volána (a čím je volána to, co ji volá, atd.) – a tím zjistit, jestli nejsi v rekurzi. Ale nevím, jestli by to bylo proveditelné, nikdy jsem caller nepotřeboval.
KryVosa
Profil
Problém jsi jako vždy pochopil na jedničku!

Caller nikdy fungovat nebude, nemá 'historii', jen 'poslední' funkci, kterou byl zavolaný. Takže i při konečné rekurzi funkce/funkcí se sám zacyklí. Šlo by to obejít přes jakýsi vlastní 'max CallStack' u calleru, jakékoliv zacyklení by bylo úplně nemožné.

Možná by šlo 'ukládat' si někam funkce, které move() zavolaly, a právě jak říkáš kontrolovat, jestli mezi nimi už není funkce, která move() už zavolala. Popřípadě určit jakýsi 'maximální počet vnoření'.

Děkuji za nakopnutí.
KryVosa
Profil
Pro ostatní, co by měli podobný problém, sem ještě posílám hotové řešení:
var callStack=[];
function callStackTest()
        {
          caller=callStackTest.caller.caller;
          callStack.push(caller);
          var count=0;
          var lastIndex=-1;
          while((lastIndex=callStack.indexOf(caller,lastIndex+1))>=0)          
            count++;
          if(count>=callStackMax)
          {
            console.error("Recursive CallStack overfilled! ("+caller.toString().replace(/\{.*\}/i,"")+")");
            callStack=[];
            return false;
          }
          else return true;  
           
        }
Přikald:
callStackMax=10
function a(){if( !callStackTest() ) return; b(); callStack=[];}
function b(){a()}
Chamurappi
Profil
Reaguji na KryVosu:
Caller nikdy fungovat nebude, nemá 'historii', jen 'poslední' funkci, kterou byl zavolaný.
Předpokládám, že tohle tedy není pravda, když nyní používáš callStackTest.caller.caller. Takže by asi šlo projít callery i bez pole callStack.
KryVosa
Profil
Chamurappi: Není, ale v případě že budou dvě funkce v rekurzi (klidně i konečné, "ne-nekonečné"), caller se 'zacyklí'.

Vaše odpověď

Mohlo by se hodit

Neumíte-li správně určit příčinu chyby, vkládejte odkazy na živé ukázky.
Užíváte-li nějakou cizí knihovnu, ukažte odpovídajícím, kde jste ji vzali.

Užitečné odkazy:

Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: