I wanted to know if there is a reason why there is no fromArray
fn for the Buffer class. All the other class data structures in the lib have a fromArray
or fromEntries
method that allows for instantiation from stable data structures.
Does having a fromArray
method in the Buffer class have unexpected consequences like with the Array.append()
fn? If not, I think it would be beneficial to include it in the base lib instead of devs implementing it in each project.
Would it also be possible for me to make a PR to the base repo with this feature?
I see no reason for not having this (@MatthewHammer whaddya think?). And do feel free to open a PR.
It’s hard to recall, but I seem to remember some pressure to keep the API very small, because it enlarges each Buffer instance to have more methods?
Separately, I’m curious what reasonable semantics doing b.fromArray(a)
would mean if b
was non-empty? Would it erase those existing elements, or append to them? Either way seems confusing to me, personally.
But how about another place for this bufferFromArray
functionality, which I agree is missing and reasonable?
For instance, I think a toBuffer
function makes sense in the existing Array
module, where it would be static, and not associated with any existing buffer object. Likewise, having a special array method toBuffer()
would also be reasonable, but perhaps more work to add.
What do you think @tomijaga and @claudio ?
Here’s a PR https://github.com/dfinity/motoko-base/pull/387
I was thinking of adding it as a static method in the Buffer module. This method would only instantiate a Buffer with all the elements in an array
So users would be able to instantiate buffers from an existing array like this:
let b = Buffer.fromArray([1, 2])
I like that you made a pr with this exact functionality in the Array module, but I think adding it to the Buffer would be more intuitive.
There is PR for Buffer.fromArray
Add fromArray method to Buffer by xlaywan · Pull Request #368 · dfinity/motoko-base · GitHub
Thanks, this is the exact functionality I was referring to.
I noticed that this pr uses the add
buffer method for the fromArray
method. The problem with that the given array could be significantly bigger than the size of the buffer. In this case, the buffer could resize and copy all its values more than once to add all the elements of the array. I made a PR that only resizes the array once if this happens. Efficient addArray and fromArray buffer methods by tomijaga · Pull Request #388 · dfinity/motoko-base · GitHub
Buffer.fromArray is listed in the Buffer documentation, but does not exist according to dfx deploy
when running dfx 0.11.2:
type error [M0072], field fromArray does not exist in type
module {
type Buffer<X> =
{
add : X -> ();
append : Buffer<X> -> ();
clear : () -> ();
clone : () -> Buffer<X>;
get : Nat -> X;
getOpt : Nat -> ?X;
put : (Nat, X) -> ();
removeLast : () -> ?X;
size : () -> Nat;
toArray : () -> [X];
toVarArray : () -> [var X];
vals : () -> {next : () -> ?X}
};
Buffer : <X>Nat -> Buffer<X>
}
My code:
import Buffer "mo:base/Buffer";
...
let media : Buffer.Buffer<Media> = Buffer.fromArray<Media>(init.mediaEntries);
I see that fromArray exists in the buffer module, so why is dfx deploy
surfacing these erroneous errors? Intellisense does not underline the function call, but the errors print out when running dfx build
or dfx deploy
and prevent a successful build.
If I change the call to an actually-non-existent function:
let media : Buffer.Buffer<Media> = Buffer.someOtherFunction<Media>(init.mediaEntries);
I get intellisense red underlines on the call and when I hover over it I see following, which does list fromArray as a function it’s expecting to exist on the Buffer module:
field someOtherFunction does not exist in type
module {
type Buffer<X> =
{
add : X -> ();
append : Buffer__33665<X> -> ();
clear : () -> ();
clone : () -> Buffer__33665<X>;
get : Nat -> X;
getOpt : Nat -> ?X;
put : (Nat, X) -> ();
removeLast : () -> ?X;
size : () -> Nat;
toArray : () -> [X];
toVarArray : () -> [var X];
vals : () -> {next : () -> ?X}
};
Buffer : <X>Nat -> Buffer__33665<X>;
fromArray : <X>[X] -> Buffer__33665<X>;
fromVarArray : <X>[var X] -> Buffer__33665<X>
}
dfx --version
returns 0.11.2, which matches the dfx version specified in my dfx.json.
What’s going on here? Am I calling the function incorrectly? I’m calling it the same as I’m calling other base library module functions. My workaround is to implement a bufferToArray function, but I’d like to know why I can’t use the one defined in the base library.
If you see here, fromArray is just a normal function making buffer by iterating over array. So you can build your own buffer to array function doing same. Because fromArray is removed actually i read somewhere.
It’s still in the codebase, and that’s the function I copied into my own bufferFromArray function (except I just used array.size() instead of newCapacity(array.size())
If the function was removed, it should probably be removed from the documentation if developers are expected to implement it themselves. But the removal of the function doesn’t explain the strange intellisense behavior I’m experiencing unless there’s some weird versioning issues going on where dfx deploy is using a different version of the base libraries than intellisense is.
Thanks to @kentosugama’s rework of the Buffer module, Buffer.fromArray()
and many more utility methods/functions now exists in motoko-base. (See motoko-base/Buffer.mo at aafcdee0c8328087aeed506e64aa2ff4ed329b47 · dfinity/motoko-base · GitHub)
As of this post, I believe these changes are in the base moc-0.7.2 release, but I’d probably use the latest moc or at least 0.7.3 since there’s a few bug fixes for the functions in that class that have come out in the meantime.
If you use vessel, you can reference the latest base release like so
let packages = [
{ name = "base"
, repo = "https://github.com/dfinity/motoko-base"
, version = "moc-0.7.2"
, dependencies = [ "base" ]
}
]: List Package
Or the latest commit via
let packages = [
{ name = "base"
, repo = "https://github.com/dfinity/motoko-base"
, version = "<commit_hash_here>"
, dependencies = [ "base" ]
}
]: List Package