%% title = "places, or what is up with *x not always meaning the same thing in different contexts"
% id = "01HY5R1ZV9DD7BV0F66Y0DHAEA"
- I recently got a question from my someone telling me they doesn't understand why `*x` does not read from the pointer `x` when on the left-hand side of an assignment.
- TL;DR: the deal with this example is that `*x` _does not mean_ "read from the location pointed to by `x`", but _just_ "the location pointed to by `x`".
- same thing with `some_struct.abc` or `some_struct->abc`
% id = "01HY5R1ZV9BMQ7NZJ06B0W48HP"
- but instead of jumping to conclusions, let's go back to the beginning.
let's think, what is it that makes places _different_?
% id = "01HY5R1ZV9JGE9FTN9CN736FJN"
- the main thing is that you can write to them and create references to them.
for instance, this doesn't work:
```c
void example(void) {
1 = 2; // error!
}
```
but this does:
```c
void example(void) {
int i;
i = 2; // fine!
}
```
% id = "01HY5R1ZV91NN3YMXFNRACPDS7"
- so really, places are kind of a different _type_ - we can do certain additional operations with them, such as writing!
% id = "01HY5R1ZV9KH99CGCFM7TM1ZZB"
- we'll call this type `place(T)`, where `T` is any arbitrary type that is stored at the memory location represented by the `place(T)`.
% id = "01HY5R1ZV9F6BEQ5RHRPZPRVM6"
- `place(T)` behaves a bit weirdly compared to other types.
for starters, it is impossible to write the type down in C code, so we're always bound to turn `place(T)` into something else quickly after its creation.
% id = "01HY5R1ZV92VA27TGY6DJPZNP9"
- for instance, in this example:
```c.types
void take_int(int x);
void example(int x) {
take_int(x /*: place(int) */);
}
```
the type of `x` being passed into the `take_int` function is `place(int)`, but since that function accepts an `int`, we convert from `place(int)`
to a regular `int`.
% id = "01HY5R1ZV9ST0B5PHERGD4J4R8"
- this conversion happens implicitly and involves _reading_ from the place -
remember that places represent locations in memory, so they're a bit like pointers.
we have to read from them before we can access the value.
% id = "01HY5R1ZV9E1NSCCTF1CXPMY3D"
- but there are operations in the language that _expect_ a `place(T)`, and therefore do not perform the implicit conversion.
% id = "01HY5R1ZV95BHSV9MF4Z46M377"
+ we're able to describe these operations as _functions_ which take in a type `T` and return a type `U` - written down like `T -> U`.
% id = "01HY5R1ZV90Z3S1FZ65R977P8Y"
- this notation is taken from functional languages like Haskell.
% id = "01HY5R1ZV9RERR87NHVSGS6TWP"
- the `->` operator is _right-associative_ - `T -> U -> V` is a function which returns a function `U -> V`, not a function that accepts a `T -> U`.
% id = "01HY5R1ZV9CG67DEA8Y649D40T"
- one of these operations is _assignment_, which is like a function `place(T) -> T -> T`.
it accepts a `place(T)` to write to, a `T` to write to that place, and returns the `T` written.
note that in that case no read occurs, since the implicit conversion described before does not apply.
```c.types
void example(void) {
int x = 0;
x /*: place(int) */ = 1 /*: int */; /*-> int (discarded) */
}
```
% id = "01HY5R1ZV9MNZKK381TS7K3VR2"
- another one of these operations is the _`&` reference operator_, which is like a function `place(T) -> T*`.
it accepts a `place(T)` and returns a pointer `T*` that points to the place's memory location in exchange.
```c.types
void example(void) {
int x = 0;
int* p = &(x /*: place(T) */);
}
```
% id = "01HY5R1ZV9YN7H33BMK0NPX4QT"
- and of course its analogue, the _`*` dereferencing operator_, which does not consume a place, but produces one.
it accepts a `T*` and produces a `place(T)` that is placed at the pointer's memory location - it's the reverse of `&x`, `T* -> place(T)`.
```c
void example(int* x) {
int y = *x;
}
```
% id = "01HY5R1ZV9KZZARNK8KXZTGAFX"
- another couple of operations that accept a `place(T)` is the _`.` and `[]` operators_, both of which can be used to refer to subplaces
within the place.
% id = "01HY5R1ZV9N6PY2ANQC45NN27E"
- the difference is that `.` is a _static, compile-time known_ subplace, while `[]` may be _dynamic, runtime known_.
% id = "01HY5R1ZV99N78RA7Z5GSVVPRB"
- the `.` operator takes in a `place(T)` and returns a `place(U)` depending on the type of structure field we're referencing.
% id = "01HY5R1ZV99PZT6SDK2HRCRMAZ"
- since there is no type that represents the set of fields of a structure `S`, we'll invent a type `anyfield(S)` which represents that set.
% id = "01HY5R1ZV9RYF2P5X53VW9S9K8"
- the type of a specific field `f` in the structure `S` is `field(S, f)`.
% id = "01HY5R1ZV9PACB0HVE976TZZ69"
- we'll also introduce a type `fieldtype(F)` which is the type stored in the field `F`.
% id = "01HY5R1ZV99M92Z0XH1H3385JE"
- given that, the type of the `.` operator is `place(T) -> F -> place(fieldtype(F))`, where `F` is an `anyfield(T)`.
- if you've been programmming C or C++ for a while, you'll know that it's pretty dangerous to just go pointer-[walkin'](https://www.youtube.com/watch?v=d_dLIy2gQGU) with the `->` operator