Nagyházi, kisházi

24.1. Kérdés.
Nem boldogulok a keretprogram futtatásával. A KCsiga.sml keresi a unit Csiga-t. Nekem van egy Csiga.sml fájlom. Mit tegyek???

24.1. Válasz.
Oktató: Fordítsa le az mosmlc fordítóval az összes modult, valahogy így:

mosmlc -c TCsiga.sml Csiga.sig KCsiga.sig KCsiga.sml Csiga.sml
vagy egyesével is lehet (a sorrend nem közömbös! azt hiszem, ez a jó):

mosmlc -c TCsiga.sml
mosmlc -c Csiga.sig
mosmlc -c KCsiga.sig
mosmlc -c KCsiga.sml
mosmlc -c Csiga.sml
A -c kapcsoló hatására csak fordít, nem szerkeszt (vö. gcc).

Interaktív módban, azaz az mosml-lel a Meta.compile : string -> unit függvény alkalmazásával is le lehet fordítani a programot,.


A fordítás után (kizárólag az interaktív módban!) az

app load ["TCsiga", "Csiga", "KCsiga"];
betölti a teljes programot az mosml-be. A KCsiga-modulban lévő f függvényt KCsiga.f néven érheti el. Vagy az

open KCsiga
deklaráció érvényességi körében a rövid f név használata is elég. (Az f helyett természetesen létező függvények nevét kell használnia.)

24.2. Kérdés.
Úgy érzem, a célegyenesben vagyok az SML téren is, de felmerült néhány kérdés bennem.

Első kérdésem: hogyan lehet SML esetén a programból gondoskodni a list könyvtár betöltéséről és megnyitásáról?

24.2. Válasz.
Oktató: Interaktív esetben, otthoni élesztéskor, teszteléskor (mosml): app load ["List"] (a listában több könyvtár neve is megadható), vagy egyszerűen: load "List". Vigyázat: a kis- és nagybetűket meg kell különböztetni!

Nem interaktív esetben, pl. a beadandó program esetén (mosmlc): semmit nem kell írni, tenni, a ,,főmodullal'' együtt az összes szükséges modult betölti a futtatórendszer. Magyarán: a fogadószkript lefordítja a kapott Lepeget.sml fájlt (a specifikációjának ki kell elégíteni a Lepeget.sig szignatúrát, amelyet azonban nem kell beküldnie!), betölti (vele együtt betöltődik minden, ami kell), és futtatja.

Ha valaki több fájlra bontja a megoldását, akkor minden állományt be kell küldenie (.sml és esetleg .sig kiterjesztéssel), ezeket a fogadószkript mind lefordítja és betölti.

A kérdező folytatja: Második kérdésem: mennyire kell szoros időkorlátokra számítani? Azért kérdezem, mert az SML programom 12 hosszúságú bemenetekre már kb. 20 másodpercet molyol, amit elég soknak érzek a Prolog programom 2-3 másodpercéhez képest.

Oktató: Valóban indokolatlanul sok a Prologhoz képest. Az időkorlátba várhatóan mégis bele fog férni, 12 elemű sorozatra most 60 s-ot adunk. De hétfő estig még javíthat a programján...

A kérdező folytatja: Harmadik kérdésem: mit jelent az, hogy használjunk értelmes neveket? Nekem ez néha nagyon nehéz feladatnak tűnt... Az elég, ha számomra értelmesek a nevek? ;-)) Nyilván nem, de ezt a kitételt nagyon szubjektívnek érzem.

Oktató: Valóban nehéz, ezért gyakoroltatjuk. ;-) Másszóval azt várjuk el, hogy kifejező neveket használjanak. A programok általában (nem a hf-ekre gondolok) hosszú életűek, rendszerint túlélik a programozójukat a cégnél. Olyan neveket kell használni, amelyeket majd a fejlesztő utódok is viszonylag könnyen megértenek. Ezért kell persze a megfelelően áttekinthető, a program felépítését, szerkezetét magyarázó dokumentáció is.

A kérdező folytatja: Negyedik kérdésem: az SML-ben hogyan lehet rendezni egy, a nagyháziban használt bemenő listát? Tudom, hogy a függvény bemenete eleve rendezett, csak kíváncsi vagyok...

Oktató: Nézze meg a Listsort.sig-ben a Listsort.sort használatát. Vagy nézze meg a jegyzetben a listák rendezéséről szóló fejezetet, és írja meg a rendezőprogramot.

24.3. Kérdés.
Elég leadni egyetlen .pl és egyetlen .sml fájlt, ha azokban minden jól megvan? SML esetén kell-e az .sml-hez mindenképpen .sig-et mellékelni? Vagy elég lesz, ha csak egy .sml-t küldök be, szépen kommentezve, benne pár függvénnyel?

24.3. Válasz.
Oktató: Igen. A .sig tényleg nem kell, de kell a kétféle nyelven készült programokhóz a közös dokumentáció a szépen és érthetően fejkommentezett SML-függvények és Prolog-eljárások mellett.

24.4. Kérdés.
Az SML házim a visszaigazolás alapján nem fordul le. Íme a hibaüzenet:

Testing SML programs
~~~~~~~~~~~~~~~~~~~~
Moscow ML version 2.00 (June 2000)
  compiling and linking Lepeget ...
Makefile:31: .depend: No such file or directory
/opt/mosml20/bin/camlrunm /opt/mosml20/tools/mosmldep > .depend
/opt/mosml20/bin/mosmlc -c Lepeget.sml
File "Lepeget.sml", line 64, characters 16-25:
! |mgdbolo(mo,n)=(list.take(mo,n))::mgdbolo((list.drop(mo,n)),n)
!                 
! Cannot find file list.ui
make: *** [Lepeget.uo] Error 2
!ERROR: compilation and linking of Lepeget failed.
Mit kéne még elküldenem, hogy leforduljon? (A list.ui, list.uo, list.sig stb. fájlok elküldésével már próbálkoztam.)

24.4. Válasz.
Hallgató: A hibaüzenet azt mondja, nem találja a list.ui fájlt. Azért nem találja, mert nincs! Van viszont List.ui. Tehát semmi mást nem kell beküldened, csak pontosan úgy kell írnod az alapkönyvtárak nevét, ahogy a dokumentációban szerepelnek. (A UNIX rendszerek figyelembe veszik a kis- és nagybetűk közti különbséget.)

24.5. Kérdés.
Az a kérdésem, hogy elfogadható-e, ha az sml értelmező egy csomó warning-ot ad a házi feladatomra, vagy warning-mentesnek kell lennie?

24.5. Válasz.
Oktató: Elfogadható, de növekszik a veszélye, hogy valamit elnéz, amit érdemes lenne meggondolnia.

24.6. Kérdés.
Nem tudom lefordítani az alábbi egyszerű SML progit:

fun nyilak _=
      [([se,s,se,sw],[w,nw,nw,w],[ne,n,ne,nw],[se,ne,se,e]),
       ([se,s,se,sw],[w,nw,nw,w],[nw,n,nw,nw],[se,ne,se,e])];
ezzel a sorral:

mosmlc -c TNyil.sml Nyil.sig Nyil.sml KNyil.sig KNyil.sml
mert ezt kapom:

File "nyilak.sml", line 3, characters 16-18:
! fun nyilak _=[([se,s,se,sw],[w,nw,nw,w],[ne,n,ne,nw],...
!                 J
! Unbound value identifier: se

24.6. Válasz.
Oktató: Nem a parancssorral van gond. Az se, s, sw stb. adatkonstruktorállandók a TNyil modulban vannak definiálva, alapesetben csak a teljes nevükkel érhetők el, azaz TNyil.se, TNyil.s, TNyil.sw stb. néven. Hogy ne kelljen annyit írni, a modul megnyitható az open TNyil deklarációval, utána már használhatja a rövid neveket is.

Megjegyzés. Az open éppen olyan deklaráció, mint bármelyik más abból a szempontból, hogy local ... in ... end deklarációk vagy let ... in ... end kifejezések deklarációs részében is használható, és ilyenkor a hatása természetesen lokális. Például

local open TNyil
in
      fun fuggv x y z = ...
end
Ui. A beadáskor figyeljenek arra, hogy a .sml fájl és a könyvtárak nevét nagy kezdőbetűvel írják, ugyanis a Un*x rendszerek megkülönböztetik a kis- és nagybetűket!

24.7. Kérdés.
Az SML házi fordítása közben a következő üzenetet kaptam:

File "Kigyo.sml", line 92, characters 8-12:
!    val [A,B] = if length(L)=2 then L else [(0,0),(0,0)]
!         ^
! Warning: pattern matching is not exhaustive
Azt értem, hogy mivel nem biztos, hogy az L pontosan 2 elemű, ezért warning-ot ad (gondolom, hogy az éppen erre vonatkozó feltételvizsgálatot nem tudja figyelembe venni). Hiba a feltétel miatt nem lép fel, csak ez a warning zavar. Hogyan lehet egyszerűen megszüntetni, illetve gond-e ez a warning a házi elfogadhatósága szempontjából? (Mivel a fogadórendszer elfogadja a programot, csak jelzi a warning-ot, úgy gondolom nem probléma, csak csúnya.)

24.7. Válasz.
Oktató: A figyelmeztetések (warning-ok) nem befolyásolják a házi feladatra adott pontszámot.

Sajnos, listák esetén az ilyenfajta mintaillesztési (pattern match) figyelmeztetéseket csak magának a mintaillesztésnek a mellőzésével lehet elkerülni.

Tegyük fel, hogy az alábbi függvény fordításakor kapta a figyelmeztetést:

fun f L = let val [A, B] = if length L = 2
                           then L
                           else [(0,0),(0,0)]
          in
             (A, B)
          end;
Az alábbi változat nem szebb, de legalább figyelmeztetés nélkül lefordul:

fun f L = let val (A, B) = if length L = 2
                           then (hd L, hd(tl L))
                           else ((0,0),(0,0))
          in
             (A, B)
          end;


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