[Tutorial] Function Type Explanation (stock, public, plain)
#1

Introduction

I made this tutorial to show people what the different function types are, when to use them, and what each of them do. I made this tutorial because everybody seemed to be using function types without actually knowing what they do.


Stock Functions

Explanation:

Stocks hide all warnings caused by that function from showing when compiling your script.

Usage:

Stocks shouldn't be used a lot unless you're making functions inside of an include.

Example:

pawn Код:
stock includeName_DoAction(playerid)
{
    // do stuff
}

Public Functions

Explanation:

Public functions can be called via CallLocalFunction, CallRemoteFunction, SetTimer, and SetTimerEx. Public functions cannot return strings. You are required to forward a public function ( forward functionName(params or blank) ) or you will receive a warning in the compiler.

Usage:

When creating a timer or a callback in an include, you should use a public function.

Example:

pawn Код:
forward timer1();
public timer1()
{
    // do stuff
}
pawn Код:
forward includeName_OnAction(playerid);

if( ... )
{
    CallRemoteFunction("includeName_OnAction", "d", playerid);
}

Plain Functions

Explanation:

Plain functions are just normal functions that do everything inside of the function.

Usage:

Plain functions should be used when you don't need to use a stock or a public for what you're trying to do.

Example:

pawn Код:
IsPlayerEnemy(playerid, forplayerid)
{
    // do stuff
}

Conclusion

Publics and stocks aren't needed most of the time and you can just use a plain function.
Reply
#2

You forgot to add that without severe modification, public functions cannot return strings, while stock functions can.
Quote:

Stocks hide all warnings caused by that function from showing when compiling your script.

Although I'm not sure if this is true or not, this is not the only thing that you could have explained about stocks.

Also, stocks are not mainly for includes, they are perfect for using within the gamemode.

Could have been much more in-depth IMO, since this is a tutorial.

EDIT:

You also could explain what happens when you don't forward a public function, and why that happens.
Reply
#3

Nice tutorial.

@Vincent, using stocks in your local gamemode or script is useless. Stocks are only used in includes because when you don't use a stock function, it won't give you an unused warning while if plain function aren't used, they will give you an unused warning. Basically, it's stupid to use stock functions because you can't have a function in your gamemode which you don't even use?
Reply
#4

pawn Код:
stock UserPath(playerid)
{
    new
        name[24],
        string[50]
    ;
    GetPlayerName(playerid, name, 24);
    format(string, 50, USER_PATH, name);
    return string; // publics can't do this
}
stock ProxDetector(Float:radi, playerid, string[],color)
{
    new Float:x,Float:y,Float:z;
    GetPlayerPos(playerid,x,y,z);
    foreach(Player,i)
    {
        if(!IsPlayerConnected(i))continue;
        if(IsPlayerInRangeOfPoint(i,radi,x,y,z)) SendClientMessage(i,color,string);
    } // stocks can go without returning a value
       // publics, you have to return a value
}
stock ClearChat(playerid)
{
    for(new j=0;j<50;j++)
    {
        SendClientMessage(playerid,COLOR_WHITE,"");
    }
    return 1;
}
stock GetName(playerid)
{
    new string[MAX_PLAYER_NAME];
    GetPlayerName(playerid,string,sizeof(string));
    strreplace(string,'_',' ');
    return string; // publics can't do this
}
stock strreplace(string[], find, replace)
{
    for(new i=0; string[i]; i++)
    {
        if(string[i] == find)
        {
            string[i] = replace;
        }
    }
}
stock GetXYInfrontOfPlayer(playerid,&Float:x,&Float:y,Float:Distance)
{
    new Float:r;
    if(IsPlayerInAnyVehicle(playerid)==0)GetPlayerFacingAngle(playerid,r);
    else GetVehicleZAngle(GetPlayerVehicleID(playerid),r);
    x += (Distance * floatsin(-r, degrees));
    y += (Distance * floatcos(-r, degrees));
    return 1;
}
Stocks are useless my ass. Think before you post.
Reply
#5

Quote:
Originally Posted by VincentDunn
Посмотреть сообщение
pawn Код:
stock UserPath(playerid)
{
    new
        name[24],
        string[50]
    ;
    GetPlayerName(playerid, name, 24);
    format(string, 50, USER_PATH, name);
    return string;
}
stock ProxDetector(Float:radi, playerid, string[],color)
{
    new Float:x,Float:y,Float:z;
    GetPlayerPos(playerid,x,y,z);
    foreach(Player,i)
    {
        if(!IsPlayerConnected(i))continue;
        if(IsPlayerInRangeOfPoint(i,radi,x,y,z)) SendClientMessage(i,color,string);
    }
}
stock ClearChat(playerid)
{
    for(new j=0;j<50;j++)
    {
        SendClientMessage(playerid,COLOR_WHITE,"");
    }
    return 1;
}
stock GetName(playerid)
{
    new string[MAX_PLAYER_NAME];
    GetPlayerName(playerid,string,sizeof(string));
    strreplace(string,'_',' ');
    return string;
}
stock strreplace(string[], find, replace)
{
    for(new i=0; string[i]; i++)
    {
        if(string[i] == find)
        {
            string[i] = replace;
        }
    }
}
stock GetXYInfrontOfPlayer(playerid,&Float:x,&Float:y,Float:Distance)
{
    new Float:r;
    if(IsPlayerInAnyVehicle(playerid)==0)GetPlayerFacingAngle(playerid,r);
    else GetVehicleZAngle(GetPlayerVehicleID(playerid),r);
    x += (Distance * floatsin(-r, degrees));
    y += (Distance * floatcos(-r, degrees));
    return 1;
}
Stocks are useless my ass.
That code didn't prove anything at all. Everything there could be done with plain functions. You make a function in your gamemode because you're gonna use it, and using a stock will only hide the 'function not used' warning in the compiler (considering the fact that your function works) which can sometimes be useful to see if you missed something.
Reply
#6

Quote:
Originally Posted by SuperViper
Посмотреть сообщение
Everything there could be done with plain functions.
With all due respect, go make a public function and try to return a string, and try another public function that doesn't return a value.

I think you'll understand what I mean.

EDIT: I saw what you meant about the 'plain' functions. (I hardly use them) Just didn't want you to convince people that stocks are useless.

EDIT 2:
Quote:
Originally Posted by Simon
Посмотреть сообщение
You make it sound it sound as if a method tagged stock will hide all warnings associated with it. This is a side-effect of what an unused stock method does i.e. nothing because it's not compiled into the P-code. The Pawn compiler will still complain about warnings associated with a stock method if it is referenced in your code.

A stock method is a method that is allowed to be skipped by the parser if it's not used. In other words, you will not be warned that it is unused and it does not exist in the compiled code. A method that is not tagged stock and is also unused is still compiled into the P-code, thus using space in the compiled code.

You might ask now why doesn't the Pawn compiler just remove unused tagged stock or not to save space? One reason being because it cannot infer whether or not the method is compiled into the script for external purposes (i.e. a public method). You may have public "unused" methods that are callable by an external program.



Код:
// start of script
main() {
    foo1(); 
    // foo2() unused, warning
}

foo1() { /* */ }
foo2() { /* */ }
// end script
I personally use stocks wherever you might use a "plain" function, dealing with unused methods/variables warnings is a hassle to me. If you want to enforce that a function MUST be used then don't use stocks. I've never had the case where a function MUST be used... most people won't unless they do a lot of design up front and would like to be warned if they forgot to include a method.
I completely agree with this.
Reply
#7

You make it sound it sound as if a method tagged stock will hide all warnings associated with it. This is a side-effect of what an unused stock method does i.e. nothing because it's not compiled into the P-code. The Pawn compiler will still complain about warnings associated with a stock method if it is referenced in your code.

A stock method is a method that is allowed to be skipped by the parser if it's not used. In other words, you will not be warned that it is unused and it does not exist in the compiled code. A method that is not tagged stock and is also unused is still compiled into the P-code, thus using space in the compiled code.

You might ask now why doesn't the Pawn compiler just remove unused tagged stock or not to save space? One reason being because it cannot infer whether or not the method is compiled into the script for external purposes (i.e. a public method). You may have public "unused" methods that are callable by an external program.

Quote:

Basically, it's stupid to use stock functions because you can't have a function in your gamemode which you don't even use?

Код:
// start of script
main() {
    foo1(); 
    // foo2() unused, warning
}

foo1() { /* */ }
foo2() { /* */ }
// end script
Using stocks vs. not using them is more of a personal preference. I personally use stocks wherever you might use a "plain" function, dealing with unused methods/variables warnings is a hassle to me after making a massive change (I'd rather let the compiler deal with removal from compiled code).

If you want to enforce that a function MUST be used then don't use stocks. I've never had the case where a function MUST be used. I'd shoot a guess that most people making SA:MP scripts won't unless they do a lot of formal design up front and would like to be warned if they forgot to include use of a required method.
Reply
#8

Quote:
Originally Posted by VincentDunn
Посмотреть сообщение
With all due respect, go make a public function and try to return a string, and try another public function that doesn't return a value.

I think you'll understand what I mean.
I was referring to the code you provided as a response to Cell. I added the returning strings in a public function to the thread, thanks for that.


Quote:
Originally Posted by Simon
Посмотреть сообщение
You make it sound it sound as if a method tagged stock will hide all warnings associated with it. This is a side-effect of what an unused stock method does i.e. nothing because it's not compiled into the P-code. The Pawn compiler will still complain about warnings associated with a stock method if it is referenced in your code.

A stock method is a method that is allowed to be skipped by the parser if it's not used. In other words, you will not be warned that it is unused and it does not exist in the compiled code. A method that is not tagged stock and is also unused is still compiled into the P-code, thus using space in the compiled code.

You might ask now why doesn't the Pawn compiler just remove unused tagged stock or not to save space? One reason being because it cannot infer whether or not the method is compiled into the script for external purposes (i.e. a public method). You may have public "unused" methods that are callable by an external program.



Код:
// start of script
main() {
    foo1(); 
    // foo2() unused, warning
}

foo1() { /* */ }
foo2() { /* */ }
// end script
I personally use stocks wherever you might use a "plain" function, dealing with unused methods/variables warnings is a hassle to me. If you want to enforce that a function MUST be used then don't use stocks. I've never had the case where a function MUST be used... most people won't unless they do a lot of design up front and would like to be warned if they forgot to include a method.
Usually people implement functions into their script because they need it for something they're working on. I'm not against stocks, but apparently not a lot of people actually know the difference between publics, stocks, and plain functions, which is the reason I posted this thread.
Reply
#9

Why would someone put something in their GM when they aren't even going to use it?


Quote:
Originally Posted by ******
Посмотреть сообщение
Do you actually CALL the function? stock functions aren't compiled if they're not used, basically I'm looking at this line:

pawn Код:
if(!IsPlayerInAnyVehicle(playerid)) return 0;
Where is playerid coming from?
http://forum.sa-mp.com/showpost.php?...52&postcount=9

I am searching for a better post of his which clearly explains the difference but can't find it.
Reply
#10

Quote:
Originally Posted by Cell_
Посмотреть сообщение
Why would someone put something in their GM when they aren't even going to use it?
Look I'm not saying it's wrong to not use stock, I'm just saying there are reasons for and against. The advice to not use stock a lot should not be held as gospel... my personal experience suggests to use stock whenever.

If you've written a massive script and had to maintain it for years then you'll know there are times when you remove references to variables or functions as a result of optimising or removal of a bugged feature (in order to keep a server playable). Traversing multiple source code files without a decent Pawn IDE can annoyingly be time consuming and/or you may want to keep a function or variable name reserved for use later on. Sometimes you might define the implementation of something while you have a working train of thought but not actually have a use for it until you've finished something else.

Writing large game modes usually involves writing a set of internal libraries, defining internal methods for developers in a team that may not be used yet. Extra warnings are usually non-useful noise to me.
Reply


Forum Jump:


Users browsing this thread: 3 Guest(s)