~sircmpwn/hare-rfc

18 5

[RFC v1] Autofilling default values in more places

Details
Message ID
<CVBAZTLUL49P.3PQSKEP3FC9UY@notmylaptop>
DKIM signature
missing
Download raw message
This proposal adapts from ideas discussed in the following tickets:
- https://todo.sr.ht/~sircmpwn/hare/581
- https://todo.sr.ht/~sircmpwn/hare/681
- https://todo.sr.ht/~sircmpwn/hare/813
- https://todo.sr.ht/~sircmpwn/hare/841

Default values for types are currently only relevant in one place, that
being struct initializers. I propose that we add syntax constructs to
make them useful in other places as well. There are multiple proposals
here. I'll start with mine, and then afterwards address some other
options and where I stand with them.

1. Make the following change to array-members (6.6.16):

   array-members:
   	expression ','?
-  	expression '...'
+  	expression? '...'
   	expression ',' array-members

   When the ... form is used and the expression is omitted, the default
   value of the array member type is used instead.

   `...` fills in zero or more values (as opposed to now, where it fills
   in one or more values). So [...] will work to initialize any array
   type, provided the member type has a definite default value.

2. Make the following change to argument-list (6.6.22):

   argument-list:
   	expression ','?
   	expression '...'
+  	'...'
   	expression ',' argument-list

   When an argument-list ends with `...`, all remaining non-variadic
   parameters are initialized to their default values. I also think it's
   reasonable to require that there is at least one remaining
   non-variadic parameter to initialize (so `...` must fill in the value
   of at least one parameter). There's no technical reason for this, but
   I still think it's a good idea.

3. Make the following change to type (6.5):

   type:
-  	'const'? '!'? storage-class
+  	type-flags? storage-class
+  type-flags:
+  	'const' type-flags?
+  	'!' type-flags?
+  	'@default' '(' default-value ')' type-flags?
+  default-value:
+  	expression
+  	'_'

   We can also add a clause that duplicate type flags aren't permitted.

   When @default is used with an expression, the value of that
   expression is used as the default value of the type. When `_` is
   used, the type's default value is undefined.

4. Update the stdlib. Some places where this proposal would be useful:

   	export type io::file = @default(_) int;

   	export fn temp::file(
   		iomode: io::mode,
   		mode: @default(0o600) fs::mode,
   	) (io::handle | fs::error);

   	// current definition uses 0 for DEC so the type has a default
   	// value
   	export type strconv::base = @default(base::DEC) enum uint {
   		[...]
   		DEC = 10,
   		[...]
   	};

   	export fn strings::sub(
   		s: str,
   		start: size,
   		end: @default(end) (size | void),
   	) str;

   	// compare with current definition which uses variadism, and
   	// needs a runtime assert to check if too many variadic
   	// parameters are supplied
   	export fn time::date::new(
   		loc: chrono::locality,
   		zo: (time::duration | void),
   		year: int,
   		month: @default(1) int,
   		day: @default(1) int,
   		hour: int,
   		minute: int,
   		second: int,
   		nanosecond: int,
   	) (date | invalid);

   	// compare with current definition which uses variadism, and
   	// then iterates through the variadic parameters and ORs them
   	// together. we can instead just have the caller OR the flags
   	// together, and provide a means to indicate that the default
   	// flags should be used
   	export fn os::open(
   		path: str,
   		flags: @default(fs::flag::RDONLY) fs::flag,
   	) (io::file | fs::error);

Some comments about other related proposals:

- Generalizing `...` to mean "the default value of the type provided by
  the type hint". This idea sounds nice since it adds one general way to
  work with default values, but I think in practice it will be
  suboptimal, for a few reasons:

  - [...] will be a legal array literal, but it won't do what was likely
    intended.
  - In order to fill in an expandable array literal, you'd need to do
    something like [1, 2, ......] or [1, 2, (...)...], neither of which
    look good.
  - The time::date::new example given above wouldn't work here, since
    every parameter would need to be manually set to its default value.
  - Within struct literals, `...` is still used to autofill all
    remaining fields, so keeping this same meaning elsewhere is more
    consistent.

- A @nodefault type flag has been proposed in the past. I opted to
  combine this with @default by adding @default(_), but I'd be fine with
  @nodefault. One thing worth mentioning is that we'd need to disallow
  using @default alongside @nodefault (in addition to disallowing
  duplicates), so in that sense combining them both into @default is
  "simpler", but it doesn't really matter that much.
Details
Message ID
<CVBQPPFH1J6I.3U24WJUW3EHAW@taiga>
In-Reply-To
<CVBAZTLUL49P.3PQSKEP3FC9UY@notmylaptop> (view parent)
DKIM signature
missing
Download raw message
On Wed Sep 6, 2023 at 4:33 AM CEST, Sebastian wrote:
> This proposal adapts from ideas discussed in the following tickets:
> - https://todo.sr.ht/~sircmpwn/hare/581
> - https://todo.sr.ht/~sircmpwn/hare/681
> - https://todo.sr.ht/~sircmpwn/hare/813
> - https://todo.sr.ht/~sircmpwn/hare/841
>
> Default values for types are currently only relevant in one place, that
> being struct initializers. I propose that we add syntax constructs to
> make them useful in other places as well. There are multiple proposals
> here. I'll start with mine, and then afterwards address some other
> options and where I stand with them.
>
> 1. Make the following change to array-members (6.6.16):
>
>    array-members:
>    	expression ','?
> -  	expression '...'
> +  	expression? '...'
>    	expression ',' array-members
>
>    When the ... form is used and the expression is omitted, the default
>    value of the array member type is used instead.
>
>    `...` fills in zero or more values (as opposed to now, where it fills
>    in one or more values). So [...] will work to initialize any array
>    type, provided the member type has a definite default value.

+1

> 2. Make the following change to argument-list (6.6.22):

This should be a separate proposal (optional parameters).

Also I am more inclined to appreciate the following syntax per your
example:

export fn temp::file(
	iomode: io::mode,
	mode: fs::mode = 0o600,
) (io::handle | fs::error);

There is prior art for this approach in many languages, and @default is
overloaded in your proposed approach -- it specifies the default value
of both types and parameters.

Moreover I don't like the approach of "all parameters are set to their
default values", I think it's... a bit meh. Better to only support
parameters which are explicitly given a default value in the type
signature.

I also think we don't need any new nonterminals, we can just accept
function calls that don't include optional parameters.

Generally I have a big +1 to optional parameters if we get the proposal
right.

> 3. Make the following change to type (6.5):

+1

> 4. Update the stdlib. Some places where this proposal would be useful:
>
>    	export type io::file = @default(_) int;
>
>    	export fn temp::file(
>    		iomode: io::mode,
>    		mode: @default(0o600) fs::mode,
>    	) (io::handle | fs::error);
>
>    	// current definition uses 0 for DEC so the type has a default
>    	// value
>    	export type strconv::base = @default(base::DEC) enum uint {
>    		[...]
>    		DEC = 10,
>    		[...]
>    	};

I wonder if semantically speaking it would make more sense to put
@default after the type description

	export type strconv::base = enum uint {
		[...]
		DEC = 10,
		[...]
	} @default(base::DEC);

Given that "base::DEC" is technically undefined (even though we could
work around it) until after the type is specified.

> Some comments about other related proposals:
>
> - Generalizing `...` to mean "the default value of the type provided by
>   the type hint". This idea sounds nice since it adds one general way to
>   work with default values, but I think in practice it will be
>   suboptimal, for a few reasons:

I agree that this original generalization was not great.

> - A @nodefault type flag has been proposed in the past. I opted to
>   combine this with @default by adding @default(_), but I'd be fine with
>   @nodefault. One thing worth mentioning is that we'd need to disallow
>   using @default alongside @nodefault (in addition to disallowing
>   duplicates), so in that sense combining them both into @default is
>   "simpler", but it doesn't really matter that much.

+1 to @default(_)
Details
Message ID
<CVC1ZXDIL5JQ.3GYD1NOCRVPO2@monch>
In-Reply-To
<CVBAZTLUL49P.3PQSKEP3FC9UY@notmylaptop> (view parent)
DKIM signature
missing
Download raw message
i wonder how bad of an idea it would be to get rid of default default
values for types, rather than requiring an explicit @default(_)

On Wed Sep 6, 2023 at 2:33 AM UTC, Sebastian wrote:
> This proposal adapts from ideas discussed in the following tickets:
> - https://todo.sr.ht/~sircmpwn/hare/581
> - https://todo.sr.ht/~sircmpwn/hare/681
> - https://todo.sr.ht/~sircmpwn/hare/813
> - https://todo.sr.ht/~sircmpwn/hare/841
>
> Default values for types are currently only relevant in one place, that
> being struct initializers. I propose that we add syntax constructs to
> make them useful in other places as well. There are multiple proposals
> here. I'll start with mine, and then afterwards address some other
> options and where I stand with them.
>
> 1. Make the following change to array-members (6.6.16):

+1

> 2. Make the following change to argument-list (6.6.22):

no strong opinions, though i do think that using @default here makes
more sense than having a separate syntax for defaults, at least assuming
that not having default defaults works reasonably well, and i
tentatively prefer to use @default here regardless of whether we do that

> 3. Make the following change to type (6.5):

+1

>    	// compare with current definition which uses variadism, and
>    	// needs a runtime assert to check if too many variadic
>    	// parameters are supplied
>    	export fn time::date::new(
>    		loc: chrono::locality,
>    		zo: (time::duration | void),
>    		year: int,
>    		month: @default(1) int,
>    		day: @default(1) int,
>    		hour: int,
>    		minute: int,
>    		second: int,
>    		nanosecond: int,
>    	) (date | invalid);

one thing to note about your proposed optional argument syntax is that
it wouldn't be possible to eg. set a default month but not a default day
here

> Some comments about other related proposals:

yeah both of these sound less good to me than your proposal
Details
Message ID
<CVPWZNYMZ5VW.39H7P26WSQNXS@attila>
In-Reply-To
<CVBAZTLUL49P.3PQSKEP3FC9UY@notmylaptop> (view parent)
DKIM signature
missing
Download raw message
>    `...` fills in zero or more values (as opposed to now, where it fills
>    in one or more values). So [...] will work to initialize any array
>    type, provided the member type has a definite default value.

About the expression... form, under the new rules, `alloc([a(), b(), c()...],
2);` is supposed to be legal.  Does c() ever get called (and side-effects
observed) in this case? I'm leaning towards no, but either way it's a bit
confusing and unfortunate.
Details
Message ID
<CVRLRHT4SKSY.2710TVIGFN60Y@notmylaptop>
In-Reply-To
<CVPWZNYMZ5VW.39H7P26WSQNXS@attila> (view parent)
DKIM signature
missing
Download raw message
On Fri Sep 22, 2023 at 9:43 PM EDT, Bor Grošelj Simić wrote:
> >    `...` fills in zero or more values (as opposed to now, where it fills
> >    in one or more values). So [...] will work to initialize any array
> >    type, provided the member type has a definite default value.
>
> About the expression... form, under the new rules, `alloc([a(), b(), c()...],
> 2);` is supposed to be legal.  Does c() ever get called (and side-effects
> observed) in this case? I'm leaning towards no, but either way it's a bit
> confusing and unfortunate.

Hm, I would think that c() would be called, but its result would be
discarded. Maybe we should just keep the current behavior when using ...
with a value ([0...]), but have it fill in zero or more values when used
on its own?
Details
Message ID
<CVRMFRMZOA3Z.1FTZGB5NWLZPH@monch>
In-Reply-To
<CVPWZNYMZ5VW.39H7P26WSQNXS@attila> (view parent)
DKIM signature
missing
Download raw message
On Sat Sep 23, 2023 at 1:43 AM UTC, Bor Grošelj Simić wrote:
> >    `...` fills in zero or more values (as opposed to now, where it fills
> >    in one or more values). So [...] will work to initialize any array
> >    type, provided the member type has a definite default value.
>
> About the expression... form, under the new rules, `alloc([a(), b(), c()...],
> 2);` is supposed to be legal.  Does c() ever get called (and side-effects
> observed) in this case? I'm leaning towards no, but either way it's a bit
> confusing and unfortunate.

i think it should probably be called here? since it should still only be
called once if the length were 4
Details
Message ID
<CWLNYZUGE6W7.1EVEX73MA69MF@taiga>
In-Reply-To
<CVRMFRMZOA3Z.1FTZGB5NWLZPH@monch> (view parent)
DKIM signature
missing
Download raw message
Right now I'm not sure about the basic idea behind this RFC, but
optional parameters are interesting in their own right and more of a
straightforwardly good idea: can you split that into a separate RFC?
Details
Message ID
<CWLYKBIJLUBD.16EPAXHK8XX21@d2evs.net>
In-Reply-To
<CWLNYZUGE6W7.1EVEX73MA69MF@taiga> (view parent)
DKIM signature
missing
Download raw message
i'd really prefer to do optional arguments via an expanded default value
system if we end up doing that
Details
Message ID
<CWMEQNHDB6I8.28K62W7B8LZJS@taiga>
In-Reply-To
<CWLYKBIJLUBD.16EPAXHK8XX21@d2evs.net> (view parent)
DKIM signature
missing
Download raw message
I liked the syntax I originally proposed for default parameters much
more than using default values.

[RFC v2] Autofilling default values in more places

Details
Message ID
<CXAA8A6WLAYJ.3AKSGDPKRBU7P@notmylaptop>
In-Reply-To
<CVBAZTLUL49P.3PQSKEP3FC9UY@notmylaptop> (view parent)
DKIM signature
missing
Download raw message
                              RFC SUMMARY

Default values for types are currently only relevant in one place, that
being struct initializers. I propose that we add a syntax construct to
allow using default values in array literals. I also propose that we
give users the ability to give types custom default values with
@default.

                         LANGUAGE IMPLICATIONS

 array-members:
 	expression ","(opt)
-	expression "..."
+	expression(opt) "..."
 	expression "," array-members

When the ... form is used and the expression is omitted, the default
value of the array member type is used instead.

`...` fills in zero or more values (as opposed to now, where it fills in
one or more values). So [...] will work to initialize any array type,
provided the member type has a definite default value.

 type:
-	"const"(opt) "!"(opt) storage-class
+	type-flags(opt) storage-class
+type-flags:
+	"const" type-flags(opt)
+	"!" type-flags(opt)
+	"@default" "(" default-value ")" type-flags(opt)
+default-value:
+	expression
+	"_"

When @default is used with an expression, the value of that expression
is used as the default value of the type. When `_` is used, the type's
default value is undefined.

                     STANDARD LIBRARY IMPLICATIONS

Some types, like io::file, can be updated to use @default(_).

Various enum types could use @default to avoid needing to provide a
"default" zero value. A great example of this is strconv::base, which
can use @default(base::DEC).

                         ECOSYSTEM IMPLICATIONS

The main implication is that types like io::file can no longer be
autofilled in structs, which may break things like providing a global
initializer for something which is initialized at runtime with @init.
Generalizing @init to expressions would mostly solve this issue (see
https://lists.sr.ht/~sircmpwn/hare-rfc/<CXA6970K8PXC.7E9LRE8BYGL6%40smlavine.com>).

                              EXAMPLE CODE

// before
let arr: [4][4]foo = [[foo { ... }...]...];
// after
let arr: [4][4]foo = [...];

export type io::file = @default(_) int;

// non-exhaustive enum, but that's not relevant for this proposal
export type strconv::base = @default(base::DEC) enum uint {
	BIN = 2,
	OCT = 8,
	DEC = 10,
	HEX_UPPER = 16,
	HEX = HEX_UPPER,
	HEX_LOWER = 17, // or something
};

                              RELATED RFCS

v1: https://lists.sr.ht/~sircmpwn/hare-rfc/<CVBAZTLUL49P.3PQSKEP3FC9UY%40notmylaptop>#<CVBAZTLUL49P.3PQSKEP3FC9UY@notmylaptop>
Optional function parameters are split off into a different RFC. No
other changes.

Re: [RFC v2] Autofilling default values in more places

Lorenz (xha) <me@xha.li>
Details
Message ID
<20231128130723.g6eayezvhosjchia@xha.li>
In-Reply-To
<CXAA8A6WLAYJ.3AKSGDPKRBU7P@notmylaptop> (view parent)
DKIM signature
missing
Download raw message
what about removing ... for default values altogether and adding
a {0} hare equivilant (replace {0} here if you want):

let i: int = {0};
let j: [4][4]int = {0};
let s: sometstruct = {0};

i think since hare is a simple language there shouldn't be default
values other than 0? i think they are confusing at best.

On Tue, Nov 28, 2023 at 03:14:06AM -0500, Sebastian wrote:
>                               RFC SUMMARY
> 
> Default values for types are currently only relevant in one place, that
> being struct initializers. I propose that we add a syntax construct to
> allow using default values in array literals. I also propose that we
> give users the ability to give types custom default values with
> @default.
> 
>                          LANGUAGE IMPLICATIONS
> 
>  array-members:
>  	expression ","(opt)
> -	expression "..."
> +	expression(opt) "..."
>  	expression "," array-members
> 
> When the ... form is used and the expression is omitted, the default
> value of the array member type is used instead.
> 
> `...` fills in zero or more values (as opposed to now, where it fills in
> one or more values). So [...] will work to initialize any array type,
> provided the member type has a definite default value.
> 
>  type:
> -	"const"(opt) "!"(opt) storage-class
> +	type-flags(opt) storage-class
> +type-flags:
> +	"const" type-flags(opt)
> +	"!" type-flags(opt)
> +	"@default" "(" default-value ")" type-flags(opt)
> +default-value:
> +	expression
> +	"_"
> 
> When @default is used with an expression, the value of that expression
> is used as the default value of the type. When `_` is used, the type's
> default value is undefined.
> 
>                      STANDARD LIBRARY IMPLICATIONS
> 
> Some types, like io::file, can be updated to use @default(_).
> 
> Various enum types could use @default to avoid needing to provide a
> "default" zero value. A great example of this is strconv::base, which
> can use @default(base::DEC).
> 
>                          ECOSYSTEM IMPLICATIONS
> 
> The main implication is that types like io::file can no longer be
> autofilled in structs, which may break things like providing a global
> initializer for something which is initialized at runtime with @init.
> Generalizing @init to expressions would mostly solve this issue (see
> https://lists.sr.ht/~sircmpwn/hare-rfc/<CXA6970K8PXC.7E9LRE8BYGL6%40smlavine.com>).
> 
>                               EXAMPLE CODE
> 
> // before
> let arr: [4][4]foo = [[foo { ... }...]...];
> // after
> let arr: [4][4]foo = [...];
> 
> export type io::file = @default(_) int;
> 
> // non-exhaustive enum, but that's not relevant for this proposal
> export type strconv::base = @default(base::DEC) enum uint {
> 	BIN = 2,
> 	OCT = 8,
> 	DEC = 10,
> 	HEX_UPPER = 16,
> 	HEX = HEX_UPPER,
> 	HEX_LOWER = 17, // or something
> };
> 
>                               RELATED RFCS
> 
> v1: https://lists.sr.ht/~sircmpwn/hare-rfc/<CVBAZTLUL49P.3PQSKEP3FC9UY%40notmylaptop>#<CVBAZTLUL49P.3PQSKEP3FC9UY@notmylaptop>
> Optional function parameters are split off into a different RFC. No
> other changes.

Re: [RFC v2] Autofilling default values in more places

Details
Message ID
<CXAPKUU6SO33.DBPELJDR084C@notmylaptop>
In-Reply-To
<20231128130723.g6eayezvhosjchia@xha.li> (view parent)
DKIM signature
missing
Download raw message
On Tue Nov 28, 2023 at 8:07 AM EST, Lorenz (xha) wrote:
> what about removing ... for default values altogether and adding
> a {0} hare equivilant (replace {0} here if you want):
>
> let i: int = {0};
> let j: [4][4]int = {0};
> let s: sometstruct = {0};
>
> i think since hare is a simple language there shouldn't be default
> values other than 0? i think they are confusing at best.

There's multiple issues with this:

- Your proposed {0} syntax will cause lots of parsing issues, since { }
  is used for compound expressions. Hare has different struct/array
  initialization syntax than C; we shouldn't blindly copy what C does.

- We already sorta have default values other than zero: the default
  value of a nullable pointer is null, and the representation of null is
  implementation-defined.

- This is also why {0} isn't a good idea: {0} is a hack in C, to get
  around the absence of empty initializers (prior to C23), and we
  definitely shouldn't inherit it. It has a subtle footgun in which
  pointers are initialized to 0, even if NULL is represented as
  something else. This isn't an issue when targeting POSIX as far as I'm
  aware, but for portable code it is a footgun.

- Not every type has a meaningful default value. Non-nullable pointers,
  for instance, can't be initialized to null. Same goes for tagged
  unions. We want to require that objects with these types are properly
  initialized.

- We also want to require that the user be explicit when autofilling
  fields IMO, so the compiler can properly error out if a field that
  should be provided isn't. Similar to how switch expressions must be
  exhaustive, and a default case must be explicitly provided if that's
  the desired behavior.

- Your proposal is sorta similar to an earlier proposal, which suggested
  using `...` to substitute the default value of the type hint. I
  discussed my reasons for disliking this in RFC v1.

- Non-zero default values can be useful. One example is a tagged union
  `(T | void)`, where `void` is a sensible default. Tagged union types
  have an undefined default value by default (as they should), but we
  should allow overriding this if it makes code cleaner.

Re: [RFC v2] Autofilling default values in more places

Lorenz (xha) <me@xha.li>
Details
Message ID
<20231129080102.ikxif6ncb4dd4i3t@xha.li>
In-Reply-To
<CXAPKUU6SO33.DBPELJDR084C@notmylaptop> (view parent)
DKIM signature
missing
Download raw message
On Tue, Nov 28, 2023 at 02:57:16PM -0500, Sebastian wrote:
> On Tue Nov 28, 2023 at 8:07 AM EST, Lorenz (xha) wrote:
> > what about removing ... for default values altogether and adding
> > a {0} hare equivilant (replace {0} here if you want):
> >
> > let i: int = {0};
> > let j: [4][4]int = {0};
> > let s: sometstruct = {0};
> >
> > i think since hare is a simple language there shouldn't be default
> > values other than 0? i think they are confusing at best.
> 
> There's multiple issues with this:
> 
> - Your proposed {0} syntax will cause lots of parsing issues, since { }
>   is used for compound expressions. Hare has different struct/array
>   initialization syntax than C; we shouldn't blindly copy what C does.

yeah this is why i mean replace it with something you want. i think we
can still figure this out, something like `let i: int = @zero;` is also
fine, idk. this, however, wasn't the point, i was just talking about
always having values initlized to zero by "default". i didn't mean the
"how".

> - We already sorta have default values other than zero: the default
>   value of a nullable pointer is null, and the representation of null is
>   implementation-defined.
>
> - This is also why {0} isn't a good idea: {0} is a hack in C, to get
>   around the absence of empty initializers (prior to C23), and we
>   definitely shouldn't inherit it. It has a subtle footgun in which
>   pointers are initialized to 0, even if NULL is represented as
>   something else. This isn't an issue when targeting POSIX as far as I'm
>   aware, but for portable code it is a footgun.

could you show me an example of a platform that has NULL != 0? also,
since null is a type in hare and not a value (?) we could just ignore
this?

null == 0 could be required by the spec and would probably make some
stuff easier too.

> - Not every type has a meaningful default value. Non-nullable pointers,
>   for instance, can't be initialized to null. Same goes for tagged
>   unions. We want to require that objects with these types are properly
>   initialized.

i think you could just forbid initilizing them by 0 since these cannot
have a value of 0 (or, a "default value") anyways.

> - We also want to require that the user be explicit when autofilling
>   fields IMO, so the compiler can properly error out if a field that
>   should be provided isn't. Similar to how switch expressions must be
>   exhaustive, and a default case must be explicitly provided if that's
>   the desired behavior.

well i don't know how much this prevents bugs and it is probably just
annoying. also, nothing prevents something similar to signal the
compiler that this shouldn't be 0-initlized.

> - Your proposal is sorta similar to an earlier proposal, which suggested
>   using `...` to substitute the default value of the type hint. I
>   discussed my reasons for disliking this in RFC v1.

i couldn't find your email, can you give me a link?

> - Non-zero default values can be useful. One example is a tagged union
>   `(T | void)`, where `void` is a sensible default. Tagged union types
>   have an undefined default value by default (as they should), but we
>   should allow overriding this if it makes code cleaner.

hmm good point but i cannot think of any situation that actually makes
this useful, it's just confusing imo because some types implement it
(because they can) and som types don't (because either they can't or
just because they don't)

Re: [RFC v2] Autofilling default values in more places

Details
Message ID
<CXBBHAA9Y1A2.2V8WVTA8AALUU@d2evs.net>
In-Reply-To
<20231129080102.ikxif6ncb4dd4i3t@xha.li> (view parent)
DKIM signature
missing
Download raw message
i'm in favor of this rfc as a whole, though i wonder if aliases should
have an undefined default value by default?

another thing: i wonder if a generalized ... would be improved by using
a different token? '_' could be a good candidate

On Wed Nov 29, 2023 at 8:01 AM UTC, Lorenz (xha) wrote:
> > - Your proposal is sorta similar to an earlier proposal, which suggested
> >   using `...` to substitute the default value of the type hint. I
> >   discussed my reasons for disliking this in RFC v1.
>
> i couldn't find your email, can you give me a link?

https://lists.sr.ht/~sircmpwn/hare-rfc/%3CCVBAZTLUL49P.3PQSKEP3FC9UY%40notmylaptop%3E

> > - Non-zero default values can be useful. One example is a tagged union
> >   `(T | void)`, where `void` is a sensible default. Tagged union types
> >   have an undefined default value by default (as they should), but we
> >   should allow overriding this if it makes code cleaner.
>
> hmm good point but i cannot think of any situation that actually makes
> this useful, it's just confusing imo because some types implement it
> (because they can) and som types don't (because either they can't or
> just because they don't)

it's less useful without a generalized ... value, but i do still think
it's useful. strconv::base is a pretty good example of something that
gets value out of @default, as well as various things with tagged unions

Re: [RFC v2] Autofilling default values in more places

Details
Message ID
<CXFJ86K3Z163.LALBT5FNSGJA@taiga>
In-Reply-To
<CXAA8A6WLAYJ.3AKSGDPKRBU7P@notmylaptop> (view parent)
DKIM signature
missing
Download raw message
On Tue Nov 28, 2023 at 9:14 AM CET, Sebastian wrote:
>                      STANDARD LIBRARY IMPLICATIONS
>
> Some types, like io::file, can be updated to use @default(_).
>
> Various enum types could use @default to avoid needing to provide a
> "default" zero value. A great example of this is strconv::base, which
> can use @default(base::DEC).

Unsure about this. Making a type which would otherwise have a default
value (e.g. io::file) NOT have a default value seems relatively free of
foot-guns, though it might add annoyances. However, adding types which
have a default value which is nonzero complicates the implementation of
initializers, since we cannot simply memset the object to zero.

> // non-exhaustive enum, but that's not relevant for this proposal
> export type strconv::base = @default(base::DEC) enum uint {

Re: [RFC v2] Autofilling default values in more places

Details
Message ID
<CXFUN9J85FZE.3376P8SRB41DH@notmylaptop>
In-Reply-To
<CXBBHAA9Y1A2.2V8WVTA8AALUU@d2evs.net> (view parent)
DKIM signature
missing
Download raw message
On Wed Nov 29, 2023 at 8:07 AM EST, Ember Sawady wrote:
> i'm in favor of this rfc as a whole, though i wonder if aliases should
> have an undefined default value by default?

I sorta like the idea, but the semantics are strange:

	// int has a default value, but when @default isn't explicitly
	// provided, the default value is stripped when an alias is
	// created
	type foo = int;

	// but if @default is explicitly provided, then suddenly the
	// default value is preserved in the alias
	type foo = @default(0) int;

> another thing: i wonder if a generalized ... would be improved by using
> a different token? '_' could be a good candidate

-1 tbh, mainly because I just don't see much benefit of having a
generalized "default value" operator.

Re: [RFC v2] Autofilling default values in more places

Details
Message ID
<CXFUOPUAHA7F.SMEX7DJWZTE1@notmylaptop>
In-Reply-To
<CXFJ86K3Z163.LALBT5FNSGJA@taiga> (view parent)
DKIM signature
missing
Download raw message
On Mon Dec 4, 2023 at 7:01 AM EST, Drew DeVault wrote:
> Unsure about this. Making a type which would otherwise have a default
> value (e.g. io::file) NOT have a default value seems relatively free of
> foot-guns, though it might add annoyances. However, adding types which
> have a default value which is nonzero complicates the implementation of
> initializers, since we cannot simply memset the object to zero.

Not sure that's a bad thing though, since sometimes the correct default
isn't zero.

Another real-world example which I missed in the examples section (note
the TODOs):

fmt/print.ha:
	assert(mod.base == strconv::base::DEFAULT
		|| mod.base == strconv::base::DEC); // TODO
	assert(mod.prec <= types::UINT_MAX);
	// TODO: mod.prec should be (size | void) but that needs @default
	return strconv::fftosf(out, f, mod.ffmt,
		if (mod.prec != 0) mod.prec: uint else void, mod.fflags)?;

I've also noted that some implementations already will need to do more
than just memset the object to zero, if null isn't represented as zero.
This isn't an issue for the majority of implementations, but it does
mean that the default default value isn't necessarily always zero.

As for annoyances: @init expressions would help a lot with this, since
it would eliminate a lot of the places where io::file would ever
actually need to be initialized to a dummy value.

Re: [RFC v2] Autofilling default values in more places

Details
Message ID
<CXHKOITNED65.9G9Z5U3H16AL@d2evs.net>
In-Reply-To
<CXFUN9J85FZE.3376P8SRB41DH@notmylaptop> (view parent)
DKIM signature
missing
Download raw message
On Mon Dec 4, 2023 at 8:58 PM UTC, Sebastian wrote:
> On Wed Nov 29, 2023 at 8:07 AM EST, Ember Sawady wrote:
> > i'm in favor of this rfc as a whole, though i wonder if aliases should
> > have an undefined default value by default?
>
> I sorta like the idea, but the semantics are strange:
>
> 	// int has a default value, but when @default isn't explicitly
> 	// provided, the default value is stripped when an alias is
> 	// created
> 	type foo = int;
>
> 	// but if @default is explicitly provided, then suddenly the
> 	// default value is preserved in the alias
> 	type foo = @default(0) int;

right, makes sense. let's not do this, at least for now

> > another thing: i wonder if a generalized ... would be improved by using
> > a different token? '_' could be a good candidate
>
> -1 tbh, mainly because I just don't see much benefit of having a
> generalized "default value" operator.

ack

Re: [RFC v2] Autofilling default values in more places

Details
Message ID
<CY2MLM6F4G7C.222X5041T1QBA@taiga>
In-Reply-To
<CXFUOPUAHA7F.SMEX7DJWZTE1@notmylaptop> (view parent)
DKIM signature
missing
Download raw message
On Mon Dec 4, 2023 at 10:04 PM CET, Sebastian wrote:
> Not sure that's a bad thing though, since sometimes the correct default
> isn't zero.
>
> Another real-world example which I missed in the examples section (note
> the TODOs):
>
> fmt/print.ha:
> 	assert(mod.base == strconv::base::DEFAULT
> 		|| mod.base == strconv::base::DEC); // TODO
> 	assert(mod.prec <= types::UINT_MAX);
> 	// TODO: mod.prec should be (size | void) but that needs @default
> 	return strconv::fftosf(out, f, mod.ffmt,
> 		if (mod.prec != 0) mod.prec: uint else void, mod.fflags)?;
>
> I've also noted that some implementations already will need to do more
> than just memset the object to zero, if null isn't represented as zero.
> This isn't an issue for the majority of implementations, but it does
> mean that the default default value isn't necessarily always zero.
>
> As for annoyances: @init expressions would help a lot with this, since
> it would eliminate a lot of the places where io::file would ever
> actually need to be initialized to a dummy value.

Okay, I'm +1 on nonzero default values.
Reply to thread Export thread (mbox)