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

RFC: Default values #330

Open
wegendt-bosch opened this issue Apr 12, 2019 · 1 comment
Open

RFC: Default values #330

wegendt-bosch opened this issue Apr 12, 2019 · 1 comment
Labels
enhancement New feature or request RFC Requests For Comments are ideas up for discussion. If accepted they result in implementation tasks.

Comments

@wegendt-bosch
Copy link
Contributor

wegendt-bosch commented Apr 12, 2019

Introduction

High level language support types that are more defined than numbers, structures and pointers. The most ubiquitous one are Objects. These are structures that carry more semantics and group together functions operating on them. They also support different constructors like a default constructor or constructors that do special initialization.

Some languages then use these default constructors to facilitate common code paths, for example in C++ declaring a variable without an explicit constructor call will call the default constructor, or in Kotlin variables with a nullable type are initialized to null. These are all some kind of default value for types declaring one.

Current Situation

Currently we validate that some types have an explicit initialization, like references, and initialize all other types with some kind of 0. Booleans are false, integers zero, structures are filled with 0, and so on. Sum types per default initialize to their first member with everything set to zero, again, by calling = {0} in C, which sets the tagged union to the first enum value and fills everything else with 0.

This has been fine for now but a more refined system can be imagined.

Proposal

I propose that types may declare a default value. If they do, users may write variables without initialization:

var i: uint32;

If they don't, there are different cases for a default default value (so the default thing we do for default values):

Product Types

Product types have a default default value if and only if all their member types have default values.

Sum Types

For sum types there are three different strategies to be discussed:

  • The default default value is their first constructor, if all its members have a default value
  • The default value is the first constructor which has only members that have a default value
  • Sum types never have a default default value

Generated Types

Generated Types have a default if and only if they declare a constructor without any arguments.

Code Example

I propose one of the following ways for declaring explicit default values, all backwards compatible by leaving out the new syntax. Other proposals or better variations are welcome.

Variant 1: Assignment

This variant is the most straight-forward one, but can become cluttered the easiest.

struct vec2d {
  var x: int32;
  var y: int32;
} = vec2d(1, 2)

alt OptionalInt32 {
  Some: int32 | None
} = .None()

export native-type int32 alias-of int32_t header "stdint.h" = 0

Variant 2.a: Haskell-style properties

In this variant and 2.b types can be followed by a block of properties. This would be forward-compatible with more extensions to types.

In Haskell, where is a common way of creating a block of follow up declarations like helper functions, type class instance functions, etc. Recommended style is inline or indented block style.

struct vec2d {
  var x: int32;
  var y: int32;
} where default: vec2d(1, 2)

alt OptionalInt32 {
  Some: int32 | None
} where default: .None()

export native-type int32 alias-of int32_t header "stdint.h" where default: 0

Variant 2.a: Json-style properties

Instead of where <block> we could also use some json-like syntax with brackets. This seems a bit more familiar, but is also more confusing since there are two blocks right after one another.

struct vec2d {
  var x: int32;
  var y: int32;
} {
  default: vec2d(1, 2)
} 

alt OptionalInt32 {
  Some: int32 | None
}  {
  default: .None()
}

export native-type int32 alias-of int32_t header "stdint.h" {
  default: 0
}

Variant 3: Separate declaration

This variant is the cleanest, however it is harder to parse, use, and may create the impression that the declaration is a real statement.

struct vec2d {
  var x: int32;
  var y: int32;
} 

default(vec2d) = vec2d(1, 2)
 

alt OptionalInt32 {
  Some: int32 | None
} 

default(OptionalInt32) = .None()


export native-type int32 alias-of int32_t header "stdint.h" 

default(int32) = 0

Variant 3.a: Embrace the state

Indeed, default(type: Kind): type could be an actual Expression that is read/writeable at runtime, if something like that is desired:

export native-type int32 alias-of int32_t header "stdint.h" 
default(int32) = 0;

every button_one.pressed {
  default(int32) = 1 - default(int32);
  let a: int32;
  // prints 1, 0, 1, 0, ... on each button press
  println(`${a}`);
}

This would then be implemented like this:

// MitaTypes.h:
int32_t int32_default = 0;

// Application.c:
/* ... */
Retcode_T handleEveryButtonOnePressed() {
  int32_default = 1 - int32_default;
  int32_t a = int32_default;
  printf("%d\n", a);
}
@wegendt-bosch wegendt-bosch added enhancement New feature or request RFC Requests For Comments are ideas up for discussion. If accepted they result in implementation tasks. labels Apr 12, 2019
@tkutz
Copy link
Contributor

tkutz commented May 20, 2019

+1 for solution (1) and (2.a haskell).

(2.a json) is a bit too much curly braces everywhere. Curly braces make sense to group things together, but when you have only one default statement inside of them, it feels overloaded with braces.

(3) gives quite some degree of freedom to the user. I am not sure if we really want this. You need to derive the default value in runtime as it can be changed everywhere. For me, a default value definition belongs closely to the type definition and is something static.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request RFC Requests For Comments are ideas up for discussion. If accepted they result in implementation tasks.
Projects
None yet
Development

No branches or pull requests

2 participants