Kifejez�s ki�rt�kel�se

8.1. K�rd�s.
Adott a k�vetkez� �rt�kdeklar�ci�:

val x = List.filter (fn true => false | _ =>true)
                          [3.0>4.0, 4.7>2.4, ~3.0<=0.4]
erre az mosml azt �rja ki, hogy x = [false]. De mi�rt? Mit csin�l a List.filter-ben megadott felt�tel?

8.1. V�lasz.
Oktat�: A teljes kifejez�s a list�ban l�v� igaz �rt�k� elemeket eldobja, a hamis �rt�k�eket kigy�jti.

A predik�tum (List.filter els� argumentuma) �ppen ezt fogalmazza meg: ha az elem true, eldobja, ha false (pontosabban b�rmi m�s, v�. _ => true, de most csak true lehet), akkor kigy�jti.

A pontoss�g kedv��rt: a List.filter els� argumentumak�nt nem egy felt�telt, azaz egy bool t�pus� kifejez�st, hanem egy predik�tumot, azaz egy bool t�pus� eredm�nyt ad� f�ggv�nyt v�r.

8.2. K�rd�s.
Az SML kish�zi megold�sa k�zben a honlapon megadott p�ld�k k�z�l mind lefutott, az utols�t kiv�ve, amely a k�vetkez� hiba�zenetet adta:

- dadogo 123456789;
! Uncaught exception
! Overflow
Felt�telezem, hogy az mosml enn�l nagyobb int t�pus� sz�mokat is k�pes kezelni, ez�rt nem �rtem a dolgot.

8.2. V�lasz.
Oktat�: 123456789 m�g val�ban belef�r az int tartom�nyba. De ha megszorozza pl. 9-cel, ezt kapja:

- 123456789 * 9;
! Uncaught exception:
! Overflow
8-cal m�g �ppen megszorozhatja. Feltehet�en olyan m�veletet v�gez a sz�mmal, amellyel kil�p az int tartom�nyb�l.

8.3. K�rd�s.
A k�vetkez� f�ggv�nyek bet�lt�s�nel a Warning: calling polyEqual hiba�zenetet kapom az smlnj-t�l. Az ir�nt �rdekl�dn�k, hogy ez pontosan mit jelent.

open List;
fun dadoge [] = true
  | dadoge a = if hd a = last(take(a, length a div 2 + 1))
                    andalso parose a = true
               then dadoge(drop(take(a, length a div 2), 1) @
                           drop(drop(a, length a div 2), 1))
               else false
and parose a = length a mod 2 = 0;

8.3. V�lasz.
Oktat�: L�ssuk akkor pontosabban a figyelmeztet�st (csak figyelmeztet, nem hib�t jelez!) smlnj-vel:
... Warning: calling polyEqual
val dadoge = fn : ''a list -> bool
val parose = fn : ''a list -> bool
majd mosml-lel:

> val ''a dadoge = fn : ''a list -> bool
  val ''a parose = fn : ''a list -> bool
Az smlnj teh�t akkor is figyelmeztet, ha valaki az egyenl�s�gvizsg�latot polit�pus� �rt�keken v�gezteti el. A k�vetkez� nagyon egyszer� esetben ugyanez a helyzet:

- fun eq (x,y) = x=y;
... Warning: calling polyEqual
val eq = fn : ''a * ''a -> bool
Ha t�pusmegszor�t�st haszn�lunk, mindent rendben l�v�nek tal�l:

- fun eq (x,y:int) = x=y;
val eq = fn : int * int -> bool
Ezzel szemben egy�ltal�n nem engedi meg a k�vetkez�t:

- fun eq (x,y:real) = x=y;
... Error: operator and operand don't agree
           [equality type required]
  operator domain: ''Z * ''Z
  operand:         ''Z * real
  in expression:
    x = y
ui. real t�pus� �rt�kek egyenl�s�ge az = oper�torral az smlnj haszn�latakor nem vizsg�lhat�.

Helyette a Real.== vagy a Real.?= f�ggv�ny haszn�lhat�. Pl.

fun eq (x,y) = Real.==(x,y);
val eq = fn : real * real -> bool
A Real.== �s a Real.?= m�veletek kiel�g�tik az IEEE standard 754-1985 szerint el��rt specifik�ci�t (l�sd: <http://www.standardml.org/Basis/real.html#REAL:SIG:SPEC>).

Most m�r az is �rthet�, hogy polit�pus� �rt�kek egyenl�s�gvizsg�latakor mi�rt figyelmeztet az smlnj: el�fordulhat, hogy a l�trehozott f�ggv�ny a k�s�bbiekben olyan �rt�kek egyenl�s�g�t akarja megvizsg�lni, amelyekre az egyenl�s�gvizsg�lat nem v�gezhet� el.

Az mosml-ben a Real.== ekvivalens az = oper�torral, ha az ut�bbi operandusai real t�pus�ak, a Real.?= eredm�nye pedig mindig false, mert az IEEE standard szerinti sz�m�br�zol�sok az mosml-b�l hi�nyoznak.

8.4. K�rd�s.
Ha egy f�ggv�nyben haszn�lok egy bels� f�ggv�nyt (let fun...), amelyben az egyenl�s�gjel jobb oldal�n (azaz a bels� f�ggv�ny t�rzs�ben) felt�telvizsg�latra van sz�ks�gem, akkor ennek else �g�ban hogyan l�phetek ki a bels� f�ggv�nyb�l?

8.4. V�lasz.
Oktat�: Ugyan�gy, mint a then �g�b�l: a megfelel� t�pus� �rt�kkel.

Hangs�lyozom, hogy az SML-ben az if... then... else: kifejez�s, m�gpedig egy felt�telt�l f�gg�en �gy vagy �gy ki�rt�kelend� kifejez�s. Ha az else �gban nincs rekurz�v h�v�s, az esetleges m�veletek elv�gz�se ut�n a f�ggv�ny ki�rt�kel�se is befejez�dik, azaz az SML visszat�r a f�ggv�nyh�v�sb�l.

A k�rdez� folytatja: Ha van t�bb lehet�s�g is, melyik mit jelent pontosan ?

Oktat�: Ezt nem �rtem: ha az if... then... else... if...else ... szerkezetre gondol, akkor a ki�rt�kel�s mindig az if ut�n �ll� predik�tumt�l f�gg. Ha a f�ggv�ny kl�zaira gondol, akkor pedig a f�ggv�nyfejben megadott mint�kt�l.

Figyelem: mind a then �s else-�gakban, mind a f�ggv�ny kl�zaiban �ll� kifejez�sek f�ggetlenek egym�st�l!

A k�rdez� folytatja: Val�j�ban a bels� f�ggv�nyb�l val� kil�p�ssel egy�tt a k�ls� f�ggv�nyt is be szeretn�m fejezni, �s a bels�b�l val� kil�p�sig kisz�m�tott eredm�nyeket visszadni. Rem�lem, nagyj�b�l k�vethet� volt a probl�ma le�r�sa, �s van �tletetek a megold�s�ra.

Oktat�: Ennek semmi akad�lya: ha a bels� f�ggv�ny visszat�r�si �rt�k�vel egy�ttal az �t megh�v� f�ggv�nyb�l is kil�p, akkor a k�ls� f�ggv�ny �ltal visszaadott �rt�k meg fog egyezni a bels� f�ggv�ny �ltal visszaadott �rt�kkel (a bels� f�ggv�ny visszat�r�si �rt�k�vel).

Abb�l, amit le�rt, az�rt nem nagyon �rtem, hogy mi a probl�m�ja. Ha esetleg arra gondol, hogy valamilyen return v vagy exit if parancs van-e az SML-ben, akkor erre nem a v�lasz, mert nincs r�juk sz�ks�g. Ha megn�zi az el�ad�sokon bemutatott p�ld�kat, sok mint�t tal�l.

8.5. K�rd�s.
Adott egy programr�szlet:

fun megy m n =
  let
    fun megy2 sor1 oszlop1 =
     if sor1 = n andalso oszlop1 > m
     then   (* legalj�n vagyunk, visszat�r�nk valamivel *)
          [[(1,1,1,1)]]
     else if sor1 <= n andalso oszlop1 > m
     then   (* sor v�g�n vagyunk *)
          megy2 sor1+1 1
     else   (* sorban vagyunk *)
          megy2 sor1 oszlop1+1
  in
      megy2 1 1
  end;
A l�nyege az, hogy v�gigl�pkedek egy m�trixon bal fentr�l jobbra le. Ford�t�s�nal ezt a hib�t kapom:

! Toplevel input:
!           megy2 sor1+1 1
!           ^
! Type clash: expression of type
!   'a -> (int * int * int * int) list list
! cannot have type
!   (int * int * int * int) list list
De mi�rt? Mi�rt akarja az

'a -> (int * int * int * int) list list
t�pust adni neki?

8.5. V�lasz.
Oktat�: A precedenci�kkal, pontosabban a f�ggv�nyalkalmaz�s m�h�s�g�val van baj: a f�ggv�nyeknek argumentumk�nt �tadott �sszetett kifejez�seket z�r�jelbe kell tenni, azaz:

...
     then   (* sor v�g�n vagyunk *)
          megy2 (sor1+1) 1
     else   (* sorban vagyunk *)
          megy2 sor1 (oszlop1+1)
...

8.6. Monol�g.
Hallgat�: Megoldottam a list�ra k�ld�tt p�ld�t mind moh�, mind a lusta m�dszerrel. Az eredm�ny egyezik, csak nem vagyok biztos benne, hogy minden l�p�s, ill. azok sorrendje helyes-e. A hib�kat, �szrev�teleket l�gyszi k�ldj�tek vissza! A f�ggv�ny:

fun  f g [] = []
  | f g (x::xs) = map g x :: f g xs;
Egy alkalmaz�sa lusta ki�rt�kel�ssel:

f chr [[2*5, 7 div 3], [round 8.0], []] =
   chr [2*5, 7 div 3] :: f chr [[round 8.0], []] =
   chr [2*5, 7 div 3] :: chr [round 8.0] :: f chr [] =
   chr [2*5, 7 div 3] :: chr [round 8.0] :: [] =
   [chr 2*5, chr 7 div 3] :: chr [round 8.0] :: [] =
   [chr 2*5, chr 7 div 3] :: [chr round 8.0] :: [] =
   [chr 10, chr 7 div 3] :: [chr round 8.0] :: [] =
   [chr 10, chr 2] :: [chr round 8.0] :: [] =
   [chr 10, chr 2] :: [chr round 8.0] :: [] =
   [#"\n", chr 2] :: [chr round 8.0] :: [] =
   [#"\n", #"\^B"] :: [chr round 8.0] :: [] =
   [#"\n", #"\^B"] :: [chr 8] :: [] =
   [#"\n", #"\^B"] :: [#"\b"] :: [] =
   [#"\n", #"\^B"] :: [#"\b"] =
   [[#"\n", #"\^B"], [#"\b"]]
Ugyanez moh� ki�rt�kel�ssel:

f chr [[2*5, 7 div 3], [round 8.0], []] =
   f chr [[10, 7 div 3], [round 8.0], []] =
   f chr [[10, 2], [round 8.0], []] =
   f chr [[10, 2], [8], []] =
   f chr [[10, 2], [8], []] =
   [chr 10,2] :: f chr [[8], []] =
   [#"\n", 2] :: f chr [[8], []] =
   [#"\n",chr 2] :: f chr [[8], []] =
   [#"\n",#"^B"] :: f chr [[8], []] =
   [#"\n",#"\^B"] :: chr [8], f chr [] =
   [#"\n",#"\^B"] :: [#"\b"] :: f chr [] =
   [#"\n",#"\^B"] :: [#"\b"] :: [] =
   [#"\n",#"\^B"] :: [#"\b"] :: [] =
   [#"\n",#"\^B"] :: [#"\b"] =
   [[#"\n",#"\^B"],[#"\b"]]


Deklarat�v programoz�s - FP-GYIK
2005. m�rcius 1.