News for hackers. Stuff that matters.
Re:My 20 Year Career Is Technical Debt or Deprecated by jcranmer on Tuesday May 16, 2023 @09:47AM (#35961860)
> I want to link it to whoever insisted on adding a useless TextDecoder class in javascript that you have to instantiate, instead of just calling textDecode(…, “utf8”) using a global function like the rest of the standard library.

I for one would rather punch the person who proposes such a global function as the only mechanism for conversion, because charset conversion is a reasonable thing to do on chunked partial inputs, and maintaining the state for conversion yourself is actually quite painful. Wrapping a stream converter into a one-shot function is much easier than the reverse, wrapping a one-shot function in a stream converter.

Re:My 20 Year Career Is Technical Debt or Deprecated by replygirl on Tuesday May 16, 2023 @10:22AM (#35962298)
This is what GP is talking about. Chunking can be done cleanly with very few internal functions (and without changing the call signature, if you want), but you're implying it must be a class and already thinking about hypothetical hacks
Re:My 20 Year Career Is Technical Debt or Deprecated by klibertp on Tuesday May 16, 2023 @10:14AM (#35962185)
You can have the global function and make it work on "chunked partial inputs" while maintaining the state between calls (that state can be hidden in a closure or made explicit as an argument or a receiver - functions in JS can be called on objects even if they were defined outside of them). The very bad example of this is C's `strtok`, but it's pretty typical for JS to encapsulate the state in a closure to get similar functionality.

Said another way: the functional, simplified interface doesn't mean you have to get simplified or lacking functionality. Haskell wouldn't exist if that was the case. The simplified interface providing as much functionality as the more complex interface is possible because the expressive power of JS is leagues above Java - porting Java patterns that emerged due to Java's shortcomings (some call them "design decisions", and they're also right) to JavaScript is simply not a good use of JS as a language.

Re:My 20 Year Career Is Technical Debt or Deprecated by tracker1 on Tuesday May 16, 2023 @07:33PM (#35969224)
It wouldn't need to be a global, it could be mounted on String for example... And one doesn't necessarily prevent the other.

    String.fromUint8Array: (input: Uint8Array, encoding: string): String;
Would be a fine, simple addition where it probably should be. Maybe calling the default for UInt8Array "String.fromBinary" instead.
Re:My 20 Year Career Is Technical Debt or Deprecated by josephg on Tuesday May 16, 2023 @09:27PM (#35970194)
> I for one would rather punch the person who proposes such a global function as the only mechanism for conversion, because charset conversion is a reasonable thing to do on chunked partial inputs

Fight me.

Javascript has a separate TextDecoderStream class if you want to support chunked, partial inputs. The TextDecoder class doesn't support streaming input at all. And it never will, thanks to the existence of TextDecoderStream.

TextDecoder only provides 1 method - TextDecoder.decode(). And the method is pure! So you could just make it a global method without any loss of functionality. The entire class has no mutable state whatsoever. Its just a container for some options, passed into the constructor. Those options could just have been passed straight to a global decode() method.

https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder

This might be idiomatic C++, but its terrible javascript. I had a friend who worked on the Chrome team years ago. He said a lot of the browser engineers who design javascript APIs are C++ programmers who don't know javascript properly. So of course they port C++ ideas into javascript directly. They don't know any better. This is why javascript's standard library is an incoherent mess.

Re:My 20 Year Career Is Technical Debt or Deprecated by tcfhgj on Wednesday May 17, 2023 @03:35AM (#35972297)
I see a benefit from having this options container: you can have a central place to set the options and then only pass down the decoder and the user of the function doesn't have to bother with the configuration
Re:My 20 Year Career Is Technical Debt or Deprecated by wruza on Wednesday May 17, 2023 @03:56AM (#35972429)
You can always pass a closure.
Re:My 20 Year Career Is Technical Debt or Deprecated by tcfhgj on Wednesday May 17, 2023 @04:04AM (#35972472)
Well, that's basically the same
Re:My 20 Year Career Is Technical Debt or Deprecated by josephg on Wednesday May 17, 2023 @10:50AM (#35976031)
Or pass an options object.

Regardless, it’s a strictly worse api in the general case. And it’s on par with passing around an options object in the case you want to share the same options in multiple places.

If the current api is either the same or worse compared to a pure function version in all cases, I’d prefer the pure function version thanks.

Re:My 20 Year Career Is Technical Debt or Deprecated by tcfhgj on Thursday May 18, 2023 @03:05AM (#35984892)
An Options object is a worse API, since it assumes an implicit dependency.

> If the current api is [...] the same [...] compared to a pure function version in all cases, I’d prefer the pure function version thanks.

Why?

Re:My 20 Year Career Is Technical Debt or Deprecated by josephg on Thursday May 18, 2023 @10:38PM (#35997121)
> An Options object is a worse API, since it assumes an implicit dependency.

No, it would be an explicit dependency.

    // definition:
    function decodeText(input, [format | options])

    // use:
    decodeText(someBuffer, 'utf8')

    // or:
    const opts = {encoding: 'utf8', fatal: true, ignoreBOM: false}
    decodeText(someBuffer, opts)
    decodeText(somethingElse, opts)
> Why?

Because a pure function is idiomatic, concise and clear. Its easier to use, easier to document and easier to understand. The only benefit of a class is that it encapsulates its state behind an interface. That makes sense for a BTree or a database. But TextDecoder has no mutable state. It has no state at all except for its passed-in configuration.

Decoding text is a verb not a noun. In programming, verbs are translated to functions, not classes. You don't have an "adder object" to add things. You don't have to instantiate a JSON stringifier before calling JSON.stringify. If thats not obvious, you may have spent too long in OO languages.