Szintaxis, szemantika

5.1. Kérdés.
Egy furcsa hibával küzdök. Ha valamelyik SML függvényben az o névvel hivatkozom egy elemre, akkor kiakad a program, és kapok egy Ill-formed infix expression hibaüzenetet.

5.1. Válasz.
Hallgató: Az o név az SML-ben egy infix operátor neve.

5.2. Kérdés.
Az alábbi függvénydefiníció az mosml szerint hibás. Miért?

- fun b((S, O, E):As, N) = (S, O, E)::b(As, N)
    | b([], N) = [];
! Toplevel input:
! fun b ((S, O, E):As, N) = (S, O, E)::b(As, N)
!                                       J
! Unbound value identifier: As

5.2. Válasz.
Oktató: Én az mosml-től más hibaüzenetet kapok:

! Toplevel input:
!  fun b((S, O, E):As, N) = (S, O, E)::b(As, N)
!                  J
! Unbound type constructor: As
Én csak ezt a programrészletet adtam oda az mosml-nek, valószínű, hogy más környezetben kapta a fenti hibaüzenetet. Akárhogy is, a hiba az, hogy egyetlen :-ot írt a megjelölt helyen :: helyett. Így az mosml típusmegkötésnek tekinti, márpedig az As típuskent nincs definiálva, és a definíció jobb oldala alapján nem is lehet típus.

5.3. Kérdés.
Most egy függvényt nem értek és nem találok sehol, az as-t. Mit csinál? Hogyan kell használni?

5.3. Válasz.
Oktató: Az as nem függvény, hanem kulcsszó, az ún. réteges minta (layered pattern) kulcsszava. Pl. az (xxs as x::xs) kifejezésben a teljes listára az xxs névvel, a lista fejére az x, a farkára az xs névvel lehet hivatkozni egy függvénydefinícióban annak a klóznak a törzsében, amelynek a fejében ez a kifejezés mintaként szerepel.

5.4. Kérdés.
Miért van az, hogy a függvényparaméter (pl. az exists-nél) fn-nel megadva nem működik, csak ha külön ,,nevesítem''? Tehát az alábbi részlet hibás:

let fun felfele (Y,X,A) =
      X = O andalso Y > S andalso A > 0 andalso
        not (List.exists (fn (Y1,X1) =>
               X1 = X andalso Y1 < Y andalso Y1 <> S) Pontok)
míg a következő már jó:

let fun felfele (Y,X,A) =
      let F (Y1,X1) = (X1 = X andalso Y1 < Y andalso Y1 <> S)
      in X = O andalso Y > S andalso A > 0
           andalso not List.exists F Pontok
      end
5.4. Válasz.
Hallgató: Nekem az első jónak tűnik, feltéve, hogy S-nek és Pontok-nak van értéke, ezzel szemben a második változat biztosan hibás, mert a let után kell még egy fun kulcsszó is. Emellett a List.exists F Pontok kifejezést be kell zárójelezni, különben precedenciahiba is van. Szóval a hiba nem itt van.

A kérdező folytatja: Pedig típushibával kidobta! Valami olyasmit irt, hogy bool nem egyezhet (valami * valami ..) -> bool-lal. Sajnos nem tudom pontosan idézni, és már átírtam. Az érdekes számomra az, hogy ha nem a könyvtári List.exists-et használom ugyanígy, hanem a saját függvényeimet, akkor síman megy. Hogy működik a típusellenőrzés, miért ,,szigorúbb'' a beépítettekkel, mint a megírtakkal? Létezik ez? Nem értem, bár lehet, hogy csak elírtam valamit, és megint nem vettem észre...

,,Ezzel szemben a második változat biztosan hibás'': igaz, de csak az emilben hagytam ki őket, a programban bent voltak, és úgy tényleg működött. Bár matching warning-ot kaptam arra is.

Hallgató: Valamit mégiscsak elfelejtettél lezárni. Azt javaslom, próbáld meg a fájlt darabokban odaadni az értelmezőnek. Legcélszerűbb felezéssel (először az első felét, ha nincs hiba, a háromnegyedét, ha van, a negyedét stb.)

A kérdező folytatja: Köszönöm, a módszer bevált, egy let-részben volt véletlenül a következő függvény előtt még egy, felesleges let...

Hallgató: ,,igaz, de csak az emilben hagytam ki őket...'': Csak azt tudom mondani, hogy biztosan nem a lambda-jelölés <-> nevesített függvény okozta a különbséget, valami más is lehetett ott még. Sajnos elég nehéz a hibát úgy megállapítani, hogy nem tudod a pontos kódot megmutatni...

A kérdező folytatja: Mindegy, a fő, hogy most működik.


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