ID:1240942
 
(See the best response by Stephen001.)
Code:
var/const/some_string = "something"

#define some_string "something"


What's the difference between the two?
Best response
When it's processed, more or less.

The const variable represents a variable you'd have in the world at run-time. It obeys the normal rules of variables, so for example you cannot do:

for (var/I in 1 to 10) 
var/const/T = I
world << T


Generally it's a good way to provide values that are scoped, have path names etc, in libraries and games.

The macro definition allows for a literal replacement within the source code, just before it's compiled. So there's no actual variable in the world at runtime. It applies from that point in the code onwards (or until an equivalent #undef) and can replace /any/ part of the code that matches.

Meaning, this could cause issue:

#define del "hello"

var/mob/A = new()
del(A) // Replaces to "hello"(A) which makes no sense.
@Stephen; What could be some good examples to use #define with? I've never really understood it either, but once before I saw a friend make a demo out of only using # (the green text). Ever since then, I've always wondered about it.
Mmmm. One obvious example would be for extra debugging code, or say ... an new algorithm would want to introduce. That debug checkbox you have in DreamMaker just puts a definition in the DME file.

#define TRACE_DEBUG
#define TRACE_DEBUG_LEVEL TRACE

// ...

proc/example()
#ifdef TRACE_DEBUG
world.log << "\[TRACE_DEBUG_LEVEL\] Entering example()"
#endif
world << "Hello!"
#ifdef TRACE_DEBUG
world.log << "\[TRACE_DEBUG_LEVEL\] Eixting example()"
#endif


Alternatively, F_Damage uses it within the Cache.dm to basically avoid proc call overhead within that file. It's not recommended to do in general, but within that file it was okay because that's a contained piece of code, that needs to operate quickly.

#define F_DAMAGE_CACHE_TICKER 10
#define F_DAMAGE_CACHE_HIT(ENTRY) ENTRY.count = F_DAMAGE_CACHE_TICKER; result = ENTRY.value
#define F_DAMAGE_CACHE_MISS(ENTRY) ENTRY.count--; if (ENTRY.count == 0) del(ENTRY)

__f_damage_CacheEntry
var
key
value
count

New(var/key, var/value, var/count)
src.key = key
src.value = value
src.count = count

__f_damage_Cache
var
list/entries = new()

proc
get(var/key)
var/result = null
for (var/__f_damage_CacheEntry/E in src.entries)
if (E.key == key)
F_DAMAGE_CACHE_HIT(E)
else
F_DAMAGE_CACHE_MISS(E)
return result

put(var/key, var/value)
var/__f_damage_CacheEntry/E = new(key, value, F_DAMAGE_CACHE_TICKER)
entries.Add(E)


#undef F_DAMAGE_CACHE_TICKER
#undef F_DAMAGE_CACHE_HIT
#undef F_DAMAGE_CACHE_MISS
Incidentally, that has highlighted three things:

Poor use of macros. F_DAMAGE_CACHE_HIT and F_DAMAGE_CACHE_MISS are used once, there's really no need for them to be macros.

Un-necessary delete of the icon.

F_DAMAGE_CACHE_TICKER cannot be overridden by library users.
For a more simple-minded alternative, if you for example wanted all of your procedures to follow one naming convention but are annoyed by the built-in procedure's naming convention, you can do this:
#define move(newloc, dir, step_x, step_y) Move(newloc, dir, step_x, step_y)


You can also do it for formulas. I find it very convenient (Although maybe not necessary) for simplifying formulas.
// for example
#define formulate(x) x+2/4*10/(100*576)
In response to Albro1
Thanks, that helped me understand it a little better. Stephen is too smart for me, lol. I got lost in his example.