Good morning everyone. Thank you for being here so early this morning and under the rain. So I have an hour, this is a lot of time, so I suggest that we do it interactive and that you stop me whenever you have questions, things you want to discuss. I know that there are mathematicians and people that might not be biologists, so don't hesitate to make it alive. And if I don't finish, I don't mind, so I can stop whenever time is over. So I'm Anna-Maria Lennon-Giménia as it was said and I work in the Curie Institute. I've been there for now 13 years I think. I have my own lab there and I work at the interface between immunology and cell biology and more lately I also started to actively collaborating with physicists and today I'll tell you a story where there will be essentially cell biology and biophysics. No immunology, except this slide, first slide, just to introduce you the cells I work on. I like them very much, but don't be stressed. There will be no CD, no fax plots, nothing too complicated. So those cells are dendritic cells, they're very important for your immune system to work properly. They are in the peripheral tissue, so those are the tissues that are often exposed to microbial attack, for example the skin or the mucosa, and their role there is to patch all the tissue. And this they do because they have this capacity to engulf very large amount of extracellular material. This is important, we're going to get back to this during the entire talk and they do that because they do macropinocytosis. So macropinocytosis is an act-independent process that allows cells to make giant vesicle above 2 to 300 nanometers and to engulf in these vesicles extracellular material in a non-specific manner. There's no need to engage receptors or something like that. So this is very specific of the immature dendritic cells that patch all tissues, they have a very high macropinocytic capacity. They stay in the tissue because at that stage they don't express CCR7, and CCR7 is a chemokine receptor that drives them to lymph node when they become mature. So when do they become mature? When they find a microbe. When they find something that tells them, hey there's an intruder in the body, so we have to get rid of them. So then they engulf this microbe, whatever it is, a bacterial parasite, a fragment from an infected cells by the virus. And then they up-regulate this molecule, CCR7, and this makes them recognize a gradient of the chemokine CCR21 that drives towards the lymphatic vessel, and then they take the lymphatic vessels and they go to lymph node. When they arrive in lymph node they are mature, we call them mature, that means that now they don't uptake extracellular material anymore. Actually macropinocytosis is completely shut down at that stage and they completely dedicate their function, their time to interact with the T lymphocytes and present whatever fragment of the microbe they have engulfed in the peripheral tissue. And this is the first step of any adaptive immune response. Without this, organisms cannot mount specific immune responses. There are kids that do not have antigen presentation molecules and then they have to live in bubbles, severely immunodepress. So to recapitulate, we have immature dendritic cells that are in the tissue, they do patrolling, and this is thanks to macropinocytosis engulfment of extracellular material. When they mature they find a microbe, they arrive to lymph node, and then they stop engulfing material and they present whatever they have found there to the T lymphocyte and this starts the immune response. So first slide, I think the only immunology will get in the talk. So what am I been doing? As I said, these different stages in the life of dendritic cells have been associated in vivo to different modes of migration. So this is thanks to experiments of intravital microscopy. So people have been able to visualize the dendritic cell when they are in the tissues and when they are either searching for antigen or when they are in the lymph node interacting with T cells. And what they've seen is that when they are patrolling the tissue, they seem to harbor a random like migration behavior. Whereas they become very directional once they find a microbe and they recognize the CCR21 gradient and finally when they are in lymph node they're rather sessile when they are interacting with T cells. So in my lab we've been trying to understand the molecular basis for this distinct migration mode. How can we explain at the molecular scale this large-scale migratory behaviors of the dendritic cell? Is this only about the chemokines and the cues that are present in the tissue or are there some cell-autonomous cell-intrinsic mechanisms that makes the dendritic cell migrate in these different manners? So this has been what we've been working on for now more than 10 years. And the approach we've been undertaking is bottom-up. So ideally we would go in vivo. The problem with in vivo imaging is that it's not resolute enough to see what's going on inside of the cell. So this is why we chose to rather take this approach. So what we do is that we prepare the dendritic cell from the bone marrow of mice and we have mice that are knockout, knocking, etc. as you will see. Then we use microfabricated devices to try to reproduce the environment of the dendritic cells in tissue. For example a key parameter, as you will see later, is confinement. And from this we isolate the specific properties of dendritic cell migration. We unravel the underlying mechanism and finally we go back to the tissue to evaluate the impact of our findings on the physiology of the cells in their natural environment. And this is a device we've been using extensively. As I said, we show that confinement is key for the dendritic cell to move. So basically if you prepare the dendritic cells and you put them on 2D, they don't move at all. Okay. If you come with a roof on top of them or you put them in a confined channel, then they start moving actively. And this is because they reproduce these devices, reproduce the confinement in which they are used to move in vivo. In vivo they move in between cells, in between matrix, in between vessels, etc. But most of the time they don't move, I mean probably never in two dimensions. So using this device, which are channels in which dendritic cells are confined, are made of plastic and one side is just glass and we coat them with whatever we want. The beauty of this device is that it's very simple. We don't need to add extracellular chemokines or things like that that will bias our results. The cells are introduced into the portals and then we time-lapse them. They look like this, little snails that move forward. In this particular movie, the nuclei have been labeled in blue, but we can label whatever we want and do automatic analysis. So it's very quantitative. So we've done quite a lot on these dendritic cells, both the biology, the basic cell biology, also some immunology and some physics. We've also started to collaborate with other people to use it for T-cells and more lately on cancer cells. But today I'll be only talking on dendritic cells. So one of the interesting findings we made is that when the dendritic cells become mature, so they become activated in the tissue, and this we can manage just by treating the cells.  And LPSDC, those are the mature cells, so we just treat them with a little bit of LPS. This is a bacterial compound that mimics the encounter between the dendritic cells and the real bacteria. And one observation we made is that when we do this, the speed of the cells increases. This is intrinsic. These are cells in the microchannel. So they become faster. If we put them in 2D confined by bringing a roof on top of them, we can also observe that they become more persistent. So they move in a more directional manner. So they become faster and more persistent when they get activated. And if we now use the dendritic cells that are made from a mouse that express LIFAC GFP, so this allows us to monitor the dynamic of affecting, what we can observe is that this is associated to different distribution profiles of acting. So this is a little cell race, the first one I'll show in this presentation. As you can see here, if you have good eyes, immature DCs have most of acting at the very front around these giant vesicles. Those are the micropinosomes. I will show them better in the next slide. The mature cells are faster and more directional. However, their acting is not at the front anymore. It's rather towards their back. And you can see it better on those movies. So in mature cells, most of acting at the front around the giant micropinosome. And in mature cells, I'm sorry because there's a lot of light so you cannot see the border of the cell. But no, I think it's the light intrinsic of the projector, but it doesn't matter. And so this structure of acting is rather located towards the back. It's just behind the nucleus and it's made of, it's cortical. It's made of acting bundles. So I will make a long story short. This was published, the reference is somewhere there. I can't see it, sorry. It's there, you see it. Okay. So don't fall asleep. So to make a long story short, what we showed is that this difference in acting distribution corresponds actually to a switch between different acting nucleators. So the mature cell, they make this giant acting coated vesicles thanks to ARP23, which you've heard yesterday, is essential for the generation of branched acting network. And this is needed for micropinocytosis. The, let's say, originality of our finding was that we found that this is absolutely not required for migration. Okay. ARP23 makes micropinocytosis, but if we remove ARP23, we have the cell accelerating. So ARP23 and branched acting are not needed for migration in this system. They're needed for micropinocytosis and they even limit migration, probably because they, they form micropinosomes. That's, we can discuss later. What is used as an acting structure for migration is this very weird structure, which is rather at the back of the cell. And it's nucleated by formins, and in particular by one formin, which is MDA1. And this is used for fast migration. However, it has a negative effect on micropinocytosis. So it seems to be a dialogue between ARP23 and formins in this system, which probably couldn't be competition for monomer. It was shown in other system by, by the group of David Kovar. So importantly, this switch in acting nucleators and this switch in, from slow and random to fast and persistent migration is needed for dendritic cells to efficiently reach lymphatic vessels and lymph nodes. So if we prevent this switch, the cells are not directionally enough in, in while getting into the lymphatic vessels and they're really delayed. It takes them several days to make it to the lymph node. I'm not showing the data for sake of time. So this is needed for the impact, the migration, efficient migration of dendritic cells in vivo. So what I'm, oh yes, I put this slide for physicists that are in this room just to maybe to discuss why ARP23 is not required in this system for migration, whereas it has always been thought to be required. So this comes from the difference between the 2D and the confinement. In 2D cells move using adhesion. And for this, they need to have ARP23 that makes the lamellipodia at the front, okay, and that allows them to generate forces that are parallel to the substrate. In this system, the forces are not there anymore. This is a system of migration which is adhesion independent. And in this system, the forward movement results from a pressure gradient that itself results from some forces that are exerted by the cells perpendicularly to the substrate. And what we think and what our results suggest is that those forces, they're not generated by ARP23, but they are rather generated by this form-independent acting network that I showed you in the previous slide. Okay, so this is a summary of the first part.  When they become mature, ARP23 is down-regulated. There's no more macropinocytosis and the migration becomes faster and more persistent and essentially depends on forming. And this is needed for them to reach the lymphatic vessels and start the immune response. So today, this is published. Today, I will show you a new story which is submitted right now. And this story is on the role of macropinocytosis on sensing of hydraulic pressure, hydraulic resistance. It's completely new. It's one of the first time I presented. So if I'm not clear, please don't hesitate to interrupt me and ask all the questions you want. Okay, before getting into the subject, I need to introduce you to what is barotaxis. Barotaxis is a concept that was proposed some years ago in 2013 by the group of Elimia and Shah at Harvard. So what they found is that these cells, HL60, which is a neutrophil-like cell line, which is a really broad model for migration of non-adhesive cells, they are able to sense hydraulic resistance in the extracellular milieu and to respond by choosing the low-resistant path. So in blue, you have the cell. It's coming through this channel and it's finding a bifurcation. It's a T bifurcation in their microfluidic device. If the device is symmetric, they have 50% of chances to choose the left or the right arm. If you increase pressure hydraulic resistance by changing, increasing the length or diminishing the width of one arm, what you observe is that the cells are biased towards the low-resistant arm. And the extreme situation is this dead end, where one of the channel has been closed. So here hydraulic resistance is infinite. In that case, what they found is that almost all the cells take the low-resistant path. And their conclusion was like these cells, neutrophil, they sense pressure and they prefer to go to pass where hydraulic pressure is rather low. So why do we think that this is important? As I said, in vivo, cells very often are confined. They're confined in tissue and in particular in the interstitial space of tissue when they are in between cells or in between matrix. They're also very often confined in networks of vessels. So for example, in the lymphatic network, this is a picture of the lymphatic networks of the mouth, the ear of the mouse. And you can see that there's very small vessels sometimes, and there are also lots of dead ends. So what suggests that those vessels could display very high pressure. In addition, cells very often move in the liver, in the lung, in the brain, in capillaries. So there, if you look at them in vivo, moving in vivos, there are some intravital imaging movies that show that they are completely confined. They look very similarly to the cells that move in the microchannel. So we think that it's likely that they are places of variable hydraulic resistance in tissue, and that hydraulic resistance is probably a major obstacle that cells have to face while moving from one tissue to another. In addition, there are situations, yes? I understand there is a difference of pressure between the body and the front, but is not this difference of pressure is pushing them, so mechanically pushing them? No, this is not what we are addressing here. No. No, it does not. It does not. No, it does absolutely not. So there's also cases, yes? In a network like that, is there an overall directionality? I mean, it seems kind of random. It's not known, probably. So what has been shown is that there's a gradient of chemokine, even though it has not been characterized in the network itself, because it's very complex to detect gradients of chemokine. And the people that have managed to image cells that are migrating with the lymphatics, what they see is that the cells do three, let's say, three step on a side and two on the other, three, and at the end, they end moving, end up moving toward one side, but it's not clear at all how cells move within such network, because it's very difficult to visualize experimentally. So there's also another situation where it's very clear that hydraulic resistance increase, and this is when you have inflammation and you have an edema. So in that case, the fluid is not flowing out from the tissue and the hydraulic pressure pressure increases. This has been really measured experimentally. And of course, this is important for immune cells to be recruited and to perform their job. So very often, edema and inflammation are associated to sites of infections, and immune cells need to be there. So our hypothesis is the following. This is an HL60 cell that I just showed you that this cell is barotactic. Here it's moving within a channel where the fluid is red and the cell is green. So these cells, as you can see, does not do macropinocytosis. And this is very, very different from a dendritic cell, which is moving within a channel, but it's engulfing at the front extracellular fluid through macropinocytosis. So here comes our hypothesis. Because this cell does not have to push fluid, but rather engulfs fluid and release it at the back, could this cell, because it's micropinocytic, not be sensitive to hydraulic resistance? So because fluid can go through these cells thanks to the macropinocytosis process, maybe these cells that do not sense, does not feel the hydraulic resistance of the milieu. And this, what we had in mind, is that could help them exploring dead ends. So exploring places where other cells that are sensitive to pressure cannot go, because the resistance is too high, and maybe this could contribute to their capacity to patrol the tissue in search for some microbe or other danger-associated particles. Okay, are we clear on this? Because I think this is the most important hypothesis, so we need to be clear for me to move forward. Okay, no question here. Good. So to address this question, we made our own device. We chose to have Y bifurcation instead of T bifurcations, because we think that we've observed that when dendritic cells move in tissue, in particular in the skin, this is the type of bifurcation they're facing very often. Okay, the Y-shaped bifurcation. We increase pressure in one arm, so either they're symmetric like here, either pressure is increased in one arm by modifying the length or the width. And these are the results of the first experiments we did just to validate the system. So these are HL60 cells. As it was shown, we found that in symmetric devices, both HL60 cells as well as the dendritic cells choose the arms, any either the left or right arms in a random manner. But when pressure increases, now the bias is towards the low resistant arm. Here what is graphed is the bias. So basically in that particular case, what you have is that about when you have a dead end, 80%, 75% to 80% of the cells are choosing the low resistant path. It's less than in the study that was previously published, we think probably because the device is not exactly the same. Yes. These are the mature, yes? No, these are the immature. So the immature cells, no, those are the neutrophil that were previously published to do the barotaxis. But you're right, they are like the mature because they don't do macropinocytosis. We'll get to the mature dendritic cells at the very end of the talk. Those are just immature cells, but they are in a condition when they don't do the macropinocytosis, I will explain you why just after. And in that case, we see that they are barotactic as well. Although maybe they're less able to sense low differences in pressure as compared to the neutrophil. But if they are in front of the dead end, similarly to the neutrophil, you can see that about 75% of the cells are rather choosing the low resistant path. So this is just validation of our system. Now, we're going to now manipulate macropinocytosis in immature dendritic cells to try to address our hypothesis that macropinocytosis renders them insensitive to pressure. Yes. But if they constantly engulf a lot of liquid, it should go out, otherwise it will slow. It does go out. We've shown this in a previous paper. So it does go out about 20 to 30 minutes. It's exposed towards the side of the cell where the nucleus is. So if not the cells would, you know, they need to recycle the membrane. They also need to maintain the volume constant. So they're up taking the fluid and they're releasing it. So exocytosis seems to be associated often to macropinocytosis. These other people have shown this. Whether there are other mechanisms such as channels, aquaporins, it's not excluded. We don't know this at that stage. So the cells. Related to the propulsion, getting rid of the water, you know, because I think mix them back. Yes. I don't think, in our hands, we don't have good experiment to invalidate or validate this hypothesis. What we know is that each time we block macropinocytosis, so there's no more neither uptake, neither secretion of fluid, the cell rather accelerates. So I don't think this is the basic mechanism that is used by these cells to move. However, it could contribute in some particular situation. I cannot exclude this. Sorry. Proteins, getting in by Michael. Proteins to everything gets in. All right. Yes. Proteins gets in. And we've shown that in the process of secreting, some of the protein remain in the cells and reach the late endosomal compartment. So the cells I just showed you that is barotactic and that behaves similarly to the neutrophil is this cell. This is a cell that is in a very small channel section, so small that these cells, although it is an immature cells, it cannot handle macropinocytosis because all the acting in this cell, it's used for migration. It's at the back of the cell. This is life act. It's concentrated at the back and it's used for migration. We now know that this is when the nucleus is very confined, the forces that the cell have to exert to move the nucleus forward are so high that all the acting is dedicated for migration. In general, we always see this competition for acting and for acting binding protein between the front and the back, and which depends on the degree of confinement. So this is the cell that I just show you, which is barotactic. To allow macropinocytosis, we need to increase a little bit the size of the channel. So in that case, we have a channel which allows, which is compatible for acting recruitment at the front, and in that case, macropinocytosis occurs. This probably also is true in vivo. We have some now in vivo imaging that suggests that when the cell is too confined in vivo, it stops doing macropinocytosis. Okay, so I'm going to discuss the results just in the context of these two devices, the symmetric one, or the one where one arm is open and one arm is closed. This is the behavior of the cells that are immature cells that are barotactic in the small channel.  But as I just showed you, those cells, they're biased. About the close to 80% of the cells go to the low-resistant path. If we now increase the section of the channel, and we have cells that do macropinocytosis, the bias is completely lost. Actually now, those dendritic cells are not able to recognize between open and closed arm. Okay, they choose one or the other in a random manner. So this is how they behave the cells that is choosing the open end. And this is how behave the cell that is choosing the dead end. So do you see that the front is very active and that the cell, let me see if I can play this again. Yes. So the cell that choose the open end and the cell that choose the closed end. Very active front and lots of macropinosomes that are being made there. I'll come back later to this for some quantification. So this suggests that maybe our hypothesis that efficient fluid transports through macropinocytosis enabling mature cells to explore the dead end might be true. Okay, but so in the normal cells, when they're doing macropinocytosis, because the channels are large enough, the actin shuffles between the back and the rear. Okay, so it depends at which state you catch it. So this cell does macropinocytosis, but when it's in the open end, it's not active doing, as active doing macropinocytosis. That's less. I will show you that later. Yes, Tom. I just want to connect this with Vivo, because I'm trying to understand when in Vivo you actually have this very bias condition confinement. In my talk, I presented a movie where we were looking at cells that were also going through a highly confined space. And this happened to be cells that were actually going through the endothelium of the cathode. That could be one case. Sort of the effect was the opposite in the sense that the leading part of the cell, I didn't discuss that, but the leading part of the cell actually was gaining surface area. It's exactly the opposite of this. Why is the opposite? Because here you're having the panocytosis in the leading front. But when the cell makes the panocytosis, it also extends the front. Well, so we were measuring the volume of the cell and the surface area of the cell. So what happened was that the cell is migrating and has an essentially constant volume, constant surface area. As it starts to go through the highly confined space through the wall of the endothelium, the volume remains. The surface area, if you wish, of the back of the cell remains quote constant. It gets corrected by the fact that the movie. The front is a massive explosion of numbering, right? And the only way I can interpret that is that you're activating exocytosis, right? You have to bring member. And the total area of the cell also increased dramatic. It's not a bad. No, no, no. It's a pure geometry. If you want to do that, if you decrease the volume, you have to increase the area. No, no, the volume is constant. No, exactly. But because we change the shape, become more narrow, you have to get an area. It's a pure geometry. No, no. This is, and this is an actual, this is not the geometry of it. It's implemented biologically, but it's forced by geometry. There is a dramatic increase of surface area and it's actually addition of membrane going on. If you squeeze it by factor of two, you have a certain factor, like a small increase there. Right, but the problem. I suggest that we leave this discussion for after, but I would be happy to show me this. I can show you some dendritic cells that are also transmigrating, so growing through the basement membrane that could be similar to an endothelium in the gut. And we might see something like this. I think this is different from this. This is, in that case, cells are facing hydraulic resistance. When they go through a membrane or an endothelium, I don't think they necessarily face higher hydraulic resistance, maybe in some cases, but not in all of them. Anyhow, we will come back to the in vivo situation later on. Okay, so to really say that the hypothesis is true, we need, of course, to further manipulate macropinocytosis. And we did it by different means. Here, we inhibit macropinocytosis as much as we can inhibit it. There's no very good inhibitor of macropinocytosis, but here are two of them. We also did two additional one, up to three inhibition and CDC 42. This one is a myeloride. It inhibits NH1. Rotary is not really clear, but it's also inhibiting the ionic exchange. Both are shown to inhibit macropinocytosis. And you can see that they have no effect in the small channels where the macropinocytosis is off. They don't affect the bias. However, they restore barotaxis when cells are treated in the higher channel when macropinocytosis is on. So this is telling that when dendritic cells are doing macropinocytosis, we block macropinocytosis, now they become sensitive to hydraulic resistance again. We also have a mutant. So we've previously shown, reference should be somewhere there, that this protein which is associated to MHC molecules controls the macropinocytic capacity. So macropinocytosis is decreased in dendritic cells that are knockout for this protein in variant chain. It's also named CD74. But I said I shouldn't mention any CD in my talk, so it's no good. And the result is the same than for inhibition. In that case, we restore barotaxis. So the cells become again sensitive to hydraulic resistance when we use the knockout for this protein in the big channels. There's no effect in the small channel once again. So there's a natural way of inhibiting macropinocytosis. I started my talk with this, which is just letting the cells mature. So we treat them with LPS. We know that the macropinosomes, they're gone. And now the cells fully dedicated to migration. So we did the experiments. We treated the cells with LPS. So in that case now we have mature dendritic cells. And as you can see in the big channels, immature dendritic cells, they don't sense pressure. However, mature dendritic cells do sense pressure. And they preferentially choose the low resistance path as do the non-macropinocytic natural fill. We have a mutant that's down-regulation of macropinocytosis in mature cells does not occur as efficiently. This is this mutant, catapsyness. In that case, we do not restore the bias. So if macropinocytosis is not down-regulated in mature dendritic cells, they're not able to sense pressure and to choose the low-resistant path. So altogether, this is showing that when we manipulate macropinocytosis, we systematically find that macropinocytic cells are not sensing hydraulic resistance, whereas non-macropinocytic cells preferentially choose low-resistant path. So it's strongly suggesting that macropinocytosis renders immature dendritic cells insensitive to hydraulic resistance. And I'll come back to the movie. As I said, this cell which is choosing the dead end is very active. This is something we systematically observe. So we wanted to test the hypothesis of whether the increase in hydraulic resistance is up-regulating, is inducing the macropinocytic process itself. And we tested this just by measuring different aspects of different parameters in the cells that were before or after the dead end. So what we found is that when the cell chooses the open end, it doesn't change velocity. So it arrives towards the bifurcation, it chooses the open end, and it is moving at the same speed. However, when it chooses the dead end, it really slows down when it's migrating in the dead end. And this is something that is compatible with what we have previously shown on macropinocytosis. The cells always slow down when they're doing the macropinocytosis. We didn't manage to measure macropinocytosis itself because the cells, when they get there, they have already engulfed a lot of material. So the data were very messy, but we measured the rate of protrusion retraction at the front and the rate of acting accumulation. Our work for many years has shown that most of the time, all the time, macropinocytosis rate is proportional to these two parameters. And we found that when the cells get into the dead ends, they really have a very high rate of protrusion retraction of the entire cell front. And there's a lot of acting that is accumulating there. Interestingly, we also found that very often the cells that will choose the dead end have already a lot of acting at the front, which suggests that maybe the cells that are doing already a lot of macropinocytosis before the choice comes to them are preferentially choosing the dead end as compared to the other cells. Could you say something about the dimensions of your microfluidic channels and the imbibo channels because you show in the microfluidic device that the cell effectively fills up the channel. So it will have to basically remove all the fluid, otherwise it will build up the pressure. Is this the same in vivo? So there's no good pressure measurement in vivo, but we chose our size of the channel based on in vivo experiments of many people, not only us, but many people. In the skin, for example, cells in vivo, they are confined and the size is compatible with these channels. In some vessels as well, small vessels, small capillaries in the skins and also in other tissue, the sizes are also very similar to the one of the channel. They can go very, very low. I mean, they can be less than two micron. But you have the whole range. No, if the liquid passes through the cell, I mean, there's a little bit of liquid that passes through the cell, this is why we don't obtain 100% of cells that go to the low resistant path. But if it's passing completely, of course, then it makes no sense. It does not apply. Confinement is key for this hypothesis. More questions? I'm just a bit confused. Couldn't this be explained just by the resistance of the just physical forces? I'm going to get to this. Exactly. When they reach the dead end, what do they do? So it's variable.  So we haven't quantified that properly. Maybe there would be something interesting. Okay, so I think I've shown so far that macropinocytosis, all experimental evidence suggests that macropinocytosis overcomes barotaxis. And in addition, latest experiment also suggests that macropinocytosis can be increased when hydraulic resistance increase. So of course, for us, the key question, as I said at the very beginning, is that could that influence the behavior of the dendritic cells in the tissue? And in particular, could this help them exploring dead ends? So we did an experiment to provide some answer to this question. I don't think it's definitive, but I think it's rather interesting. So we built a mouse that has half of the dendritic cells that are in one color and do macropinocytosis. And the other half, they're knocked out for this protein in variant chain that I mentioned before, and that reduce their macropinocytic capacity. We put them in the, and then we image by two-photon microscopy the behavior of these cells in the dermis of the ear. So those mice, they're imaged by intravital microscopy in the dermis. So you can see that both cells have cell types have colonized the dermis. And we did not, or we did induce an edema. So what we observe is that in the mouse dermis, in the absence of edema, the two cells behave quite similarly. Even though there is a tendency for the, I'm sorry, the colors are super. There's a problem with the colors. I'm sorry for this. So this is the knockout, the yellow is the knockout cell, and the green is the wild type cell. And what we found is that if we now induce an edema and we calculate the exploration of the space by the two different cell types, we observe that the wild type cells, the here in green, I don't know why they should be red, are better exploring their space. It means that within the length of the movie, the cells are having a better coverage of the tissue than the knockout cells. So we need, we've done many experiments. This is robust. What we haven't been able to measure so far is macropinocytosis at the same time. It's for some technical issue. When we inject the liquid, we have it everywhere and we cannot measure what is getting inside of the cell, which would be really the definitive answer that shows that the less macropinocytic cells are less able to explore the edema. Do you distinguish exploration versus motility? Yes. Because we also measure the speed of the cell and the tendencies that the knockout cells go faster, which is compatible with the fact that they don't do macropinocytosis. We always found that when there's no macropinocytosis cells go faster. So this is not due to motility. Even if those cells go faster, they explore less. Okay. So this is the take-home message of the first part. So I will not have a lot of time to talk about the theory. It doesn't matter. First, macropinocytosis overcomes barotaxis. Second, macropinocytosis is induced by hydraulic pressure. Third, it might facilitate the exploration of space by immature dendritic cells and by macropinocytic cells in general, maybe. Okay. Just a thought. I would like to mention that cancer cells are macropinocytic. You will hear Daphna Borsagi on Friday that will be talking about this. She's not coming. Oh, how sad. Storm. Oh, how sad. And she showed that this really provides them an advantage. She had shown that the advantage is rather, I mean, she has studied it for metabolism because it brings them all the protein they need to produce amino acids and to survive. But what we would like to explore, and we've been discussing actually with her, is whether this could also help them maybe hiding in some places, in some dead ends, with other non-macropinocytic cells can go. So could this modify the migratory behavior of cancer cells in vivo? It's something we would like to address. So finally, I'm going to talk very briefly. I'm sorry, Patrice, I have only 10 to 15 minutes about how barotaxis work. So please let me first tell you why barotaxis and in general, hydraulic resistance as a force, as an obstacle for cells in tissue was not considered so much so far. The reason was that if you measure the cell forces on adhesive patterns, so for cells in 2D, for example, by traction force microscopy, you find forces that are in the kilopascal range. But if you now measure, and this is the work of Eva Palouche, the forces of cells that are confined, and this is the situation where most of cells are in tissue, at least immune cells, which do not use adhesion, but rather friction to move, they're rather in the range of the Pascal. These values are compatible with the differences in hydraulic resistance, which are found in tissues, which are also in the range of the Pascal, whereas these values are not. If cells would exert such forces when they would be in tissue, they wouldn't care about hydraulic resistance, they would still be able to move forward. So we think that the friction forces are compatible with pressure sensing, and this comes back to your question. In that sense, we don't need maybe active mechanism, receptors, signaling pathway, etc. as it was suggested initially in the PNAS Barotaxis paper. Maybe barotaxis is just the result of an opposing force that is exerted towards the cells, and it prevents it from moving forward. And this is the hypothesis we wanted to test, and for this we build a model. The model was made by Raphaël Vauturier and Carleste Blanc-Mercader and Jean-François Joanny, so active gel theory. Don't ask me too much about the model because I will explain you what I understand, but what I don't explain is what I don't understand. So basically, the model cells are considered as a polyastic gel. The motion entails friction forces, and the key parameters are acting input, acting depolymerization, and polymerization, contractility, and of course, permeation. Permeation is what the parameter that was used in the model to mimic the macropinocytosis, so fluid going through the cell. And the outputs are cell direction, bias, cell behavior, acting distribution, and time. So this is a simulated cell in a symmetric bifurcation. This is what we obtain from the model. So the cell is in front of the bifurcation and it's extending the term symmetrically. Then there's a spontaneous polarization of the system, but that occurs at a critical length of the arms, but where the difference between the two arms is very, very low. And I think this is what took me a lot of time to understand. If somebody has a pen, I can explain it the way the physicists explain it to me. Then when this polarization occurs, the acting accumulates in the losing arm and makes it retract, and therefore the cell chooses the opposite direction. So this is just showing that when the arm here in pink retracts, so reduces its sides, whereas the other one keeps increasing, the difference between the length between the two arms is very low. So the idea is that this system self-amplify as a result of the property of the actomyosine network, so maybe if you're showing me a pen, so I couldn't understand this. I was asking Rafael, but why the term extends, maybe one feels a mechanical load, so it extends less, and no. So the two arms extend the same way, but there's a very, so in the ideal system, this pen I would put it and it would never fall. But when I put it, it does fall.  Patricia, am I saying it well? So this is intrinsic of the actomyosine property of the actomyosine system, which leads to this amplification of this very small difference between the length of the two arms towards a black or white response. The arm retracts and it chooses the low-resistant path. And this is the real cell. It's in a symmetric bifurcation. It's behaving very similarly than the other cell. And again, what we see is that when the two arms, one arm retract, the difference between the lengths of the two arms is very, very small. So this difference is amplified by the actomyosine, the contractility of the actomyosine system. And one of the prediction of the model, so all this is in symmetric bifurcation. So this is just explaining why a cell, the cell when it's facing a Y-shaped bifurcation, it's choosing preferentially one path. In that case, it's random. So what happens now with the cell?  So what the model predicts is that the fact that the arm that is in front of the dead ends will retract first, it's because actin accumulates in this arm earlier. And this is what the simulated experiment, so it's not an experiment simulated, the theoretical cell. So you see actin that accumulates slightly before in the arm that is facing the dead end. And these are the experiments that are observed of the dead end tritic cells that choose the low-resistant path. Indeed, we observe that actin accumulates earlier in the losing arm when this one is facing a dead end. Why? What's happened? You don't believe? You have a question? I figure out the spelling. It's okay. It's a losing arm. It's not losing. It's losing. It's losing of losing. Ah, yes. I think the arm is behave. Okay.  It's the losing arm. You're right. Okay. Another prediction is of course the more permeation increases and the less cells, I mean the more cells are biased. And this is predicted by the model and it's also observed in the experiments as I showed at the very beginning. So the model basically reproduces quite well the result and suggests that barotaxis, it's a simple mechanism. It just results from the opposing forces that the fluid is exerting on a cell. It doesn't require, it's something passive. It doesn't require receptor or signaling pathway. So the very last point I'd like to discuss is that as we said, the cells when they become mature, they are down-regulating macropinocytosis. Now they are biased by extracellular pressure. Does this help them finding their way when they're migrating from the tissue to the lymph node? For example, through the lymphatic networks of tissues, as I already shown. So this is the lymphatic network. As I said, it's quite complicated. It's made of dead ends, smaller vessels than others, et cetera. So we had experimental data using this mutant. We had published those data already in 2008, I think. Using this mutant catapsynase knockout that does not down-regulate macropinocytosis after maturation. And we had found that this mutant takes much longer to arrive to lymph nodes. So we thought, okay, maybe this experimental evidence could be explained by the fact that those cells, because they don't, they keep doing macropinocytosis, they're not guided by extracellular pressure. So we did this, this simulation. Now the cells are put into this labyrinth and we look at the path, the length of the path, whether they are macropinocytic or whether they are not. So the cells that are macropinocytic are not barotactic and vice versa. And what you can see that when macropinocytosis is on, the red shows the coverage. They will cover pretty much all the labyrinth. So these cells will be good at patrolling and searching for potential microbe, but they will not be good at finding the exit of the labyrinth. And this, of course, is the opposite when macropinocytosis is off. Now the cells are not good at finding anything in the labyrinth. However, they're very good at finding the exit. So they take the shortest path to find the exit. So we think that this might explain this experimental evidence we had obtained many, 10 years ago and suggest that down-regulation of macropinocytosis in the mature cells guides them to the infant. And this is the conclusion for the model. The model reproduces the role of macropinocytosis in limiting barotaxis, the role of barotaxing in guiding migrating cells. It explains barotaxi as a passive mechanism, no need of receptor or signaling pathway. And it shows that hydraulic resistance might be guiding cells by imposing simply an opposing force to migration. And it in general explains how cells choose a direction through this amplification mechanisms due to the polarization of the actomyosine network. And the take home message is that there are physical property of the microenvironment of moving cells here. We show one example, but many other physical cues that prevent the migration of cells in tissue, and they're not a lot study actually. So the example here of hydraulic resistance, but we show also that some cells, at least immune cells that really need to travel from tissue to tissue, they have developed specific mechanism in that case macropinocytosis to diminish the influence of these bias. And we think that this is what makes them efficient, reaching their final destination and achieving their function as immune sentinel. And with this I'll close the talk. I was exactly 55 minutes. So the person who did most of the experimental work is Elaine Moroche, she's a postdoc in my lab, and Mathieu Morin helps a lot with image analysis. This is a close collaboration with Mathieu Piel and Raphaël Voiturier. Mathieu Piel lab, Raphaël et Attia took care of all the microfluidic device, built all the microfluidic devices, and also helped for some experiments. And together with Raphaël Voiturier and Jean-François Joanny, Carles Blancmerica, there was really the person who took care of all the theoretical parts. And we thank also many people for providing mice and regions. Thank you very much for your attention. Do you think these hydrodynamic effects might also help distribute the cells within the network? Because I was thinking when two cells get close. Yes, yes, they will, they will, they will repel. Yes, it could perfectly explain also some repulsive effects that are observing vivo of cells or of pieces of cells. For example, in the brain there's neurons that can repel. Of course, there are molecules that have been shown to be involved with this, but this doesn't mean that the physics physical parameters do not, do not play your role as well. In the model you presented, so is there a difference between the case where you have this macropinocytosis where acting is in the front, at least spend a lot of time in the front, and the case where you have norm, so basically no permeation in the model and acting is in the back to push yourself. So, I mean, is it, is this kind of distribution of acting present in the model? I think that yes, but I would need to verify, I would need to verify.  So, the front membrane doesn't help forward movement, never. So, this we really explore because it was our hypothesis at the very beginning, and the front of the cell does not allow movement. The movement is always generated by this actomyosine structure at the back. There's flow of myosine to, towards the back. There's this weird, like, stellar, like, star-like structure of acting cables, and this is on which myosin is working. This is what generates the movement, even in the macropinocytic and non-macropinocytic cells, in dendritic cells. But then what you say is, if you have more in the front, you have less. Yes, because then you have the competition between the different actomyosine pool. But the movement at the front is never generated. It decreases movement because the machine is being recruited there. So, in vivo, is there pressure gradient from the tissue to the lymph node? This is a great question I would like to answer, but there's no tool. So, I'm trying to convince physicists to really develop tools to do this. But for now, they don't know how to do it. So, if you take the lymphatic and you do theoretical measurement, yes, there are gradients, I don't know, but there are differences in hydraulic resistance that are supposed to exist. Yes, but experimental data do not are lacking. So, I hope one day we'll be able to do this. Yeah, okay. So, if I understand the model, the cell feels with its own volume completely in the channel, right? And the reason it can't move in a dead-end channel is because it cannot push the fluid in front of itself. And the fluid is not compressible. Yes. So, it's very simple. And then comes the micro-pinocytosis, which engulfs volume and allows. So, if the model is correct, the amount of fluid engulfed by micro-pinocytosis should correspond exactly with the amount displaced during the movement. So, that would allow a quantitative measurement test of the micro-pinocytosis problem, just measuring exactly. You're completely right. We haven't been able to measure this because of an experimental issue, but you're completely right. So, we're setting up a system where the problem is the Y-shaped channel. It's, to measure this, we need to add some fluorescence once the cells are already, just get into the channel. And this cannot be done in the Y-shaped channel. So, what we're going to do, we're trying to do is to have channels where the cells get in and we apply pressure in a dynamic way or in a static way while the cells are already migrating. And this would help us. Why are you going to add fluorescent markers to one of the channels for the problem? To make fluorescent markers? No, we have fluorescent markers, but we cannot add them at the precise time then the cells get into the dead-end arm. And so, what happened? The cells, while it's getting into the, towards the bifurcation, it has already engulfed a lot of material. It's already red and we cannot measure the difference with what it is engulfing when it's running in the closed arm. Also, if you make an elastic dead-end, an elastic one, you should be able to measure the force against which the cell is able to push. If you make, you mean with a soft material? Yes, it's not easy neither. So, we've tried for many years to use the acrylic amide to vary the stiffness of the walls. And it has been a failure. You know why? Because cells, the dendritic cells, they put a little protrusions below and they push the acrylic amide, so then they go below. They don't follow the channel anymore. Now we're trying with soft PDMS, but I've not seen yet some good results, but this is a good point. Like in fluorescent, we just decay this time. If you adjust the time of the speed of the cell, you see exactly how it moves. In fluorescent, but the fluorescent decays this time. And you adjust the rest of the markers, which did a lot of decays. And then you see exactly how it develops. But here what we would like to see is the volume, calculate the volume of that is. Exactly, you know the rest of the decays, the rest of the movement, you can do it. You could use a fluorophore that can be switched on by light. Yes, exactly. Yes, this could be another way to use a fluorophore, yes. No, this is possible. It's all, it's only, it requires some setting up. Nothing is easy in this system. So, more questions here. Yes. Micro-pinocytosis is not always occurring in cancers. It is induced by oncogenics. By chemists, yes. So I wonder, what is the signaling pathway in that itself that will promote a macro-pinocytosis? It's an open question. I keep writing a grant to try to understand this, but I never get it. So I haven't managed to start this. So K-RAS is probably constitutively active, because you need it to make, no, K-RAS is in general involved in dictostilium. It's very well shown in the formation of macro, I mean, RAS. It's, when it gets activated, it forms this circular patches from which the circular ruffles build and close and form the macro-pinosome. Why is this pathway constitutive in dendritic cells is not known? It's not known whether this is, there's some specific physical, biophysical property of the membrane that are associated to this. It's a, it's very understudy process. Last question, Amir, and then we're done. Coffee. I think I'm a little bit confused about this Y chamber experimental system of the cells, because if you have micropinocytosis and you lose the bare taxes, wouldn't the cells just move backwards also? So cells never move backward.  I'm exaggerating. But most of the time, they don't move backward in the microchannel. Why is this? So we explained this in a, in a, in paper we published in 2015. So this is because there's a correlation, very good correlation between speed and persistency through a mechanism that is self-sustained. So the most, the faster the cells go, the most persistent they reach. And this is due to the flow of acting that is transporting the factors that stabilize the cell polarity towards the back. So the faster the cell goes, the faster is the flow and the more polarity factors arrive at the back and the more stable is the polarity of the cell. So it is more persistent. And this is the loop that explains why most of the time the cells, unless they find an obstacle that reverse this, this machinery and these mechanisms, they keep going forward. They don't go back. Most of the time they don't. Actually, when we started looking very carefully in the movies, we found that almost every time when the cells choose direction, because there's some impurity on some little thing in the channels that had them slowing down and stopping before going back. So if you want, I can give you the reference of all that paper.


Thanks, good morning everyone, thanks to be back here with you in awesomely awesome phoenix. Awesomely awesome phoenix. That's good, as we say. Anybody, so what we're going to do today is we're going to continue with where we left off. Kind of give me an idea of what are the big differences between static scoping and dynamic scoping. Symbol table changes, also changes when? Changes, okay, yes. Static scoping resolution of a name is done at compilation time. Dynamic scoping is done at one time. Great, so yeah, so the big difference is, if I give you some code here, say here. If I said, okay, what does this reference to variable C, what does this refer to? What definition, right, doing that resolution? What is this name C at this instance here? What definition does that refer to? So can you tell from this C here? The char C. The char C, right? And you can tell statically, with static scoping, you can tell just by looking at it. The same thing with this variable X here. Right, so what is statically looking at this, what does this X refer to? The internal index. The index, yes, exactly. But at runtime with dynamic scoping, right, we have no guarantees that that actually refers to that X. Right, we can know this statically because we statically create the symbol table as we're going through here. So when we look at this reference X, we look at our symbol table, we say, is X in the current scope? No, X is not in the current scope. Is it in its parent scope? Yes, it's in the global scope X. So I know at compile time that this X refers to this static X. Does that make sense? Okay, so dynamic scoping, right, is this building of the symbol table. So in static scoping, the compiler itself is actually building the symbol table while it's going through in order to resolve names to declarations. Right, so it's doing this resolution at compile time. Whereas with dynamic scoping, as the program is being executed, names are being resolved to declarations. So this is happening while the program is executing. So this symbol table needs to be created and updated at runtime. So the rules for how you look this up are identical. So that's the important thing to keep in mind. The rules of, hey, I need to resolve X. So what do I do? When I'm resolving a name, what scope do I look in first? Current scope, and then what after that? If it's not in that current scope, then where do you look? Does the outer scope global? Not necessarily global, we don't know. The scope above it, right, the parent scope. And then if it's not in there, where do we look? The parent scope. And then we keep doing that. Then we're at the top, we still can't find it. Then what do we say? Error. At the very top, the very top scope is global, right? So we'd say there's a compilation error. The fact is you use a variable that's never declared. So this is exactly what your compilers are doing. The only difference is with dynamic scoping, this is happening at runtime. What this means is that X can actually change depending on how, this means that some variable X can change depending on how a function is called. So here the scopes that we're looking at are actually the call stack scopes. One function calling another function. Those scopes, not the lexical scopes that we can just look at and say, okay, this scope is valid here and here. So this is actually not, we'll talk about it later about why this could be useful or not useful. Any ideas off the top of your head? So why, which one are you used to using? Static. Static scope? Plus you. So why would you care about dynamic scoping? It happens at runtime. It happens at runtime. It does not happen in every language at runtime. So languages get to decide which one they support, right? So this is how your C, the C code, in Java code you can look at and tell exactly what that variable is going to refer to at. You know that beforehand before it runs. So why would this be useful having these things change? It would be easier on your memory. Easier on memory in what sense? Well, I mean, because you don't have to keep referencing a very, like memory accessing a static symbol table every time. You're just able to update as you go. So it's kind of, you're referencing it from a more local perspective. I don't know the words to describe it. I could see that, that being a possibility. So at least it makes compilation simpler, right? Because when you're compiling you don't have to keep track of this symbol table, right? But then you kind of move that complexity into the runtime, or the runtime has to do that. Yeah. Can't with dynamic scope increase you have some extra functionality that it enables so you can, you know, have your variable change. I mean, I can't think of a good example to describe what I'm trying to say. Yeah, so you can kind of think of, these variables could kind of be parameters to your functions in some sense. But they could be functions that maybe you up top, you call a function, what's called a function, what's called another function, right? Which is using some variable. Well, you can't directly pass a variable into that function, a parameter in that function. But if you can define a new variable, for instance, Emacs actually uses dynamic scoping. And this allows you to change variables for the size of the font and the number of characters on a line only in this specific instance. So you can do that by setting these global variables. They kind of be like configuration options. Let's look at an example. We can kind of look at some things. Okay. So we have our program, right? We have the global int x. We have a global bar, a global function foo, a global function baz, global function bar, then we have our function main. So if I asked, using static scoping, what is this going to output? What's the first thing that's going to output? And a new line, right? Testing followed by a new line. So we know it's going to start executing a main. We know this x here statically is going to set this global x to be 10. And then inside this block, this x is testing. So it's going to output testing. And then it's going to call foo. So foo is going to get called. This local c is going to be set to c. Bar is going to be called. This is going to set x to be 100. Baz is going to be called. Then we're printing out x. So what does this x refer to statically in Baz? 100. Statically? How does it refer to this? Not statically. It'll grab the global, right? Yeah. It'll be the global, which was 10. Yeah, exactly. So let's do this statically first. So it should output 10. Then this x is going to reference which variable? The global variable. Set it to 1, 3, 3, 7. Then Baz is going to return. So we're going to be here. R is going to return. So we're going to be here. And now we output the value of x and c. So now it's the value of x. What does this x refer to? The global x, which is 1, 3, 3, 7, the value. C is what? Character c. So we output that. And then we return from foo. Which means we return here. And we're done. So statically, we can know exactly what that's going to refer to. So let's see how this changes when we do this dynamically at runtime. So we got to think, OK, at runtime we're basically going to go through and execute each of these lines. And as we do this, we're going to build up the symbol table. So our symbol table we're going to represent as having a name, some metadata, and some metadata. And we'll have it have the value there. So it's easier to think about. So when I see this declaration of x, what am I going to create in my symbol table? Yeah. So it has the name x. It has an int. And what does the c standard say an uninitialized variable has the value of? Doesn't. Doesn't. We don't know. It could actually be anything. If we try to read from that, it'll be undefined. So let me go to the next one. So is this going to create a declaration in our symbol table? So what's the name? Bar. Bar. And what kind of object is bar? What is bar? It's a function that returns void. And right now, we don't have a definition for bar. All we know is that as the programmers are declaring, hey, there is a function called bar, and it returns void and accepts no parameters. So we get the function foo. Bless you. What? So then what are we going to create in our symbol table? A function which returns void with some definition. Yeah. Exactly. So this one, right, the difference between foo and bar here right now is that we have the definition of the function foo, right? We know it exists online for. So it's just an abstract way of saying, like, hey, this is where this function is. So when we want to call it, we know where it is. Or you can think of this code in here, whatever. It doesn't really matter. The idea is when now, when we see a call to the function foo, we know exactly where to go. Okay. Function baz, same thing. Okay, function baz. We're going to do line, we're going to say that it is a function also that takes turns nothing and it's defined on line nine. Now I'm going to get to this. What am I going to do? Yeah. Go back to bar. Right. I'm going to update the entry here to update it and say, hey, look, the bar is defined on line 13. Right. Here's where the definition of the body of bar is. So you're extending. Extending it. Extending the definition of it. In some sense. Yeah. You could say that. But the important thing is you're not creating a new entry called bar in this single table. Right. We look it up and we say, oh, bar, we've already declared bar. Great. Now let's, now we have the definition there. So if you think, so. Okay. Then we get here into main. So then what are we going to do? Yeah. We have a function called main that returns an integer which I didn't put in there, but I should. Or at least it accepts nothing. So the parameter is void and it's defined on line 17. Right. So now we get here one of the semantics of C. What's the first function that gets executed? Main. Main. So now we know we can start executing it main. Right. So we execute main. So what do we need to do? We see this ID called x. Then what do we need to do? Make a new one. Or is it updating it? Yeah. We do need to update the x, but we first need to ask what is x. Right. So how do we resolve it to some declaration? Right. So how do we resolve this x? Well, we know it's in the symbol table. Yeah. So we're looking at symbol table. Right. We would first look in main scope. Right. Main scope. Main doesn't declare any variables. So I didn't make a scope here for main. What if you gave it a double? X equals some double. We'll see that in a different, in another example. That's a little language. No, it should be fine. We'll see that in a second. So we, so which x does this refer to? The global x, right? This entry here. So we're going to update the value here of x. And we're going to set it to be 10. Right. That's what the semantics of that instruction means. Now when we enter this, when we enter this new block, what are we doing with our symbol table? Are we in the global scope? No, no. We're under main. No, we're under main actually. So there would be another scope, but there's nothing to find there. Right. But here we've entered another scope. And so I'm going to draw this kind of with arrows to show how this, like to separate the symbol table by scopes. Right. So to say that this, so inside, right, this scope, this declaration says, hey, in this scope here, I have a character pointer called x that has the value of testing. And I know that I'm not updating it here because this is a declaration, right? This is saying, hey, we definitely have, I'm declaring that there's a new variable called x. And the type here is a character pointer. And the value is the string testing. So when I get to this line, I try to resolve x. What do I do? Print the most local x. I first need to resolve, right? So I look up x and I say, what does this x refer to? So I first look up in kind of bottom up. Right. Yeah. So in the closest scope versus to the widest scope. Right. So the closest scope is at the bottom here. It's this scope inside this block. We say, OK, I see x. Great. It's a character pointer. And it's the string testing. So it's going to out. So it's going to say, OK, resolve this x to that value here. And so it's going to output the string testing. So then what happens when I go to the next line? We're leaving that scope. So we no longer care about that symbol table. Exactly. That's pointing you somewhere else. This, because of the scoping rules, right? C is block level scoping rules. So as soon as we exit this scope, we know we can totally clean up and get rid of that, that blocks scope. Right. So we're completely gone. We don't care about it, because we know that after that scope, we can't ever refer to this character pointer x. Right. Because that definition of this character pointer x is only valid inside this scope, inside this block. So once we leave, we clean that up and we get rid of that symbol table. Questions on that? That's an important point. I don't know, to me, it doesn't seem like a big deal, but OK. If you don't do it, what would happen? We get all confused. Yeah. Don't do it. If you're going to have this x hanging around, your next declaration of x is going to refer to that x that's defined in this block. But the scope of that block is only these two lines. So there's no way you can refer to that x outside the scope. So it goes away. OK. Then we call foo. So when we get, so we're going to call foo, right? And how do we know which function to call? Because we define the search of both. Yeah, we first look it up in our symbol table, right? Because it was defined above. We search above and we say, OK, foo is a function. It's void. It accepts no parameters. It's on line four. So we start executing in here. Now when we get in here, what have we entered? A new scope. A new scope, right? So we're going to create another scope in our symbol table. And what's going to be inside that scope? What's declared in here? A character named C defined with the character C. Yeah, a character named C that's defined as initially having the character C. Then we call bar. Then what do we do? We first look up bar. Yeah, we first have to look up bar, right? We have to resolve bar because bar is just the name, right? And we all know, I mean, we've maybe done this before. If we try to call x as a function here, we would expect an error, right? Because we'd look up x and we'd say x is an integer, x is not a function. So this is an error, right? Or if we put gobbledygook in here, we try to look that up in the symbol table, right? It's not going to find anything. So it's going to be error. You have an undefined reference to some function. So we see that bar is on line 13. We jump in here. Now that we've entered bar, what are we going to do? Enter a new scope. Enter a new scope. So we're going to create a new entry. What's going to be inside the initial bar of that scope? Oh, that's going to make us update. Oh, wait, no, that's a... We create a new int x to find out. Int x with value 100, right? This decoration here. When we go in Baz, we look at Baz. We say it's Baz in our local scope. Nope. Is it in our parent scope? Nope. Is it in their parent scope? Yes. Yes. So it's a function void on line nine. Great. I'm going to start executing from there. New scope. I do that. I would create a new scope, but it would be empty because there's no declarations here. There's no declarations in Baz, right? It's an update. So now when I try to resolve x, what do I do? Use the global. Use global. Use the global scope. The parent scope, then parent to parent. Yes. Check in my scope. My scope has nothing. So I check in the parent scope. I say, is there a variable named x in my parent scope? Yes. There's a variable x. I'm going to print out what now? 100. 100. So this x, because of the symbol table, is going to reference the declaration of x that's actually in bar. And this is because that we're resolving these symbols dynamically at runtime. So you can maybe try to see if we didn't call bar before calling Baz, then Baz, this x would refer to the variable x. It's the fact that bar declared a variable x, a local variable, that Baz now when it references x, it looks up the symbol table and it says, OK, this is the x. Oh, its value is 100. Great. What do we print out in the static case? 10. You're printing out 100 questions on y. So for static, if there is no local variable x, it defaults to the global x. Not quite. Well, it looks out in scope, what they call lexically or statically. So here we'd say, OK, like this x looks in its local scope. If there's nothing in there, it would look in main scope. Because if there is a declaration of x in main, then the x in this nested scope would still refer to it. But if you had some screwy function that called main, that had an x in there. It doesn't matter at all. It would never check there. Exactly. Yes. Because everything is resolved statically. So it doesn't matter who calls you or what their scope is when they call you. All that matters is statically looking at this. So if it's not in the end, if it's not in the block, it's embedded in. Yes. Exactly. In the nested blocks, right, that it's embedded in. This is why they call it lexical scope, because it's the lexical at the kind of lexical level where you can just look at the blocks, how they are arranged. Where dynamic is happening at runtime. So depending on how, so this x right here, right, depending on how main is called, what other things are calling name, it could refer to some other x rather than the global x. So definitely not here. We're definitely not referring to this global x because that x is up here, and we already see that there's an x defined in our simple table. So when we go here, what is this x going to resolve to? Which x is this going to set the value of? The local one. The one that's currently set to 100, right? It's actually not even our local one. It's actually bar's local variable. The last known. Exactly. So it's going to update that to 1-3-3-7. We're going to exit baz. Baz does not have any variables declared, so we don't need to clean up the scope. We are now in bar. We get to the end here, so then what's going to happen before we return? We get rid of the simple table. Yeah, we get rid of completely the simple table. It goes away. And so now we're here in foo. So now when we print out, so what's this x, what's this first this c going to resolve to? C. C, right? It's going to look up in here in its local scope in the first scope in the simple table. So yeah, this c is going to output the character c. What's this x going to refer to? Ten. Ten. Is this ten in here? It's out in global. So it goes out one. Goes out one. But we look in this, right? We look in this simple table. We say is x in here? Then we go to the parent. We say is x in here? Yeah. Yeah, and then we grab that value. This is actually going to output testing 110 c. So first testing, then this one's going to output 100. And then this one's going to output 10 c. And then when we get past main, we're going to clean up. When we get to the end of main, we're going to, oh, I guess this isn't from me. Now with this one we get to foo. We clean that up. And eventually we continue and everything goes away. So if we were to compile this, is this how c is going to work? Can I make c execute this dynamically with dynamic scope in? By just saying dynamic gcc. Yeah. I don't think so. No. Yes, exactly. This is me. I have to do this. This is a fake program. This program does not exist. But showing, okay, if we were to be able to execute some kind of version of gcc that used dynamic scope in. I'm sure it's out there. Think about that. Isn't that more of a stack of a language rather than an island? Yes. I mean it would have to be like a dynamic version of c. So yeah, it would be the, this is the signix for the language. So if we output this, right? We saw it's going to output testing. And then what's going to output? 100. 100. 10 c. 10 c. No comma. Tricky. No. Print s. So questions on static dynamic scoping. This is how I recommend you do this when you're doing an exam, right? To actually build this simple table as you're tracing through the program. Yeah. So on the computer level, this simple table is represented via the stack, right? Say it again? So in actually during runtime, the way the computer keeps track of the simple table is via the stack. Right? Not necessarily. So it doesn't actually create this data structure. Yeah. It can create exactly. Yeah. It can create it on the heap or whatever. But it just needs this data structure. And it has to have instructions for every time it enters a scope, it creates a new scope on the simple table. And then when it leaves that scope, it pops it off the simple table. So that would be a functionality? Yeah. Well, the compiler would have to ensure that those semantics exist. So it would put in those instructions. But I imagine, depending on what compiler you use, the implementation of this can be different. Yes. Absolutely. Yeah. Why didn't you print testing 110c? Because main did that. Why didn't it print testing? It didn't print. Yeah. It was testing 110c. I mean, it didn't really output it. This is me doing this, right? I didn't actually run this. It does not work. So why would you want to do this? What might it be useful? It seems like we have to do a lot of work, right? We have to add stuff. And the compiler has to add in instructions. So actually, one of the reasons is really kind of related to how we were doing this here. So we're doing this here by going through line by line, right? Stepping through, executing each part of the program, right? I think we talked about the difference between some compiler and an interpreter, right? So this would be interpreting a program line by line, right? Going through. So it's actually, to do this thing statically, right? You have to go through and look everything. You have to resolve all the references, basically, either first or you have to keep track of a separate table of the static scoping rules versus actually the runtime rules. So it turns out that this is building this table. Building the table is a lot easier if you're interpreting it line by line because that's exactly how you look up and call things and you can just do that with here. So if you use dynamic scoping, your implementation of the interpreter becomes a lot easier. Yeah? What about duplicate variables in a function? What do you mean duplicate variables in a function? Can I declare index twice in the same function? Oh, like index twice here in May? It depends on the language, but usually I would say they would throw an error. So you can only have one name in one scope, right? But the important thing is you can have an index here and then inside when you have a new block, a new scope, you can declare another x. And inside that block you can declare another x. You can keep going as long as they're not in the same scope. And so I think the tricky thing would then come into play of what about parameters? What's the scope of parameters versus local variables? I think that's language dependent. Do you mean parameters on functions of the same name? Yes. Like if you had a parameter here called index you could declare a variable, a local variable inside that function scope as index. I believe in C you wouldn't be able to do that because they have essentially the same scope. So it should complain, but that would be interesting to look at. So would this mean then that creating a program with dynamic scoping would actually run is a lot more depending on the programmer being smart about... It seems like it would be hard for the compiler to catch a lot of these errors and would just be depending on the programmer. Absolutely. Yeah, so you can think about we've kind of pointed to it here where we have defined a character pointer, right, x with the same name as an integer x. So if I called inside this scope, if I called baz, now this x in baz is going to refer to this x in the scope here and now I'm going to be... And d means interpret that as an integer. So I think it would actually still work in C because these type systems are terrible. But in the normal language it would say, hey look, a character pointer is not an integer so this is a type error, right? So yeah, you have to be a lot more careful as a programmer that you don't define a variable name that something else down the line is going to use. It also makes... Basically, so here we know even dynamic or static, right? We can see that this x is always going to refer to this x because it's in its local scope, right? So that you don't need to worry about, but you need to worry about things like this when you have... We'll see... Maybe I'll call back to this when we go into the landing calculus. But this x isn't bound to anything in the local scope, in its scope. So yeah, when you use this you're kind of... It's in essence you're kind of saying this is some global x that anybody who calls me could potentially change. So it really kind of messes with the meaning of what a global variable is. But it can give you some flexibility in some sense. So like other programs that they know what variable to use, they can tweak them to their values of whatever they want them to be. So it's kind of this... You do get a little bit more expressivity and customizability, but at the price of... It becomes really hard to reason about these programs. This is why it's pretty much died out and most normal languages are static scoping. You know, there's all kinds of nightmares, right? Yeah, I mean there's a big kind of trade-off between how much power does the programming language give you to do cool things and how much rope does the programming language give you to hang yourself? So oftentimes... And actually what's better can depend on what you're doing. So it could be companies may want it to be harder for you to shoot yourself in the foot, right? So that way kind of everybody's at this one level and maybe it's hard to do really cool crazy stuff. Like if you look at like doing Ruby on Rails and doing all their magic methods and domain specific languages for defining models, like you look at how what that equivalent is like in Java, it's crazy, like crazy verbose, right? So you have this trade-off plus the Java code, you know, type checks and compiles, whereas the Ruby code is all this crazy magic that takes weeks to dig through what's going on if there's ever a problem. So yeah, all kinds of programming and language design is all full of these trade-offs. Yeah? I mean, is dynamic scoping just a better way to manage the memory dripply as the programmer? It really doesn't. It's a way to cut out ambiguity, isn't it? It kind of adds more ambiguity in some sense but you can't tell exactly what this variable who's going to define.  You're still, well you're still using this heap. Yeah. Or you're still essentially using this stack, it could be on a heap, it doesn't really matter. I think memory-wise it's pretty much the same at a high level, like I don't think there's any like huge magnitude difference here. Really, well, it is easier to implement so that's like the one big nice part about it but the downside is the programmer is hard to reason about which you'll see on some examples of midterms and such. Homeworks first. Okay, so when we were going through here and we saw this name, Baz, what did we need to do, right? So we needed to resolve not only this, the name X, right, to know where X was declared, but when we saw a function called like this call to Baz, what did we have to do? You had to go navigate and define Baz. Right, we have to resolve Baz too, right? We need to resolve functions. Are functions, I don't know, are they more complicated than variables? It's a weird question, I guess. Maybe you have hard to answer parameters. Yeah, right, so functions, they're actually, can be very similar, right? And depending on the language, if you use a language that has what they call first class functions, you can treat functions just like regular values. You can pass them into functions. You can have functions that return functions. You can build functions dynamically at runtime. But they do have a little bit more special meaning, right? They have not just the type, but they have the type of their parameters, the type that it returns. They have scope just like, you know, the name here just has scope just like any variable declared. So, when we're going through, we want to be able to ask, to answer the question, how do we resolve, just like we try to resolve ID usages to a specific definition of a variable, how do we resolve function calls to the appropriate function? So, what are some ways from your experience programming? How do you know when you see a function call, how do you know which function is being called? And don't say it because you right click on it and you go, say, go to definition. You search. You search? Maybe one way. Yeah, you can have the prototype, the declaration above, maybe the definition below. But what are you looking for? How do you know that this call, this invocation of a function calls which function definition in C? Let's do C first. The function signature matches. In C, what's a function signature? So, that actually also gets to what function resolution is. Isn't it like the type and parameters? Actually, no, it's just surprising. It surprised me too, in C. Memory address? Memory address? No, we're not. We don't care about memory addresses at this point. This is more higher level concern. Maybe when it was first declared? But how do you know? You see an invocation. We see Baz parentheses. How do we know which function is actually going to be called? If you look in the local and then in the parent. For what? What are we looking for? For that definition. Something that matches up Baz. What's definition? That same Baz. The name. The name, yeah. That's the name. Actually, in C, it's just the name. You can't declare multiple functions that have the same name but different numbers of arguments. The other way you may have been thinking about this before is in function signatures. It's the exact same idea. The idea is I see an invocation of a function. How do I know what definition? When I resolve that reference, I want to know what body is going to be executed. Which function is actually going to be encoded? The other way to think about it is, how do I know if two function definitions are different? It would be if they have two different function signatures. So what if could you use the names plus the return type? Could this be a way to resolve functions? Yeah? It's part of building a signature. But just the names and return types. Only names and return types. I'm saying, can you do it? So you can do it with names, right? Pretty easily. Could you do it with names and return types? You're designing a language, yeah. We have a bunch of different methods with the same return types, so we weren't really able to specify whether it's resolved. Say it again? You can have a bunch of different methods with the same return types, so it doesn't really specify what you're trying to resolve. The name is... Right, the name. So let's say, in this type of a language, so resolving functions is just on the name. So I have a call to a function foo. I look for a function declared in the scoping rules called foo. If I find it, I use that. If I don't find it, I don't use that. But could I use name and return type? Can I define two functions foo, one with a return type of int and one with a return type of a character pointer, and use that to resolve? It would work, but it'd be dangerous. I think it's a bad idea. It would very easily return something that we might not even know. So what about... Yeah, it's dangerous, right? Well, but why is it dangerous? Because it depends on the context in which you call it. Right, so it could depend on the context. Like int x equals foo or double x equals foo. Right, so int versus doubles. Yeah, you could have int x equals foo, double x equals foo. Or a char, an array of characters versus a string. But why is it... Here we're trying to resolve, right? So we're trying to resolve that name to that reference. So what is... It's dangerous because... But does the compiler know unambiguously exactly which one you mean? No reason if you want to... Okay, let's say that you have one function that... They have the same name. Okay, so you have two functions with the same name. One has a return type, and the other one has a return type. A char. Okay. So in your code, you have int x equals... It doesn't... The compiler can't figure out which one it wants. Which one is the right one that you want to call because you can represent a char as an integer or an integer as a char. So it can't really figure out... Or even what happens... What did you say the int? Or do you understand that? It's like a long or something? What happens if you're just casting it as a string? Because that's neither of those. Yeah, what if I'm doing... So can we resolve this foo to one of these two? You can pick one, but do you want your compiler to pick one as a programmer? Not unambiguously. Exactly. Yeah, so in this example, right, it's just the return value is often not enough to actually be able to disambiguate which one. Right? Because it depends on context. It actually gets into really deeply the context. What about this? Do you have to use the return value of functions? No. What if I just call this? Which one of these functions is going to be executed here? Hellify, though. Yeah. Exactly. And they could do something completely different. They just have the same name and the same return, different return values. I feel like that's kind of your fault as a programmer if you're like partially at least, like if you're using the same function names like that. It could be nice, though, right? You could be useful. I mean, you could think of maybe you want a function called like return ID, right? And when you call it, it's going to return, if you call it with an integer, right? It means you want that integer value of that ID. And if you call it with a character pointer, it's because you want the string value of that identifier. It could be useful. And that's actually one of the hard things about programming languages and these program language design. If you've never programmed something in this, it's hard to think of why it would be useful, right? Because you're used to thinking about your programming language and what it does, right? So if I tell you about some cool new useful feature, well, if you've never programmed in that or used it, it's hard for you to appreciate what exactly it is. Yeah. If you did do that, would it look at it just like, you know, get variables in scope and in hard scope sort of deal? How did you do that? I was like, if you actually did that. If you actually did it like this? Yeah, you have to look at the type. It actually gets into the type system. So you have to look at the type of the variable that you're using this return value as and saying like, does this type match, like is the left-hand side type going to be the return value of one of these things? Yeah. And then maybe you could do it unambiguously, right? Like this, it was just these cases. You could probably easily tell between here. But otherwise, if it's anything else, like especially with C, right, as we said, you can like implicitly cast different types of the same type. So you get into all these kind of problems about which one's actually going to be called. So this is actually why in most programming languages the function's signature. Because it depends on context and it depends on how it's used, yeah. In that situation there, could you like make your own type of namespace so you could tell if I want to use this specific one? In that case, you're just giving it a different names, right? Namespaces are just a way to give different names, right? Could you put some sort of implementation saying, okay, I want to use this? Yeah, you could do it like this, right? And then when I use it, I say infu or character foo. Right? Yeah, here you have unique names. And that's all namespaces are, right? If I had like, actually, what's called bar, right? And I had an int. Bless you. What happens if the names are not unique? I thought namespacing did take care of that. It does, but let's do this bad, right? So... Okay, you declare the namespace, right? So yeah, I'm saying that this foo is inside this namespace bar. But when I use it, right, I'm going to use bar colon colon foo, right? Yeah, yeah, yeah. But essentially, you can see here, I'm essentially changing the name, right? The namespace is just a way to give it a different type of name. Fingerprint. I mean, it's the same as this, in essence, right? It's just the difference between global and local and all that kind of stuff. Where is that name valid? Where do you use that name? It allows you to group things together a lot better. Namespaces have a lot of benefits, but the core is about the name, right? Or unambiguously specifying this function. So what's the function resolution strategy in C++ and Java? The arguments and the name, right? Well, I guess so. Actually, this gets an interesting point. Is it the number of arguments? It's the types of arguments. Right? So this gets in a more fine-grained specification about what you can and can't do. The function that has the same function or the same name would character parameters to the function. Right? So the difference is? The parameter types. Right? So one way could be just numbers and say, hey, you can't actually define the same function with the same number of parameters. Right? You could definitely create a language like this. Would it know the difference between, say, one through a day and two through a day? Is there a difference between those two? Like this? Yeah. Yeah, the return type is different. So that would be, yeah. So then you have to think, okay, so it's all about what we use. So do we use the name and the number of parameters, the name, the number of parameters, and the return value, the name, the types of the parameters, the number of parameters, and the return value? Aren't those rules set in the language? Yes. And we're talking about what are those rules, right? Because they're not. They're just design decisions done by the developer of the language, right? So we're trying to study what those are. If we were to add return type onto here, then we actually kind of get into the same problem, right, that we had with just having the return types. Now it actually depends a lot more on context, right, which is actually why most languages return type is not used as part of the signature. So most languages, right, it's not only names, it's names, the number of parameters, and the parameter types. So these kind of rules, these rules about how we resolve function names, right, and what constitutes a function name, we call them function signatures or disambiguation rules, right, if the name is the same. So in C we talked about the signatures are names only. In C++ signatures are names and parameter types, right? So here I'm kind of putting the function name in brackets here so we can see that, like, okay. So the question you kind of have to ask yourself is when I see this invocation of a function, can I unambiguously select a definition of that function? Right, so with a name it's really trivial, you just look up the name. But if we're using names and parameter types and number of parameters, right, then we have to do some additional computation. All right, so we are done. Looks like we have some other people who have this problem. Thank you.