28. Čísla v CombiScriptu: Jak sjednotit isNumber, abs a sign v PHP a JS

Ilustrační obrázek k článku: Čísla v CombiScriptu: Jak sjednotit isNumber, abs a sign v PHP a JS
Ukážeme, jak v CombiScriptu sjednotit práci s čísly mezi PHP a JavaScriptem. Vytvoříme funkce nm_IsNumber, nm_Abs, nm_Sign a nm_IsAsInt – včetně striktní kontroly typů a chybových hlášek.

Funkce pro práci s čísly budu ukládat do knihovny nm_Util – logické místo pro všechny nm_ funkce. Každá funkce bude interně rozvětvovat kód pro PHP a JavaScript pomocí CombiScriptového přepínače. A samozřejmě – budeme dodržovat striktní režim a kontrolu typů.

Začneme funkcí nm_IsNumber - základní cihlou pro všechny další operace. V JavaScriptu využijeme typeof. V PHP existují dva číselné typy float a int a proto pro detekci použijeme pro to určené funkce is_int a is_float samozřejmě s operátorem OR. Výsledná funkce bude vypadat takto:

  1. <!-- --><?php /*
  2. "use strict";
  3. //*/
  4. function nm_IsNumber($num)
  5. {
  6. 0&&0<!--$_;/*
  7. return typeof $num === 'number';
  8. /*/
  9. return is_int($num) OR is_float($num);
  10. //*/
  11. }

Jako další bychom si chtěli vytvořit funkci vracející absolutní hodnotu čísla. Pro PHP použijeme abs a pro JS použijeme Math.abs

  1. function nm_Abs($num)
  2. {
  3. 0&&0<!--$_;/*
  4. return Math.abs($num);
  5. /*/
  6. return abs($num);
  7. //*/
  8. }

U funkce nm_Abs se na chvíli zastavíme – protože tady poprvé narazíme na jeden z principů CombiScriptu: striktní kontrola typů a strojově čitelné chyby

.

Funkce nesmí dělat automatické přetypování – to by v PHP a JS vedlo k odlišným výsledkům. Místo toho – při chybném vstupu vyhodí výjimku

.

A tady přichází další princip: Chybový kód musí být strojově zpracovatelný. Nesnáším chyby ve stylu „Duplicate entry 'abc' for key 'xyz'“, kde si musím parametry „vyparsovat“. (a pak mu někdo přepne SQL engine do češtiny a parsování zkolabuje).

Funkce s kódem volajícím výjimku by podle mne měla vypadat nějak takto:

  1. function nm_Abs($num)
  2. {
  3. if (!nm_IsNumber($num)) throw new cs_Error('nm_Abs-$num-NotNumber', [cs_Type($num)]);
  4. 0&&0<!--$_;/*
  5. return Math.abs($num);
  6. /*/
  7. return abs($num);
  8. //*/
  9. }

Kde cs_Error je třída výjimky a cs_Type je funkce vracející typ proměnné. Zároveň je vidět jak budu konstruovat chybové kódy výjimek. Odděluji znakem "-", jako první uvádím název funkce, kde chyba nastala, jako další v jakém parametru a jako další typ chyby, kde používám PascalCase (Upper-CamelCase) syntaxi.

Pokračujeme funkcí nm_Sign. JavaScript má Math.sign(), PHP ne – tak si ji napíšeme sami. A můj oblíbený trik? ($num > 0) - ($num < 0). Elegantní, rychlé, a krásně ukazuje, jak boolean hodnoty v PHP fungují pod kapotou. (Ano, true - true = 0, true - false = 1, false - true = -1 – tohle je ta „magie“, kterou mám rád :-))

  1. function nm_Sign($num)
  2. {
  3. if (!nm_IsNumber($num)) throw new cs_Error('nm_Sign-$num-NotNumber', [cs_Type($num)]);
  4. 0&&0<!--$_;/*
  5. return Math.sign($num);
  6. /*/
  7. return ($num > 0) - ($num < 0);
  8. //*/
  9. }

A nakonec přidáme funkci nm_IsAsInt. V této funkci budeme kontrolovat zda se nějaké číslo "tváří" jako celé. V JS toto zjistit není problém, má na to přímo funkci Number.isInteger($num). V PHP docílíme stejné funkčnosti odříznutím desetinné části a porovnáním.

  1. function nm_IsAsInt($num)
  2. {
  3. 0&&0<!--$_;/*
  4. return Number.isInteger($num);
  5. /*/
  6. if (is_int($num)) return true;
  7. return (is_float($num) && floor($num) === $num);
  8. //*/
  9. }

Nyní si celou naši knihovnu můžeme shrnout:

nm_Util.php.js
  1. <!-- --><?php /*
  2. "use strict";
  3. //*/
  4. function nm_IsNumber($num)
  5. {
  6. 0&&0<!--$_;/*
  7. return typeof $num === 'number'
  8. /*/
  9. return is_int($num) OR is_float($num);
  10. //*/
  11. }
  12. function nm_Abs($num)
  13. {
  14. if (!nm_IsNumber($num)) throw new cs_Error('nm_Abs-$num-NotNumber', [cs_Type($num)]);
  15. 0&&0<!--$_;/*
  16. return Math.abs($num);
  17. /*/
  18. return abs($num);
  19. //*/
  20. }
  21. function nm_Sign($num)
  22. {
  23. if (!nm_IsNumber($num)) throw new cs_Error('nm_Sign-$num-NotNumber', [cs_Type($num)]);
  24. 0&&0<!--$_;/*
  25. return Math.sign($num);
  26. /*/
  27. return ($num > 0) - ($num < 0);
  28. //*/
  29. }
  30. function nm_IsAsInt($num)
  31. {
  32. 0&&0<!--$_;/*
  33. return Number.isInteger($num);
  34. /*/
  35. if (is_int($num)) return true;
  36. return (is_float($num) && floor($num) === $num);
  37. //*/
  38. }

Tvorbu nm_Util tady na chvíli přerušíme. Příště se přijde čas na cs_Util a cs_Error, která nese nejen zprávu, ale i strukturované parametry- což není u výjimek zcela běžné a může se Vám to hodit i v čistém PHP nebo JS.

Předchozí   Následující