helen
helen

Reputation: 587

SML - changing the value of a tuple element in a list of tuples

I've just started learning SML and I want to write a program which takes 2 int and a list of tuples, makes changes on them and then returns a list(BOXES is a list). List always has 2 tuples. In some if conditions I need to change the amount of an element in a tuple. So for example I define Xb1 and I gave it the amount of first element of the tuple ( #1 head ) and later I change the amount of Xb1 in the code(and return the list). But the problem is that this amount isn't changed. Here is the code:

fun MoveBoxL(Xw,Yw,boxes:(int * int)list) : BOXES =
let
val head = List.hd boxes
val tail = List.hd boxes
val Xb1= #1(head)
val Yb1 = #2(head)
val Xb2 = #1(tail)
val Yb2 = #2(tail)
in
if Yw=1 then boxes
else if head=(Xw,1) andalso Yw=2 then boxes
else if tail=(Xw,1) andalso Yw=2 then boxes
else if Yw=3 andalso head=(Xw,1) andalso tail=(Xw,2) then boxes
else if Yw=3 andalso tail=(Xw,1) andalso head=(Xw,2) then boxes
else if head=(Xw, Yw-2) andalso tail=(Xw, Yw-1) then (Yb1=Yb1-1 ; Yb2=Yb2-1 ; boxes)
else if head=(Xw, Yw-1) andalso tail=(Xw, Yw-2) then (Yb2=Yb2-1 ; Yb1=Yb1-1 ; boxes)
else if head=(Xw,Yw-1) then (Yb1=Yb1-1 ; boxes)
else if tail=(Xw,Yw-1) then (Yb2=Yb2-1 ; boxes)
else boxes
end;

cpn tools picture what's wrong?

Upvotes: 1

Views: 905

Answers (1)

John Coleman
John Coleman

Reputation: 52008

I'm still not 100% sure what these rules for moving boxes are, but the following seems to capture your intent:

fun MoveBoxL(Xw,Yw,boxes:(int * int)list) =
let
   val [box1,box2] = boxes
   val (Xb1,Yb1) = box1
   val (Xb2,Yb2) = box2
in
   if Yw = 1 then boxes
   else if box1=(Xw,1) andalso Yw=2 then boxes
   else if box2=(Xw,1) andalso Yw=2 then boxes
   else if Yw=3 andalso box1=(Xw,1) andalso box2=(Xw,2) then boxes
   else if Yw=3 andalso box2=(Xw,1) andalso box1=(Xw,2) then boxes
   else if box1=(Xw, Yw-2) andalso box2=(Xw, Yw-1) then [(Xb1,Yb1-1),(Xb2,Yb2-1)]
   else if box1=(Xw, Yw-1) andalso box2=(Xw, Yw-2) then [(Xb1,Yb1-1),(Xb2,Yb2-1)]
   else if box1=(Xw,Yw-1) then [(Xb1,Yb1-1),box2]
   else if box2=(Xw,Yw-1) then [box1,(Xb2,Yb2-1)]
   else boxes
end;

I renamed your head and tail to be box1 and box2 respectively. (and fixed a bug of yours where you were giving the wrong value to tail) and used pattern matching to make the bindings easier to understand. More importantly, I replaced

(Yb1=Yb1-1 ; Yb2=Yb2-1 ; boxes)

by

[(Xb1,Yb1-1),(Xb2,Yb2-1)]

which is what I meant in the comments when I said that you should directly return what you want the new value to be.

It seems that the logic can be cleaned up by combining the clauses with have the same return value into single conditions using orelse.

Upvotes: 1

Related Questions