ID:133179
 
I think the compiler should forbid the use of usr in procs except for Click() etc. NOT for login or any others where src is always correct, though. This would probably prevent a lot of bugs.
Awwee, but then we won't have the fun to yell at those who do! :(
This shouldn't be done, there are cases where usr may be valid in their code. This really depends on how the proc is called, and where.

Besides, all a verb is is a proc that a client can call themselves; if I added a proc to a client's verb list, it would act as a verb.
This would probably slow the compilation process down by quite a lot since it would have to do some pretty specific checking for this stuff. Probably best to just leave it be.
If it helps, this usr in proc issue has been brought up before, because it's a veritable mine-field and seems to only have real niche application. The notion of removing usr from procs entirely and just passing a usr into the relevant common use procs like Click() as an argument instead has at the least been debated by a few people. For a language that typically tries very hard to shield programmers from all manner of problems (including some really unlikely security issues), leaving this open does leave new programmers particularly vulnerable to mistakes for niche gains and as we've seen is a common mistake. That said, I wouldn't expect any limiting or phasing out to be anything we'd witness in the near future, if such action is decided to be the way forward. Binary compatibility could be maintained I guess, but I frankly have no idea on the issues surrounding that. It's mainly the source transition that people will complain about, when one version suddenly switches off such functionality.

A compiler warning might be a good start, if it's doable.
In response to Stephen001
What about setting usr to null after any verb finishes executing?
In response to Immibis
usr is a bit of a magic variable, it is presumably set when the stack-frame is setup, so I don't think that would do anything. If it makes it easier to understand, usr is probably set to an appropriate value just before a proc or verb executes.

If you're going to make a language change though, stripping usr out of procs altogether would be cleaner than setting it to null. They both have the same effect, in that you can't effectively use them. It's just removing it makes usr a special variable exclusive to verbs, where it makes sense. Click() and company can just pass the usr in arguments, meaning the variable is defined only in procs it's needed and users can recreate the usr functionality by doing the same with their procs, for the niche cases where usr makes sense in programmer defined procs.

You're really looking to take usr out of the default toolkit for procs altogether, so people don't see it available and make incorrect assumptions on what it means. Experienced users and Click() etc can emulate usr as per their needs. The big problem is the transition period. Eventually the variable usr will have to throw a not defined compiler error, which will invariably annoy some programmers. Warnings and binary compability should help smooth this transition, along with a small period where usr is defined in general procs as it is currently but the proc signatures are updated on Click() etc to be Click(var/usr) or perhaps Click(var/U) if you must maintain usr uniformly across procs during this signature update.
The problem is not usr in procs, the problem is that many people are 'learning' from horrible, horrible leaked source code.
In response to Airjoe
Even if you look beyond that to the people who made the leaked source code, or the people who are learning independent of it, usr in verbs denotes a physical player at a keyboard. So you'd naturally extend that notion to usr in procs, particularly with usr being a logical shorthand for user, the actual player. I don't think this logic is a quantum leap (tee hee) for new programmers and opens them up to runtimes. A trap like that must have some real benefit to justify it's existance. Frankly I don't see one semantically, Click() and company only happen to use usr because it's there, it could be replaced by argument passing the caller. Lummox has identified performance benefits in symbiotic callback scenarios, which strikes me as pretty niche and thus doesn't offer a major benefit to justify that pitfall. Once again this can be emulated with argument passing of the caller, although presumably with a performance hit. I appreciate the difficult case comes from jumping up the call stack, seen as without usr you either need to trickle the initiator down the call stack manually, or bubble up the stack through returns. I still question if this convenience justifies the common newbie trap, considering how most programmers on BYOND probably manipulate the call stack (or more appropriately, don't) and their needs to do so.

To phase out usr in procs represents removing a common newbie trap (the fact "no usr in proc" has become a canned response says it all I think), at the cost of (presumably) minor performance losses on callbacks and Click() etc, along with legacy source incompatibility. The performance issues are something that would need to be looked at, along with how easy it would be to maintain binary compatibility etc, making it a change with a similar process (but perhaps not technical timescale) to the increased runtime limits change. After that it is just a matter of a sound deprecation strategy for this functionality, over a 6 month / 1 year / 2 year timescale, as per Tom's discretion.

It would kill a common newbie programmer pitfall, cause some complaining when the switch finally occurs (some people never pay attention), obfuscate a small number of snippets of advanced code and perhaps even deprecate some of BYOND's leaked Anime source code bases, as the switch may well render them simply too broken to be fixed (300+ potentially non-trivial compile-time errors) by the people who typically utilise them. I think it's worth it.
In response to Stephen001
Stephen001 wrote:
Stuff about phasing usr out of procs, newbie traps and pitfalls, a Creator, callback scenarios, made a early '90s TV reference, and most importantly wrote that "...usr in verbs denotes a physical player at a keyboard. So you'd naturally extend that notion to usr in procs..."

Well, have you looked at the DM Guide or the DM reference/Help Files lately? Neither of them mention the pitfalls of using usr in procedures. Naturally, newbies would have no idea, unless they have read carefully over the guide, they are a 'browser,' or they just happened to have come into a thread where people were complaining about it. I read over the variables section of the DM Guide a few times before I started coding and I didn't realize usr pitfalls until I hit one. I mean, even in the DM Reference, it specifically says that "Verbs are fundamentally the same "type" as procs, so their vars are the same." Naturally, newbies would expect to use those variables the same way.

... I think that was all I was going to say. I was going to metnion useful usr's in procedures, but t's like 3 A.M. so, ... yeah.
In response to Hiro the Dragon King
There are very few procedures where usr is useful - they're all pseudo-verbs, like client/Click() or client/Move() (NOT mob/Move(), where it is VERY BAD). Stephen is proposing that that be handled by a variable passed to those pseudoverbs.

As for usr in the guide, here's how it is first mentioned:

Notice the funny stair-step indentation again! That will be explained in a little bit. For
now, read this example from top to bottom. Once again we are defining a property of a mob
(the player’s avatar). In this case we are adding a verb, an action that the player can instruct
the mob to perform. The name of the verb is smile. The final line displays a message when the
mob smiles. Notice the [usr] in the message; as you may have guessed, that is not displayed
literally but is replaced by the name of the user, the player who initiates the command.


"The player who initiates the command". There is no such player for procedures. You'd have thought people would have worked it out.

Worse yet, the section on variables (Page 35, to be precise), in a section entitled "The usr and src Variables", says the following:

Two variables that you have already seen can be used with the dot operator because their type
is automatically defined for you. The variable usr is declared as var/mob/usr since it always
refers to the mob who is executing a verb. The variable src has the same type as the object
containing the verb (obviously).


"refers to the mob who is executing the verb".

It could be made clearer, but the guide definitely implicitly says that usr is for verbs only.
In response to Jp
Jp wrote:
There are very few procedures where usr is useful - they're all pseudo-verbs, like client/Click() or client/Move() (NOT mob/Move(), where it is VERY BAD).

How about a proc that is called from another mob that changes something in both the called(src) and the caller(usr). Sure, you could pass that through a variable, but why bother if usr is there. Why phase something out that can still has use, especially if it would ruin older games? It would just create more reasons for people cling to their 3.5s.

"The player who initiates the command". There is no such player for procedures.

Maybe not a player, but there is a usr.

You'd have thought people would have worked it out.

You've seen the people in the forums... they don't.

"refers to the mob who is executing the verb".

It could be made clearer, but the guide definitely implicitly says that usr is for verbs only.

No, it does not. It merely states who the usr is in a verb.
In response to Stephen001
But it would also break legitimate code that uses usr in a proc. All a verb is is a proc, and a proc will function as a verb if added to a mob's verb list.

I think that a compiler warning should be given, if anything at all.
In response to Jeff8500
It would break legitmate source code after a 6 month / 1 year / 2 year warning period during which you should've made modifications. I don't think that concern holds any serious water against the benefits I've listed.
In response to Stephen001
A good example of a place where usr is legitimate in a proc not built into BYOND would be the CGI/Topic() proc in the CGI library. I'm sure many programmers have built up more secure procs like this for ease of use; you just have to be careful with how you call it.
In response to Jeff8500
I still think it's niche case that can be modified suitably over a transition period.
I could see throwing a warning for this, but an error would be overkill. Putting usr in a proc isn't the end of the world, it's just a really bad idea for newbies because they don't know how to handle it properly. A warning would however be difficult to implement, not least because it requires modification of the compiler.

One example of a source for confusion is when to throw the warning. usr is expected in Click(), etc. but if those procs are ever called manually, they are no longer usr-safe. And what about cases where an NPC AI manager might set usr manually and then call a verb? Analyzing proc behavior is the only way to tell for sure if a proc is usr-safe; doing that properly is not only non-trivial, but probably intractable. Much easier is keeping a list of procs that are supposed to be usr-safe, but leaving the programmer dangling if they do something really weird.

Another issue is implicit usr references showing up in view(), input(), alert(), etc. Those have to be caught for a warning as well.

Finally there's the question of how to handle procs that are only ever meant to be used as verbs--as in, something you might add to src.verbs at runtime. I don't see any way of avoiding the possibility of throwing a warning for those in such cases.

I think this is doable on the simple level of keeping a list of supposedly usr-safe procs, but not necessarily easy. I very much like the idea of throwing a gazillion warnings into shoddy ripped sources though.

Lummox JR
In response to Lummox JR
Maybe have the user specify which procs are usr-safe.
Then warn for all procs that the user hasn't marked "usr-safe", except for procs such as Click.

The only effect of this would be to suppress the warning.

Example of marking a proc as "usr-safe":
// This proc will be added to objects' verb lists
obj/proc/usrsafe/get()
usr << "You get [src]"
loc = usr


Also phrase the warning so it sounds scary to newbies, eg "You have used usr in a proc. THIS IS A COMMON CAUSE OF BUGS. ONLY DO THIS IF YOU KNOW WHAT YOU ARE DOING."
In response to Immibis
Actually it'd be better if it was used with set.

Example :

obj/proc/get()
set usr_safe=true // or 1
// etc
In response to Lummox JR
If this is added, please include some sort of flag to indicate that we know what we're doing and understand the problems that could occur with usr. It'd be annoying to get the warning for procs only meant to be used as verbs.
Page: 1 2