ID:151750
 
I am busy going through some of the 9 years of BYOND code that I've created and horded in my vile dungeon of archives, and I found a handy little test snippet that I previously ran.

I'm not sure what I mean by "threading backwards/forwards", but this snippet basically shows you the order in which ..() calls are processed if you have lots of statements in your code.

mob/Login()
..()
src << "I am login 5! (threading fowards)"

mob/Login()
src << "I am login 4! (threading backwards)"
..()

mob/pc/Login()
src << " I am login 3! (pc, threading backwards)"
..()
src << " I am login 6! (pc, threading fowards)"

mob/pc/thief/Login()
src << " I am login 2! (pc/thief, threading backwards)"
..()

mob/pc/thief/Login()
src << " I am login 1! (pc/thief, threading backwards)"
..()
src << " I am login 7! (pc/thief, threading fowards)"

mob/pc/thief/Login()
..()
src << " I am login 8! (pc/thief, threading fowards)"

world/mob = /mob/pc/thief


The output would then print out all these lines in numerical order (1,2,3,etc.) - it's of particularly important note that 1 appears before 2, even though they're practically the same, programmatically. This is because 1 appears in code AFTER 2, and therefore when you compile it is similar to being on top of the stack.

Anyways, there you have it! Just in case anyone was wondering, and I doubt you were.


~Polatrite~
Typically you shouldn't define a proc for one type twice; it just gets messy, regardless of the order in which they're processed. However, otherwise the parent just calls whatever is above it within the type tree.
In response to Jeff8500
Jeff8500 wrote:
Typically you shouldn't define a proc for one type twice; it just gets messy, regardless of the order in which they're processed. However, otherwise the parent just calls whatever is above it within the type tree.

Libraries that you use typically add additional functionality to existing methods - it's standard behavior, and it's encouraged as the proper way to do it.

The above line of thought is correct if you're doing one simple project, but true object oriented and encapsulation methodologies frequently recommend grouping related functionality together - which can generally involving overriding or expanding on the same function in multiple places.

Also, "otherwise the parent just calls whatever is above it within the type tree" is a generalized and pointless statement given the scope of the thread. In this instance we're clearly defining multiple occurrences of the same method within the same type. It's helpful to know how the compiler handles these situations, that way when you're doing true encapsulation and using object oriented methodologies, it's easy to understand what is going on.

This post was created for the avid C# developer that's sure to join the community one, two, or four years down the road who is wondering exactly that.


~Polatrite~
In response to Polatrite
Oh, I skipped your post considering the subject a question, rather than a hypothetical question which was answered. Sorry.
In response to Jeff8500
Jeff8500 wrote:
Oh, I skipped your post considering the subject a question, rather than a hypothetical question which was answered. Sorry.

Well, this IS the Creations forum, though I'm sure with some of the community that makes about as much difference sky blue and robin's egg blue.

I word it this way so that it will return better search results for future searchers.


~Polatrite~
In response to Polatrite
Polatrite wrote:
Jeff8500 wrote:
Typically you shouldn't define a proc for one type twice; it just gets messy, regardless of the order in which they're processed. However, otherwise the parent just calls whatever is above it within the type tree.

Libraries that you use typically add additional functionality to existing methods - it's standard behavior, and it's encouraged as the proper way to do it.

I would not go so far as to say it's encouraged as the proper way to do it. If someone on Byond is encouraging it as such, please correct them.

The "proper" way to do something of this nature (I quote proper not to mock your statement, but because this is one of those things where you can continue to do things your way and be fine, even though I personally would not encourage it) would be to create seperate functions. Remove code that should logically be grouped together into their own seperate functions, then call those functions from within the function that should do multiple things.

That is, instead of doing
mob/Login()
// thing 1
mob/Login()
// thing 2

you should do
mob/proc
thing1()
thing2()
mob/Login()
thing1()
thing2()

Then, with your example, the library should have a thing1(), then you should call thing1() where appropriate.

There are several reasons why this is preferred. I'll only list the Dream Maker-specific one; Dream Maker automatically compiles your code files in alphabetical order, so, unless you want to worry about compilation order, your overwritten functions will be compiled out of order (the order you want them in, anyway).

You can change the names of your files, such as with number prefixes, to compile them in a certain order, or change the file that certain parts of code are in, to "solve" this. I've done that before, but it's very annoying and is an unnecessary hassle.

I am hereby encouraging people to seperate actions into seperate functions. There, now it's encouraged behavior to do so. ;)
In response to Loduwijk
Loduwijk wrote:
The "proper" way to do something of this nature (I quote proper not to mock your statement, but because this is one of those things where you can continue to do things your way and be fine, even though I personally would not encourage it) would be to create seperate functions. Remove code that should logically be grouped together into their own seperate functions, then call those functions from within the function that should do multiple things.
[...]
There are several reasons why this is preferred. I'll only list the Dream Maker-specific one; Dream Maker automatically compiles your code files in alphabetical order, so, unless you want to worry about compilation order, your overwritten functions will be compiled out of order (the order you want them in, anyway).
[...]
I am hereby encouraging people to seperate actions into seperate functions. There, now it's encouraged behavior to do so. ;)

I still think this is a moot point - should library integration be as easy and clean as it is now? Or should developers have to manually add-in function calls in their own code for every procedure the library developer wanted to overwrite?

I think that if I had to manually implement things like Deadron's CharacterHandling or Shadowdarke's DynamicAreaLighting - as the average user, I may not ever touch them because of the complexity of implementation.

This is where it's helpful to know the "order of compile-erations" so that you understand how your code is being threaded through.


~Polatrite~