4 ms·
Minor nitpick println can only print things that implement the traits Display or Debug. As a result, Paths cannot be printed directly. Not all OSes store pa
by koito17 1y ago
Minor nitpick
println can only print things that implement the traits Display or Debug. As a result, Paths cannot be printed directly.
Not all OSes store paths compatible with UTF-8. In Rust, all strings are UTF-8 encoded. Thus printing a Path is a lossy operation (i.e. cannot safely be round-tripped). Path exposes a `display` method returning a type that implements Display. This is a fact Rust is encoding in its type system, whereas in JavaScript (and TypeScript), it's not really possible to state "strings internally are UTF-16 and you may need to invoke TextEncoder / TextDecoder to safely deal with paths that are not Unicode". If you fetch from a server sending Shift_JIS text and invoke `response.text()`, you get an empty string at runtime (in my experience). If you aren't experienced in dealing with text encoding issues, I can see this becoming a lengthy debugging session.
As others have noted, the JavaScript program has a bug not present in the Rust program, and a syntax error (should probably use for..of, not for..in). The example definitely uses more concepts than "first-class functions". You still have to understand iterators, just like in Rust, and it uses CommonJS instead of ES Modules, but I digress. The usage of async/await and Promises is another concept to teach, and the usage of top-level await is specifically something that wasn't supported in some runtimes (e.g. Node) until recently. It still isn't supported in the latest version of some mainstream JS engines (e.g. Hermes, which is used in React Native)
- tracker1 1y agoI find that understanding thenables/Promises and async-await in JS/TS is emphatically not something a lot of devs really understand. It really shows when you see something like... var fn = async (param) => new Promise((res, rej) => { ... fooLibraryCall(param).then(res).catch(rej); }); I've literally seen similar to this... where devs see wrappers for the callback syntax, then apply the same to thenables and use manual Promises inside an async labelled function. It makes my mind bleed to see it, and I've seen it a few places. Then, of course, there's dealing with module imports and async import() methods and how they operate or get transpiled or split, etc.
- tomjakubowski 1y agoSometimes you still need to work with promises even inside an async context. Imagine an async function which needs to `await Promise.all([...])`. In this case, `then()` can be a useful tool to make new promises from an async call.
- tracker1 1y agoOf course.. I was referring to having an async function, but having it create a "new Promise" that in and of itself is just calling a method that already returns a promise... it's creating extra closures and overhead that aren't necessary at all. Sometimes I'll add a `.catch(() => null)` or similar for manipulating a specific call with `.then`, if I want to manipulate something out of flow. Such as a convenience method to normalize api fetch calls, etc. That's just useful functionality, not making literally wrappers for no benefit or reason.
- deleted 1y ago[deleted]
- stouset 1y agoTo your above point about paths, it’s things like this that keep me coming back to Rust. This was just one example, but other languages are absolutely littered with pitfalls and gotchas that—individually—aren’t all that likely to happen. But all of them? Over a given program’s lifetime? In aggregate these end up being responsible for an absolutely wild number of random bugs that crop up in your exception logs that need to get tracked down. And it never ends. There are an infinite number of edge cases you’ve never thought about that aren’t fully handled and that some of which are constantly being tripped. This just… doesn’t happen in Rust. The type system catches (and/or completely rules out) a ridiculous number of these situations. I have repeatedly written finished software in Rust, where once it was released there was only an occasional need to add features but the typical bug-squashing treadmill just doesn’t exist. That’s not to say there are never bugs. You can express faulty logic in any language. But the number of stupid impedance matches that are categorically ruled out makes the experience of operating and maintaining Rust program once written a widely different experience than I’ve had with any other language.
- devnullbrain 1y agoI spent months working out all the kinks of a C++ codebase to make up for decades of assumptions about paths and strings and locales that failed to stand up to reality. The 'difficulty' of Rust would have been preferable, in hindsight.