Yeah multiple things in JS have been inspired by C#. Arrow function syntax and async come to mind. I think they explicitly mention C# in the section where they mention prior art when proposing some of these features.
Also, I'd much prefer something like python's `with`, creating a new context where the disposal will happen once the context is exited, rather than changing the current context.
Fully with you on this one. The feature itself is great, but the syntax is weird. I wonder if they just didn't want to introduce yet another keyword along with "using", and thus reused "await". I can already see beginners getting utterly confused by this.
The problem is needing to call it. If it was only. await using something = resource; With no call it would be better. There's no call, nothing is happening except the promise construction. Which is stupid. C# doesn't work like that.
Arrow functions are great for callbacks. But for other functions, I prefer the 'function' way. I even have a vim macro defined for js/ts files. It expands 'ff' to 'function' :)
It's also not a drop-in replacement for a function declaration, as anybody who tried referencing 'this' in the function body would find out real quick.
My issue with arrow functions is that as Prime mentioned. They're not named, all anonymous and every time it's called actually creates a new copy of the same function. Generally it's fine for callbacks.
Yet another feature copied from C# and people who hate that language getting excited for coming it in javascript. What a irony 😂😂. I guess prime it's really time to try c#.
@@mihailmojsoski4202 it was always. I mean the features that you see are added to language decade ago. It's just people started to looking at c# this days only.
Regarding performance of ad-hoc objects versus class instances. There is a real and surprisingly high cost of long prototype chains, and ad-hoc objects tend to be 2-layer (instance + Object.prototype) while class instances are at least 3 layers (instance + class.prototype + object.prototype). You probably aren't going to get a concerning performance hit at 3 levels, but frankly you aren't going to get a concerning performance hit with a new closure for existing function code. And the prototype chain hit comes from referencing properties throughout the object's lifetime, where the closure hit happens only when the object is created. Arrow functions are good to prevent use of 'new' with the function. An interface should only be able to be used in one fashion, and it should immediately fail if used in any other way. Using 'class' for constructors requires 'new' and using arrow or class/object methods will throw an error with 'new'. The arrow syntax might be ugly, but there's a reason to never ever ever use a 'function' keyword as they can be invoked either way, and unless you boilerplate your functions with a crapton of guards you might end up with strange results if you used the incorrect invocation. I agree that the syntax for this proposal is godawful. It's getting awfully close to magic, which is the worst feature of any language. Take it from a guy who still has to maintain ancient Perl scripts. Programming magic is designed to make it easier for the first programmer to write, but it makes it much much harder for the second programmer to trace and maintain.
Destructors are C++. Other languages (except those also designed correctly with them in mind from the beginning, like Rust) just keep having to find kludges to imitate them, including C# and now JS.
C# makes more sense: await using (var resource = useSomething()) { // block to do something with resource } // gets cleaned up Can have nested using blocks easily and can read left to right top to bottom. Similar to python’s with statement/block
Exactly and if scope of using and function ends in the same place you can simplify brackets but it was added later and most of C# devs knows the origins
Doesn't C# also has await using? I'm pretty sure i've used it before without a {} block, and it is not clear where in code actually disposes the resource. At least in C# we can use it with a code block between { }, makes it way more clear than letting the compiler "guess" where to dispose.
@@tiagosutter8821 It has, in general I'm not a great fan of await using, but using alone is great and I understand the necessity of having an await version
@@tiagosutter8821 The compiler doesn't "guess". It disposes it at the end of the scope. If there are multiple usings, they get disposed in reverse order. Also, `await using` was introduced in C# because of async enumerators. Does JS have async enumerators?
I think what would make it less confusing for Prime is to make it "async using resource = getResource()" instead of "await using resource = getResource()", because "await" usually means right now and "async" mean that this has something to do with "await"
If you look at the DB example, turns out that the creator function can also be async (and most of the time when you have an async dispose you'll have an async creator). You're actually awaiting the creator function, which means it's not as bad.
After writing Javascript for 11 years, I'm finally ready to be off this ride. There's only so much wonky syntax I can learn year after year. I'm gonna go learn Rust.
@@supIMJohnFaulkner I might try Go as well. JS isn't the only language I've ever used, I've written Java, Python, Obj-C, and a very little bit of Swift. But frontend has been my jam for the longest time. I'm just too tired to keep up with the constant changes, and the fact that it's building on top of bad design choices from 20 years ago. I just need something new.
I see the future of all programming languages... Over time every enthusiast of every programming language will get their favourite features of whatever language they love into JavaScript. Why? Because eventually they have to do some web development, they find they have to use JS instead of their favourite language, but Javascript is shit for them, so they push to make it look more like what they know and love. I first had this thought when JS sprouted the unnecessary "class" feature. Ah, I thought, a lot of refugee Java programmers have been forced to use JS, they want to make JS look like Java. All of a sudden the innocent simplicity of JS was defiled, sullied. Of course bolting syntax and semantics of one language into another results in a chaotic, unfathomable mess. We see this with natural languages like English. Concocted as it was from old Viking, old French, old German, Latin, and other influences as it is, and then bent out of shape by Americans. I'm sure there is an "original English" still in there somewhere. Of course this processes of language rotting is not confined to just JS. Look at what has happened to C++ as every idea from every other languages is injected into it, as it flails around pretending to be a functional language rather than an OOP language, etc. No, every language we have will get stirred up by every possible feature from every other language. Entropy always increases as the Physicists tell us. The heat death of programming as we descend into chaos, unable to do anything.
javascript has been taken over by people with late stage autism. anyone who is actually making useful apps prefers oop patters, stateful programming, classes... the only people who want all this stateless, function / declarative programming have late stage autism that can never be cured.
@@diadetediotedio6918 Hei, Bro, Dude, my man, hope you don't mind my hint of drama. But I do believe there is a rather large pinch of reality in what I have said.
"like deconstructors in javascript" Ah a new baby! Oh no, its deficient. *Throws baby in the dumpster* I appreciate that you bagged on the symbols in js arrow functions. It drove me nuts when I was coming from python and now I'm just comfortably numb.
@@Amejonah not really. a defer runs anything u mark as defer at the end of a block. this is like python's context manager where the one creating the class/type defines what happens at the end of the block and you're merely a user of it, you're not exposed directly to what is going on underneath
With each JS feature it's getting more confusing... And I am 7 years into it. Can't wait for this feature to get into production and mess GC even more. Wish we could just be more explicit and not hide even more abstractions under some implicit behaviours which you need to know because there is no compiler for you to catch that and say you are going a little crazy.
@@Mike-uk2oq Yes and no. From my understanding of this now, this will invoke once object is going outside of scope, so being deallocated by GC sometime later + I can imagine that someone will gladly use such location for strange behaviours
Why are they going the pseudo-destructor route rather than just having an explicit `defer`? The Drop trait makes sense in Rust due to its ownership+lifetime semantics, but does this `using` idea actually make any sense in JS? Why would `defer` be a bad idea? (I know `defer` is kind of already a thing for `` but that's not technically JS at that point). let resource = getResource(); defer resource.dispose(); // or defer await resource.dispose(); This is just objectively clearer, even if you have to type an extra-line (oh no, not another line(!) /s). It would work with everything else already too that doesn't have the Symbol.dispose/asyncDispose nonsense too.
Because "defer" doesn't really have use-cases other than destructors. Writing defer line for every resource instead of simply using it is obviously worse.
@@eugenakv I use scope-based `defer` in other languages all the type for many things which are not "destructors" whatsoever. A good example are any calls that are effectively in nature begin/end, open/close, increment/decrement, etc, most of which have nothing to with type construction.
It does make sense he doesn’t like it. The functionality is nice, the way to use it is annoying. The `using` key is also changing the known meaning of `await`. IMO the way it just respects the scope is hidden magic. It’d prob be more interesting if it created a scope
please remember that JavaScript is a modular language that oaradigms the DOM from a JAVA engine that runs the API of the browser. You programmers that are matriculated out of college needed a Object Oriented Programming syntax so you can feel better about all the student loans and years you didnt need to be in a classroom… Typescript is the result to help you adjust to the paradigm of this… Because the new paradigm of software development lives in the web and cloud. Thus companies are not waiting on solutions that are JAVA or C# which have expensive life cycles and are higly depend on the Client Object Model of an OS
i am happy i went to college i went to a state college i lived in said state i paid 3600/y (at the highest, it was 2700 when i started) checkmate, atheist
it is like javascript imports "import {some} from file" instead of "from file import {some}" when they designed it they did not think about ease of use.
Typescript is a fantastic language. Its only downside is its intrinsic ties to Javascript. Someone needs to build a TS only compiler and runtime with its own rules and break free from mother Javascript's teet.
I did testing, object itself are much faster than classes, if you have a factory function, is also much faster than a class... but classes create instances with many prototypes faster... also you can create yourself a prototype function so it's like meh... class is much cleaner... if you do like idk GreenSocks GSAP animations and using Classes for flying animated shit is probably much slower than using prototypes and creating object with a factory function.
What is the best language feature for resource disposal? 1. using (C#, JavaScript), AKA with (Python) 2. defer (Go, Zig) 3. RAII (C++, Rust) 4. goto (C)
@@JuvStudios I agree but I wish I understood the historical context in which someone invented the phrase "Resource Acquisition Is Initialization", because any time anyone actually refers to it, they're referring to the opposite concept "releasing resources when leaving scope". it's the best feature with the worst name.
The arrow function thing is basically because the standard is to treat function as values (assigning them to variables, passing them to other functions, etc) instead declarations. It's just a matter of perspective and getting used to it. I personally prefer that style, but yeah a lot of people prefer declarations. As for the `using` feature... I guess it's fine for some use cases, but I feel like it just doesn't belong to JS.
why would I ever want a function to be a value / variable? lol the whole point of a function is its a definition you pass variables in to... it seems this whole functional programming community has late stage autism
It was really needed... But I still prefer real RAII because then its not strictly scope-tied, but you can move that out of the scope or put it in variables. The reason why JS needs this because there are a lot of resources (including native .close() methods when integrating cpp libs)... GC never solved these - RAII and also rust does from the start... The fun fact is that wih this await bullshit.... they managed to make it tenfolds more complicated than C++ RAII lol (yet less powerful haha)
> but you can move that out of the scope or put it in variables. would it be possible to still use `[Symbol.dispose]` (without `using`), and e.g. `myResources.push(getResource())`, then later `myResources.pop() // dead_resource`, then when something is released (recovered by the GC?) it would call `dead_resource[Symbol.dispose]()`? that is, `using` is only syntax sugar for releasing resources in scopes, but `Symbol.dispose` can be called when something is released?
@@Tigregalis The way it works in C++ is, the object's destructor always gets called at the end of a scope, no matter what (white lie, there are also some optimizations I won't get into but this is the basic mental model). What happens when you, say, store a unique_ptr that owns a resource somewhere, is it'll get _moved_ which transfers the ownership so that when the original unique_ptr gets destroyed, nothing happens. Rust is slightly different because moves are destructive so the original object's destructor won't get called, but conceptually the crucial step is still a move with the associated ownership transfer. I only know enough javascript to know I want to stay away so people who actually use it are invited to correct me, but I don't think the kind of move semantics that would be required to make sense of this sort of operation even exists in JS.
JS keeps on adding stupid (barely used) features but they freaking won't implement a strict type system It's like Ecma script foundation not even working On the other hand Dart ( Flutter's language), just see that language's progress. It improved so nicely. It's basically my 2nd fav after Rust JS is my first language after getting traumatized by Java. I just want it to improve as a language Typescript is great but pure JS typing is heaven
I thought this would be a great idea, but testing this on 5.2beta, it's only seems to be lexical scope. :( pass this object into a closure and it will dispose at the end of lexical scope no matter if your closure still has a reference. This part of `using` really needs highlighting in Docs, because scope is not just lexical. Because of this limitation your not getting much more than a `try / finally`, only benefit I can see is that your dispose can be defined up-front, and you save 1 level of code indent. TS docs correction -> function when it leaves lexical scope. What would have been great is `[Symbol.dispose]` directly with `Object`?, no need for `using` in the first place. I assume the reason is that it requires low level JS integration to do this, not something Typescript could polyfill or transpile. And because JS is in so many Browsers / Backend it would take a while before becoming mainstream, but this is something Ecmascript should have pushed years ago, if they had it's likely it would now have been mainstream among JS Engines. I assume it is still something I'll use, but just have to be aware that all code inside using will need awaiting, and don't pass this object into a none awaited closure as the dispose could get called before the closure is done. setTimeout(() => db.clean(), 1000); //BOOM!!.. DB closed, you plonker!!..
Naively I would assume that calling a method on a class instance that uses a field would be slower than calling a method on such an object using a variable in the closure. To call the method you need two hashtable lookups, one directly on the object, which fails, then going one up the prototype chain. Then you need another hashtable lookup for the involved field. For the object+closure case you need only one lookup for the method and the variable is bound via closure. That should be accessible via a pointer deref and array element access, basically. However, any of that could be optimized in any way and it ignores the added GC pressure for creating a closure for each method.
@@alalalavaladu3670 Pretty sure arguments just like locals and closed over variables aren't looked up via a hashtable. The parser can already disambiguate what is meant lexically at parse time and just generate the correct reference (pointer/array index).
0:31 No it's like using ... from C#. By leaves scope it depends on how they have implemented it. In C# its either the scope in which it was declared or its explicitly scoped using curly braces. i.e. using (var someResource = new Resource()) { ... } // Disposes here Or public void MyEnclosingMethod() { using var someResource = new Resource(); .... } // Disposes here
3:17 FP zealotry but I agree. It's dumb with a capital stupid. 7:48 isn't the point that it's dealing with unmanaged memory? Thats what its for. i.e. if you didnt close it it would be a memory leak.
@@isodoubIet No it's not. C# has destructors. This is not not at all that (because C# and JS are managed languages and this is a pattern for dealing with unmanaged code).
@@sacredgeometry "C# has destructors" They're not the same as C++ destructors because the latter are _deterministically_ called at the end of scope, and IDisposable is just a hack to imitate that behavior.
@@isodoubIet I know that was exactly the point I was making. C# and JS dont have C++ style destruction and the pattern they are using to dispose of unmanaged memory is the dispose pattern. Which was directly borrowed from C# and is in use now in JS. It has nothing to do with C++ destructors. It isnt a hack to imitate that behaviour. Its a pattern to implement it.
This file handle thing would peibably work well for libraries, but otherwise I think I prefer the older code style. Surely, if you remember to use using and create the fn for it plus the dispose fn, you would remember to close the handle.
using vs await using is only different in that it tells which destructor to call at the end of the current scope. Destructors are always called at the end of the current scope where using or await using is used, pun intended. I hate that you have to manually tell the runtime which destructor to run...
CODE SAMPLES BELOW The reason why people are using that thing where functions are declared as const set to an arrow function is because for whatever brain dead reason, doing it this way binds THIS context automatically. So in typescript if you have a class and you call one of it's methods with it written in the traditional function declaration syntax, if that function calls a private method of the class you have to .bind(this) to that method explicitly. If that private method is declared with the const myCrap = () => syntax then it automatically binds THIS and so you can call it like this.myCrap(). It's actually brain dead that JS/TS works this way. You shouldn't have to explicitly call bind(this) in either circumstance when you're literally in the context of a class calling a private method lol. Like OF COURSE you are referring to this INSTANCE of the class. But yeah people write functions this way purely for that reason. Anyone who is writing them with the arrow function syntax not for that reason literally has the wrong idea of what's happening. IT'S NOT FOR STYLE. It's literally because of the automatic THIS binding. If you think it's for style or are using it for style I really don't know what to say other than, I can smell your code from here buddy. -------------- ARROW FUNCTION -------------- class MyAwesomeClass { private myPrivateMethod = () => { // some private code here } myCoolFunction() { this.myPrivateMethod() //
@@JorgetePanete Yeah, but that's really only possible because the compiler knows exactly when it will no longer be accessible. That is just a technical impossibility without rewriting the compiler and in the case of Java, the JVM as well. A lot of the headaches that exist with resources not being closed are instead built into the language on a fundamental level in Rust. That increases the headache of doing just about anything complex. So there are tradeoffs to consider.
3:08 the reason, I think, why arrow function are preferred over function declaration is that the arrow functions in JS don’t redefine the value of “this” in their function body which makes them more “stateless”
Who thought this was a good idea? They literally reject proposals that add way smaller changes but are a lot more useful, citing it could be done another way. Destructors are useful and should be included, I agree, but I don't think the syntax for this is right. It should be part of a class and labelled as "destructor", just like constructor and implicitly called when out of scope, just like how other languages do it.
So `using` should be used in place of const but can have await before it? In the example, IMO, would make more sense to have `{ const resource = await using getResource() }` thought that await just feels poorly placed. Like we're not awaiting getResource, we're awaiting the eventual dispose.
Defer isn't the most appropriate word due to the implicit try/finally. Using is a great word choice since many other languages "use" it. You can probably also add a block scope to using with braces? In C# you have both options and trust me, it's way better without the extra braces if you can get away without them. "The GC doesn't close the file handle?" Oh man, we've found the source of the leaks :D
this is modeled after C#. Basically same sytax. And I agree that it's not logical. Should by async using. In c# it's historical, becouse using tended to had a block(like try), but now it can be used in var declaration statement as in this example. But it had hystorical reasons in C#. Bun now they brought it into JS with same keyword. Shame on them.
This is simply Microsoft continuing to try to turn JS into C#. I can't think of any use cases for this outside of the server. Turning JS from a simple client-side web language to a do-anything all-purpose language is a horrible shame. Even the original argument for using JS on the server always revolved around it being a simple language that lots of people were already familiar with from using on the browser, that argument is undercut when JS is quickly transforming into the most complex and feature-overloaded backend language.
This is really weird feature. Im using JS to make big uploads to some dbs and this is useless by a mile. I need validators or decorators first. Or "optional" typing for check data types, whatever more useful than this lol. BTW im looking for (not rust) another language for the same uses (not golang) with a robust framework like Spring (without a soup of choises)
When I think they can't do anything worse, JavaScript always proves me wrong. Its like the haggis of programming languages. This is going to bite somebody really hard.
Some of the examples are wrong, if the function returning the "async disposable" is itself async, there will have to be two "await" keywords on the same line, like: await using connection = await getConnection();
What a terrible keyword. Why using, we're not drop or disposable or defer or something like that. Using doesn't imply anything about the resource being marked for death.
It looks strange because they overload the keyword to mean a different thing, maybe it should have been like "awaited_using" or something but introducing keywords is never liked by language devs (with good reason)
If you use "using", you kind of already need to know that something will happen when leaving the scope... the "using" statement is "deferring" to the end of scope so to speak... If you look at it like this, the "async using" feels natural... it's deferring an async operation to the end of the scope in stead of a non-async one.
this one developer at my company has autism and told me to always use const and never use var. and he said classes are toxic and to always make everything a functional component and use arrow functions for everything... after debugging one of his 50 layer deep arrow functions I switched back to classes
There was a lot of pressure in the committee to use “using async” instead of “await using” but there were issues with the language parser complexity or backwards compatibility or something.
6:46 is the same as just using a callback. I guess the whole point is that you can defer (or await using) many resources in the same scope. So when scope is done, all of them are unloaded at the same time. Am I getting this right? All this can be done with Promise.all and a bit of structure...
I always thought that when looking at JS, I’m a C# developer, I always wondered why in JS all functions seemed to be defined as lambda functions when they didn’t need to be, as if the writer of the function was showing off, but didn’t understand the when and where the feature they was using was supposed to be used. In-line code becomes unreadable when abused
people assigning an anonymous function to a variable is also a pet peeve of mine. If you want a named function, use a named function. If you want an anonymous function, use an anonymous function. Don't mix and match.
i agree with you, my eyes are twitching every time i see an arrow function. i think regular function is semantically better. because it says function not const, like why?
I agree that the syntax is weird. I think that they are trying to prevent nesting in the resource scopes and bind their usefulness to the parent function scope
The main diference between ()=>{} and function(){} is that the first can excute in the global scope and access it's variables, when inside a class or an object. The function declaration, runs inside the local scope of the object and canot access the values from where it was called, this comes from vanila JS, in frameworks this does not make a diference, it's only visual.
React on the server is going to look lit
"use using"
using using = use(use)
Finally, IDisposable in JS
Yeah it's effectively a copy of IDisposable (C#) and AutoClosable (Java)
Just syntactic sugar for calling a close/dispose function on recourses.
It's IAsyncDisposable
Next thing they will copy is IAsyncEnumrable
Naming interfaces with ISomething should be a crime
@@andrebrait why is that so?
Us C# devs have been using the "using" keyword for a while now
Yeah multiple things in JS have been inspired by C#. Arrow function syntax and async come to mind.
I think they explicitly mention C# in the section where they mention prior art when proposing some of these features.
@@kebien6020 and C# got async/await from F#.
Shhh - He hates c# - I don't think he realises how good it is.
Also, I'd much prefer something like python's `with`, creating a new context where the disposal will happen once the context is exited, rather than changing the current context.
with already exist in JS and it's garbage that should never be used.
It turn an object into variables in a scope.
Or Java's try-with-resources.
@@vukkulvar9769 so it's like jai's "using", lol. Jai uses that so you can do "inheritence" without inheriting in the polymorphic sense
@@notuxnobux Or PHP "extract".
@@Yay295 that's Microsoft bringing c# syntax into JS world (if I uderstand correctly it would have same syntax in JS like in this example with TS)
Totally unreadable... Congrats JS devs, you have created a new crap
Fully with you on this one. The feature itself is great, but the syntax is weird. I wonder if they just didn't want to introduce yet another keyword along with "using", and thus reused "await".
I can already see beginners getting utterly confused by this.
Feels like that to me. Though they could have used `async using`.
Should have reused async then
The problem is needing to call it.
If it was only.
await using something = resource;
With no call it would be better. There's no call, nothing is happening except the promise construction. Which is stupid.
C# doesn't work like that.
Nah it actually also await the creator function, which makes it fine to me.
async using or using await would be better
Finally, someone addresses the silliness with using arrow functions to make a named function!
Arrow functions are great for callbacks. But for other functions, I prefer the 'function' way.
I even have a vim macro defined for js/ts files. It expands 'ff' to 'function' :)
It's also not a drop-in replacement for a function declaration, as anybody who tried referencing 'this' in the function body would find out real quick.
My issue with arrow functions is that as Prime mentioned. They're not named, all anonymous and every time it's called actually creates a new copy of the same function. Generally it's fine for callbacks.
@@oblivion_2852 Wait, is it true that a new copy is created whenever it's called? That's wasteful
@@NphiniT I'd like to know this as well, this sounds incorrect but what do I know
@@BigBahss I did not find anything to that effect. I'd take that with a mountain of salt
Yet another feature copied from C# and people who hate that language getting excited for coming it in javascript. What a irony 😂😂. I guess prime it's really time to try c#.
C# has gotten really good recently
@@mihailmojsoski4202 it was always. I mean the features that you see are added to language decade ago.
It's just people started to looking at c# this days only.
Regarding performance of ad-hoc objects versus class instances. There is a real and surprisingly high cost of long prototype chains, and ad-hoc objects tend to be 2-layer (instance + Object.prototype) while class instances are at least 3 layers (instance + class.prototype + object.prototype). You probably aren't going to get a concerning performance hit at 3 levels, but frankly you aren't going to get a concerning performance hit with a new closure for existing function code. And the prototype chain hit comes from referencing properties throughout the object's lifetime, where the closure hit happens only when the object is created.
Arrow functions are good to prevent use of 'new' with the function. An interface should only be able to be used in one fashion, and it should immediately fail if used in any other way. Using 'class' for constructors requires 'new' and using arrow or class/object methods will throw an error with 'new'. The arrow syntax might be ugly, but there's a reason to never ever ever use a 'function' keyword as they can be invoked either way, and unless you boilerplate your functions with a crapton of guards you might end up with strange results if you used the incorrect invocation.
I agree that the syntax for this proposal is godawful. It's getting awfully close to magic, which is the worst feature of any language. Take it from a guy who still has to maintain ancient Perl scripts. Programming magic is designed to make it easier for the first programmer to write, but it makes it much much harder for the second programmer to trace and maintain.
Are you for real my guy?
Typescript is blatantly copying C# features these days. 😂
And i'm all for it. Cause it's awesome.
Because typescript is microsoft..
Destructors are C++. Other languages (except those also designed correctly with them in mind from the beginning, like Rust) just keep having to find kludges to imitate them, including C# and now JS.
C# makes more sense:
await using (var resource = useSomething())
{
// block to do something with resource
} // gets cleaned up
Can have nested using blocks easily and can read left to right top to bottom.
Similar to python’s with statement/block
Exactly and if scope of using and function ends in the same place you can simplify brackets but it was added later and most of C# devs knows the origins
thats because the C# community isnt full of people with late stage autism like the javascript community
Doesn't C# also has await using? I'm pretty sure i've used it before without a {} block, and it is not clear where in code actually disposes the resource. At least in C# we can use it with a code block between { }, makes it way more clear than letting the compiler "guess" where to dispose.
@@tiagosutter8821
It has, in general I'm not a great fan of await using, but using alone is great and I understand the necessity of having an await version
@@tiagosutter8821 The compiler doesn't "guess". It disposes it at the end of the scope. If there are multiple usings, they get disposed in reverse order.
Also, `await using` was introduced in C# because of async enumerators. Does JS have async enumerators?
Your frustration with the overuse and abuse of arrow functions makes me happy. Javascript is a mess because most of its evangelists are a mess.
I think what would make it less confusing for Prime is to make it "async using resource = getResource()" instead of "await using resource = getResource()", because "await" usually means right now and "async" mean that this has something to do with "await"
Yes this is what I was thinking as well. I’ll get used to await, but I think Async would have been more clear right from the start
I had this thought initially, and then I wondered if people would confuse it with async functions.
@@disguysn well, python for example had "async for" for ages. keyword "async" just says that it is asynchronous, while "await" implies some waiting
they copied C#
If you look at the DB example, turns out that the creator function can also be async (and most of the time when you have an async dispose you'll have an async creator). You're actually awaiting the creator function, which means it's not as bad.
After writing Javascript for 11 years, I'm finally ready to be off this ride. There's only so much wonky syntax I can learn year after year. I'm gonna go learn Rust.
Don't tell him boys
I recommend go
@@deado7282 I recommend Rust
@@Tigregalisfrom one branded frying pan to another branded frying pan
@@supIMJohnFaulkner I might try Go as well. JS isn't the only language I've ever used, I've written Java, Python, Obj-C, and a very little bit of Swift. But frontend has been my jam for the longest time. I'm just too tired to keep up with the constant changes, and the fact that it's building on top of bad design choices from 20 years ago. I just need something new.
I see the future of all programming languages...
Over time every enthusiast of every programming language will get their favourite features of whatever language they love into JavaScript. Why? Because eventually they have to do some web development, they find they have to use JS instead of their favourite language, but Javascript is shit for them, so they push to make it look more like what they know and love.
I first had this thought when JS sprouted the unnecessary "class" feature. Ah, I thought, a lot of refugee Java programmers have been forced to use JS, they want to make JS look like Java. All of a sudden the innocent simplicity of JS was defiled, sullied.
Of course bolting syntax and semantics of one language into another results in a chaotic, unfathomable mess. We see this with natural languages like English. Concocted as it was from old Viking, old French, old German, Latin, and other influences as it is, and then bent out of shape by Americans. I'm sure there is an "original English" still in there somewhere.
Of course this processes of language rotting is not confined to just JS. Look at what has happened to C++ as every idea from every other languages is injected into it, as it flails around pretending to be a functional language rather than an OOP language, etc.
No, every language we have will get stirred up by every possible feature from every other language.
Entropy always increases as the Physicists tell us. The heat death of programming as we descend into chaos, unable to do anything.
javascript has been taken over by people with late stage autism. anyone who is actually making useful apps prefers oop patters, stateful programming, classes... the only people who want all this stateless, function / declarative programming have late stage autism that can never be cured.
Bro just stop with all the drama already
Fart
@@diadetediotedio6918 Hei, Bro, Dude, my man, hope you don't mind my hint of drama. But I do believe there is a rather large pinch of reality in what I have said.
"like deconstructors in javascript"
Ah a new baby! Oh no, its deficient. *Throws baby in the dumpster*
I appreciate that you bagged on the symbols in js arrow functions. It drove me nuts when I was coming from python and now I'm just comfortably numb.
this is basically `with` from python
but much worse
I don't think so
Context Manager in Python is really smoth, readable and easy to use. This crap in JS give you more worries than profits
it's more like defer in Go
@@Amejonah not really. a defer runs anything u mark as defer at the end of a block. this is like python's context manager where the one creating the class/type defines what happens at the end of the block and you're merely a user of it, you're not exposed directly to what is going on underneath
We C# now
TypeScript is just c# for the most part with out saying it out loud. You know there is a namespace keyword in TypeScript.
@@FilipCordasthat for JS
C++
With each JS feature it's getting more confusing... And I am 7 years into it. Can't wait for this feature to get into production and mess GC even more.
Wish we could just be more explicit and not hide even more abstractions under some implicit behaviours which you need to know because there is no compiler for you to catch that and say you are going a little crazy.
That's why I went from JS to Rust with WASM for webapps. Same runtime, but compile-time errors and real typechecking.
This has nothing to do with GC, you are confused
@@Mike-uk2oq Yes and no. From my understanding of this now, this will invoke once object is going outside of scope, so being deallocated by GC sometime later + I can imagine that someone will gladly use such location for strange behaviours
@@ichizos9615 It just calls the dispose method at the end of the scope. The GC is not necessary here.
@@Mike-uk2oq Yea you are right, I was clearly confused here.
Why are they going the pseudo-destructor route rather than just having an explicit `defer`? The Drop trait makes sense in Rust due to its ownership+lifetime semantics, but does this `using` idea actually make any sense in JS? Why would `defer` be a bad idea? (I know `defer` is kind of already a thing for `` but that's not technically JS at that point).
let resource = getResource();
defer resource.dispose();
// or
defer await resource.dispose();
This is just objectively clearer, even if you have to type an extra-line (oh no, not another line(!) /s). It would work with everything else already too that doesn't have the Symbol.dispose/asyncDispose nonsense too.
Because "defer" doesn't really have use-cases other than destructors. Writing defer line for every resource instead of simply using it is obviously worse.
@@eugenakv I use scope-based `defer` in other languages all the type for many things which are not "destructors" whatsoever. A good example are any calls that are effectively in nature begin/end, open/close, increment/decrement, etc, most of which have nothing to with type construction.
It does make sense he doesn’t like it.
The functionality is nice, the way to use it is annoying.
The `using` key is also changing the known meaning of `await`. IMO the way it just respects the scope is hidden magic. It’d prob be more interesting if it created a scope
The trend of languages without RAII coming up with kludges to imitate RAII remains undefeated
Making JS worse one poorly thought-out addition at a time 💪
please remember that JavaScript is a modular language that oaradigms the DOM from a JAVA engine that runs the API of the browser.
You programmers that are matriculated out of college needed a Object Oriented Programming syntax so you can feel better about all the student loans and years you didnt need to be in a classroom… Typescript is the result to help you adjust to the paradigm of this… Because the new paradigm of software development lives in the web and cloud. Thus companies are not waiting on solutions that are JAVA or C# which have expensive life cycles and are higly depend on the Client Object Model of an OS
i am happy i went to college
i went to a state college
i lived in said state
i paid 3600/y (at the highest, it was 2700 when i started)
checkmate, atheist
it is like javascript imports "import {some} from file" instead of "from file import {some}" when they designed it they did not think about ease of use.
The syntax/semantics is too outrageous
Totally agree. Will be nice to have but the syntax is needlessly confusing.
This is like python's context managers... but way less clear😂
Typescript is a fantastic language. Its only downside is its intrinsic ties to Javascript. Someone needs to build a TS only compiler and runtime with its own rules and break free from mother Javascript's teet.
I think TS is trying to "replace" JS but by eating it veeeeery slowly
I did testing, object itself are much faster than classes, if you have a factory function, is also much faster than a class... but classes create instances with many prototypes faster... also you can create yourself a prototype function so it's like meh... class is much cleaner... if you do like idk GreenSocks GSAP animations and using Classes for flying animated shit is probably much slower than using prototypes and creating object with a factory function.
Do you have an example code?
What is the best language feature for resource disposal?
1. using (C#, JavaScript), AKA with (Python)
2. defer (Go, Zig)
3. RAII (C++, Rust)
4. goto (C)
RAII best.
'with' in Python is really nice
Defer ain't specifically for resource disposal, it could also be used for logging and shit.
that's like asking what's 7+3
third option
@@JuvStudios I agree but I wish I understood the historical context in which someone invented the phrase "Resource Acquisition Is Initialization", because any time anyone actually refers to it, they're referring to the opposite concept "releasing resources when leaving scope". it's the best feature with the worst name.
The arrow function thing is basically because the standard is to treat function as values (assigning them to variables, passing them to other functions, etc) instead declarations. It's just a matter of perspective and getting used to it. I personally prefer that style, but yeah a lot of people prefer declarations.
As for the `using` feature... I guess it's fine for some use cases, but I feel like it just doesn't belong to JS.
why would I ever want a function to be a value / variable? lol the whole point of a function is its a definition you pass variables in to... it seems this whole functional programming community has late stage autism
It was really needed... But I still prefer real RAII because then its not strictly scope-tied, but you can move that out of the scope or put it in variables.
The reason why JS needs this because there are a lot of resources (including native .close() methods when integrating cpp libs)... GC never solved these - RAII and also rust does from the start...
The fun fact is that wih this await bullshit.... they managed to make it tenfolds more complicated than C++ RAII lol (yet less powerful haha)
> but you can move that out of the scope or put it in variables.
would it be possible to still use `[Symbol.dispose]` (without `using`), and e.g. `myResources.push(getResource())`, then later `myResources.pop() // dead_resource`, then when something is released (recovered by the GC?) it would call `dead_resource[Symbol.dispose]()`?
that is, `using` is only syntax sugar for releasing resources in scopes, but `Symbol.dispose` can be called when something is released?
@@Tigregalis The way it works in C++ is, the object's destructor always gets called at the end of a scope, no matter what (white lie, there are also some optimizations I won't get into but this is the basic mental model). What happens when you, say, store a unique_ptr that owns a resource somewhere, is it'll get _moved_ which transfers the ownership so that when the original unique_ptr gets destroyed, nothing happens. Rust is slightly different because moves are destructive so the original object's destructor won't get called, but conceptually the crucial step is still a move with the associated ownership transfer.
I only know enough javascript to know I want to stay away so people who actually use it are invited to correct me, but I don't think the kind of move semantics that would be required to make sense of this sort of operation even exists in JS.
JS keeps on adding stupid (barely used) features but they freaking won't implement a strict type system
It's like Ecma script foundation not even working
On the other hand Dart ( Flutter's language), just see that language's progress. It improved so nicely. It's basically my 2nd fav after Rust
JS is my first language after getting traumatized by Java. I just want it to improve as a language
Typescript is great but pure JS typing is heaven
Use a language with a compilation step, there is no reason not to
I’m not “using” JavaScript.
I thought this would be a great idea, but testing this on 5.2beta, it's only seems to be lexical scope. :( pass this object into a closure and it will dispose at the end of lexical scope no matter if your closure still has a reference. This part of `using` really needs highlighting in Docs, because scope is not just lexical. Because of this limitation your not getting much more than a `try / finally`, only benefit I can see is that your dispose can be defined up-front, and you save 1 level of code indent. TS docs correction -> function when it leaves lexical scope.
What would have been great is `[Symbol.dispose]` directly with `Object`?, no need for `using` in the first place. I assume the reason is that it requires low level JS integration to do this, not something Typescript could polyfill or transpile. And because JS is in so many Browsers / Backend it would take a while before becoming mainstream, but this is something Ecmascript should have pushed years ago, if they had it's likely it would now have been mainstream among JS Engines.
I assume it is still something I'll use, but just have to be aware that all code inside using will need awaiting, and don't pass this object into a none awaited closure as the dispose could get called before the closure is done.
setTimeout(() => db.clean(), 1000); //BOOM!!.. DB closed, you plonker!!..
Naively I would assume that calling a method on a class instance that uses a field would be slower than calling a method on such an object using a variable in the closure. To call the method you need two hashtable lookups, one directly on the object, which fails, then going one up the prototype chain. Then you need another hashtable lookup for the involved field. For the object+closure case you need only one lookup for the method and the variable is bound via closure. That should be accessible via a pointer deref and array element access, basically. However, any of that could be optimized in any way and it ignores the added GC pressure for creating a closure for each method.
You forgot var keyword can override arguments. So you might still need 2 lookups.😅
@@alalalavaladu3670 Pretty sure arguments just like locals and closed over variables aren't looked up via a hashtable. The parser can already disambiguate what is meant lexically at parse time and just generate the correct reference (pointer/array index).
0:31 No it's like using ... from C#.
By leaves scope it depends on how they have implemented it. In C# its either the scope in which it was declared or its explicitly scoped using curly braces.
i.e. using (var someResource = new Resource())
{
...
} // Disposes here
Or
public void MyEnclosingMethod()
{
using var someResource = new Resource();
....
} // Disposes here
3:17 FP zealotry but I agree. It's dumb with a capital stupid.
7:48 isn't the point that it's dealing with unmanaged memory? Thats what its for. i.e. if you didnt close it it would be a memory leak.
"No it's like using ... from C#."
Destructors, from C++.
@@isodoubIet No it's not. C# has destructors. This is not not at all that (because C# and JS are managed languages and this is a pattern for dealing with unmanaged code).
@@sacredgeometry "C# has destructors"
They're not the same as C++ destructors because the latter are _deterministically_ called at the end of scope, and IDisposable is just a hack to imitate that behavior.
@@isodoubIet I know that was exactly the point I was making. C# and JS dont have C++ style destruction and the pattern they are using to dispose of unmanaged memory is the dispose pattern.
Which was directly borrowed from C# and is in use now in JS.
It has nothing to do with C++ destructors. It isnt a hack to imitate that behaviour. Its a pattern to implement it.
This file handle thing would peibably work well for libraries, but otherwise I think I prefer the older code style. Surely, if you remember to use using and create the fn for it plus the dispose fn, you would remember to close the handle.
agreed. seems like it's designed purely for library developers.
using vs await using is only different in that it tells which destructor to call at the end of the current scope. Destructors are always called at the end of the current scope where using or await using is used, pun intended.
I hate that you have to manually tell the runtime which destructor to run...
waiting for `lock` ..
CODE SAMPLES BELOW
The reason why people are using that thing where functions are declared as const set to an arrow function is because for whatever brain dead reason, doing it this way binds THIS context automatically. So in typescript if you have a class and you call one of it's methods with it written in the traditional function declaration syntax, if that function calls a private method of the class you have to .bind(this) to that method explicitly. If that private method is declared with the const myCrap = () => syntax then it automatically binds THIS and so you can call it like this.myCrap().
It's actually brain dead that JS/TS works this way. You shouldn't have to explicitly call bind(this) in either circumstance when you're literally in the context of a class calling a private method lol. Like OF COURSE you are referring to this INSTANCE of the class. But yeah people write functions this way purely for that reason. Anyone who is writing them with the arrow function syntax not for that reason literally has the wrong idea of what's happening. IT'S NOT FOR STYLE. It's literally because of the automatic THIS binding. If you think it's for style or are using it for style I really don't know what to say other than, I can smell your code from here buddy.
-------------- ARROW FUNCTION --------------
class MyAwesomeClass {
private myPrivateMethod = () => {
// some private code here
}
myCoolFunction() {
this.myPrivateMethod() //
This is try-with-resources from Java 8
Yeah, but with worse syntax. It's sad when Java does something better. I say that as someone who actually likes using Java as well.
@@CottidaeSEAnot better than just disposing of it when leaving the scope or dropping it like in Rust
@@JorgetePanete Yeah, but that's really only possible because the compiler knows exactly when it will no longer be accessible. That is just a technical impossibility without rewriting the compiler and in the case of Java, the JVM as well.
A lot of the headaches that exist with resources not being closed are instead built into the language on a fundamental level in Rust. That increases the headache of doing just about anything complex. So there are tradeoffs to consider.
@@CottidaeSEA the headaches are _not_ closing them
@@JorgetePanete Yes, but now you have a whole heap of other things to think about such as lifetimes. It's a tradeoff.
I would like to have a way to trigger garbage collector manually. It will be useful...
I would rather have defer
3:08 the reason, I think, why arrow function are preferred over function declaration is that the arrow functions in JS don’t redefine the value of “this” in their function body which makes them more “stateless”
That might make sense if they were actually using the “this” value, but generally they don’t.
@@calebvear7381 The overhead exists, whether 'this' is used or not. Also, arrow functions don't get an 'arguments' object, another source of overhead.
@@grumpylibrarianno overhead if you don't use this and arguments and eval
Ah! Excellent point! Still, I laughed my butt off & agree with Prime's (hilarious) frustration.
the functional / stateless programming community has literally taken over javscript now. its too far gone at this point
What is the point of this? Can anyone clarify? Don't the garbage collectors in JS engines already delete crap that's not in scope?
Garbage collection is non-deterministic. This is the C# pattern of deterministic resource management.
@@McZsh C++
They fr copying c#
GC not closing files?! OH MY FREAKING GOD! Of course! Why should it? It is not his job, HAHAHA!
Who thought this was a good idea? They literally reject proposals that add way smaller changes but are a lot more useful, citing it could be done another way. Destructors are useful and should be included, I agree, but I don't think the syntax for this is right. It should be part of a class and labelled as "destructor", just like constructor and implicitly called when out of scope, just like how other languages do it.
So `using` should be used in place of const but can have await before it?
In the example, IMO, would make more sense to have `{ const resource = await using getResource() }` thought that await just feels poorly placed. Like we're not awaiting getResource, we're awaiting the eventual dispose.
Defer isn't the most appropriate word due to the implicit try/finally. Using is a great word choice since many other languages "use" it.
You can probably also add a block scope to using with braces? In C# you have both options and trust me, it's way better without the extra braces if you can get away without them.
"The GC doesn't close the file handle?" Oh man, we've found the source of the leaks :D
Why not just introduce defer like this (from Go):
```
defer function() {
// do db close here or whatever
}
```
This using stuff is very confusing.
Number of times I see this useful - zero.
this is modeled after C#.
Basically same sytax. And I agree that it's not logical. Should by async using.
In c# it's historical, becouse using tended to had a block(like try), but now it can be used in var declaration statement as in this example. But it had hystorical reasons in C#.
Bun now they brought it into JS with same keyword. Shame on them.
This is simply Microsoft continuing to try to turn JS into C#.
I can't think of any use cases for this outside of the server. Turning JS from a simple client-side web language to a do-anything all-purpose language is a horrible shame.
Even the original argument for using JS on the server always revolved around it being a simple language that lots of people were already familiar with from using on the browser, that argument is undercut when JS is quickly transforming into the most complex and feature-overloaded backend language.
This is really weird feature. Im using JS to make big uploads to some dbs and this is useless by a mile. I need validators or decorators first. Or "optional" typing for check data types, whatever more useful than this lol. BTW im looking for (not rust) another language for the same uses (not golang) with a robust framework like Spring (without a soup of choises)
The whole `[Symbol.asyncDispose]` is too OOP like and not functional. I hope this never lands. It ruins the language.
Who uses normal function this days, arrow functiona are better looking
When I think they can't do anything worse, JavaScript always proves me wrong. Its like the haggis of programming languages. This is going to bite somebody really hard.
Some of the examples are wrong, if the function returning the "async disposable" is itself async, there will have to be two "await" keywords on the same line, like:
await using connection = await getConnection();
What a terrible keyword. Why using, we're not drop or disposable or defer or something like that. Using doesn't imply anything about the resource being marked for death.
It looks strange because they overload the keyword to mean a different thing, maybe it should have been like "awaited_using" or something but introducing keywords is never liked by language devs (with good reason)
If you use "using", you kind of already need to know that something will happen when leaving the scope... the "using" statement is "deferring" to the end of scope so to speak... If you look at it like this, the "async using" feels natural... it's deferring an async operation to the end of the scope in stead of a non-async one.
I converted a small custom vuejs with typescript library from class to defineComponent and the compile time was significantly worse as defineComponent
PHP magic methods all over again. JS-devs really don't like learning from the past of other languages.
Yeah this is why i avoid microsoft programming products, their syntax is always poorly thought out and convoluted.
I agree. Those who like this await are probably people who don't actually understand async, which is far too common in the js world.
this one developer at my company has autism and told me to always use const and never use var. and he said classes are toxic and to always make everything a functional component and use arrow functions for everything... after debugging one of his 50 layer deep arrow functions I switched back to classes
There was a lot of pressure in the committee to use “using async” instead of “await using” but there were issues with the language parser complexity or backwards compatibility or something.
6:46 is the same as just using a callback. I guess the whole point is that you can defer (or await using) many resources in the same scope. So when scope is done, all of them are unloaded at the same time. Am I getting this right?
All this can be done with Promise.all and a bit of structure...
Complaining about await using, as bad way of saying defer
But in rust everyhing is terrible to express, still love it...
Waiting to get defer, oop destructors, free() possibly and maybe like a referencing counting thingy that interacts with all of these features.
Js: python sucks
Also js implementing features python got since it's initial release when js wasn't even an idea
I always thought that when looking at JS, I’m a C# developer, I always wondered why in JS all functions seemed to be defined as lambda functions when they didn’t need to be, as if the writer of the function was showing off, but didn’t understand the when and where the feature they was using was supposed to be used. In-line code becomes unreadable when abused
thats because the JS community has been taken over by people with late stage autism
people assigning an anonymous function to a variable is also a pet peeve of mine.
If you want a named function, use a named function. If you want an anonymous function, use an anonymous function. Don't mix and match.
Just let us define destructors, and force destruction+garbage collection, replacing all references with null 🐴
idk
are they going to make typescript into c#, this is microsoft all over. please kick microsoft out. they are ruining the language
I don't hate it but I'm worried that Typescript is going to take on more of the dumpster fire that is the ever growing monster of C# feature creep.
i agree with you, my eyes are twitching every time i see an arrow function. i think regular function is semantically better. because it says function not const, like why?
JavaScript clearly needs async isomorphic monads
I agree that the syntax is weird. I think that they are trying to prevent nesting in the resource scopes and bind their usefulness to the parent function scope
Your rant at 3.23 was like me practically every day at work. Why?
I hate js so much. Just keep improving wasm so nobody needs js again
So my understanding at 5m is they are implementing defer like Go but worse.
This has been in C# a long time and while it's cool it's a little late to the party in JS
JS is still crap
I think I'm beginning to agree more and more with Crockford about js
im glad im not the only person hates these dumbass arrow functions for normal function declaration
I don't know about you but I don't put a signature on my website because my signature is butt ugly.
python's async context managers look way better
The main diference between ()=>{} and function(){} is that the first can excute in the global scope and access it's variables, when inside a class or an object. The function declaration, runs inside the local scope of the object and canot access the values from where it was called, this comes from vanila JS, in frameworks this does not make a diference, it's only visual.
bro fails to understand a simple concept that has been in C# for ages
I just don’t like JavaScript 3:35
What kind of keyboard switches are you using?
Is it still thenable? They are limiting composability more and more it seems
Wait why do you need to do all this sh*t wont the object get removed when it goes out of scope anyway?
All these gross red functions. Blegh. Just use blue functions.
Sounds like the with keyword in python aka a context manager
"It feels like the most try hard annoying feature of all time" He says as he try hards his text editor