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

Allocate type with an initial value in one function #11484

Closed
Jarred-Sumner opened this issue Apr 21, 2022 · 3 comments
Closed

Allocate type with an initial value in one function #11484

Jarred-Sumner opened this issue Apr 21, 2022 · 3 comments

Comments

@Jarred-Sumner
Copy link
Contributor

Jarred-Sumner commented Apr 21, 2022

Related to #11479, but not the same

Currently, to create a new allocated type:

const Bar = struct {
   foo: *u32,
};
var foo = try allocator.create(u32);
foo.* = 123;
return Bar{
  .foo = foo,
};

In complex functions or nested structs, this gets tedious.

There's a case to be made for why that's good – discouraging dynamic allocations means people will usually write faster software. That being said, sometimes the only sane thing is dynamically allocate.

Suggestion

What if std.mem.Allocator had a new function?

const Bar = struct {
   foo: *u32,
};
return Bar{
  .foo =  try allocator.new(u32, 123),
};
Why new as the name?
It is a similar convention used by other languages, so it should be easy to learn
// Java?
Object obj = new Object();
// Objective C
id obj = [NSObject new];
// C++
auto* obj = new Object();
// JavaScript
var foo = new Bar();

Example implementation:

pub fn new(self: Allocator, comptime Type: type, value: Type) !*Type {
  var ptr = try self.create(Type);
  ptr.* = value;
  return ptr;
}

Once #7772 is implemented, perhaps value would be inline and there would be zero difference in performance:

pub fn new(self: Allcoator, comptime Type: type, inline value: Type) !*Type {
  var ptr = try self.create(Type);
  ptr.* = value;
  return ptr;
}
@matu3ba
Copy link
Contributor

matu3ba commented Apr 21, 2022

In complex functions or nested structs, this gets tedious.

This should only be tedious for init(bar: *Bar).
Also, this sounds like a bunch of local optima to me, because it only works nicely with primitive/simple types or breaks weak coupling.

Can you provide examples with estimations of amounts in a realistic code base ?

@ikskuh
Copy link
Contributor

ikskuh commented Apr 21, 2022

I don't think this is a good idea as it might introduce unnecessary copies and temporaries, as well as breaking result locatation. This means that types that require result location semantics can't be constructed with allocator.new, but the function basically hides that fact.

Also how does this work with types that are sequentially initialized (piece by piece)?

Imho this proposed API has more footguns than benefits

@Jarred-Sumner
Copy link
Contributor Author

I agree with you @MasterQ32

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

No branches or pull requests

3 participants