Skip to content

Conversation

@lpil
Copy link
Member

@lpil lpil commented Jan 10, 2026

No description provided.

export function List$NonEmpty<T>(head: T, tail: List<T>): List<T>;
export function List$isEmpty<T>(list: List<T>): boolean;
export function List$isNonEmpty<T>(list: List<T>): boolean;
export function List$isEmpty(list: any): boolean;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can write this as:

export function List$isEmpty(list: any): list is List<unknown>

...and the same for the other guard functions.

This lets typescript actually refine the type of a value based on the guard.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't List$isEmpty take a List as an argument though? Or is the api supposed to work no matter what we pass to the function?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It needs to take any otherwise we can't use these functions for dynamic.classify or string.inspect

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does that still effectively return a boolean @hayleigh-dot-dev ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it look right to you now @hayleigh-dot-dev ?

@yoshi-monster
Copy link
Contributor

Does that mean all the properties/getters on BitArray should be considered private?

@lpil
Copy link
Member Author

lpil commented Jan 16, 2026

Does that mean all the properties/getters on BitArray should be considered private?

Yes, everything not in the documented public API is private.

@yoshi-monster
Copy link
Contributor

yoshi-monster commented Jan 16, 2026

I think there's no way to work with non-byte-aligned/non-zero bitSizes then?
If it's just not done yet I'm sorry ignore me please ^.^

export const BitArray$BitArray = (buffer, bitSize, bitOffset) =>
new BitArray(buffer, bitSize, bitOffset);
export const BitArray$isBitArray = (value) => value instanceof BitArray;
export const BitArray$BitArray$data = (bitArray) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that the DataView returned here doesn't work for an unaligned bit array input, and if bitArray.bitOffset is non-zero the DataView will give the wrong result in all cases.

Unfortunately, it's not possible to return a valid DataView object for anything except a perfectly byte-aligned BitArray.

One option is to throw an exception similar to what's done above where it'll throw "BitArray.buffer does not support unaligned bit arrays".

Is there a desire to provide functions for safely working with bit arrays in JS FFI code (and that also work with unaligned bit arrays)?

@lpil
Copy link
Member Author

lpil commented Jan 19, 2026

@yoshi-monster @richard-viney How could unaligned bit arrays be used at all in JavaScript? The language doesn't have any capability to work with data like that, that I'm aware of.

I couldn't think of a design that would provide something that wouldn't be replicating the functionality they have in the Gleam language, and if they can do it in Gleam without loss of performance (or some other drawback) then I don't want to encourage doing it with FFI instead.

@yoshi-monster
Copy link
Contributor

How could unaligned bit arrays be used at all in JavaScript? The language doesn't have any capability to work with data like that, that I'm aware of.

I have to admit every time I FFI to BitArrays I always assert they are byte-aligned, I think my initial reaction was just based on feeling there should be a way to do this without a concrete use-case in mind.

@richard-viney
Copy link
Contributor

richard-viney commented Feb 7, 2026

@yoshi-monster @richard-viney How could unaligned bit arrays be used at all in JavaScript? The language doesn't have any capability to work with data like that, that I'm aware of.

I couldn't think of a design that would provide something that wouldn't be replicating the functionality they have in the Gleam language, and if they can do it in Gleam without loss of performance (or some other drawback) then I don't want to encourage doing it with FFI instead.

I think the only sensible use case for FFI is conversion to a Uint8Array / DataView etc.

My suggestion would be:

  • BitArray$BitArray$data to throw an exception if bitSize % 8 !== 0
  • BitArray$BitArray$data to work on unaligned bit arrays that store a whole number of bytes (this does however require a copy, but should be rare in practice):
export const BitArray$BitArray$data = (bitArray) => {
  if (bitArray.bitSize % 8 !== 0) {
    throw Error("Bit arrays that aren't a whole number of bytes can't be read in JavaScript");
  }

  let array = bitArray.rawBuffer;

  if (bitOffset !== 0) {
    array = new Uint8Array(bitArray.byteSize);
    for (let i = 0; i < array.length; i++) {
      array[i] = bitArray.byteAt(i);
    }
  }

  return new DataView(array.buffer, array.byteOffset, array.byteLength);
};

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

Successfully merging this pull request may close these issues.

5 participants