Hello everyone. I'm Sanjay Gupta. I welcome you on Sanjay Gupta Tech School. In this video, I'm going to demonstrate a scenario based on record. Let's understand the record type check scenario that I'm going to implement with the help of record trigger flow. So in this demonstration, I will be explaining how you can apply the record type check. So the scenario is we need to create two record types named as partner case and customer case on case object. Now, after creation of any case record, we need to count like how many partner cases and how many customer cases are related to particular account. And that counting we need to populate into two separate custom fields. Those will be available on the account record. So first of all, I'm going to create two record types, partner case and customer case. So jumping into developer edition org and here in the object manager, we need to search for case object. And here under record type, you can create new record types. So whenever you want to create the part type on case, so you need to create a support process as well because in case of case object, the status pick list is basically controlled with the help of support process. So I'm going to create a support process first. So here you can see the status field pick list values are available new working escalated and closed. So I'm just having all those and clicking on save. So this support process is created. Now, if we go to case object, so we will be able to create the record types on case properly. So I'm just clicking on new. Now here you can see we need to provide the record type label. So, naming it as partner case and support process, then make available for all the profiles, then we need to select the layout. So layout I'm keeping as case layout, then save and new so that you can create one more record type. So this time record type label is customer case record type name is customer case support process. I'm choosing case support process, then available for all the profiles, clicking on next, then case layout, and this time I'm clicking on save. So this way to record types are created on case object. One is customer case and one is partner case. So we need to jump to account object. And we need to create two fields. So I'm going to create first field as of type number. So total partner cases, clicking on next visible to all the profiles. Again, clicking on next available on all the page layouts and clicking on save. So total partner cases field is created. I'm going to create one more field and its label will be total customer cases. Clicking on next visible to all the profiles next and save. So this way to record types and two custom fields are created. Now it's time to jump to flow so that we can create automation so I'm just selecting record trigger flow. Now here we need to select the object as case because on case creation, we need to update the custom fields those are available on the account record. So a record is created and here we need to apply the condition so condition I'm keeping like account ID is null false. So it means if case is related to any account then only we need to run the flow. And from these two options I'm selecting actions and related record, because this flow will be initiated on case creation but it will be updating the account record. So I just clicked on done. Now here I need to apply a report type check so let's first have a decision and inside this decision like we can have a report dot report type. So here you can see we have report type ID option. Okay, so we need to compare this report type ID with particular report type that we created on case, but we cannot manually, or we cannot hardcore the record ID report type ID here because if you deploy this flow from one org to another org so in that case record type ID will be changed. Right, so what we need to do instead of hard coding report type ID, we need to get record type with the help of get record element. So first we need to get partner case record type so here you need to search for record type so report type is basically an object. So whenever you create any report type so report type information will be available with this report type object. Now here you can search for developer name. Developer name is similar to API name for the record types. So now you just need to go to object manager search for case and from report types you can just copy the developer name so if you open. I just need to open the partner case report type. So here you can see this is the record type developer name so I just copied it and I'm pasting it here. Then only the first record and automatically store all the fields that I'm clicking on done. So this way I just got the partner case information. Now I'm just going to use it one more time so that we can have customer case report type as well. So we need to apply the same steps we need to choose a record type object here we need to use the developer name equals. Then this time I need to select customer case and it's developer name. So I'm putting it here. And everything will be same. Now I clicked on done. So this way we have both the record type information. Now I can apply the decision. Check report type. Right. So here. I'm writing partner case. So in case of record type sorry in case of record trigger flow, all the information of a particular record through which that record trigger flow is initiated is available in this dollar record variable. So from here you can just search for record type ID equals and then you can search for this get partner case. So this get partner case record type and then dot ID so it will give you the ID. Right. Then you can have one more outcome. So it will be customer case. And here also you can write report dot report type ID equals. And this time you need to select get customer case record type dot ID. So this way we have applied the record type checks. So we have these two outcomes. So I'm just going to implement the partner case outcome first. So here what I need to do I need to fetch all the cases. And then I will be counting their number and I will be updating the related account. So here I'm going to use get record. So get partner cases object is case. And we are account ID equals dollar record dot account ID. So the account sorry the case record which you created it is related to particular account. Right. So now we are getting all the cases which are related to that particular account. And those information will be available in this get partner cases. And we need to fetch all the records and click on done. Now we need to create a new resource. This is a variable count. So it's data type is number. And the rest of the things I'm keeping as is and here I'm going to use assignment variable. So we need to calculate partner cases count and we need to store that into counter variable. So here we can have equals count and get partner cases. So whatever record whatever number of reports are available in this partner cases. So that will be counted and it will be available in this count variable. Now after this we need to have one update record element because we need to update the related account. So update account. And here we need to choose the second option. Sorry, we need to choose this third option. And here I'm choosing account as an object. Now which account we need to update. So I'm just matching ID equals dollar report dot account ID. So the newly created cases having account ID populated so that account ID matches whichever account record that account we need to update. And here we have these fields like total partner cases and we need to assign count here. So this way the related account will be updated with the latest counting of the partner cases accounts. Now same steps I need to apply here for customer case. Right so I'm just having. Okay what I can do I can just copy this and I can paste it here.  So this is the case object account ID this will be same. Okay one more thing we need to apply. So if we are on partner case so here we need to apply report type check as well. So we are just getting cases so actually what will happen it will fetch all the cases related to that account, but we need to fetch the cases where report type is partner case. So we need to search for report type ID equals and then get partner cases dot report type ID right so this you need to add here and here as well. In this we need to select this customer case and it's record type ID. And rest of the things will remain same. Then I'm copying this assignment element as well, pasting it here. So here we need to calculate customer cases count equals count and get. So here we need to have get customer cases done. And I'm copying this element and pasting it here. So this will be same the thing we need to change is total customer cases.  Right, so this is the flow. Now it's time to save this flow and do a test. So I'm naming it as count cases on account and clicking on save. Now I'm activating this. So if I go to any account. So I'm opening this account record and okay in on this account we already have cases so let me open the account where there is no case so there is zero cases and if I go to details. So here you can see we have total partner cases and total customer cases which is blank right now. Now I'm going to create related cases so I clicked on new. You can see we have this option partner case and customer case apartheid, and it is related to this account. Then I'm putting case or is on status as new and I'm clicking on save. So one partner case is created. And if I go to the details and do a refresh. You can see total partner cases is having a value as one. Now again I'm going to related list, and I'm going to create one more case. So this time I'm creating customer case. Click on save. And let's create one more case as partner case. So now two partner cases and one customer cases available. And if I do a refresh. So you will see the updated values. You can see total partner cases are two and total customer cases are one. So this way you can apply report type check in report trigger flow as per the requirement. So I demonstrated it for case object but in real time scenario, you can apply this report type check for any type of object. And if you remember like whenever you need to apply report type check so you need to first get the report type because you can't hard code report ID because it changes orb to orb, but developer name will be same for all the orgs. So this way, I hope you understood how we can apply report type check and report trigger flow.


Hey everyone, happy Friday, July 23rd ending the week on a nice note plus $2,445 on the day Which puts me at let's see. That's the best I had I had a pretty similar day about a month ago had a $2,000 a couple weeks ago on a Friday, but Actually, it looks like Monday June 14th, so this is the best day I've had since Monday June 14th So nice way to end the week So let's well might as well go over the week and then I'll get to today's trades So for the week Tuesday was a winner plus 665 Wednesday minus 16 35 yesterday scratch Plus 30 and then today 2445 so total P&L for the week plus 1505 And that was pretty much mostly runners had a Little over $1,800 in runners didn't have any pairs trades all week and then just one mighty 90 which is interesting Only 300 and that was minus 324. So that puts us total since the beginning of the year for the mighty 90s 116 pairs trades a little over 4300 runners a little over 3400 total almost 50 almost 50,000 For total day trades year to date and then total going all the way back to the end of August mighty 90s a little over 18 pairs trades almost 5k runners over 62k total 85,000 so That's the that's the week Let's take a look at the individual trades all runners today. No mighty 90s.  It's 579 Let's actually hit six. Okay, there we go. So actually 2345 was the total. Let me go back and fix these 2345 so not so my let so best day since about a month ago Still pretty good So that means the total for the week 1405 Yeah, so okay, so that's right All right, so the those are the trades. Let's go over these trades. I'll show you what we did here I'm starting with AMC so AMC is not one that I trade a lot But it's set up look like a nice trade setup had this initial flush and then the market bounced I got short about right here based on the based on the volume and Looking for it to roll over now. It literally Squeezed me out. It did exactly what I wanted it to Unfortunately, it just it just kept pushing pushing pushing look like it was going to be, you know, breaking out into new highs And so I literally got out about right here and it rolled over and would have given me a winner But ended up taking a loss on that one DK and G was my other loser And DK and G actually was had a nice nice nice profit in there as well Then it pulled back here. I was I was long got long I think in this area here caught this nice win pulled back Added to it looking for another bounce and then this thing just pushed pushed down And so I ended up having to when it broke through in a negative territory I just cut out and took a loss on that one. So net net minus 98 Dollars Disney was a nice winner. Actually, this was a couple different trades in Disney The first one was on this volume spike here pulled back Got long caught this run up there for nice winner and then And then when it pulled back so I was out of it and then when it pulled back to unchange right here I got long again kind of chopped around and then finally pushed up and I got it in my last piece Right there. I know actually with my last piece. I think I got out right here So just about 20 minutes ago. So nice winner in Disney for plus 466 Amazon my biggest winner now part of this is because Amazon is just so big. So my position size Naturally is bigger But had this nice push up had this initial weakness bounced all the way up through the highs pulled back Got long right here caught that bounce. I was out pulled back again got back in and caught that bounce right there So plus 1009 30 on Amazon on that little bouncy bouncy trade Facebook plus 670 Facebook was a monster today. It's up right now. It's up over 6% and so on this so on this initial push up here when it pulled back I got long right here and Held I think I got out of my last piece right here. Obviously. There's a lot more in the tank Of course, we don't know that that's a little bit of hindsight trading but still booked a nice winner in Facebook 670 and then my only other loser was Roblox and This I really like this setup I thought I thought Roblox was really gonna follow through had this really strong push off the bottom When it pulled back here got long looking for an extension and just kind of kept dwindling I added right here at unchanged thinking we might get a bounce there And they just started chopping around and so I ended up cutting out and taking a loss there And then lastly the Nasdaq MNQ. I just did the micros And what I was looking at here is after this initial weakness Nasdaq pushed up pulled back to yesterday's high I got long right here and just held on got out of about half about right in this area Scaled out of some more here, and then I think I scaled out of my last piece around here So nice trade in MNQ for plus $5.79 So plus $2,345 on the day We will be offline on Monday, so we won't be streaming live on Monday We'll be back live on Tuesday everybody have a great weekend and rest of your day. We'll talk to you then


Good morning, it is November 30th today, and I am going to be filming my intro for Vlogmas and preparing for doing Vlogmas. So this morning I premiered a video and in that video I announced that I was going to be doing Vlogmas. Last week I only filmed one self-tape audition and today was supposed to be the callback for that self-tape and I didn't hear anything which means I didn't get it. They were going to be filming the beginning of December, so very likely that I didn't get it because I never heard back. But I am going to be submitting to a bunch of casting calls as usual every morning when I check my email. I submit to a bunch of casting calls and of course I check on my YouTube comments and throughout the day I wait for a self-tape audition request from my agent or voiceover request, whatever my agents have for me. And right now I am also taking an acting class that I love so much. So right now my acting class is Monday through Thursday from 7 p.m. to 10 p.m. So it's every evening and I can share with you guys a little bit about that class and after that class is over I will give you a full review of my thoughts on that acting class and if it was worth the money, the time, all of that. And to be honest, in the winter months specifically between Thanksgiving and New Year's it is so so slow but now with COVID I know that if somebody is able to do any filming, if they're able to get a project done, they're just going to do it.  It's gonna be a lot of acting related things as well as Christmas related things. It's all gonna be blended in a vlog and as well as normal content. So if I do have a video that I want to share with you guys some tips and open casting call, anything new, I will definitely make an actual video and also potentially add some vlogs to there. But I have lots and lots of acting related ideas that I have for it the whole month. And I thought it would also be fun to show you the Christmas decorations that I have up because we've had our Christmas tree up for a while but we just decorated it and I made this beautiful wreath for over our bed as well. So today I need to film the intro. I don't have to do a Vlogmas intro, but I really want to because I love Christmas. Submit to casting calls and get more storage for my camera as well as show you the Christmas decorations that we have up. I don't like the way all of that looks on that side. So I'm going to see if I film in this direction. If it feels less busy. Oh, and no, I absolutely do not fill myself tapes with that. Those lights there, those Christmas lights. I am doing this purely because of Vlogmas and whenever I do get a self-tape audition, I'm absolutely gonna take off those lights. I do like the way that looks better. Hi, my name is Véljica. Hi, my name is Véljica Rodriguez, and I will be reading for the role of Vlogmas 2020. I don't know if that's silly, but I wanted to incorporate acting. I thought it would work. I'll find out when I'm editing if I like it. I can always edit out any Audio that I use and just do everything as if it was B-roll. Also thinking about putting the red paper backdrop here. I like it much better the way it looks here. I have moved the phone, the camera to a Stick, a selfie stick because I'm gonna be filming my Christmas decorations that I have up so far. And I thought I would give you a tour of my Christmas decorations while I film some of this B-roll. So in my room, I have this wreath right here that has little tiny twinkle lights, and it is right above my bed. I wanted to make the decorations in the apartment not only be in the living room. So I thought I would put this above the bed and I absolutely love the way it looks. Let me show you the rest of the decorations in the apartment. So we have some Christmas cards here right when we come in. Our door is there and I thought we could put some of the Christmas cards there because we keep our Christmas cards. And so I wanted to display them. So we put a bunch of Christmas cards on the fridge door so it can be more Christmas-y. And then we have our beautiful Christmas tree that has been up since the beginning of October. But we just decorated a few days ago. So there's our tree and So we have our Christmas tree over here and then we put garland over this Balcony doors, which we've never done before and I put a little Santa over there. And then we also put blue lights in the patio, which aren't Christmas lights. Well, they are technically Christmas lights, but they're blue and it doesn't feel as Christmas-y. So we're actually gonna leave those lights on forever. This garland has lights on it, but they're really bad. They stay on for a couple of hours and then they burn out. This was hidden. I took it out because I want to return them anyways. So we have garland up there and then over here we have this Santa next to a little baby me. But we have some pine cones because around here there are a lot of pine cones.  And of course I baked out the bugs that were in them. So I put them distributed in random places so that it feels more Christmas-y And I'll maybe pick up more or just reorganize them. In general, this year we are way ahead of the game because all of our Christmas decorations are up and Thanksgiving just happened and most importantly, we have our Christmas letters already ready to go. Christmas cards. So we've done our Christmas card a couple of times. I have... Do I have both? Oh, I do have both of ours. So this one is from 2017. We've been dating since 2012. So we could have been doing it since then, but we didn't. And then this one is from 2015. And other than that, we always end up thinking of it a few days before this picture. This year we went to Virginia for Christmas because we flipped one year with his family, one year with my family. And this year we went to Virginia. And those photos were taken December 21st or something like that. But this year, when November started, I said, Hey, let's take our photo. Our photo is super fun. I'm not going to show it yet because none of my family has gotten it. And we have 50 cards that we're going to be sending out. And I don't want to spoil the surprise for them. But I photoshopped some really fun things. It was inspired by one of our favorite movies, one of our favorite Christmas movies. But yeah, those are all of my decorations.  Okay, before I go do that, I am realizing that the reason why I don't have enough storage is something wrong with either my phone or the app. Because when I go into the settings, I'm using open camera app to film all my videos and take photos. And that's not the app that came with my phone. And I am realizing that it says my external SD card still has over 35 gigs of data available or storage available. So instead of buying more storage, I am going to figure out what the settings are, why it's not letting me record. I'm back from running some errands and I picked up the headshots. And when I was ordering the headshots on Costco, it did tell me it was going to be cropped and I thought whatever, it's fine. And this is for my headshots flat lay, which I'm about to go do. And then that's going to be it. I'm going to do two different flat lays for my vlogmas intro. And that's it. I'm going to edit. And then I'll see you guys for the next vlogmas day, vlogmas vlog. But let me show you my headshots. It cut my head off on all three photos. Well, this is a good test run because of course I haven't had to physically give my headshot to anybody since I got these done in July because everything is online. So I'm glad that I had this test run. So when I do ever have to give these in real life, I've print them out far in advance and make sure they're cropped appropriately. But right now I'm going to go to my kitchen and do this flat lay Christmasy flat lay. Christmasy flat lay. I'm so exhausted. I don't know if any of you guys feel this, but I get anxious sometimes from drinking coffee and I was super anxious yesterday when I drank coffee and today I'm exhausted and I just can't drink coffee because I don't want to feel like that. I want to be productive, but at the same time, I'm just like, and this flat lay that I'm going to do is going to be there on my counter again, just like I did the flat lay for the Christmas commercial that I did, the Etsy Christmas commercial. So it's going to be right there again. I just need to clear it off. And throw on my cropped headshots like this. I could not figure out how to lay it out. So it looks Christmasy, but not too crazy. So I'm going to leave it very minimalistic and just do snowflakes and some sparkly snow. And that'll be it. Thank you so much for watching. At the end of every video, I feature another channel. This is today's channel. If you would like to be featured on my next video, make sure you're subscribed, like this video and leave me a comment.


There's no Martin Luther King here, there's no his wife, there's no celebration, there's no joy, there's no excitement, it's just, just ugly. It's, the hands are well done, I mean, fine, and, and, but, but it's, it's just ugly. Where's the celebration? Where's the excitement? Where's the elation? He's just wanted a Nobel Prize. Where's the celebration of, of, of this amazing man's life? I mean, agree with him or disagree with him, an amazing man.  Great, let's celebrate it. Let's have an embrace. You can find the, the photograph of the actual embrace, and you could have made, you could have made an magnificent, this is grotesque. It's monstrous, it's, it's disgusting. Is it art? Maybe, but if it's art, it's offensive and just ugly.


Welcome to another episode of GUI Challenges where I build interfaces my way and then I challenge you to build it your way Because with our creative minds combined We're gonna find multiple ways to solve these interfaces and expand the diversity of our skills and in today's GUI challenge We are building split text animations We're gonna split by letter and we're gonna split by word and what is your cue in that intro? The debugging corner so nice I have each of our examples I made four examples out of this technique today This first one is an animated letter example you can see it's an infinite animation and I just love highlighting this It's so cool. The browser is like, oh, did you highlight text? Let me just scale that highlight with it for you for free and looks really cool We could even go apply that to our animation if we wanted to it's all CSS driven at the end of the day Over here is the same thing split letters But we've made it so that you have to hover on them to interact with them And I like that the hovering on the whole space pushed the entire container of text back But the one that you hover on Comes back to the front and it just makes this really nice like double interaction effects And I just really like I don't know pushing things away is a really cool way to bring something into focus, right down here Is a split word animation, right? We split a paragraph of content into multiple words and now we're animating each of those infinitely with some keyframes And then over here we have another transitional focused split word animation There's a couple of things worth noting though in here I'm going to open up the dev tools go to the rendering tab and I'm going to reduce the motion and Notice the animation stops here, but that's not really the important part So I'm going to reload the page and inspect these elements here and notice it's an H1 with some text in it That's legible content if I go back to red rendering and I set this to no emulation and I reload it They're all spans. So that's not really content. That's sort of Ready for everyone and so I'm kind of gating this Dom manipulation behind a client-side JavaScript check as well as some CSS checks, right? So I'm going to make sure that Animation and motion is okay I'm also going to make sure that the device is capable of hover before I go employ any of these Techniques because look at this one down here. I'm hiding content until you hover So I've put a media query in the CSS that is conditional of hiding these Only if the device can hover so anyway kind of cool You know little notes that I thought were neat in here to keep this sort of readable by default and then we upgrade it into this fun You know whimsical experience only if it speaks if it's okay, so let's go check out the HTML and kind of uncover How a lot of this is working? Okay Well the sections here are just to center the text that's in here and to be scroll snap points But let's check out the HTML now the HTML has these attributes and values We have split by letter and letter animation breathe and the way that these are split up in my project here Is that's the split by is a JavaScript hook that's going to look at all the elements that want to be split by and then you tell the JavaScript how you want it to be split so we have split by letter split by letter These are our two split by letter examples, right? So here's the other letter example here that we're looking at And notice it says letter animation hover and I get a hover animation on each letter So that's all coming from CSS the letter animation is the CSS hook and you tell it What kind do you want and the JavaScript hook is how do you want it to be split and here's split by word Split by word if I come down here any of the ones that are split by word. So in JavaScript, yes, we're gonna start with JavaScript today I have in my index.js file imported two functions that I've created here in splitting.js This is just a little exported functions area I'm looking to see if the motion preference is set to true or false via JavaScript here We've talked about this and then if motion is okay I'm gonna go ahead and find all those split targets by looking at the presence of that attribute is there Do they want to be split by something and if they do we're gonna go through each of those elements Well, let's look at splitting.js first to see what functions are doing in here We have split by letter and split by word split by letter takes text It spreads the text into an array So it's gonna be each letter and it maps each of those letters to a span same thing with by word We're gonna grab we're gonna get past some text or we're gonna split it on space That's gonna give us an array of words and then we're gonna map each word to a span All right. Well, what does span do span takes a text String and an index it's gonna create a span element Put the text in the text area and it's gonna set the property based on that index so that we can use that to stagger And score return the node and we're pretty much ready to go manipulate the DOM Let's go manipulate the DOM for each of these elements that want to be split So for each item that wants to be split, how does it want to be split? We store the type right here We get the attribute split by and we're gonna create a little empty variable for some nodes If the type wants to be split by letter, we call our by letter function We pass it the inner text of this current node and we get back all the letters as spans if it's a word type We're gonna get back a bunch of word spans and if we got some spans back We're gonna go into this current element that we're iterating on go to its first child And we're gonna place it with all the you know all the nodes that we made and we've got words or letters in CSS marked with an index for us to reference and do some cool stuff with okay So let's go check out in the browser what some of that looks like with the dev tools And I think that's just a fun place to show you how these are working Command shift C. I love that hot key find the element that I want. Okay, let's do some inspecting We've got an animation being applied here. Hey, look, it says prefers reduce motion No preference letter animation breathe for each child span. Okay for each of these child spans They're getting this animation called breathe over 1200 milliseconds with a nice easing function Here's that easing function visualized you can change these here in dev tools, too And this is our calculation which does our delay and we're going infinite and alternate. Okay I want to also check this out in the animations panel. This is just a cool tool So if I reload it's gonna find all those keyframe animations I can select it here and grab this play head Look at this and I can drive the animation at the speed that I want and sort of inspect it and look It's even named here. Look, they're called breathe. So these are all the animations that have breathe They're offset all the way down to look the last one plays at about a second and a half Right kind of cool that I can inspect that and here's another animation that's playing down here called trampoline I think that's these ones If I scrub this I should see it. Yeah, there's the trampoline boing boing boing boing I mean, that's kind of why I named it that even though I ended up with an animation It was like much slower. So here I can click this and play it much more floaty like they're sort of really lightweight But okay, anyway, so we're looking at animated letters this is a really cool view and I just like checking it out and Let's let's go look at the CSS for a kind of how I created this. Let's let's go there next And we've done this before right. We've stashed our preference Query into a little custom media variable super cool And here is the letter animation selector. So this is sort of a way I'm doing in post-css It kind of allows me to I know this looks like a custom element selector, but I'm using it down here as an attribute So I'm wrapping it in brackets with nest and it's a little tricky But it allowed me to centralize all this stuff and I liked how it read so I'm basically like in this attribute name space Called letter animation as long as motion is okay find each of those children and set them to display inline block and give them White space break spaces. So this is like that space between animated letters here That's consuming space because of this white space style and we're now gonna look at breathe So how is breathe working? So if the attribute is matching breathe We're gonna set a glow color to white and if it's a custom color scheme or if the user prefers light We're gonna set the glow color to black, but that's kind of besides the point We're looking at each span got that animation called breathe now. This is the same code that we looked at before But let's go look at the keyframes. Here's the keyframes for breathe We are going from animation timing function ease out Did you know that you can change your animation timing functions in keyframes? Totally, and I think it made for a really nice breathing effect. That's very natural looking Alright, so then we're going to so we're going from pretty much all the default positions and default transitions and Opacities and all that sort of stuff and we're going to somewhere interesting And if we remember our animation was alternating, so we're gonna kind of bounce back and forth between these We're gonna go to scale 1.25. So that's like up 25 percent. We're gonna go translate wise negative five pixels That's like moving up just a little bit as it's scaling up and that's what gives us sort of this like stationary looking scale I don't know. I thought it looked really cool and then perspective one pixel is so that those text animations don't jiggle There's this kind of issue where if the text isn't in a very specific and custom perspective It can shift in between them. I don't know how to explain it exactly, but this essentially sets it in place Very meticulously and all the browsers go. Oh, well, then I'll just keep this text smooth I also set a text shadow on here and that glow is going in and out So we're growing and shrinking in that in that text shadow and it gives it this glow type of effect And then there's that animation timing function So we can see that in the example here for animated letters We've set some keyframes and then each of these children are using the keyframes, which is a different delay All right, we have one more example I want to go over and that's this hover me letters one if you want to learn more about these go check out the blog post There's always like more explanation and deeper dives into all this stuff in there Okay, so let's look at hover me hover me has this cool effect where like when I go into the element It pushes all of them back and then the one that I hover on comes forward Let's go see how I did that in CSS We have a hover so this is hovering on the parent element for each of those children if the hover is happening We're going to scale them down, right? Okay, so that's why when we're hovering on the element itself We target each child and scale them down still applying that perspective trick. It's about down 25 percent then for each child We're going to make sure that transition is available on a transform So if the transform changes we want to interplay it over point three seconds with an easing function We're going to set the cursor to pointer, right? This is for just each child of this animation and we're going to set the wheel change to transform and that's again So we're just like making sure that this is ready to shift through user interaction and sort of like keep that in memory browser Don't make it as like high-quality is normal rendered text We're going to be animating this so be prepared and then it says here if we're hovering on a span specifically Then the transform scale of that is up at 1.25 with again the perspective of one So it's kind of cool as we're hovering on the parent We set a downscale of on all of them But if one of them is hovered it's scaled up and that whole effect is just contained right here in this little nesting selector And it gives us just this really cool effect. I thought this turned out really nice So I hope you enjoyed this episode of gooey challenges There was a lot of like potential here And I hope you're just sort of seeing that this is a Kickstarter into something much more Dramatic that you could do there's like so much potential and tell me how you enhance it What are the sort of splitting JS functions? Do you want to write? Tell me I'm interested and I look forward to all your comments. Take it easy y'all. See ya


What's up everybody, Jason here for jazzybiscasebrakes.com.  It is Ranham Team's number one, where we're giving away $874 leaf spot giveaway. So there's a random hip break on our website here, guys. You can buy a spot straight up, brand new, four spots guaranteed to hit, 2020 Leaf Best of Multisport Premium Edition. I mean, I don't know if you can see this guys, but Chase, some very legendary cards right there. Little Mickey Man of 52, an 86 Fleer Jordan PSA8, a Jeter 9.5, Brady, Fintenders, and then you have a Mike Trout 2011 Topps update. So pretty, pretty nice hits in here, guys. And again, it's almost a $900 spot, so you can win one spot for a fraction of the price of $32 here with this one pack. We're probably gonna do at least one more, guys, but this is break number one, and the way it works, guys, is first we'll do the break. Excuse me. Randomize only the customer names and teams, and distribute the hits out of the fat pack. And at the end of the break, we're only gonna do the customer names. And then customer number one gets the spot in that break here. And then again, we'll have another one posted up as well. So good luck. Let's roll the dice, and we got a six and a two, four, eight times. Two, three, four, five, six, seven, and eight. Nancy, down on Nancy. Eight times here. One, two, three, four, five, six, seven, and eight. Thunder down to the heat. All right, so no trades, guys, but let me just quickly go through the teams you guys have.  I'll quickly alphabetize this, let's print it, and let's rip it out. At the end of the break, we'll randomize the customer names here, see who gets spots in the break itself.  There you go, guys. All right, I appreciate it, guys. Now let's see who's gonna win the spot in the break itself. Dice Roller, List, good luck. Roll it, you got ourselves, wow, six and a two as well. You guys can see the timestamp, that's exactly what it is here. We roll the same thing. Six and a two, eight times, good luck. One, two, three, four, five, six, seven, and eighth and final time. Good luck. Jack B, after eight times. Congratulations, Jack. You just got a spot on that leaf, random hit, or you're guaranteed to hit as well. Another one of these pack breaks should be posted soon. If not, I'll post it up right now, guys. And again, we'll get another one of these rolling. JacksB'scasebricks.com.


Hello everyone and welcome back yet again to another crust of rust this time. I wanted to tackle Functions and closures and the function traits and function pointers because Sort of like the situation is with strings in rust There are a lot of different Function things or function like things and the distinction is not always clear and I feel like It would be useful to just sort of get a survey of the scene What we're going to talk about today is like Not necessarily a Super large area. We might be able to cover it in as little as an hour. I don't know But but I do think it's useful to have some information about the distinction between these different types and traits and how they interact Just because you're gonna come across them a lot like especially things like being generic over functions is I Think something you run into a lot in the rust world where you want to sort of have these nice Like callback functions or you want to be able to write things in a slightly functional style And then function pointers just come up everywhere And so I wanted to to make sure that everyone sort of understands that fairly Versatile primitive in rust Before I start I do want to say that I wrote a book it is called rust for stations It is the it's intended to be basically a follow-up to the original rust book the rust programming language by Stephen Carroll, so this book sort of picks up where that book left off and tries to give An introduction to all of the slightly more intermediate slightly more niche slightly more I Don't quite want to say advanced although maybe that is an appropriate word to it tries to cover more of what you've run into After you know rust the language and you want to know how to use it better for particular use cases And it focuses on things like idiomatic usage But also like how some of the more complex building blocks of the language work and how you can use them effectively The e-book version is now up on no starch press And the print book is like with the printers And I think the goal is like early November for it to actually get printed and shipped from those starch It will be get like distributed by I think Penguin Random House And because it's like global shipping problems it might take a little bit longer to get the book If you buy it through other retailers, but it will be available on like Amazon and stuff already as well and Yeah, it's a lot of what I talked about here is covered in that book to please get the book It's a good way to support me as well if if that's your cup of tea All right now let's get into functions and closures and traits so when we talk about Functions in rust generally what people think about and in fact, let's let's start a new Lib over here or something. Let's start a bin and we're gonna call it We're gonna call it Closure See it doesn't work. I was thinking of closure in the sense of like Feeling yellow like you get closure in something, but it has the same as the types. It doesn't really work. Let's go with call me And what we're gonna do in this is Well, here we have a perfect example, right? So fn main is a function Perhaps unsurprisingly and fn main specifically has a type like if I in let's say I Go bar over here So if I in the main set let equal let X equals bar Okay X now has a type. What is that type? Some of you might say well, it's a function pointer It is in fact not in rust in fact if we try to look at the type of this It sort of looks like it's a function pointer, but it's not actually what this is is a function item Which is subtly different Notice here. I'm not calling bar. I'm just taking the sort of identifier of bar and The type of X here is a function item, which is a zero sized value That is only carried around at compile time that references the unique function bar And in fact if if bar was generic then I wouldn't be allowed to do this Because this does not uniquely identify a function. I would have to do something like I 32 for example So this now specifically names bar differentiated with the type I 32 as T But if I now said X equals bar you 32 Then you'll notice here. I get a mismatched type error and That is because this is not a function pointer, right? The the signature of this function right is that it takes no arguments and return nothing So bar I 32 and bar you 32 are really the same in terms of if you thought of them as a function pointer But that's not what X is here X here is a function item That's uniquely identifies the function bar that takes I 32 as a T if you try to assign that bar That takes you 32 as a T. They're not the same type And if we tried to if I if I skip this and I tried to do something like print line Mam size of X size of I Forget what it's called This is size of Val size of Valia And CD call me and cargo run You'll see that the size of this is zero zero bytes So it doesn't hold a pointer at all because this is just a an identifier that the compiler uses to identify this unique instance of this function now Function items have a coercion defined for them into function pointers though is I can define a function bass That takes a function pointer, which is written like this. Let's I'm gonna make this a little Just give it a better signature and then change bar to match So bass here takes a function pointer. That's what this signifies so here I'm saying I take a function pointer. So an actual like Pointer sized value to any function that has the signature 1u32 in and 1u32 out and I can call bass with bar u32 I Can also call it with bar I 32 in both cases what happens here is that the compiler Coverses the function item type into a function pointer type So that this function can be called So inside of here if I now print size of Val of f and Run this What oh Zero that's fine You'll see that here the the size of the values eight because it's an actual function pointer and that's necessary because These two point functions are distinct from one another right there are two instantiations of bar for different types, which means they have different code, right? They've been optimized separately. They're just they are different Chunks of code that happen to share sort of a generic name But we need to pass the the pointer to the first instruction of one instance of that function When we call bas the first time and a different function pointer the second time around But this does allow us to be generic if you will over which exact function is passed in as long as it has the same signature right and And of course if you passed in something that was the wrong signature like if I did this Right, then now it wouldn't compile because it'll tell me the it expected a function pointer To a function that had the signature you 32 in you 32 out what it found was a function item that has a Different signature that is it's a void function. It takes no arguments and returns no value And crucially here you see it doesn't course here because it doesn't match the required type But what we learn from this is that? Function items and function pointers are different from one another but function items are Coercible into a function pointer and part of the reason we need this coercion is because if I do this If I didn't ever call this right then now Even though I've named the function bar with t instantiated to I 32 the compiler doesn't actually need to Generate the code for that function there. It's no under no obligation to because it's never called however here I'm calling Baz right and so and I'm passing in this course to Computer needs to be able to produce a value that's a pointer to that body and therefore it has to generate the function So that it can get generate that function pointer in the first place Of course if the whole thing get that code eliminated then that won't happen but but in general this forces the compiler to actually have to Generate this function body in general of course you'll do the same here like you're unlikely to just assign it and then leave it But but regardless All right video choppy this time What is going on? Oh It's fine now. Okay, it's fine now. I'll keep going if it's fine now. If it's not fine now, I'll stop What do you think fine not fine? It's really weird that this is happening. I did upgrade OBS. So maybe it's OBS That's very very strange find on twitch, okay so the the takeaway from this right is that a Function item uniquely identifies a particular instance of a function Whereas a function pointer is a pointer to a function with a given signature and you can turn one into the other But not go the other way around and This of course would would then work again All right, so That's function items of function pointers and then we have this thing called closures. So you might have seen Is isn't quacks is like the next Metageneric type I think So this takes an F Where F and let's start out with is Just fn okay, so quacks with bar U32 What does this do? so this also works and What we're saying here is That quacks is a function that is generic over some f where f implements the fn trait And notice that fn with capital F is different from the lowercase fn that we use for a function pointer although the Construction is the same. So if I wanted to say it takes a u32 and returns to u32 I do it in the same way, but one is a trait bound and the other is a function pointer type So this is not a type. This is a trait and Here there are three different traits. So if we go back and look at The list of operations. There's fn fn mute and fn once and the distinction between these is the definition of the trait Specifically fn takes a shared reference to self Fn mute as his name applies takes an exclusive reference to self and Fn once takes an owned reference to self and the implication here as the name implies for fn once You can only call an fn once a single time and at that point You've moved the value of the the function that you wanted to call and you can no longer call it again Fn mute you how you can only call once at a time So you need a mutable reference to it in the first place And if you have one you can call it multiple times, but you can only call it once at a time And this is important for example, if you stick an fn mute in an RC, you wouldn't be able to call it Similarly, if you've given a shared reference to something that's fn mute You also cannot call it. This is also why in general an fn mute If you passed it to multiple threads like through something like rayon Then you couldn't call an fn mute for multiple threads at the same time because it wouldn't be exclusive Fn on the other hand is sort of the equivalent of having a shared reference in that you can call it multiple times And you can call it multiple times at the same time or at least through a shared reference and The reason for this will become clear once we look at what closures are and what they do But let's first think specifically about what this means for function items and function pointers So a function pointer And in fact a function item has no state, right? They are standalone chunks of code and they don't reference anything in any other stack frames, right? They don't reference any memory that's stored outside of themselves There's no lifetime associated with a function pointer or a function item is the other way to think about this And what that means is that they don't really care about self, right? Like for them all self contains is well Nothing really for a function item and for a function pointer self is the pointer to the function But there's no state to really mutate there. There's nothing to move and therefore function pointers and well function items cores to function pointers and function pointers implement all three of these traits So if you have a function pointer, you can pass it to something that takes an fn once You can pass it to something taken fn mute and you can pass it to something that takes an fn The one way to think about these fn traits is that they are sort of a a hierarchy where Anything you can you can almost think of it as Here implement fn once Implement fn for f where f implements fn mute We wouldn't actually ever write this but you you can think about it this way and the reason you can think about it this way And I'll show you in a second It takes no arguments. I am lying. It should be this So If we go back here to Yeah, so as you see in the documentation do since both fn and fn mute are sub traits fn once Any instance of fn or fn mute can be used where fn once is expected So in other words fn implements fn once So start from there and then we can and the reason for this is if it requires if we're given an owned version of self that is So far we've only talked about function pointers, but if we're given an old owned reference or an owned self rather Then we can trivially produce a reference to self. So I can really then do the sort of fn call of Like I can easily translate one to the other Right because if I have something that implements fn and I'm given a self I can just take a reference to it and pass that to the fn and Similarly, I can do the same thing for something like fn mute If I have an fn mute, I'm given a self right, so I'm given ownership of it I can trivially just generate an exclusive reference to it and Similarly Fn mute I can easily implement for fn right, so I'm given a Mutable reference to self well I can just turn that into a shared reference and then call the fn version right because These are sort of strictly more powerful Does that does that make sense like why these end up forming a hierarchy? So anything that implements fn also implements fn mute and fn ones anything that implements fn mute implements fn Once as well, but not fn because you can't if you're given a shared reference you cannot produce an exclusive reference And fn anything that implements fn ones only implements fn ones all right Does that make sense so far? Yeah, I don't know what's going on. I think it's my internet that's being weird So we have this hierarchy and and I think it'll make a little bit more sense why why this Hierarchy is is needed once we start looking at closures because again a function pointer implements all of these because it doesn't actually actually care about the ownership of the function pointer because it's just a pointer to code or you can think of it as a Function pointer implements fn and therefore it also implements fn mute and fn ones but by virtue of the same rules We just talked about And So that's why here when we require an f that implements fn We can easily pass in a bar you 32 because it coerces to a function pointer which implements fn And similarly if I made this fn mute This would still work and if I made an fn once this would still work because function pointers implement all of them In terms of actually calling them though, you'll see that here. Let's say that I wanted to actually call The f that I was given if I have an fn once then I Need to take it by ownership if I did this for example Reference to something that implements fn once then the compiler won't let me call it because fn ones requires ownership of the f It requires that I be able to move the f into the call Which it's telling me it can't do because it's behind an exclusive reference right and now similarly if I Get an fn if I say that it's an fn mute then now all I require is an exclusive reference which I have and therefore I can call it But if I got a shared reference I couldn't call an fn mute because it can't be borrowed as mutable Which is required in order to call an fn mute, but I could if it was fn Right, and so then we've ended up going full circle here All right, so let's now go back to why are these different like we already mentioned how function pointers implement all of these By virtue of implementing fn. So why do we need this distinction? The distinction comes up once you start start talking about closures. So fundamentally a closure is written this way So You've almost certainly used closures if you haven't this may not be the stream for you But basically it takes arguments which are passed in between these And it has some body that returns the contents of those let's say here We can annotate these with the takes an i32 and i32 Right, so this is a closure. This happens to be a non-capturing closure. So in general Closures are named closures because they close over their environment That is they're able to capture things from their environment and generate a unique function If you will that specifically absorbs or uses or references data from the surrounding environment at the time when they're created In this case it doesn't capture anything from the environment It only references its own arguments and therefore this is a non-capturing closure And what's interesting about non-capturing closures is that they are Coercible to function pointers. So I can actually call Baz with f if it had the right signature Which we can make it do So see here Baz takes a function pointer and Closures that do not capture over their environment can be coerced to function pointers They can also be they also implement that the standard sort of function traits, right So they implement fn for example and because they implement fn they also implement fnmute and fn1s and all the way up But if I have a Closure that does capture from the environment. So let's say that I declare a Z which is a Non-copy value, so it's going to be a string new if it's copy I'm going to hand wave a little bit and say that we don't want it to be copied because it makes us Reasoning a more complicated than it needs to be so here I'm going to declare this closure as just consuming Z and You'll notice that now it it no longer can be passed to Baz and if we look at the compiler errors You see that it says closures can only be coerced to fn types if they do not capture any variables And in this case it does capture a variable, right? It captures the Z variable from from its own stack now Let's say that all the closure did was like print line Z Right, so it doesn't actually move Z It just takes a reference to Z But nonetheless it captures over the environment and that means that you cannot represent this closure as just a function pointer Because in order to like this this closure think of it as the compiler generates a sort of anonymous struct for the closure that contains a Fields for everything it captures from its environment because when this closure runs it needs access to that to that information So you can sort of think of this as it generates like a f closure struct That has a Z field which is a string and Crucially right this is an a or if you will scope Which is a reference to the surrounding scope And then you can think of it as it implements fn for f closure and it can do that because if it's given a Shared reference to self then it can still call that closure in the sense of this Implementation is going to be sort of copy paste from closure definition Right, it'll just turn that into self dot Z And that works just fine because this is just a shared reference anyway So you can you can't actually write this code but you can think of this is what the compiler generates and Therefore you see why it needs access to the Z the function pointer Which would just be a pointer to like the start of this code block would not be sufficient It needs the additional state of this Z Does that make sense? so far Okay, so so now let's look at what happens if I make this mutable and I say that this is gonna z dot clear so clear is a Method on string that takes an exclusive reference to self and it clears the string it doesn't deallocate anything but it clears the string So now the f closure that gets generated the sort of state for the closure has an Exclusive reference to a string because that's what it needs to capture in order to call clear Right, it can't capture a shared reference because this requires an exclusive reference and at this point If we now again imagine that it sort of copy paste the the body This clear won't work Right self dot Z dot clear and the reason this isn't going to work is because the Z here Requires an exclusive reference, but all we have is a shared reference to self to the the sort of closure state if you will and so we can't actually get an exclusive reference through through that even though we have one here this ends up being a Shared reference to an exclusive reference to a string which is only Usable as a shared reference to a string And so this won't compile or in other words When you have a closure like this it cannot implement fn it can implement fn mute Right because here we now an exclusive reference to the closure state Which has an exclusive reference to the Z and therefore we end up having an exclusive reference to the string and this works just fine and Again anything that implements fn mute implements fn once and so therefore this would also implement fn once And so so this closure is an example of something that implements Let me comment this out just to avoid the compiler errors for a sec So you'll see that this doesn't course to a function pointer, right anything that captures cannot be It we we try to call quacks with it But it says the closure is fn mute because it mutates the variable Z here Right it expected a closure that implements the fn trait, but this closure only implements fn mute and That is indeed exactly what's going on as we just discussed it cannot implement fn because it needs to mutably borrow for a mitts environment Right if I made this take an fn mute Then I would need to take at least this or I could just change this to be owned right then now This And I don't pass in a shared reference to it so now Now f is just fine to pass to quacks because all it requires is a An fn mute and this closure is fn mute So what then you might ask is okay, what about this fn once well Let's imagine that what we wanted to do in here was actually drop Z So to drop Z we need to have ownership of Z which means that we need to move into the closure Right, so Z gets moved into the closure And that means that you just like obviously cannot call this closure more than once because to call the closure you move Z But if you tried to call the closure again, you would have to move Z again But you can't move Z Z again because it's already been moved or If we expressed it this way like we've been talking about so far This no longer has sort of a lifetime here. It owns the Z string, right? Or you can think of it as it still has scope But there's just no use for that scope if we try to implement fn mute and this tried to call drop self It's not possible for us to drop self here because calling drop requires ownership of self But all we have it as an exclusive reference therefore this won't work We can however implement fn once because fn once is given ownership of self and therefore we can drop self dot Z Sorry, this should have been self dot Z all along So here we are allowed to because we get ownership of the closure state And so this implements fn once but it cannot implement fn mute and it cannot implement fn And you can see this also by if I comment this out again because you can't actually manually implement the fn traits at the moment You'll see here that it says That we can't this call to quacks is not valid because it expected a closure They implement the fn mute trait But this only implements fn once and it implements fn once because it moves the variable Z out of its environment here So that's sort of the the path that we go around here, and you might have seen move closures So you can write the move keyword before the definition definition of a closure closure and what that means is So closure capturing is actually a little complicated Because here the compiler sort of knows that what the closure needs is an owned version of Z It needs to own Z and therefore it it determines that it should move Z into the closure When we called Z dot clear the compiler sort of automatically figures out that all we need is an exclusive reference to Z And therefore it only needs to Move a an exclusive reference into the closure and not all of Z itself And similarly when we had print line of Z it realized that all you need here is a shared reference and therefore it only Moves a shared reference into the closure rather than all of Z And that logic generally does what you want But but it's not perfect and there are some cases where you want to move a value into the closure even though you don't technically need it an example of this could be if The closure you want the closure to be the thing that drops the value that is when the closure exits You want the value to be dropped So currently the way this is this is organized is that Z the string will not be dropped until the end of this scope down here Right at the end of main Because it's not dropped in the closure if I write move here what I'm telling the compiler is move Z Into the closure and so now Z is dropped here We still only needed a shared reference, but we're telling the compiler I want you to move into it here and now because we're moving Z into it we end up in the same state of We actually need to own the Z and so we can only implement fn once we cannot implement fn mute or fn Does that make sense actually? I don't know if Why does this compile? Maybe I lied to you. I think I lied to you. I think the move it'll still apply this heuristic Yeah, you're right the the reasoning for this is actually slightly different which is Well that it is true that you can make a drop-in here But but it's also because if I do this the lifetime of the closure is tied to the To the stack here so so maybe if I if I give a slightly different example So make fn is going to return an impulse Fn once sure why not and it does Z equals string new and then it's gonna return a closure that is gonna Print line Z Right, so here is an example of I want to return a function, right? I'm not going to tell the caller whether it's a closure or not but I'm gonna return something that's callable and it's only callable once and Or in fact, let's say fn I want to return something that's callable and I want it to be callable multiple times which this one is right It's just printing Z over and over the problem is that right now this borrows Z Right and so the closure that's returned sort of has a lifetime that's associated with the The sort of self of this function, right this you can sort of read as Z is like a reference to Z that's moved into here and This reference has some lifetime Right, which means that this closure type really has that same lifetime but if you don't specify a lifetime it assumes that it's static and So here we're promising to give back something static but the closure that we return isn't static because it references this Z and so there You can apply the move to say move Z into the closure and now this closure is fn Because every call to the closure does just References the string that's stored in the closure self contents and that's fine, right? You can have multiple calls that all get a shared reference to the closure state Which gives a shared reference to the string for printing If it would not work if this tried to say Drop Z because it wouldn't implement fn Right because once you've called it once you've now moved out of self And so you cannot call it again And so this is where move is useful now one downside of move is that move means move everything There's no like move like let's say we had X as well This will move both X and Z into the closure And that that is oftentimes what you want right in here. We wanted to return something that was static But that's not always what you want But the way that you work around this is you either don't use move right if you can get away with it Or you use move and if you if there's something you specifically want only to be borrowed you do like Let X to equals reference X and use X to in here Now this this won't work in this case because this makes it no longer static But that's the way that you can move some things by reference and some things by ownership And then there are many ways to express this like sometimes use shadowing if you don't care about the old value You could introduce a new scope So that you don't have to deal with this later Regardless of how you end up doing it. This is the way that you would move some things but borrow other things into the closure Does that code create a new string in static every time make fn is called Yes, so the way we had this if I go back here And remove Z and make this pub. I guess This every time you call make fn. It's gonna allocate a new string And then return a closure that owns that string that was allocated You can't choose per variable which to move or not move move is all or nothing so that's why you end up with a pattern like this for example to Specifically say the thing that I want to move in here the X is actually a reference to the real X So I want to move the reference And of course if you do move something into a Into a closure then now the closure as as we saw up here, right the closures Collectively or the closure owns the string and so It's only when then any call to that closure uses that same string And it's when that closure is eventually dropped like the actual Variable that holds the closure or the allocation that holds the closure when that gets dropped the state structure for For that closure gets dropped and therefore the string also gets dropped All right, so we've now actually talked most of what's Important to grasp about these function types But there are a couple of more things I want to touch on the first of these is around din Fn So din fn So just like with other traits you can also use the fn traits through din to get dynamic dispatch And you specify the full function signature and you just put din in front of it and this works just fine In fact here, I can just call f And similarly if this was a bit din fn mute, I can call it As long as I take this as mute Right, so that works fine. And if it's an fn ones, I can also still call it. So so far so good This was not always the case interestingly it used to be that there was this special fn box trait and the reason for this was that This is a little bit of an anecdote, but it but it is an interesting one I think it used to be that box din fn once And in fact box din fn anything did not implement fn anything So basically it used to be that box din fn did not implement fn and similarly for fn mute and fn ones and The reason for this actually is kind of interesting So let's imagine that we were the people trying to implement this Because I do think this gives a sort of interesting insight Let's imagine that we are the standard library and we want to implement. Let's say fn For a box din fn So we have to implement call. We take no arguments. We return nothing and now the question is what do we put in here? right so Self is a box But we have this challenge here of Like let's say I do self dot zero let's say that's how I get at what's inside the box and I want to do call With no arguments, right? So it seems like this is all I should really need to write sort of dereference the box And then call the thing that's inside The problem is what is the type of self dot zero here? If we were to write this out as a variable, right and Let's let's take fn ones just because it's more clear what's going on So I move out of self dot zero to get at the thing that's inside the box And then I do x dot call What's the type of x the type of x here is din fn once But this type is not sized So how much space does x take up on the stack here? Remember din in general is unsized, right? It's it's not sized And that's why in general for box you always need either a reference Or an exclusive reference or something like a box around it You can't have a freestanding din because it's not sized so the compiler wouldn't know how to range the stack frame for this method call And so it's kind of interesting if you look back sort of historically And this is going to be bright for a second. I'm sorry about that So here in the release announcements for rust 135 You see it was like a big thing that now these traits are implemented for the appropriate box types And previously those is fn box that got to do special compiler magic And as you see here this sentence This was ultimately due to a limitation on the compiler's ability to reason about such implementations Which has since been fixed with the introduction of unsized locals And so someone said why couldn't you take a reference to the box contents? Well, this is why I chose fn once because here to call it. You need an owned self So you can't take a reference to this because if you had a this you couldn't call it because fn once requires ownership of self and So slightly similar issues arise with fn fn mute And then so there is actually an rfc specifically for unsized r values Which is required for this implementation to exist and this rfc the rfc is landed But there's lots of implementation questions and basically the compiler gets to take advantage of this particular feature But it's unstable. So you like you can opt into it on nightly But you can't generally use this on your own code on stable But it is required for this particular thing to work which I thought is like an interesting tidbit And there's all sorts of cool implications of what we could do if we got unsized r values, but but that's neither here nor there So when you have boxed in and then some fn trait that just works now You don't really have to treat it specially like in general din just works But you do have to keep in mind that if you get something like a How am I gonna demonstrate this best So this implements fn, so let's say I here gave a din f din equals So this works just fine, right? I turn f into a dynamically dispatched fn This is sort of like a function pointer except it's allowed to Right, so it has a it has a self Basically it constructs a self for this closure and then uses that as the data pointer of the V of the Dynamic dispatch and the V table just has the call method So that's so fine as far as fine The challenge here, right is let's say that I tried to make this fn mute So now I have a Din fn mute, but all I have is a shared reference to it and therefore I can't actually call it because this Doesn't implement fn mute. This only implements fn because all you have is a shared reference. So when you use Dynamically dispatched function traits You need to make sure that the sort of the wrapper the indirection type the the wide pointer type that you use Allows the kind of access that you actually need in order to call that function, right? So in order to call an fn mute, you need to stick it behind a shared reference In order to call an fn. All you need is a shared reference In order to call an fn once you actually needs a wide pointer type that allows you to take ownership right So, I mean I would have to box new And of course again the same hierarchy applies So if you have a wide pointer type that allows you to take ownership then it will also work with any of the sort of weaker function or Less restrictive function Traits so I can have a box din fn mute because if I can take ownership that I can certainly get an exclusive reference If I can take ownership then I can definitely get a shared reference So these are both fine and will implement the appropriate trait outside of the wide pointer And if you think of something like arc right so standard sync arc standard sync arc will allow you to To stick Unsized things into it, but an arc but by necessity will only give you shared access to the thing that's inside and therefore arc din of fn implements fn, but arc din fn mute still only implements fn Or in fact, then can't implement the trait rather. So here if I say this takes fn Whoo Maybe they haven't implemented this for arc. Maybe they've only implemented for box Interesting so I'm guessing then that this implementation doesn't actually exist for for arc yet if we go back to look at Fn for example you see there's an implementation of fn for box Of f where f f implements fn, but there is no implementation of arc. I wonder why that is That implementation should exist interesting Right and we can use the intuition we've built up so far for why that should be the case an arc supports unsized values, right basically arc can support being a wide pointer and therefore it can hold the din fn and If it can hold the din fn and it's able to give you a shared reference to the closure state Then it should be implemented implement fn because all that requires is being able to get a shared reference to the closure state So this suggests that there's sort of an implementation missing here and it might be because Because of this issue we were looking at about unsized our values. Maybe it's like specialized to box somehow But but that would be an interesting implementation to add That's pretty good. Okay, so about an hour. I think I guessed about right the the last thing I wanted to touch on was Const fn's so What's a good example of this? Let's try to erase some of this stuff Okay, so let's say I define a closure that takes a That just returns zero right, so this closure is a Constant closure you could evaluate this closure at compile time Right, this is sort of equivalent to const fn like make zero that returns a u-size or I guess I 32 is the default, right? These are both the same in the sense that they're both callable at compile time They're basically both const But the question becomes let's say that I want a const fn Foo and I wanted to take an f That's let's say fn once and I want my const fn to be able to call f Well, that's not currently okay Because the compiler doesn't know that f is callable as a const right Because we've just said this is an any any type that implements fn once and we don't know that the implementation of fn once is actually const So there's nothing in stable that you can do about this today But there's a sort of interesting pre rfc discussion that's going on and has been going on for a while about is there a way to say I Want to take I want to be generic over any type that implements this trait But only using things that are const Evaluatable and the syntax I've come up with is this and Let's see if I can opt into this easily. I forget what the actual thing is called I might not be named anywhere that I can easily get at What happens if I run cargo R? Let me just pull this up real quick to see what the But what is the name ah Future get a concentrate impulse So we're gonna add this Here and then we're gonna be rust up overrides at nightly and we're gonna cargo R and see what happens Oh Yeah, there's here There's the second one you need to add which is this one So again, as you can see, this is very experimental. Okay, so So what this signifier means this this cons this this tilde cons is that it doesn't actually mean This f and ones or this f must be consed It doesn't mean that I will only take types that that have a constant implementation of f and ones That's what this would mean, right? This would mean f must have a constant implementation of f n ones It's also not question mark. Like you might think of like question mark sized It's not really question mark cons because it's not saying may or may not be consed Which is what question mark sized means rather what the tilde here signifies is Foo will be consed if f is consed if f is not consed then f n is not consed And we haven't talked too much about consed on stream But the basic premise here is if you have a const f n It's callable at compile time or at runtime like you can call it either of them Which sort of means that it's a const f n is also an f n And what this is saying here is that this const f n is only consed So it's only callable to compile time if its generic parameter is also consed in its implementation of f n ones And so that's why this is like new sigil here because it doesn't really mean the same as the other sigils that we have So that that's that's why I mean this this is not a full rfc yet It hasn't been merged so this is very very experimental as you can see with like the two features We need to opt into But but it is an interesting thing to keep in mind and something you will see going forward as we start seeing more More constification of rust code Foo calling x. Oh, sorry. Yeah, so if foo calls x here Foo, what am I missing? Expected zero arguments. I think this is just rust analyzer being confused because it doesn't know about these features Right, so this runs just fine Why oh because string new is const If I said string from Foo this is not const. Oh a string from const to What is not const? Vec 1 2 3 What is not const? Oh? Sorry, it's fine. Okay, so right. So this is what I was. Yeah, this is what I was getting at Let's let's do a const of n Test foo that's how what I need to do The the problem here right or the reason why I have to do this is because main isn't const So there's no requirement that foo is const So I think this can go back to a string from foo now a string new is const So in main I'm allowed to call foo because I don't require foo to be const I can call it even if it's not const and the closure here So the implementation of fn1s is not const and therefore foo Sort of genericized over this closure is not const, but that's fine for main So if I comment out this for a second You'll see that this runs just fine But in a const fn In a const fn you can only call things that are themselves const So here if I try to run it, you'll see that it complains Expected an fn1s closure found this closure And here you'll see the errors aren't very good and that's because it doesn't the error reporting doesn't know about this const fly yet, but the actual complaint here is that const fn's require that everything they call is also const So this requires that foo when generic over this closure is const But this closure is implementation of fn1s is not const Therefore foo is not const and therefore this call is illegal If on the other hand I use string new here, which is const is maybe not const Interesting That's interesting Does it work if I do this? weird Yeah, I think this is a evidence of this being a very experimental feature But the intention is that if the closure is itself constant or constant Evaluatable which string new is because I believe string new. Yeah string new is a const fn then foo should also be const fn and therefore should be callable from const context Const of const events are stabilized, but This kind of bound is not stabilized and so error reporting doesn't know about this kind of bound And so it doesn't really talk about it in the error message you get it does know about const fn more generally All right, I think that's all I wanted to cover about Functions and closures and the the traits and types that are involved are there questions about any of the stuff that we've talked about so far Like any of the any of the bits that you want me to go over again And I'm sad about the audio issues, but hopefully at least in the video in demand. I'll chop it up a little No, people seem to be happy. You've generally followed Any questions about anything else now that we we ended up with sort of a relatively short stream, which was kind of as expected Anything that I can answer outside of this particular topic Sometimes you end up with complicated lifetime bounds with for our So let's get rid of the const fn stuff for a second Yeah, okay, so an example of this is If I write a F and it takes an f and I want to say that f is a function that Let's imagine that it's a map function. So it's gonna be given a sort of I Don't know. It's gonna be a given a reference to a Stir and it has to return a stir So let's imagine that I I want to write a function like this which maps a string And I want to try to call quacks with a closure that takes x and returns x So far so good, this is not a problem. This this works just as expected But There are cases where this gets a little bit more complicated in particular like remember in bounds you usually Although not always but you usually have to specify Lifetimes what are the lifetimes here? Right whenever something returns like that you can often omit the lifetimes But if we were to try to specify what the lifetimes are here, what are they? Because there's no lifetime here if we tried to fill in the lifetime for this for this trade bound What actually is it? There's no tick a because we can't assign a tick a here what we're really saying is we want f to Sort of reuse the lifetime that it gets in in its output We want to say that it's allowed to reference the same thing that was referenced in its input And this is where you get this special for syntax And what this syntax means this is the actual desugaring of that syntax This you can read as for any lifetime tick a F is implementation of a function from a stir with a stir reference with a lifetime of a to another stir reference with the same lifetime of a So it's not actually that's comp that complicated. It's a way to say that This this needs to hold for any lifetime. This is what the bound should be It's very very rare that you actually need to give a for bound like this It does sometimes happen if you if you have trait bounds that have lifetimes That are not f n's the compiler is pretty good about inferring it for anything that is of Fn type or fn muter effort once it can usually figure this out But once you start having other traits that aren't fn in here you sometimes need to reach for four But but it should be very very rare You Be doing another Q&A session sometime I will but I don't quite know yet I really want to get back to the hazard pointers library So I'm trying to find time for that too How much will I enjoy rust for rustations over 9,000? How do you broadcast both video into your screen at the same time what software using I'm using OBS very happy with OBS If I want to pass a closure to an ASIC function the closure needs to be static, right? How does this kind of closure capture its environment? If you want to pass a closure to an ASIC fn, you can just do so There's nothing Preventing you from taking any fn. It doesn't need to be static. It's more that usually with Usually with futures especially if you want to do something like Tokyo spawn of the future you get back then Tokyo spawn just like thread spawn requires that the argument is like static and If f here is not static then the return future will also not be static, right? If we sort of think of the desugaring of this right, it's fn this to impulse future That's really the desugaring of of this and Imple trait just like async fn automatically captures the lifetime of its inputs So if this input is tied to some lifetime then the output type will also be tied to that same lifetime Which means it will not be static unless the input is static and so that's why you often end up having to add static to Generic types that you pass into async functions. It's not because they're required like if I If I just directly awaited here, then there's no need for the function to be static the future that's returned to be static It only comes up if you try to do something like spawning where the future needs to live longer than the current stack frame You often need to pin it I mean you should very rarely need to pin things manually In general, I wait since I should take care of you All right in that case, I think we're gonna end things there Thanks everyone for watching. I hope you learned something go teach someone else what you learned and I will see you all In a few weeks, I really want to do more Hazard pointers, but I just need to actually find the time to do six hours of coding All right. Bye everyone. Hope you enjoyed it