Reputation: 587
I'm new to SML. I've written a function which takes 2 int and a list of tuples as input.
fun move(x,y,mylist:(int * int)list): NOxNO =
let
val counter = ref y-1
in
if y=1 then (x,y)
else (
while !counter > 0 do (
if List.exists (fn s => s = (x,!counter)) mylist
then counter := !counter - 1
else break
);
if !counter = 0 then (x,y) else (x,y-1)
)
end
I may have syntax error since I'm a beginner. What the function is trying to do is: it will check the list to find all the tuples whose first element is x and second element varies from 1 to y-1 (tuples like this: (x,1) (x,2) ... (x,y-1) ) and if all of them exist in the list it will return (x,y) else (x,y-1). I used a while loop and a counter. counter is set to y-1 at first and in while loop if (x,counter) was found, counter's value will decrease. At last if counter=0 it means we have found all the tuples. After running the program I encountered this error:
Caught Error ../compiler/TopLevel/interact/evalloop.sml:296.17-296.20
../compiler/TopLevel/interact/evalloop.sml:44.55
../compiler/TopLevel/interact/evalloop.sml:66.19-66.27
What's wrong?
Upvotes: 1
Views: 451
Reputation: 16125
Here's some feedback:
(Error) As Andreas Rossberg said, break
doesn't exist. But if you use ()
, the loop won't terminate when y > 1
and the predicate evaluates to false. You probably want to "break" by setting counter := 0
or counter := -1
, depending on what you want the subsequent if !counter = 0 ...
to do.
(Error) As Andreas Rossberg said, ref y-1
gives the following type error:
! Toplevel input:
! val r = ref y-1;
! ^
! Type clash: expression of type
! int
! cannot have type
! int ref
This is because function application (ref y
) binds tighter than infix operators (y-1
). What you mean is ref (y-1)
, since you can't subtract 1 from a reference.
This isn't very comprehensible or robust. I tried to run it in the simplest case I could think of,
val test1 = move (1,1,[])
But that's a weird base case not handled by the loop. If I change the numbers slightly,
val test2 = move (5,6,[])
then it returns either (5,6)
or (5,5)
depending on what you change break
into.
Based on your description below the code, here is a suggested implementation, although I'm still not completely certain I understand the use of this function:
(* verticalPointsExist (x, y, ps) checks that
* (x,1), (x,2), ..., (x,y-1) are all in ps. *)
fun verticalPointsExist (_, 0, _) = true
| verticalPointsExist (x, y, ps) = List.exists (fn p => (x,y) = p) ps
andalso verticalPointsExist (x, y - 1, ps)
fun move (x, y, ps) =
if verticalPointsExist (x, y, ps) then (x,y) else (x,y-1)
Considerations I made:
Use recursion rather than iteration.
Split the checking part into a helper function, so move
doesn't do two things.
Give the functions good names so the code reads more easily. Since I don't know the domain and am really guessing as to whether y
is some kind of vertical dimension, there are probably even better names out there. (verticalLineExists
? verticalPathClear
?) Maybe a more general function will have a better name, e.g. one that took two points and saw that the line is clear between them.
Upvotes: 1
Reputation: 36118
There is no break
in ML. You probably just want to write ()
there. Also, you'll need parens around the argument to ref
in line 3.
Upvotes: 1