Ticket #234 (new defect)

Opened 2 years ago

Last modified 1 year ago

The nature of byte

Reported by: lth Assigned to: lth
Type: defect Priority: major
Milestone: Component: Spec
Version: 4 Keywords:
Cc: graydon, brendan, jeffdyer, pascallouis, chrispi

Description (last modified by lth) (diff)

What is the nature of byte?

Can we construct bytes?

Do we need a byte literal suffix for completeness? (We have one for all the other numeric types.)

Graydon suggests maybe "y" (since "b" would be confusing since it's a hexdigit, 0xfb could be the byte 15 or the uint 251).

For those that consider it redundant (it is pretty much redundant), consider also that the 'i' suffix for integers is redundant. So this is a "completeness fix".

My guess is that implementers would thank us if there were not a particular data format for byte; that byte is just a storage format.

See comment #2 for more thinking.

Attachments

Change History

  Changed 2 years ago by lth

But what does "new byte()" return, if not an instance of byte?

  Changed 2 years ago by lth

  • description changed from Do we need a byte literal suffix for completeness? (We have one for all the other numeric types.) Graydon suggests maybe "y" (since "b" would be confusing since it's a hexdigit, 0xfb could be the byte 15 or the uint 251). For those that consider it redundant (it is pretty much redundant), consider also that the 'i' suffix for integers is redundant. So this is a "completeness fix". My guess is that implementers would thank us if there were not a particular data format for byte; that byte is just a storage format. to What is the nature of byte? Can we construct bytes? Do we need a byte literal suffix for completeness? (We have one for all the other numeric types.) Graydon suggests maybe "y" (since "b" would be confusing since it's a hexdigit, 0xfb could be the byte 15 or the uint 251). For those that consider it redundant (it is pretty much redundant), consider also that the 'i' suffix for integers is redundant. So this is a "completeness fix". My guess is that implementers would thank us if there were not a particular data format for byte; that byte is just a storage format. See comment #2 for more thinking.
  • summary changed from Byte literal suffix? to The nature of byte

The thinking so far:

  • byte values are unsigned integer values
  • there are not byte values in the wild that aren't uints
  • there is no byte suffix
  • byte can be an annotation
  • you can't say "new byte"
  • if you "byte(x)" then it's converted to uint and chopped, and returned as uint
  • "x is byte" is always false

In fact byte is just a chopper for uint values.

  Changed 2 years ago by pascallouis

  • cc changed from graydon, brendan,jeffdyer to graydon, brendan, jeffdyer, pascallouis

  Changed 2 years ago by pascallouis

Based on the thinking so far, it would seem natural that

uint <: byte

since any byte value is a uint value. The conversion from byte to uint is natural, and the conversion from uint to byte chops.

follow-up: ↓ 6   Changed 2 years ago by lth

All the numeric classes in ES4 are "final" peer types, and our painful and long-in-coming conclusion was that they really ought to be -- reasons are optimization in the implementation (notably in the interaction between built-in operators and the generic functions that allow methods to be added), future-proofing, and the fact that there are no clear subclass-superclass relationships among them anyhow.

There is no way in ES4 to express that a class can have only specific subclasses (unlike what I believe is the case in Java), so having a restricted base type in order to express a final subtype is not an option -- if byte is an open class, anyone can subclass it.

Why should uint <: byte when uint in a sense has fewer constraints / can express more values than byte? If anything I'd expect byte <: uint.

in reply to: ↑ 5   Changed 2 years ago by pascallouis

Why should uint <: byte when uint in a sense has fewer constraints / can express more values than byte? If anything I'd expect byte <: uint.

Yes, got it reversed.

  Changed 2 years ago by chrispi

  • cc changed from graydon, brendan, jeffdyer, pascallouis to graydon, brendan, jeffdyer, pascallouis, chrispi

  Changed 2 years ago by cormac

Perhaps the simplest approach would be to have a class:

   class ByteVector extends Vector.<uint> {
      ... usual Vector behavior, excepts truncates everything to bytes
   }

This approach has some benefits: it satisfies the use-case for byte, requires no extension to the language, and modest extension to the builtins (one new class, and making Vector non-final).

Two issues remain: should we extend Vector.<int> or Vector.<uint>? Also, should putting 257 into a ByteVector be an error, or just truncated?

  Changed 2 years ago by lth

Cormac, I like your suggestion a lot. Getting rid of byte would be a plus.

The only issue is in reference to #196: whether Vector needs to be final for integrity reasons or whether, at a minimum, its meta::get and meta::set methods need to be final. I think the anwers are probably "no" and "yes", but I'll work on that. But if that turns out to be the case then if we're going to truncate the values on setting we have to get a hook in there. I think that's doable, for example by having a "protected" variable in Vector that allows for the installation of a hook function. It's a hack, but it's not too bad.

  Changed 2 years ago by brendan

I'm in favor of Cormac's proposal too, if Lars can make it work without too much hacking ;-).

/be

  Changed 2 years ago by cormac

Lars, if meta::set needs to be final, you _could_ override meta::get and do the truncation there. Just a though to avoid the extra hook function ...

  Changed 2 years ago by lth

By resolution of #196, the catchalls of Vector are final, but it can be subclassed, so I say we kill byte as you proposed. We'll think up a simple protocol whereby subclasses can override a setter hook. Here's one:

   function onSet(name:EnumerableId, v:T):T { return v }

Then in ByteArray:

   override function onSet(name:EnumerableId, v:uint):uint {
      return v & 255
   }

This is a workable solution. I think we should have a goal to avoid making meta::get and meta::set in Vector final, but it's not on the critical path (not even for ES4), and we need more time to think about the integrity of Vector before we do anything there.

  Changed 2 years ago by lth

Of course I meant ByteVector, not ByteArray. Sorry :-/

  Changed 2 years ago by lth

Discussion at f2f:

  • LH: Getting rid of byte is Good
  • LH: We could also go back to ByteArray?
  • CF: Or we could have a separate ByteVector? type with similar methods
  • => We're not doing anything with this right now because there are several options available
Note: See TracTickets for help on using tickets.