Functions vs Procedures - Passing Arguments and which to use
Author |
Message |
np_123
|
Posted: Thu Jan 02, 2014 12:58 pm Post subject: Functions vs Procedures - Passing Arguments and which to use |
|
|
What is it you are trying to achieve?
Functions or Procedures - Which one to use
What is the problem you are having?
Deciding whether to keep passing variables arguments to procedure or somehow turn it into a function
I should mention that I did look through the Tutorial section - The Turing Walkthrough... - Functions and Procedures
Cervantes wrote:
I sincerely hope this has convinced you that functions are superior to procedures. I'm not saying that functions should be used exclusively. There are times when procedures are needed. Rather, I'm just saying that when you have a choice of using a function or using a procedure, choose the function. Nice functions are ones that compute a value based soley on the parameters they take. They don't rely on any global variables. These are functions that are easily documented. At the other extreme are procedures that use global variables inside their definition and also take in variables and modify them. These procedures are dangerous! and very hard to document.
After reading that, I am still unsure about whether my procedure is fine as it is or if I should find another way in order to avoid passing variables as arguments.
I am willing to put effort forward into any suggestion or critique - my primary concern is the way I SHOULD do it, rather than how I've already done it...
After all, I've rewritten the code for the entirety of the program at least 3 times already, using different methods and making it better each time.
My problem is that he values of the elements within the arrays bpcs, rpcs, bking, rking must be changed at some point because the pieces are being moved within the procedure, and the new positions must reevaluate to being true, and the old positions false
Post any relevant code (You may choose to attach the file instead of posting the code if it is too long)
This is what I currently have in one of my procedures...
The code may be more understandable if I mention that this is a complete procedure, and an excerpt from a working checkers game that I created
Oh, and the couple of commented lines are simply what I used for debugging
I've attached the main body of the program, the file from which it would actually be run from, to show where I initially declare the variables and the general path for the execution of the program. If necessary, I can upload other/the remainder of files required for one to run the program.
Turing: |
proc redmove (var bpcs, rpcs, bking, rking : array - 2 .. 11, - 2 .. 11 of boolean, center : array 1 .. 2, 1 .. 8, 1 .. 8 of int)
const posx := 1
const posy := 2
const size := maxy div 10
var X, Y, Btn, btnUpDown, sqx, sqy, sqx1, sqy1 : int
var square1, square2 : array 1 .. 2 of int
loop
square1 := GetPieceRed (bpcs, rpcs, bking, rking )
sqx := square1 (1)
sqy := square1 (2)
%locate (1, 1)
%put "redx", sqx ..
%put "redy", sqy ..
redselect (rking, center, sqx, sqy )
square2 := GetPieceRed1 (bpcs, rpcs, bking, rking, sqx, sqy )
sqx1 := square2 (1)
sqy1 := square2 (2)
if sqx1 < 9 and sqx1 > 0 and sqy1 > 0 and sqy1 < 9
and abs (sqx1 - sqx ) = 1 and abs (sqy1 - sqy ) = 1 and bpcs (sqx1, sqy1 ) = false
and bking (sqx1, sqy1 ) = false and rpcs (sqx1, sqy1 ) = false and rking (sqx1, sqy1 ) = false
and ((rpcs (sqx, sqy ) = true and sqy1 > sqy ) or rking (sqx, sqy ) = true) then
exit
else
Draw.FillOval (center (posx, sqx, sqy ), center (posy, sqx, sqy ), 25, 25, brightred)
if rking (sqx, sqy ) = true then
Draw.FillOval (center (posx, sqx, sqy ), center (posy, sqx, sqy ), 5, 5, yellow)
end if
end if
end loop
Draw.FillBox (sqx * size + size, sqy * size, sqx * size + (size * 2), sqy * size + size, green)
Draw.FillOval (center (posx, sqx1, sqy1 ), center (posy, sqx1, sqy1 ), 25, 25, red)
if rking (sqx, sqy ) = true then
Draw.FillOval (center (posx, sqx1, sqy1 ), center (posy, sqx1, sqy1 ), 5, 5, yellow)
end if
if rpcs (sqx, sqy ) = true then
rpcs (sqx, sqy ) := false
rpcs (sqx1, sqy1 ) := true
else
rking (sqx, sqy ) := false
rking (sqx1, sqy1 ) := true
end if
%Input.Pause
for count : 1 .. 8
if rpcs (count, 8) = true then
rpcs (count, 8) := false
rking (count, 8) := true
Draw.FillOval (center (posx, count, 8), center (posy, count, 8), 5, 5, yellow)
end if
end for
end redmove
|
Please specify what version of Turing you are using
4.1
Description: |
This file shows initialization of variables and the general path for the execution of the program |
|
Download |
Filename: |
0Main.t |
Filesize: |
3.34 KB |
Downloaded: |
53 Time(s) |
|
|
|
|
|
|
Sponsor Sponsor
|
|
|
Raknarg
|
Posted: Thu Jan 02, 2014 1:22 pm Post subject: RE:Functions vs Procedures - Passing Arguments and which to use |
|
|
The reason functions should be used over procedures is that functions simply return a value for you. The value resulting from the function does not need to be tied to a variable
Take the randint function for example. In turing, you have randint (v, low, high) which puts a random value into v. There is also Rand.Int(low, high) which simply returns a value. It just makes more sense to use a function in this case, because the random value doesn not need to be tied to anything.
Turing: |
var x : int := Rand.Int (1, 10)
var y : int
randint(y, 1, 10)
if Rand.Int (1, 2) = 1 then
do_something ()
end if
var rnd : int
randint (rnd, 1, 2)
if rnd = 1 then
do_something ()
end if
|
It's sloppier, and lot's of languages don't exactly support passing by reference (that's what it's called when you put var in front of a parameter), so it's better just to learn to use functions instead.
In any case, it makes your code cleaner and happier, easier to read. That's something you should always strive for
Also, I should mention, that you need to stop how you're doing variable names. Either write names that make more sense, or document it better, because if anyone has to read it(that includes you in the future, when you forget what everything does, because you WIL forget), they're going to shoot themselves in the head first
|
|
|
|
|
|
np_123
|
Posted: Thu Jan 02, 2014 1:58 pm Post subject: Re: Functions vs Procedures - Passing Arguments and which to use |
|
|
If I pass the value into the procedure like redmove (...) without using the var, can I call a function within that procedure to modify a variable that isn't declared in the procedure, if the right values are passed into it?
Because the way I see it, I need the arrays to updated in order to represent the piece locations, and to do that using functions, the function would then have to return a corresponding array, correct?
Except, then I wouldn't be able to do that from 'within' the procedure since I wouldn't be able to modify the value...
So, unless I return to the place where I declare the variables, I won't be able to change their values
I was told in my Gr11 ICS class, something along the lines of not using global variables - so ever since, when I write programs, I've tried to keep everything within procedures and functions, rather than declaring variables and whatnot outside - is that acceptable or should I be doing things differently???
And for the variable naming...for the most part I tried keeping it fairly straightforward (for me at least): sqx,sqy for coordinates of a square, rpcs for red pieces, etc. The main idea I tried following is that the variable was named, then I added r or b to represent the colour of the pieces...
(I originally started off using green as a piece colour, so I never actually changed the name for many variables or procedures/functions)
I'll take the critique as it's meant, and start trying to use more meaningful names
I probably should have learnt that lesson when I first tried making the program, like a year or so ago - then I stopped working on it - by the time I went back to it, the code was so much of a headache I started all over from scratch
|
|
|
|
|
|
np_123
|
Posted: Thu Jan 02, 2014 2:20 pm Post subject: RE:Functions vs Procedures - Passing Arguments and which to use |
|
|
I'm glad you mentioned that though, because I've actually applied to Software Eng, so all these pointers will be extremely helpful, cuz I have a lot of work to do before September
EDIT: I just headed back to The Turing Walkthrough in the Tutorials section - found Turing Style Guidelines by wtd, so I'll be going through that for sure
|
|
|
|
|
|
Raknarg
|
Posted: Thu Jan 02, 2014 3:55 pm Post subject: RE:Functions vs Procedures - Passing Arguments and which to use |
|
|
In general, the idea is if you're going to do something, try to do it in the way that makes the most sense, is easiest to understand, and be consistent. What I have up there are suggestions.
You would use var when you need to modify multiple variables or you need to modify an array, so if you're using var with an array, I would say that's fine.
Why do the arrays stretch from -2 to 11 though?
|
|
|
|
|
|
np_123
|
Posted: Thu Jan 02, 2014 4:25 pm Post subject: Re: Functions vs Procedures - Passing Arguments and which to use |
|
|
Hmm...I think that's something I had from when I first tried to make the program last year
I had it as such because to check if piece (x,y) can jump, I check if piece (x+2,y+2) is there or not, and a few other checks as well
I kept it above and below the 1-8 so it wouldn't crash when I check if an edge piece can jump
In that sense, it should actually be -1 to 10 for the arrays
I haven't been able to think of a way to get around that
Oh, and I set all the pieces outside the 1-8 range to True, so that moving off the board would not be a valid move
|
|
|
|
|
|
Dreadnought
|
Posted: Thu Jan 02, 2014 4:41 pm Post subject: Re: Functions vs Procedures - Passing Arguments and which to use |
|
|
np_123 wrote:
If I pass the value into the procedure like redmove (...) without using the var, can I call a function within that procedure to modify a variable that isn't declared in the procedure, if the right values are passed into it?
You mean, something like this?
Turing: |
proc Add1 (var x:int)
x += 1
end Add1
proc AddAndPrint(x : int)
Add1(x)
put x
end AddAndPrint
var a : int := 1
AddAndPrint(a) |
This won't work since inside AddAndPrint there is no reference to a in fact in that procedure x is a constant.
np_123 wrote:
Because the way I see it, I need the arrays to updated in order to represent the piece locations, and to do that using functions, the function would then have to return a corresponding array, correct?
Except, then I wouldn't be able to do that from 'within' the procedure since I wouldn't be able to modify the value...
So, unless I return to the place where I declare the variables, I won't be able to change their values
As Raknarg said, modifying arrays with procedures is the correct approach.
np_123 wrote:
I was told in my Gr11 ICS class, something along the lines of not using global variables - so ever since, when I write programs, I've tried to keep everything within procedures and functions, rather than declaring variables and whatnot outside - is that acceptable or should I be doing things differently???
It is good practice to restrict the scope of variables as much as possible. In small projects there aren't really any consequences to not doing this, but in a big project it avoids variable names being already taken and clarifies the intent.
np_123 wrote:
And for the variable naming...for the most part I tried keeping it fairly straightforward (for me at least) sqx,sqy for coordinates of a square, rpcs for red pieces, etc. The main idea I tried following is that the variable was named, then I added r or b to represent the colour of the pieces...
(I originally started off using green as a piece colour, so I never actually changed the name for many variables or procedures/functions)
I'll take the critique as it's meant, and start trying to use more meaningful names
I probably should have learnt that lesson when I first tried making the program, like a year or so ago - then I stopped working on it - by the time I went back to it, the code was so much of a headache I started all over from scratch
The general guideline are that the more important a variable is the more descriptive its name should be. (when I say "important", I think of some vague measure of its scope and occurrence)
Overall, for coding style I think that what is really important (Raknarg mentioned this) is consistency. Pick a style (preferably one that promotes readability of your code) and stick to it. If you are modifying someone else's code, try to stick to their coding style to maintain consistency.
Also, for something like your array indices starting at -2, this is the kind of thing that looks odd when you look at it so placing a comment there clarifying whats going on might be nice (or you can try to think of a way of avoiding this oddity)
|
|
|
|
|
|
np_123
|
Posted: Thu Jan 02, 2014 8:03 pm Post subject: Re: Functions vs Procedures - Passing Arguments and which to use |
|
|
A fair amount of my procedures have very similar purposes, so naming them 'uniquely' was a bit tricky
So, the same procedure as I posted earlier...but would you consider this more readable?
(I added comment concerning the indices of the arrays when I first declared them)
Turing: |
%Regular move Red
proc red_move (var blue_piece, red_piece, blue_king, red_king : array - 1 .. 10, - 1 .. 10 of boolean, center : array 1 .. 2, 1 .. 8, 1 .. 8 of int)
const X_POSITION := 1
const Y_POSITION := 2
const size := maxy div 10
var X, Y, Btn, btnUpDown, x_location, y_location, x_location1, y_location1 : int
var square1, square2 : array 1 .. 2 of int
loop
square1 := select_red_piece (blue_piece, red_piece, blue_king, red_king )
x_location := square1 (1)
y_location := square1 (2)
redselect (red_king, center, x_location, y_location )
square2 := select_second_red_piece (blue_piece, red_piece, blue_king, red_king, x_location, y_location )
x_location1 := square2 (1)
y_location1 := square2 (2)
if x_location1 < 9 and x_location1 > 0 and y_location1 > 0 and y_location1 < 9
and abs (x_location1 - x_location ) = 1 and abs (y_location1 - y_location ) = 1 and blue_piece (x_location1, y_location1 ) = false
and blue_king (x_location1, y_location1 ) = false and red_piece (x_location1, y_location1 ) = false and red_king (x_location1, y_location1 ) = false
and ((red_piece (x_location, y_location ) = true and y_location1 > y_location ) or red_king (x_location, y_location ) = true) then
exit
else
Draw.FillOval (center (X_POSITION, x_location, y_location ), center (Y_POSITION, x_location, y_location ), 25, 25, brightred)
if red_king (x_location, y_location ) = true then
Draw.FillOval (center (X_POSITION, x_location, y_location ), center (Y_POSITION, x_location, y_location ), 5, 5, yellow)
end if
end if
end loop
Draw.FillBox (x_location * size + size, y_location * size, x_location * size + (size * 2), y_location * size + size, green)
Draw.FillOval (center (X_POSITION, x_location1, y_location1 ), center (Y_POSITION, x_location1, y_location1 ), 25, 25, red)
if red_king (x_location, y_location ) = true then
Draw.FillOval (center (X_POSITION, x_location1, y_location1 ), center (Y_POSITION, x_location1, y_location1 ), 5, 5, yellow)
end if
if red_piece (x_location, y_location ) = true then
red_piece (x_location, y_location ) := false
red_piece (x_location1, y_location1 ) := true
else
red_king (x_location, y_location ) := false
red_king (x_location1, y_location1 ) := true
end if
%Input.Pause
for count : 1 .. 8
if red_piece (count, 8) = true then
red_piece (count, 8) := false
red_king (count, 8) := true
Draw.FillOval (center (X_POSITION, count, 8), center (Y_POSITION, count, 8), 5, 5, yellow)
end if
end for
end red_move
|
|
|
|
|
|
|
Sponsor Sponsor
|
|
|
|
|