###### tags: `Guide To Contibuting`
# Datatypes
Datatypes is a concept of *what* some piece of information is.
Is it text? A number? An instance of an object? A path to an object? Etc.
Basic types you'll probably deal with:
`var/list/L = list()` - An array and a map all in one. Can store lists of.. well, anything, and associate values to them. More on this in 'lists'.
`var/datum/thing = new` - An object! You can create objects like this and BYOND will type-infer what you're creating. You can even pass arguments to the creation which goes to /New() (see objects section).
`var/atom/A = new` - Syntatic sugar for `var/datum/atom/A = new`. You just don't want to have to type /datum every time
`var/obj/O = new` - Syntatic sugar for `var/datum/atom/movable/obj/O = new`.
`var/mob/M = new` - Syntatic sugar for `var/datum/atom/movable/mob/M = new`. You're getting sick of this, right? Unfortunately, some other codebases **conceal typepaths even further than this.** Our guidelines is that code must never conceal typepaths further than what BYOND already did to this. It can be concealed/shortened on the user interface side in game (admins really don't need to have their screens flooded with /obj/machinery/atmospherics/component/portable_atmospherics/blah instead of just PORT_ATMOS/blah), but coders **must** know the actual path. More on all of this in the OOP lesson.
`var/number = 5` - A number. **All BYOND numbers are 32 bit floating points.** If you don't know what that means, don't worry about it.
`var/string = "text"` - Strings. Already explained.
`world` - The /world object, allowing the code to access the code object representing the server.
`var/client/C = GLOB.directory["ckey"]` - Clients are the representation of a player's connection
`var/icon/I = new icon('iconfile', "state")` - Icons represent a graphics asset and is used to determine how things look.
`var/sound/S = new sound('sound/effects/AImalf.ogg')` - Sounds datums represent a sound that you can play to players.
`var/matrix/M = new(1, 2, 3, 4, 5, 6)` - A matrix. Don't worry about it for now.
`var/thisisapath = /datum` - A **typepath**. This isn't a string. You can't say `new "/datum"()` but you can do `new thisisapath()`. Convert strings to typepaths with text2path, and vice versa with just ``"[thisisapath]"``
`var/acolor = rgb(255, 255, 0)` - This is just a string. Colors aren't special - while there's a special `color` mode for `input()` so users can pick colors, they're in reality just represented by `#abcdef` hexcolor strings. More on this in the BYOND guide.
## Type-casting
While in other languages like Java you'd do something like `type name = (type) othervar` to cast `othervar` to `type`, in BYOND, say, you want to cast an atom to an atom/movable.
```DM
var/atom/existing = new /atom/movable(locate(1,1,1))
var/atom/movable/casted = existing
```
You just do that.
Now, in this case, it seems fine and dandy because you know it's a "valid" cast
But say, you have this
```DM
var/turf/T = locate(1,1,1)
var/atom/movable/wrong = T
```
BYOND will let you without a second thought
And then,
```DM
wrong.loc = locate(1,2,2)
```
Yeah that'll be an instant runtime error, because `wrong` isn't actually an atom/movable - you just casted it.
Casting things in BYOND is basically sticking a paper tag onto it saying "this thing is this type now, please do not have the compiler error when I try to access that type's methods and variables". The compiler doesn't know if you're doing it right, so you have to remember what you're putting where (or better, check).
Now, say you don't **know** and it's better to have something be generic?
```DM
var/turf/T = locate(1,1,1)
var/atom/movable/wrong = T
if(!istype(wrong))
return
else
wrong.loc = locate(1,1,2)
```
You use `istype`. You can either do `istype(object, /path/to/check)` to check if an object is a specific type, or just `istype(object)` to check that the object is the type of its variable. **`istype` returns true also on subtypes, so it isn't an exact type check - use `type == /path/to/check` to check exact.**
## The Good
These types are pretty comprehensive and allow you to do most things.
Calling procs on lists vs objects etc etc aren't any different.
This is intuitive for people who haven't coded at all.
You can typecast variables (see: you **should** typecast variables) like the above to ensures that you're calling the right procs on it.
## The Bad
Types aren't actually enforced.
BYOND won't care if you assign a wrong type to a wrong variable. You'll just cause a runtime error. **It's therefore extremely important to have good code practice, as otherwise you are giving yourself a hard time when you start creating impossible to debug bugs, and making every coder after you miserable.**
You'll do this a lot starting out. Don't worry about it.
A lot of things are just syntatic sugar - the simplicity forced by BYOND will usually drive experienced coders screaming up the nearest wall because, ironically, it's very inflexible due to this.
What's worse, BYOND basically looks up procs by name. I can't imagine this is very efficient.
Example:
```
/datum/A/procA()
/datum/A/procC()
/datum/B/procB()
/datum/B/procC()
/proc/example()
var/datum/A/A = new
var/datum/B/B = new
A.procB() // this doesn't compile
B.procA() // this doesn't compile
A.procA() // this runs fine
var/datum/B/not_actually_B = new /datum/A
not_actually_B.procC() //this runs fine
```
This might seem like a cool thing but it's really not, as in general, trying to bypass single inheritance with this is a terrible idea.
## The Ugly
Advanced material warning: Skip this section if your head hurts from reading it. There's plenty more to read in BYOND internals.
BYOND variables, are, essentially two things.
- 32 bit floating point numbers
- A reference.
Text is just a string reference.
Our TRUE and FALSE defines are just **for coder convenience** - It's enforced because it makes code more readable when we want to know if something should be a boolean value. We use #defines because we don't have enum. A lot of good, readable SS13 code is only that way because we as programmers created guidelines for each other to make the code better. The engine is absolutely horrible at enforcement of this.
Your decimal numbers are still a floating point.
Think you are fancy with BITFLAG_1 | BITFLAG_2? You're doing floating point math with the 23 bit significand. It's faster and more efficient because **cramming 24 booleans into one field is kinda good, eh?** (and it's certainly magnitudes better than list operations) But it'll never beat a real boolean or bitfield.
<https://github.com/willox/auxtools/blob/master/auxtools/src/raw_types/values.rs> These are all the datatypes of BYOND.
In your time coding, as you (hopefully) start to do more advanced things you'll inevitably run into cases where things don't behave the way you think.
BYOND calls everything that's an array a 'list'. += and -= however work very differently, for, say, an `overlays` list, than a `contents` list or a normal list you defined yourself.
Sometimes BYOND will flat out crash if you modify things the wrong way (try to modify the `vars` list or a read only var, it'll runtime like usual but sometimes it just flat out crashes and at time of writing it hasn't been fixed).