Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nulls/Optionals #55

Open
jdpage opened this issue Aug 10, 2018 · 1 comment
Open

Nulls/Optionals #55

jdpage opened this issue Aug 10, 2018 · 1 comment

Comments

@jdpage
Copy link
Collaborator

jdpage commented Aug 10, 2018

In #6, and #19, we discussed pointers, and in #53, error handling. This neatly leads on to the question of nullable pointers.

In my mind, our existing pointers aren't nullable; we don't even have a way to create a null pointer at the moment (there's no null keyword or equivalent, and no concept of default initialization). However, it's generally useful to be able to indicate that a function didn't return a useful value.

It's actually pretty hard to accidentally invent a null pointer on the C64, since the entire address space is addressable. The best candidate for a null value is probably 0xffff, which points into the middle of the hardware ISR vector, and is at the end of memory, so a pointer with value 0xffff is totally useless. But also has a chance to bone your hardware good if you try to write to it, since it'll clobber the high byte of your ISR vector and possibly also your processor port direction register 0x0000 if it wraps around.

In general, I'm a fan of systems which (a) distinguish between nullable and non-nullable pointers, and (b) either force you to check a nullable pointer before using it. We could just extend the error-code system I suggested in #53, but that means flags for everything ever forever. That's not necessarily the worst approach.

The other option would be some way to make types nullable, which either adds a flag or chooses an appropriate sentinel value as appropriate for the type. (This is what Rust does -- option<u16> is three bytes wide, and carries a flag; option<&u16> is two bytes wide, and uses a sentinel value.)

@jdpage
Copy link
Collaborator Author

jdpage commented Aug 10, 2018

fun div(a: u8, b: u8) -> u8?
  if b == 0 do
    return none
  else
    return a / b
  end
end

let x: u8? = foo(4, 2)  -- store the optional directly

let y: u8 = try unpack(foo(4, 2))  -- u8 unpacks into a bool, u8

if let p: bool, z: u8 = unpack(foo(4, 2)) do
  -- but this makes p a redundant binding
end

if let w: u8 = foo(4, 2) do
  -- syntactically special but ergonomic
end
if try w = foo(4, 2) do
  -- probably plays nicer with type inference; it's now obvious that w is a u8
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant