The first phase in Bitcoin is what I would call the discovery phase. This is when people were first introduced to the concept, very technical people were still coming to grips with it, really command line based, so no tutorials really and very little use cases. So the risks for investors were extremely high. If you did VC investment, chances are very high that you got burnt. Even if you just bought Bitcoin, chances are high that you kind of lost them because there was no glacier protocol back then. So the strategy back then would have been to just buy and hold Bitcoin. The infrastructure phase is what we're in still today, I would argue, starting in 2013. And the reason why I picked that year was because that's when ASIC mining chips started being developed for the first time. So specialized mining chips, we saw the advent of these hardware wallets. And then it was also the year where it was clear that Mongkaks needed competition. And I remember in, I think it was like May 2013 at the San Jose conference, there were a lot of newly starting exchanges, Bitcoin exchanges. So to me, that's a good year for infrastructure phase to start. Infrastructure in Bitcoin really means that you work on the protocol stack. You work on debugging the code as much as possible. You work on improving the efficiency. So you work on scaling too. And then you think about how to, in a modular way, how to grow the system. And privacy, obviously, because Bitcoin is all about financial autonomy, censorship resistance. So having that goal of privacy in mind is important. So that's all that happens during the infrastructure phase. One other element that I think is part of that is what I call custody hardening. It's basically where custody systems, custody companies get tested. And when they fail the test, there's others who take the roll over. It's like creative destruction, basically. Exchanges get hacked and then new ones pop up. Also, lots of scam cycles. So as the price goes up, scammers see that there's a lot of money and information imbalance. So they pretend to know things that the investors don't and then, you know, scam them for the money. Infrastructure is also where we saw, we see early invest, sorry, early institutional involvement. So funds coming in and obviously that grows more and more. Like we're seeing the size of the funds that are looking to invest in the space are just massive. It's really impressive to see. But also institutions that get involved to start providing services because they see that there's a lot of money going around and so they want to be part of that ecosystem. So the strategy here would be still, you want to hold Bitcoin, you may want to invest in a basket of, you know, and I do mean a small basket of e-gold currencies that have maybe some complementary value. You can do trading, you can invest in the exchanges, which is also part of the infrastructure and the hardware solutions and so on. And so what I left out here is like the consumer facing startups and such. I don't think they will outperform Bitcoin until the infrastructure phase is really kind of over. So one part of infrastructure phase is that the market is still very immature and you see these beautiful setups in the charts. Like this is Litecoin, for example, last summer. It was $46 the month after it was already doubled in price and that's because the emotions are just very raw. Traders are often inexperienced and so it's not like you're playing chess with a grandmaster. It's more like, you know, everybody's an amateur. So it's a very interesting environment for trading. I wanted to mention mining as well because that's part of Bitcoin infrastructure. So what I did here was I looked at the daily mining revenues expressed in Bitcoin as a percentage of the circulating supply. So right now we have about 16 million Bitcoin in circulation. So what you see in red is the block reward. So that's the subsidy that miners get and that's how new Bitcoins are brought into circulation. And over time that's going to go to zero. And what's beneath that in blue is the transaction fee revenues. So basically what users do is they decide for themselves whether or not a Bitcoin transaction is worth doing and whether or not they want to, you know, pay a certain price for security. So one way that I look at, it's not a perfect analogy, but one way that I look at mining and Bitcoin as a security focused system, it's kind of like a custody bank. It's like a system that holds your funds in custody. And then the question is, well, how much are you willing to pay for the security of that system? And so right now we're talking about 0.7% of the market cap that is being given to miners on an annual basis. And so I think that that might increase a little bit of the mining subsidy declines. But overall, I think that's, you know, it's a pretty viable system. You know, there is no free lunch. So if you want security, somehow you have to pay for it. And so as we see here, there is actually, it makes sense that as more and more value was created or added in the system, the fee that's being charged for securing all that, it should go up as well. Just kind of like from an investment point of view, the mining revenues have gone just really high. We're talking about over $2 billion in revenues. That's not profit, but revenues the past year, that's definitely going to raise, have some potential projections later on. So then the third phase, I would call the deployment phase, which, you know, I think should come around by 2019-2020. That would be the kind of Windows 95 moment for Bitcoin. Wide adoption by institutions, Bitcoin is being used as a collateral asset for lending. Reserve asset as well, it could be held by central banks slowly, it could be held by banks. Mass markets start getting involved. And so this is like the Lightning Network that we're talking about, all these second layer solutions, like that is going to be under the hood when people use Bitcoin for payments, all that stuff. So mass market use. So the strategy here would be, not only are you going to hold Bitcoin, not only do you invest in the infrastructure still, because that's not going to stop in 2019, but you might have some chance to invest in second layer applications specifically, derivatives that are the things that are assets that are derived from cryptocurrencies, like we'll see assets being issued in this cryptocurrency environment. Like basically, we're challenging Wall Street, that's what's happening from a global or kind of like a macro perspective. Blockchain to blockchain trading, because exchanges are going to be more decentralized, we'll have more solutions to do that. Bitcoin e-commerce is going to be a thing, brokerage and banking service providers that is all, I expect all of that to happen in the Bitcoin ecosystem. So shifting gears to some analogies that work for me to like try and understand this market because it is unique, but at the same time there's always some parallels that could be drawn. So when it comes to the way the market is structured and how immature it is, I think it's interesting to look back at the forex market of the 1980s, like I wasn't around, but based on what I read and heard is that really it was a very early stage of that market. Right now it's the biggest market on the planet, but back then it was just the advent of electronic trading. And so if you wanted to buy Danish Kroner or something, then you had to make all kinds of weird phone calls and then the prices could be out of whack and things were not very reliable. So in that sense there might be a comparison there. The caveat is that there's no insurance in this market, there's no clawbacks. If the exchange is bust, there's no bailout for you. So caveat investor I guess you could say. Another analogy that it's often used and kind of obvious, this is the dot com bubble of the 90s where 99% of the startups are probably going to fail, but there is going to be a Google, there is going to be an Amazon eventually. The difference is that right now you can invest in the backbone. You can invest in the protocol backbone. It's as if you could buy shares and TCPIP by just buying bitcoin. So you don't have to have this wide diversification over all these startups and maybe have a domain name portfolio on the side. If you own bitcoin basically you're already, you have a seat on that train. So that's I think an interesting analogy. And of course dot com when it was at its height was totally a lemon market where lots of information, asymmetry, lots of scams, very hard to navigate for retail investors and even for institutions, lots of institutions lost their shirts as well. Another analogy, especially when people ask the inevitable question like isn't the government going to shut it down? It's like well, it's kind of the big torrent of money. So the government tried to shut down bit torrent and they never succeeded. And it's still around right? At some point bit torrent was over 20% of all internet traffic. It might be a little less now but it's still significant. And I remember reading recently that Netflix and all these video streaming services, they actually use bit torrent technology as part of their backbone, which I think is interesting. In terms of the value distribution in the space, like you know, are we going to have like let's say 10 years from now looking at all these cryptocurrencies? Is it going to be like fang where there's going to be five big ones like you know the way now Facebook, Apple and so on? Or is it going to be a duopoly? Is it going to be a monopoly? Is it going to be spread even over like 100? To me it's interesting to look at the top level domain name market to think about how value might be distributed in the cryptocurrency space because top level domain names and that's like .com, .org, .be, .fr, all that. Technically they don't differ from each other. A .ru domain name is technically exactly the same as a .com. But what happened is that early on people started associating .com with slightly better quality. It was slightly more reliable just in the even the subjective perception. And that caused people to be willing to pay just a little bit more. And that attracted entrepreneurs who had a little bit of a longer perspective. You know a scammer always wants to move on so he wants to minimize his overhead. And so it's interesting that the .com is so dominant even though that there's over 100 top level domain names I believe now. But if you look at the actual value in the market over 90% is .com. And it makes sense if you think of it like pizza.com is what it over five million or something if you want to buy it. Pizza.org is going to be like 50 grand or something like that. And so you know when thinking about like the network effects that Trace mentioned all these do add up and they make it so that the Bitcoin ecosystem is associated with I would argue less scams and a higher standard of security. So there's more reliability there. Like it's no coincidence that we have a list of like what seven or eight applications for Bitcoin ETFs. And then where's the rest right? Where's the Dogecoin ETF application? Whereas even the Ethereum ETF application I think there's only one so far and a very low chance of being approved. So the top level domain name market is interesting and there is research that backs this idea that .coms are more reliable. If you look at what percentage of a domain name market is associated with malware for .coms that's .5%. That's better so lower than .org it's better than what is the other one .net and obviously it's better than .ru there's the main names that have up to 50% scams associated with them for example .science ironically so don't ever serve to .science names. So that's basically my argument is that I think that Bitcoin is the .com of the space. Another analogy that works for me is just look at technologies with mass market appeal. So for example the radio there's some more here like electricity, air conditioning, telephone. So all these technologies like how were they adopted? Well they were adopted by people buying it but radios you can just keep producing radios you can't do that with Bitcoin it's finite in supply so that's going to have some effects on the price and so what we see over and over is this s-shaped adoption curve it goes from 0% to 100% adoption and an example is obviously the smartphone 10 years ago hardly anyone had one I'm probably I'm willing to bet that 99% of the audience here has one on on himself tonight. So when you look at the prices of you know of this market any investor that looks at this chart and especially if I actually make it realistic and make it go up to 20,000 would say stay away it's this is a bubble it's gonna you know it's gonna die after this it's unsustainable but if you look at the same chart on a logarithmic scale all of a sudden it looks a lot more orderly and then if you in your mind's eye take this graph and kind of slant it a bit and imagine that's part of that s-shaped adoption curve maybe it makes even more sense right maybe we can look at it this way where you know a million dollar bitcoin is not all that outrageous to to project. A few possible scenarios just kind of like you know it's always interesting to get the discussion going if bitcoin because I do think that fundamentally bitcoin is digital gold that's its first value proposition a reserve asset so bitcoin achieves 20% of the value of the above ground physical gold we're probably talking about an $80,000 bitcoin price there's lots of assets that are stored offshore and the censorship resistance of that is very questionable nowadays right I mean the even the swiss banks are with all the leaks and stuff are more and more vulnerable to scrutiny so it's it's not unthinkable that bitcoin might take that role at some point and then you're talking about $400,000 bitcoin there's also a huge assets you know a collection of assets that are the the low yielding bonds so bonds that basically pay negative interest rates zero or up to 1% which means negative really I mean we have more than 1% inflation even in the strongest fiat currencies so these these assets are losing value every year I think it's about 20 trillion dollars if I remember right so if you then you know calculate that back with that what would that mean if all that money went into bitcoin you're probably talking about a one million dollar bitcoin um and it's interesting also to kind of look at what would that mean for the mining sector right if we keep that same ratio of like a 0.7 percent annual tax for security well then you're talking about a mining sector that would have revenues of between 50 to 500 billion dollars and that seems incredibly high until you realize that maybe what's happening is that you know this is wall street that might be replaced like you know Manhattan and all the other buildings that you can imagine and you know the Federal Reserve and all the other central banks that is being challenged and we're we might be going to a system where energy is being converted into financial security right I mean bitcoin is basically a proof of energy spent and so in order to attack it you have to spend the same amount of energy which is I think incredibly efficient I'm going to skip this one it's just we can definitely go back it's basically my my view of what happened last year which could be interesting but it's it's just the it's just a bit far probably from the people behind so looking forward um well so basically let me just say this like last year to me what happened was that the bitcoin fees went to kind of one dollar uh not actually even the mean bitcoin fee but it was more like people started running into one dollar bitcoin transactions and they kind of freaked out and they were like hey well we thought that bitcoin was this crazy free money that was free to you know send and now all of a sudden I have to pay a dollar um so so basically this chart shows you the dominance of bitcoin it's like how what percentage of the total market share was represented by bitcoin and so early 2017 it was like 90 percent people started freaking out about this one dollar bitcoin transaction um they new investors came in they started buying ether because it's like it had a lot less kind of conflict associated with it and then we had stories about forks coming in bitcoin and forks that were going to threat threaten bitcoin that might split the chain all kinds of scary stories and then we had this political movement of the user activated soft work which also could have led to a chain split and so that's why around the summer bitcoin dominance dropped to a low and then segwit got merged and the optimism increased with the promise of lightning and and then the cme came out with bitcoin futures um all the while people were buying like for example ripple which is a centralized currency which is like nothing to do with crypto but uh people liked the idea that it had you know low transaction fees maybe it wasn't as scary because it wasn't associated with so many cipher punks um ether had some problems which lowered its dominance as well and then basically at the end we saw this massive junk rally right i mean the the the altcoins that were top 10 and lower now below the top 10 they started taking it's like 23 percent of the entire market which is something by the way that usually happens at the end of bull markets so this is something to you know keep in mind like this could alert everyone that people are throwing money at anything that moves so that could mean that there's a lot of weekends in the market so very brief wrapping up looking forward i see more institutional involvement even more lots and lots of stuff is in the pipeline second layer scaling is happening i mean like look on crypto twitter or bitcoin twitter it's just you know lots and lots of examples of how lightning is being used and there's other other things in the pipeline too smart contracts are coming to bitcoin more privacy is coming to bitcoin and then finally i do expect a stress test basically you know it could be a you know kind of a regulatory crackdown which scares people but um i'm kind of thinking it could be more that the the custody infrastructure i think might be challenged because a lot of the infrastructure was built when when the whole ecosystem was maybe five billion dollars and now it's what almost a trillion and so that means that all these exchanges have huge targets on their back they're like huge bug bounties for hackers to try and attack and steal the bitcoins and so because they've been scaling so fast i don't know if they've been able to just as fast upgrade their security protocols so i think it's possible that we'll see some exchange hacks that really surprise people that's it thanks


Before taking your questions, I want to share with you just briefly my reflections on the important events that we've witnessed today. From Moscow, we've learned to the death of President Brezhnev, a man who played a major role in world affairs for more than two decades. Here in the White House, I met with Phil Habib about our plans to help bring peace to the Middle East, where the opportunity for progress has been fundamentally improved by recent developments in that region, and also today the Space Shuttle was successfully launched. Once again, we will expand mankind's opportunities or enriching the human experience through peaceful exploration of the universe.  If there is a lesson for us, it is that we as a free people must always be prepared for change so that when it comes, we are ready to meet new challenges and opportunities. Our system of government is unique and best able to adapt to change and move forward without disruption or break in continuity of purpose. I want to underscore my intention to continue working to improve our relationship with the Soviet Union. Our two nations bear a tremendous responsibility for peace in a dangerous time, a responsibility that we don't take lightly. Earlier this year, we put forth serious and far-reaching proposals to reduce the levels of nuclear and conventional forces. I want to reconfirm that we will continue to pursue every avenue for progress in this effort, but we shouldn't elude ourselves. Peace is a product of strength, not of weakness, of facing reality and not believing in false hopes. Today we honor American veterans, men and women who by their courage and dedication protected our freedom and independence. In the wake of events in the Soviet Union, we remain hopeful for a better relation. Conscious of our national interests and determined to remain a free people, I can think of no better day than Veterans Day to rededicate ourselves to peace and to do those things necessary to maintain the peace and to preserve our freedom. Now, Jim, I believe. Mr. President, who will be leading the U.S. delegation to the International General, if you won't be going, how come? And also, aside from your personal hopes for peace, you have reason to believe that the next coming months might see the new Soviet leadership flexing its muscle a bit and a period of increased tension coming about. Well, answering the last part first, no, I don't anticipate that as they make this transition. We certainly can hope that there won't be anything of the kind. But with regard to these services, we've had no direct official word yet on anything about the service, although we are in communication directly with them. And it was just a plain case of looking at schedules and my own schedule calling for visits here by the head of state next week, and it was felt that it would be better for George to head that delegation, but it will be an appropriate and a very distinguished delegation. So it will be the vice president, it will be heading the delegation? This is what we're considering now, no final decisions have been made because they say we're waiting to hear some word about the services. If there is a period of tension, how would you respond? Well we've had periods of tension before and I think you just, you can't guess that in advance or what the answer would be except that I think we must remember that our goal is and will remain a search for peace and we would try to find the best way to achieve that and incidentally I believe that we can continue that search without my attendance at the services. President, at your last news conference you said it would take a palace coup for you to approve a five-cent a gallon increase in gasoline to build highways and create jobs. Have you changed your mind and I'd like to follow up if I may. Well Helen, I don't think that I said it with reference to that. I said that on a general subject of tax increases as such it would take a palace coup. But on the thing that we're talking about this particular subject is under discussion but it was under discussion a year ago and at that time I asked the Department of Transportation, Drew Lewis, the secretary to hold off certainly for another year because of the economic problems that we face. I don't view this proposal as let's say a job creating program although obviously there would be jobs created by going forward with that effort but what we're talking about here is also and we have used the term to try and make people understand what it would be that if we do it, it would be a user fee. It would be dedicated to the rebuilding of our highways and bridges. This is a problem that must be met sooner or later. I wish the economy were such that we didn't have to worry about it at all but it is still under discussion, no decision has been made and if it is put into effect it isn't anything that would in any way reduce the incentive features of our tax cuts because the average individual's tax would only for that purpose would only go up about $30 a year. That's like you're leaning toward it and while I'm on the subject with 11 million people out of work, would you be willing to have some cutbacks in defense spending to help these people who are out of work? Well Helen, we're doing a number of things to help the people that are out of work. It is true that there are other voices that are being raised in the Congress who are suggesting that the answer is to go back to things that have been tried before in previous recessions, namely make work job programs with the government taking billions of dollars out of the private sector to spend on these projects and no one has ever noticed or looked to see how many people might have lost employment over here because of the transfer of funds to those government projects. The truth is that over a seven-year period which includes 1981, a year in which that budget was not ours, we inherited that, but through 1981 the government has spent $66 billion on the kind of job programs that some of them are talking about now on the Hill and that $66 billion got us nothing but an increase in unemployment. It did not resolve the problem. We can't resolve the problem and really do what is right for the unemployed unless we make the economy sound, expand the economy and thus create the jobs that we must have. One of our problems, if I may just point out and then I'll quit lecturing, one of the problems is that three million of the unemployed are the result of that many new entrants into the workforce over the last two years and because of the stagnant economy we did not create the three million new jobs for those new entrants into the workforce and this has got to be one of our great problems is creating the jobs to keep up with that kind of expansion. Well, Leslie, you're now. Thank you. Mr. President of the Polish government announced that they're about to pre-Lukwalesa and as you mentioned, Mr. Brezhnev is dead and a new Soviet leadership is coming into power. Is there any thought in your mind that this would be a good time for you to take some big step, even a symbolic step to that would lead to the lessening of tensions between East and West and are you thinking of taking any initiatives that would give the world a signal that you would like that to come about? We have been trying to do that in the area of quiet diplomacy, tried in the summit conference, tried in the NATO conference of various things. We are prepared and ready and they know that about trying to have a better relation. But it's going to require some action, not just words. For 10 years, detente was based on words from them and not any deeds to back those words up. And we need some action that they, it takes two to tango, that they want to tango also. Are you willing to take the first step at this stage, at this juncture? Well, there are some people that have said I took the first step with lifting the grain embargo. Have we gotten anything for it? Well, after the last set of unemployment figures came out, your spokesman said that there would be an improvement in the situation in the near future. Do you foresee the unemployment situation becoming worse before it gets better or can we look for an improvement next month? The unemployment, as I've said so many times before, and as we all know, is the last of the indicators that comes up as you're coming out of a recession when you're in that period of transition. But also, if you look back at history, you find that in that same period, it is very volatile. It could possibly go up some more. It could go the other way. It could stay level. It isn't a sound indicator to look at that and say, which way is the economy going? But we believe that what we're doing is the only course that can stimulate the economy. And I think we've seen evidences of that in the marketplace. We have just received word that in September, the applications for FHA home mortgages, single dwellings, has gone up to a point that is higher than it has been for the last several years, for the last four, at least, the sale of homes in October of new homes already built was way above the normal level for the month of October. And you can find other things, automobile sales last month increased 3.9%. So we think we're on the right course. But this doesn't mean that we don't do some of the things, such as our job training program to try and solve that problem of the increasing people in the workforce, which will train a million people a year. The program for export trading companies that we have passed, they estimate that for every billion dollars of exports that it's about 40,000 jobs in our country. We're pursuing that. We're still trying to get action. And we've been trying for about a year on the enterprise zone proposals. But we're doing those things that we think are proper. We're not going to go down the dead end street that just leaves us set up for another recession. Yeah, Lou? Mr. President, if I can return to the defense budget question, a number of Republicans, not just those who want to return to policies of the past, have suggested that in the spending cuts that are necessary in this next budget, that it would be good if the Pentagon also participated in this. And some have even said that in the long run, the defense budget would be better if the economy is healthier. Have you ruled out the possibility that you would modify in any way your call for an increased defense budget, maybe just for this one year when the economy is not what you'd like it to be? Well, Lou, it isn't the kind of a budget that you can do it for just one year. The various weapon systems and so forth are things that have to go on down the line. You don't just call up a supplier and get a delivery on what it is you want to buy or call them and say send it next month. And you've got to remember that a great share of the defense budget is for humanity. It is for the men and women and the armed forces. The pay scale that is now approaching some reasonable level. But we're looking at everything and we're not prepared of any indications yet of what we're looking at. I would have to say that yes, we're looking if there are savings that can be made without delaying or setting back what we think is the improvement we must have if we're going to close that window of vulnerability that we inherited. We can't do that. The first and primary function of the federal government is the national security. Chris? Mr. President, Israel continues to ignore your call for a freeze on settlements on the West Bank. How damaging is Israel's ignoring of that freeze to the peace process? And what are you prepared to do about it? Well, Prime Minister Begin is coming here and I'm sure that he and I will have some talks on that as well as other subjects. We do think that it is a hindrance to what we're trying to accomplish in the peace movement. Obviously, the solution to the Middle East must be what we outlined earlier. And that is to bring the Arab states and Arab leaders and the Israelis together at a negotiating table to resolve the differences between them. And that begins with them recognizing Israel's right to exist as a nation. So I am still optimistic and that's why Phil Habib is going back there. Please follow up, sir. Are you prepared to do more than just talk with Prime Minister Begin? Are you prepared to consider any sanctions to force a change in Israeli policy? Well, I don't think that it would be a good diplomacy. It would be threatening or anything. And I don't believe that's necessary. I think that all of us realize that peace is the ultimate goal there. Sam? President, your Social Security Commission is to report by the end of the year. But Senator Dole says that the Democrats ought to come forward with a program to repair the social security system before the commission reports. Or he fears the Democrats just won't support it. Now, do you support Senator Dole's call in that respect? Well, let me just say without whether I support it or not, I can understand the senator doing that in view of the experience we've had with others laying back and then offering no proposal to solve a problem. If you will recall a little history a year ago when we talked about the threat to social security and solvency, they claimed there was no such threat. But we said at the time it could not get through July of 1983 without having its house put in order. They denied that. Now they are admitting it can't get through July of 1983. But, sir, what about my question? Do you support Senator Dole's call? I said that I wasn't going to comment as to whether I support it or not. I said I could understand why he would say that. I do feel this. The answer to this problem is so serious. The solvency of social security that it is time that those who have frightened the senior citizens of this country, the way they have, quit frightening them because I know of no one, and especially me, who is going to support any program for restoring fiscal solvency that reduces the checks below the level that the present beneficiaries are getting. And these poor people have been frightened to death by charges that there were some of us out there that were trying to take this away from them. And we're not. Now, I don't want to get into whether we should do it or not. But what he is saying is what has to happen. It is time for the leadership of both of us, both sides of the aisle, to come together with a knowledge that we've got to sit down around the table and work out a solution to this problem. Very excuse me, but if you don't want to answer my question, I understand, but may I try another one then? If you don't want to reduce the benefits, the only other way is to raise taxes or to remove from the rolls some number of people in the future who might otherwise be on it. What course do you prefer? Sam, there are a number of opportunities that go back in a long way and can go back to people they're presently paying in or a long way from collecting. There are a number of opportunities. As for taxes on Social Security, I think it's time the American people knew that for the next eight years, beginning in 1983, there is going to be a tax increase every year in Social Security tax. Five of the eight years, it will simply be for part of the wage earners because their tax increase will come from the increase in the amount of salary or wage that is being taxed. But three of those eight years will also be, in addition to that, an increase in the rates. I don't think that there's very much more room. More people working for a living today are paying a higher Social Security tax than they are income tax. More people than there are the other way. Kathy? Back on the gasoline tax. Secretary Lewis briefed you yesterday. Can you at least tell us what you see as some of the pros and cons of that proposal, particularly the mass transit aspect? And can you make it equitable for all states or will some states bear an unfair burden of that tax? Well, again, as I indicated earlier, you'll have to wait on that one because that one was just presented yesterday. No decision has been made. It is under consultation and deep thought by all of us. And we are faced with the need, both at the local and state level and for our own interstate, the federal highway system. And the program that has been proposed deals with both those problems. But you'll just have to wait and see if we make a decision we make. Sir, you like to describe yourself as an optimist a man who sees opportunities instead of problems. And in that light, I'd like to hear what you think are the opportunities that the United States now has with the depth of President Brezhnev. Well, I don't think that the death of President Brezhnev is a factor in this of what opportunities we might have. I have felt for a long time that we have an opportunity because while the entire world, including the Soviet Union and ourselves, is involved in a deep recession and deep economic problems, all of us, it would seem to me that out of those troubles, that might be a time where, in a cooperative sense, we could find out that we'd all be far better off if we decide to get along with each other instead of one pursuing an aggressive policy and the other one resisting that and so forth. So I am optimistic that and would have been, without his death today, continue to be optimistic that we can get together. Yes, Bob? No, that's Bob Ellison. If you'll run earlier statements about jobs and employment, will you firmly oppose the jobs bills coming down to Capitol Hill, or are there certain guidelines or criteria under which you will support them? The guideline and criteria for anything that is proposed is going to be, does it further or does it delay the improvement of the economy? Now, nothing has come down from the Hill. There's only been talk that you have repeated on the air or that you've written in the press about what they're talking about up there. I will say that several proposals I've heard sound exactly like the kind of job programs that I was criticizing a little while ago, in which they're simply going to take billions of dollars for the creation of temporary work without realizing that that would be a drag on the economy and would slow down our effort to really restore legitimate employment. Now, Bob Kettle. Mr. President, you've said recently that you believe a number of sincere Americans who support a nuclear arms freeze are being manipulated by those who want the weakening of America. Could you elaborate on this for us? Do you have any evidence of foreign involvement in the US peace movement? Yes, there is plenty of evidence. It's even been published by some of your fraternity. There was no question, but that the Soviet Union saw an advantage in peace movement built around the idea of a nuclear freeze since they are out ahead. And I'm gonna emphasize again that the overwhelming majority of the people involved in that, I am sure, are sincere and well-intentioned. And as a matter of fact, they're saying the same thing I'm saying. And that is we must have a reduction of those nuclear weapons, and that's what we're trying to negotiate now in Geneva. But to put the freeze first, and then believe that we have not weakened our case for getting a reduction when the other side is so far ahead doesn't make sense. But yes, there has been in the organization of some of the big demonstrations, the one in New York and so forth, there is no question about foreign agents that we're sent to help instigate and help create and keep such a movement going. Is that the extent of the involvement as you know it, or has there been money involved, or are there other ways that the Soviet involvement has manifested itself? I can't go beyond what I've done because I don't discuss intelligence matters, and that's what I would be getting into. Mr. President, evidence mounts that key weapons in your $400 billion weapons procurement buildup are in trouble. Navy testers say that the F-18 on which you'd spend $40 billion is too heavy for its major mission. Your closest military science advisor says the latest basing plan for the MX won't fool the Soviets. The Pershing missile on which NATO defense would defend literally can't get off the ground. The anti-tank weapon the Army wants to buy seems to be ineffective against modern Soviet tanks. The Maverick missile can't find its targets. I wonder whether, in light of all these failures, you have any reason to wonder whether a $400 billion arms buildup is money well spent? Well, it isn't $400 billion in any single year that I know of, that's exaggerating. I've read also the same articles also, and having access to information closer to the source, I don't believe those things about the weaponry. Obviously, in any new weapons system, there are problems, and there are bugs that have to be worked out. But I have faith in our technology, in the level of that technology, and I know that we have been markedly increasing our defensive capability with what we're doing. And I say, some of my sources I can't reveal. President, as you may recall, last June in Berlin you talked about the danger of accidental nuclear war and put forward the idea that this might be a new initiative that the administration could consider in the arms control field. I wonder whether in your planning for next year you have some arms control initiatives in the works? Well, all of these things are in the works, and that's why we have three teams negotiating, one on the matter of conventional arms, one on the matter of strategic missiles, and the other on the matter of the INF, the zero option that I announced a year ago. But I tell you what I'd rather ask you to do and wait for is in the very near future I am going to be speaking in a major address on that entire subject. Jerry? Yes, sir, thank you, Mr. President. You said in September that you could not determine how long America agrees with Maine and Lebanon. But since that was six weeks ago, don't you think it's time to give the American public an indication of how long they'll be there? Jerry, I wish I could. This is one of the reasons why Phil Abib is going back over there and take charge of what's going on. The plan as proposed is one that requires, of course, the ability of the new administration in Lebanon to stabilize and to be able to take charge of its own borders. This calls for as quickly as possible also the removal of all foreign forces from that soil, and that's why our multinational force is there. I can't give you a closeout date on that, but I can tell you that we're trying to push as fast as we can on the two things that must happen. And that is the ability of the Lebanese government to heal the wounds and bring their people together and have control, but also it hinges on getting the three foreign factions, the PLO, the Syrians, and the Israelis out of Lebanon. And we are pushing on that as fast as we can. Yes. I can follow up. Is there any reason to believe the truth might be home for Christmas? I just can't speculate on that. I can't tell you, but I do know this. We think our plan is working. It's working as fast as we'd like or not. It remains to be seen. But I think the important thing is that that force, that multinational force is there in the name of helping bring about peace. And I think the most important thing is to see that that job is done, and I believe they understand that. I'd like to try again on Israel and possible sanctions. Is it possible that the United States might cut back on aid to Israel in direct proportion to the cost to that country of establishing new settlements on the West Bank? All this is a means of achieving the freeze that you are seeking. I don't think, to answer that question one way or the other, I don't think would be helpful in the situation that we're in today where we have made so much progress with the Arab states, the unusual, the unique thing of the representatives of the Arab League being here to meet with me as they were just some days ago, the need now for Israel to itself recognize that they too must play a part in making it possible for negotiations, the part that must be played and recognized that one of President Jameil's problems now is reconciling Muslim groups within his own country. I don't think to start talking about whether I should or should not make threats of some kind or other is going to be fruitful at all. I got a quest here for some factual information. Is it true that the pagan government now is spending about $100 million a year to subsidize settlements on the West Bank? Do you- Dad, I don't know that figure. I imagine I could find that out very easily. Mr. President, in two weeks, the United States will celebrate Thanksgiving. Given the passing of Brezhnev, inevitably there are comparisons between two systems. Could you take just a minute to tell Americans why at this time they especially should be thankful for their blessings and give a comparison of the two systems? Yes, because I think the comparison is so obvious and you don't even have to use our own country. Turn to some of the newer and the developing countries and those that have chosen our way, the free way, free trade, democracy are so far ahead in standard of living and the happiness of their people than the others that have chosen the other that control the authoritarian way. And I think here is Lincoln said it then and it's true even today. This is the last best hope of man on earth. We are freer than any other people. We have achieved more than any other people. And if you looked around this room, I thought the other day when we had all those representatives from all over the world, all of those representatives in this room who were here to look at our election to learn how they could spread the word about that kind of freedom in their own countries and in other countries on the rest, the other continents. I thought that we could have a meeting of Americans in this room and the ethnic heritage of the Americans in this room would be as diverse and there would be as many represented as there were in those hundreds of people who have come from foreign lands here today. And here we all live together proudly as Americans in spite of that difference in birth. There just isn't any comparison with what we have and what we have to be thankful for. Yes, Ralph, just properly in the proper time.  Okay, sir. And, Mr. President, are you close to an agreement with West European countries on an East-West trade policy that would enable you to lift the sanctions on the Soviet natural gas pipeline? Well, we are in negotiations and have been for some time on the East-West matter with our allies. And we are at last making what I think is sizable progress. I have nothing to announce as to any definition of that at the moment. But we've made progress. We started this long before there were sanctions. We started at Ottawa last year. We tried again in Europe and the two meetings there and the summit meetings. We have continued. We had a team negotiating over there. We finally put the sanctions in effect but we're discussing that relationship or that arrangement with our partners without the sanctions playing any part in it. Our decision on the sanctions will be based on when we feel they've served their purpose and when we feel that there could be a better situation without them. Thank you. All right, gentlemen. I didn't get any other things on there. Oh, it's great. Thank you. We had a Vietnam memorial in a few days. But we'll be visiting the Vietnam memorial I'll be at a memorial at my home for my family's, Nancy's family. They're having a memorial at the end of Saturday in Chicago. We'll be there.


All right, you guys we are here for week three of the Royal Wedding Sew Along I've got new look six five to six and I've also got my fabric laid out Today we are gonna be working on the bodice of view a and or b Which is that really pretty princess seam v-neck?  So I just tossed it up there But so this is the cutting layout that I'm going to use feel free to copy this if you're also making this pattern But the rest of the video is going to be dedicated toward putting together the bodice for view a or b I'm going to show you some tips for marking your dots and also how to attach the Princess seams in a way where it's nice and smooth and you don't get like a ton of puckers or anything like that Where you get a really beautiful seam. So let me get this all cut out and I'll be back in a minute Alright, so I have cut out all of my bodice pieces. They are very beautiful As well as the pocket piece and I just wanted to point out that in addition to clipping all of your notches I just clip right to the point of the Triangle, I don't actually cut out the triangle. I just clip right through but after you cut All your notches if you're making the sleeved version, which is technically view B Then you're also going to need to mark these dots On your arm side So this is the one for the front and this is the one for the back and this is going to help you line up your sleeve Whenever you go to sew them, you'll notice on your sleeve piece as well that there are also these dots So they will all Match up as you're sewing your sleeve together And I just want to show a real quick and easy way to mark them and how I mark mine pretty much every single time So you just take a um a pin like you would use for anything else and you put it through the Circle that you want to mark right through the middle of it You remove this one to make it easier.  I still honor the grain line So that's parallel to the selvage edge This interfacing if you're wondering is a fusible tricot. I think it's the heat and bond brand But honestly any of them will do I think the most important thing is just make sure that it's lightweight And nothing too stiff You still want to maintain the fluidity of your fabric But you still need to have some structure and stability so that these Bias angles never warp or got a shape So I lay it down and then I trace around it and then I'm not a huge fan of cutting exactly the same Seam lines as the fashion fabric It's not going to go all the way to the edges and that will help reduce some of the bulk that you have In your seam lines So for the back interfacing piece, which has its own Pattern piece. I just wanted to show you quickly how I am Eliminating the seam allowances from the pieces. So for the back that has its own Facing piece. I'm just trimming right off the pattern piece I'm not tracing or anything like that and I'm only going to trim the interfacing seam allowance from the Edges that have a seam. So that's going to be your shoulder seam here and your back collar here This seam here is this line here is not a seam. It's just going to fit nicely into the Collar of your back pattern piece like so something along these lines Like that and you can see it's just the interfacing is just going to stop a few inches Below the collar. So you don't really need to trim the interfacing there You probably actually do want it to go as far down as the pattern piece indicates So once I determine which Seam lines are going to get trimmed then I take these very handy seam allowance curves Um These are by lunagraphics and these are handy because the width of the plastic here is five eighths seam five eighths of an inch So that is your seam allowance on most patterns.  So you can be a very good non lazy sewist And trace them off onto your favorite tracing paper Or you can do like I do and trace them directly onto the interfacing and then use this ruler to mark your Seam allowances or your trim line. However, you want to look at it Directly on to the interfacing and then trim out that line. It's really up to you how you want to do it It's probably if you're going to make the pattern multiple times more time Effective if you go ahead and trace it off that way It's just one step one time instead of multiple steps multiple times. All right. So I have got the fusible interfacing applied to the Back remember, it's just the little collar section shoulder section and a little bit of the arm side for the back The entire side front piece This is the front. I'm sorry. This is the back Midriff waistband thingamajig and this is the front piece which is cut on the fold So I've got all my pieces prepped and ready to go So now we can go ahead and get sewing The very first step in our instruction booklet Is to Let me focus this a little bit better Okay, first things first. This is step number one after we've applied the interfacing We are going to stitch the center front seam of the bodice front sections from lower edge to small dot which means um on the Front piece here. We're going to stitch from this edge Up through to the center front. That is going to be our Very first step and then from there Um, we stitch the side front sections to the bodice front And I'm going to show you give you some tips on how to do that So that you get a really beautiful seam here without any puckering Um whatsoever, so let me get this sewn first and I'll be right back all right, so the easiest and most Effective way to attach seams is to Try and not worry so much about matching the raw edges So we've got a few notches to help us out. We've got a lower notch here a lower notch here We've got another one here and another one here So my first step always is to pin those two points together That's going to tell us a lot about where to ease everything in And where not to um this whole thing is not eased so it doesn't really help you to just um match the ends you really need to match the um the Those notches as well. So after I match the notches and pin them then I go and match the edges Like so All right, so now you can tell you've got a smooth Where the raw edges match here And then the raw edges also match from here to here But in this area you can see it's like creating this little opening where the two seem like They don't want to go together But they definitely do they just go together at the seam line Not necessarily at the raw edge. So work them together Manipulate them around a little bit This is why it's also beneficial to not have your interfacing all the way to the edge Because you can kind of stretch this out a little bit and make the two fit in Together better And then you'll also see as you start doing this this edge here is going to create Little ripples along this edge here So I like to take my scissors and cut The one that's not rippling the edge that's laying flat because that is going to Give it enough room to kind of mimic what is happening here So once you clip to The seam line but not through and again having the interfacing there helps a lot I'm clipping maybe half an inch worth You can start to see how it starts to automatically Lay flat So now the two seams are totally laying flat together and it'll be much easier for you to sew those together And I'll show you again on the other side So we want to take Our side bodice piece We want to line up The bottom notch like so And then we want to line up the top notch like so then Line up the top edge like so And now the bottom edge And again, you'll see between the two notches. It's like they're not really getting along But if you put in a couple of pins Move things around a little bit You will get them You'll get the um side front piece to ease in to the front bodice piece and then To help the um The two kind of marry themselves together even better You're going to clip to the seam line of the one that's straight not the one that's all bubbly And it looks like I'm only needing really two clips one Two and once you do that it creates a little wedge And they automatically Lay flat So you can see here. I've got my two Princess seams ready to be sewn So I'll show you what they look like after that and after I get them pressed. Okay, there we have it This is our completed Like I don't know. I'd call it our upper bodice where we have the center front seam done And we also have our princess seams Um sewn the instructions tell us to press These seams open and these seams toward the center front So that's what I did. You can use a pressing ham to help you but honestly, I didn't even use mine It wasn't that hard um So it's looking really beautiful again still loving this little sweetheart neckline So moving right along the next step is to attach the Front which is this piece to the back pieces at the shoulder seams So you're going to take this like so and this Like so and you are going to sew along this seam and this seam. You just want to make sure you don't get these two swapped um So like this, I know it seems hard to do but if you're not paying attention in a hurry like sometimes that can happen So just make sure you get the arm size matching. So like Over here. There's an arm side for the back and there's an arm side for the front and then the same thing over here So you sew the um shoulder seams and then you also want to sew together the side seams So we're going to match that notch and sew the side seams together And then we'll have our entire upper bodice um And then from there There's just all straight seams from after you get the princess seams done. It's all straight seams So from there, we'll attach the front midriff to the back midriff again similarly You want to make sure everything matches up because these this can look similar the this edge and this edge And you need to make sure that you're attaching it the right way. So it doesn't end up upside down Um, so again, you've got a curvy edge here and a flat edge here But also if you can't tell the difference, you know that your notches are going to Match up all along the side. So if you're in the right place, they will match up If you're in the wrong place On the wrong side, they won't match up.  That is our completed outer Bodice Um We are going to be working on the bodice for view c and d next week So if you are Sowing view a or b feel free to watch that video and see how it comes together Or just skip ahead to week Five where we will be attaching the skirt if you're making view c and d stay tuned next week I'll have the same similar style video, but for the wrap version So look forward to seeing you all here then. Goodbye


This talk is called Building a Better OpenStruct, and that's what we're going to talk about. But I do have to say it's a little bit scary to come up on the stage to be kind of the sequel to Matz. So I want to also introduce something big to the Ruby community. I call it Matawan Swavin. It's short for Matz's talk, was nice, so this talk will also be nice. So I'm going to do my best to give also a nice talk, Matawan Swavin. Okay, so let's talk about OpenStruct. Before we can talk about what it means to build a better OpenStruct, we have to know what OpenStruct is. How does it work? What are the problems with it, and why would we want to build a better one? I like to think of OpenStruct as Ruby's JavaScript object. It's funny. The initial commit on the Ruby repo goes back to 98, so not quite to the beginning of Ruby, but OpenStruct was already there, and it was described as a Python object. But at this point, I like to think of it as a JavaScript object, and you'll see what I mean in just a sec. You can require OStruct anywhere in your code. It's just part of Ruby's standard library, so it's always there. And when you initialize an OpenStruct, you can either initialize it raw, just openstruct.new, or what you'll do most of the time is you'll initialize it with a hash. So in this case, we're initializing it with a hash, with a key of foo, and a value of bar. In this case, both symbols. And generally, keys have to be either strings or symbols. Once it's initialized, it's not too late. You can still add properties. So in this case, we actually have two ways to add properties. We can use dot notation, like dot-bas equals four. Or we can use bracket notation. In this case, we're setting a key of the symbol something to the string of whatever. Once you have all your information in your OpenStruct, you can start getting properties out. So you can either use dot notation. Here we can see it doesn't matter when you put the information in. It's going to be available. And if you try to access a key, you'll see at the bottom, we're accessing a key that's not there as part of the attributes that you've added, it'll just return nil. And it doesn't matter whether you use dot notation or you use bracket notation. Again, with either symbols or strings, it all works fine. So you have an object with arbitrary attributes. You can use dot notation or bracket notation to add and retrieve attributes. That sounds pretty much like a JavaScript object. So that's why I like to think of it that way. Now that's really nice, but why would we use it? So Eric Michaels-Ober gave a really great talk at Rails Israel last year where he listed three common use cases of OpenStruct. And the code examples that we're going to use are my code examples, but the list is his, and I have to give him credit for identifying these three cases. The first and the one that we're really going to focus on in this talk is consuming an API. The sort of more straightforward way that you might do this is you make a call to an API, you get some JSON back, parse out that JSON into a Ruby hash, and then you pass that hash into an OpenStruct. A more complex pattern that you might follow, and we certainly do this a lot in our apps, is you actually subclass OpenStruct, and then create a new instance of your subclass with that hash. So it comes out to pretty much the same thing, but the nice thing about it is that now you can actually put a name to the kind of object you're creating. So let's say you hit the Twitter API, you get back some kind of a hash, you feed that into your OpenStruct subclass, and now you have a tweet object. So it makes it much easier to work within the console to debug stuff. It's much nicer that way. Just to flesh it out more, if the API response looks like that, we have a couple keys, a couple of values. If you were just to leave it as a hash, you would have to use bracket notation. But because we put it into an OpenStruct, we can use dot notation. And it seems like a pretty subtle distinction, like OK, why do we really care? But now you're actually starting to think of your information as not just raw data, not just hashes with keys and values, but as an object. And if you use that more advanced version that I mentioned, you can do this, which is super cool. So here we have a user class that inherits from OpenStruct, and it has a name method. We actually can start defining our own methods, which interact with the data that was passed in. So in this case, we make an API call to slash user slash one, which for some reason I guess I'm the first user, Ariel Kaplan.  And what's cool is that if we call dot first name, it would just give us a raw value. If we call dot name, it'll give us a computed property. And from the outside, we don't know which is which. And that's basically the point of objects, is abstraction and encapsulation, and that's a really nice way to get that from an API call. OK, so that's all case number one consuming an API. Common use case number two is a configuration object. Let's say that you made a gem, which requires some configuration, you want to have a DSL like this. So you call dot configure, you get a block, which takes a configuration argument, and then you'll start setting settings on your configuration. This is all the code that you need to do it. The configure method on your gem is just going to yield your configuration object, which is an open struct. And since open struct has that really nice property where it lets you just set and get random keys, so it just works. It's really simple, and it's built in. Third use case, it's a little complicated, so if it goes over your head, don't worry too much about it, but it's good to know about, is a test double. So in this case, we have an order class where it takes a payment gateway and some products, sums up the total cost of the products, and charges the payment gateway. Well, if you're actually going to feed it a real payment gateway and put in someone's credit card information, your tests are going to be really expensive. And I'm not talking in terms of hardware, I'm talking in terms of your credit card is going to get charged every time you run your suite. So you don't want to do that. So instead, what you're going to do is put in something that's going to quack like a payment gateway, but not actually charge a credit card. And it turns out open struct is a really easy way to do this, because every key value pair that you put into your open struct becomes a method and its return value. So in this case, we have an open struct which has a key of charge and a value of the symbol paid. Every time you call dot charge on that open struct, it's just going to return paid. So it's a really simple, easy to use test double. We can inject it into our order class, assert that something's returned. We can also, if we want for some reason, to assert that something is set on the open struct. But again, the basic point is is that open struct, because it has the charge method now, it's a really easy to use test double. OK, so that's why you might want to use open struct. But how does it work? Let's peel back the surface and look at the code. And before I move on, I have to note, just to be honest, the code has been brutally edited in this presentation. And it's not because I want to lie to you. It's because this code has a lot of little details, edge cases, and error handling, and everything that I'm going to show you in this presentation. That's the way the code works. So I've tried to pare it down to just the code that you need in order to very, very quickly understand how these things are working. But it's all open source, and you can all check it out later and find out what I hid from you. So it has to work. Well, under the hood, open struct defines attributes, setter, and getter methods on the object's singleton class. Now, I know that not everyone is necessarily familiar with singleton classes, or you might be a little fuzzy on it. So here's a quick refresher. In Ruby, if you have an object, in this case, we'll call it foo, but it could be any object of any class. You can define a method that exists just for that object. So in this case, we define a dot bar method just for the foo object we can call it. And if we call foo.singleton methods, we'll see that the singleton method bar has been defined on foo. So the reason we talk about a singleton class is that technically that method doesn't live on the object itself. It lives in the secret class that every Ruby object has that exists just for that one object. Because methods live in classes and not in objects. But if that's too much to remember, the basic point is that a singleton method is a method just for one single Ruby object, one single object in your program, and nothing else has access to it. So let's look at what happens when you create a new open struct. In this case, we pass in a key of foo and a value of bar. We're going to hit initialize, and this is what initialize looks like. The first thing that we do is we create an at table instance variable, and we set it to a hash. That table, you want to follow it very closely, because that's where all of our information is going to be stored inside of our open struct. Now, assuming that you've passed in a hash as an argument, which in this case we have, we take every key value pair, coerce the key to a symbol, we set that key value pair inside of our at table hash, and then we call newOstruct member. And I will show you what that is, but you're going to have to wait just another minute, because I want to talk about something else first. What happens when you already have an open struct, and then you set a new property using dot notation, dot baz equals four? The first thing to remember is that in Ruby, that's just in tactic sugar for calling the baz equals method with an argument of four. There is no baz equals method, so we're going to hit method missing. The first thing it's going to do is convert that baz equals to a string. We're going to say, OK, what is the nature of this method? It's going to be either a setter or a getter. If it's a setter like we have right here, so we chop off that last character, which is an equal sign, we're left with just baz. And then we call newOstruct member on baz. We get back the symbol, baz, and then we're going to set baz to four inside of our internal hash. The other option is that it's a getter, like dot baz. So all we do is we pull the value for baz out of our internal table. Now, I said we're going to talk about newOstruct member, and this is where that happens. But remember that it's called during initialize and during method missing. Here's what it looks like, and this is kind of where the real magic of open struct happens. So the first thing that we do is we just coerce the name to a symbol, and then we say, OK, let's say we call this with baz. Do we respond to the baz method already? If so, then we're done. We don't want to overwrite any methods. But if there's no baz method yet, then we're going to start defining methods. So the first thing that we do is we define a baz method, which just gets the value for baz out of the table. And the next thing that we do is we define a baz equals method, which sets the value of baz to the argument within the table. OK, so it's kind of like add a reader and add a writer, just that instead of what we'd normally do, which is write to an instance variable, instead we're using that internal at table hash. What you might have figured out from this is that no two open structs share a set of methods, even if they look exactly the same from the outside. But those methods are being defined every time for each individual open struct object. Now, here's the problem. Open struct is slow. And you might be wondering how slow is open struct. So I had my Madiwan's Twavin, however it was. Matt's has animals, so I have animals.  So my snail friends will tell you that it's about, depending on your use case, 10 to 40 times slower than an explicitly defined class. And that seems really, really bad. That's terrible performance. Why is that happening? So I would say that there are two and a half reasons why that happens. Reason number one, and this is the main reason, defining methods is slow. In Ruby, when we define a method, it just takes a long time. Number two, as you've seen, we're going to rely on method missing a good deal. Method missing is also pretty slow. Not as slow as defining methods, but it's a contributing factor. And before I tell you the third reason, or the two and a half reason, let me do a quick survey. How many of you have heard, just by show of hands, in the last, let's say, a year and a half, two years, don't use open struct because it's going to invalidate your global method cache? All right, we got a good number of hands here. You've been lied to. It's not true anymore. In Ruby 2.1, this is fixed. It's no longer a problem. And this bothered me because I see a lot of misinformation out there about open struct, about this particular issue. It's not a problem anymore in 2.1 and above. But why that is, is actually kind of an interesting story. So I want to delve into that for a second. And we have to talk about how method lookup in Ruby works. So let's say we have this object graph. We have an animal class, which is just a standard class. It has dog and cat, which inherit from it. And meowable is a module included on cat. Now we're going to create a new cat object, and then we're going to call 2s on cat, the 2s method. Well, where does that exist? Initially, we don't know. We have to figure it out. So Ruby is going to actually start hunting around in the class and its ancestors and include modules. We found it in kernel. So we're going to mark, OK, in the future, any time we call 2s on a cat instance, we know that that is defined in kernel. We know how we can execute that method. So let's not look it up next time. But what if you reopen the cat class and you define 2s? Well, that information is no longer true. So because of that problem, every time you reopen a class in Ruby, that happens. The global method cache is blown away because it's a simplest way to say, we don't know what to rely on anymore. Now the problem is, every time that you use an open struct, you're defining methods. And that happens. So our global method cache has been busted every single time that we created a new open struct. And it turns out that looking up methods is actually really expensive. And if you're wondering why, look no further than active record. Every method you look up an active record the first time, you have to look through all those places, all those classes, and all those modules in order to find where that method is. And that method probably defines other methods, which you then have to go through that same series of events again. So it's really expensive. James Golic was a New York City Rubyist. He unfortunately passed away about two years ago very suddenly in a car accident. And this is one of the big things that he did for the Ruby community, so I like to talk about it because it's part of his legacy. So he did a little bit of profiling. He found that 10% of the time spent in his Rails application was just rebuilding the global method cache. It was reset 20 times on a request because of all these method lookups. And open struct was, of course, one big culprit. So he said, look, I could complain about it. I could go on Twitter and rant about it. But why don't I just fix it? So he did. He implemented what's called a hierarchical method cache. And we'll see how it works. But he actually wrote it for 1.9. It was not included in Ruby Core until 2.1. But from 2.1 and on, this is no longer a problem. So I'll show you how it works. We effectively have one method cache per class in our Ruby program. So we have an animal method cache and a cat method cache, and there are links between them. So that if we invalidate animal, then it's possible that some of the information we have about cat is also incorrect, so we also invalidate that. But let's say I reopen dog and define a method there. Well, dog is gone. But cat's still fine. There's no reason why a defining method on dog would ever affect cat. So we only invalidate the cache with respect to the classes that would be affected by it. And the same thing is true with open struct now. When you add methods to your open struct, we just invalidate that open struct cache. But everything else in Ruby is totally fine. That's a blog post where you can see all the details. It's actually a really interesting read, all kinds of cool stuff about monotonic sequences. And anyway, check it out. But the bottom line is, again, let's bust that myth. Ruby 2.1 and above, we can absolutely create open structs without slowing down the rest of our application. But there's still that little problem that open struct itself is kind of slow. So hi, everybody. Don't worry, the intro was supposed to take this long. It's fine. My name is Ariel Kaplan. You can find me online at amkaplan. I tweet about mostly programming, but increasingly about software teams and what it means to write code. I also have my GitHub profile there where you can find much of the source code for this presentation. And on amkaplan.ninja, I'll post the slides after the talk. I really like coming to conferences because I get to meet new people and hear new perspectives and ideas and just geek out. So I really want to meet all of you. And I want you to say hi after the presentation. And just to bribe you, I brought a lot of chocolate that I want to give out. And it's not just chocolate. It's actually popping chocolate. So come over and say hi after the presentation and get some sweet treats. Even if you don't like chocolate, I just don't want to meet all of you. I work for Vitals. We pay people to use high-quality, low-cost health care. Basically, we're sending people checks in the mail for going to their doctors. So that's kind of a fun business. And in order to get all this information, it's really a lot of number crunching. And so we use a system of microservices and external APIs communicating via JSON, parsing to Ruby hashes, which are fed into open structs. So essentially, in our whole system, open struct is mediating the communication between our various services. Now we had some performance problems. I did some profiling, and I found, oh, open struct. Yeah, big problem. Now I know people are afraid of profiling, so I just want to quickly show you what I had to do. This slide is basically all that I had to do in order to get profiling information. So I use the StackProf gem. I find it to be really nice. What you do is you call the run method on StackProf. You give it a mode, which will be either CPU if you want to test how long things take, or object if you want to check object allocations. You have memory issues. And then you just give it an out file, a place to dump the information. And then you just run the block that you want to profile. So that's all it takes. Then you have that file, which you can't really read. But if you use the StackProf command line executable, just give it the name of the file and call dash, dash, text, boom. You have all this information about what's going on in your app and what's taking the most time. So yeah, open struct. It was taking a lot of time. Here you see it was 17% of the time. But this is not even all the information, because there's a long tail there. So it ended up being about 20% total of our app time, at least the CPU time, was just spent on open struct. And that was not acceptable. But as an aside, congratulations. Now you know how to profile. So there you go. So we wanted to keep open struct, because it was really nice. It was really a flexible interface. It let us change things upstream, have access to them downstream. It was very pleasant to work with thing, but it was so slow. And so the question became, can we have our cake and eat it too? Can we build a better open struct? Nope. So I'm sorry that you're all bored. I'm going to provide this talk. You're going to get a little bit early today. Enjoy the chocolate. I'm just playing with you. This talk would not have been accepted, I hope, if the answer was no. Yeah, we can absolutely build a better open struct. And I'm going to tell you four stories, or really four more stories, because what James Gullock did in terms of method caching is sort of like the zero width story. Because it's not open struct specific, but it is a story of how someone basically fixed stuff because of open struct. But we have four more stories to share with you today. So let's get to it. Round one is open fast struct. So I still remember opening up my Ruby Weekly email. This was around the time we were having these issues, and I was trying to figure out what we were going to do about open struct. And I saw this. Open fast struct. A faster open struct. And that was really exciting. Like, that looks really cool. Let's follow the link, check it out. So it says, yeah, this is the GitHub repo. It says it's still slower than a hash, but four times faster than open struct, which is a significant improvement. And it basically works the same. So I said, let's open up the code. Let's see how it works. Now, again, it's supposed to be the same interface. So let's talk about this is going to look the same, right? Just instead of open struct, it's open fast struct. So what happens when we call open fast struct.new, and we pass in a hash with, in this case, we'll just keep it simple, single key value pair. We hit initialize, which first defines an at members hash, which is actually, it's the same as the add table. I guess Arturo Herrero, who created this, liked the name members better than table. Maybe it's more specific. And then we call update with the arguments, with our hash. Update just basically takes each key value pair and calls a sign, which converts the key to a symbol and puts it into our members hash. So if you kind of do the math, you add this all up, it basically comes out, it's the same thing that open struct is doing, minus new O struct members. So we're not defining any methods. Well, if we don't define any methods, what's going to happen when we start trying to access stuff or assign things? We're going to hit method missing. And this method missing is kind of wacky. So I'll walk you through it. But it's trying to deal with not two, but three separate possible situations. The first situation is, let's say we're calling method missing and we're trying to get a value out of our open fast struct. It's going to call fetch on our at members hash. And fetch is a method which has, it has different behavior depending on what arguments you give it. But if you give it a single argument and a block, as we're doing here, it will first check, is this a key in the hash? If so, return the value. If not, run that block as a kind of a default result. So first we say, OK, is Baz a key in the hash? If so, then we're done. If not, run the block. And the block has to decide, is this a setter or a getter? If it's a setter, if the last character of the method name is an equal sign. So just take the rest, the beginning of that method. If it's a Baz equals method, so take the Baz part and assign Baz to the first argument, which in this case is going to be four. So what's left is when we're trying to, it's a getter, but the key doesn't exist in the hash. And this is kind of interesting behavior here. What he does is, or what it does, I guess, is it assigns to that key of Baz a new instance of open fast struct. So where open struct would just return nil here, it's going to assign a new open fast struct. So that was an interesting design decision. The main thing to remember is that open fast struct does not pay the upfront cost of defining methods. Like I said, it costs a lot to define a method. And it's really only worth it if you're going to get that debt repaid. But if you're only going to access the properties once, then it doesn't really matter. Method missing is still going to be much, much cheaper. So that's an idea of open fast struct in there. With just one little problem, it broke our app because of the different behavior that I alluded to earlier. But I want to understand why Arturo Herrero made that design decision. So if we go back to the documentation, it actually says outright there are a few differences between open struct and open fast struct. And if you look at the last one, it says it allows infinite chaining of attributes. And there's a link to an example. So the example says that open fast struct is a black hole object, which supports infinite chaining of attributes. And we have an example of that. We create an open fast struct called person. And then we call person.address.number equals 4. And indeed, we can retrieve person.address.number. And that's kind of nifty. So how's it working? Well, again, when you create an open struct and you try to call a property that does not exist, you just get nil back. But if it's an open fast struct and you try to get a property that doesn't exist, then it's going to give you back a new open fast struct. So when we call person.address, we get a new open fast struct. And then we can call .number equals 4 on that. So that's really nice. The problem is in our app, we did a lot of this. So let's say our API would sometimes leave out a key if the value would be nil. So when we call open struct.foo, and there's no foo key, then it's just going to return nil. And that's going to be a full c value. If it's an open fast struct, we call .foo. It's truthy. So our conditionals were all flipped. Turns out that's not very good for your app working. So my point here is that if you're going to create a drop in replacement, it should just be a drop in replacement. It should be the same thing, but faster. Faster, but also the same thing. And if you break the API, that's going to create certain barriers to adoption. And for us, it was to the point that it would have been easier to monkey patch open fast struct, not to do this, than it would have been to rewrite our app. So the question became, can we do better? Can we have something that's closer to the actual open struct API, and still is performant? So I thought about it, and I came up with an idea, and I called it persistent open struct. I want to show you how it works on the outside, and then we'll dive into how it works on the inside. This is specifically designed for the use case that I spoke about, the advanced version of API consumption. So you have your class, which inherits from open struct, in this case. So you're going to inherit from persistent open struct. We're basically just substituting in persistent open struct. Then you can define methods. In this case, we have a speak method, which relies on type and sound. And then we can go off to the races. So we create a new animal with some information. This is our dog. We can call that dot speak method, and we see that type and sound are properly used. And we can set properties with dot notation, with bracket notation, and it all works fine. But when we look at the instance methods that are defined on animal, meaning the methods that are accessible to every instance of the animal class, we start seeing type equals and type, sound equals, ears, nose, tail. We have all of these methods already defined, ready to go for every instance of the animal class. How's that working? Well, it turned out it did not take a lot of code to make this happen. I literally copied over the open struct code, and I changed two lines. And just to make it pretty obvious, I'm going to underline it. So instead of defining singleton methods, we're basically just reaching out to the class and defining standard instance methods. Otherwise, it's working exactly the same. All we're doing is skipping that stage of method definitions. So it's kind of a terrible hack, because you have instances of your class changing the way that the class works in the middle of runtime. It might have security implications also, by the way. If you ever had this facing user input, they could start passing in random keys, and then eventually you would run out of memory, because you're defining all these methods, and your server crashes. So never for user input. This is only for trusted APIs. But user-responsibly, which I think we are doing, it made our app 10% faster, which I thought was pretty good for a two-line code change. If you look at just the solutions themselves, so in this benchmark, which I'm not even showing you honestly, but you can look it up on the persistent open struct repo, in the use case that we're looking at, persistent open struct is about five times faster than a standard open struct. It's still about five times slower than a regular class, but that is a much, much closer margin. And I noticed what some of you were thinking, like, OK, that's nice, looks cool, but I want to see math. I want to see incontrovertible, absolute proof of the supreme superiority of persistent open struct over open struct, and I will give that to you.  Let's define our terms. n is going to be the number of methods that you have to define, which is just two times the number of attributes, right, one getter, one setter, a piece. O is going to be the number of objects that you want to create. If you use persistent open struct, it is an O of n definition, or sorry, an O of n operation, because you only have to define all those methods once. It doesn't matter if you create a million objects, you're just defining those methods once. If you use open struct, it's O no, because that's the sound that you make when you realize that open struct is killing your application's performance. OK, so the goal here was, OK, honestly, the goal was to make a terrible pun, but there is also a serious point here, which is that that doesn't tell you anything, right? Math is a really useful framework for thinking about problems in the abstract, for considering various solutions and figuring out where you should put your efforts. But we're engineers, we work with real apps, and we have to have answers that are grounded in reality, and that means benchmarks. If you're writing a library or a gem, benchmark it. You're writing an app. All of you are presumably writing apps, otherwise I'm not sure what you do for a living. So benchmark your apps. Have running benchmarks which are checked into source control, and you can follow them over time, make sure you're not having performance regressions. Just benchmark everything. And I know a lot of you are thinking, OK, Arielle, that's really nice advice, but how do I benchmark? That sounds hard. Nope, it's not hard. This is all that you need to know, this one slide. So I like to use a benchmark IPS gem. There's a lot of really nice benchmarking tools even in the RubyStandard library, but this gem is just beautiful. Also written by Evan Phoenix, who is one of the organizers here. So if you have used this in the past, you can go think him. So what you do is you just call benchmark.ips. You pass it a block which takes an argument of x. I don't know what x is. I just know that you have to call all the methods on it. So for every test case, you call x.report. You give it just a string that labels your test case, and then the block that you want to check gets performance characteristics. And at the end, if you want, you can call x.compare. And then you get this beautiful output. So what it does is it'll run your code for a short warm-up period, and then it'll run the code each block that you gave it for five seconds as many times as it can, and it'll tell you how many times was I able to get this done in those five seconds. So in this case, we see that our new code is 1.28 times slower than the old code. And it looks like a performance regression, so you might want to check that out. So now you know how to benchmark. That wasn't too bad. So congratulations. Back to our topic now, persistent open struct. So it's really good when you're repeatedly creating data objects with the same shape, like in the case of API consumption. This would be terrible, or at least overkill, for any of the other use cases that we mentioned. But in the case of API consumption, it's really, really good. Round three, open struct. Turns out, open struct actually still has a few surprises up its sleeve. So Eric Michael's over, wakes up one day, and tweets out this thing. Hey, I just made open struct initialization 10 times faster. Cool. So that sounds actually really cool. So how did he do it? How much code did he have to write? Not very much. It was actually negative code, believe it or not. He got rid of the new old struct member and initialized. So essentially, the idea is that let's hedge our bets. Why are we paying down that upfront cost of defining the methods when we don't even know if we're ever going to use them? Let's say I'm going to call out to the GitHub API just to get, I don't know, the name of a repo. It's going to give me 20 different keys, and I'm only going to use one of them. So why would I bother paying the cost of defining the other 39 methods that I'm not going to use? So just don't. And as we see that we need the methods, we define them. This was introduced in Ruby 2.3. It's just part of Ruby now. And it's a really dramatic improvement when some keys are never accessed, because defining methods is the slowest thing of all this. So it's nice to skip it. Round four. So I wrote a persistent open struct, and I waited about a year, and I just kept having this nagging feeling. I think I could have done better. I was very bound by the open struct way of thinking. And I said, I think if I just try to re-engineer it from scratch, I can make something better. So finally I found some time, and I got the motivation, and I just did it. And that's where dynamic class came from. This slide is hopefully going to look very, very familiar. The major difference is that, unlike persistent open struct, here you actually call dynamicclass.new and you give it a block. So if you ever work with struct or you've worked with delegate class, there are some tools in Ruby that work like this. It's a class factory. So when you call .new and you give it a block, it creates a new class for you, and then it'll run the block in the context of that class. So you can do anything in there that you would do in a standard Ruby class declaration. Now the rest of this is going to look really similar. We can initialize a new instance, give it all the attributes, and all those instance methods, all those getters and setters are defined. So pretty close to persistent open struct, but the implementation is totally different. The first thing that you have to see is that on the class level, we have two methods. We have an attribute method, which just holds onto a set. A set is kind of like an array, but you can look up much more quickly whether something's a member or not. That's probably its own talk. It's actually pretty cool. So we have our set of attributes that we've defined on our class. And then we have the add methods method. And what add methods does is it just calls add a writer and add a reader, just like a regular Ruby class. And of course, it just checks if you want to write your own add writers and add readers, so we're not going to step on your toes. But otherwise, we just call add a writer and add a reader, and then we mark that attribute as having already been added. We're going to just add that key to the attribute set. So keep that in mind. What happens when we create a new animal? Again, animals are a dynamic class, example, with a key of bads and a value of four. So this is how initialized looks. It's very different from what you've seen before. So for every set of attributes that you're passing in, it actually will send the attribute or the key equals method with an argument of value. So in this case, it's basically the same as creating a new animal, and then you call dot baz equals four. Well, there is no baz equals methods. We're going to hit method missing. Here's how method missing works. That reg x is scary. I know, but just trust me that it works. It's testing. Is this a setter? So if it is a setter, then we're going to call the bracket equals method with our key and our value, so baz and four. Otherwise, it must be a getter. So we call the brackets method. So like dot baz, we're just going to call bracket and then baz in the middle of the brackets. Here's how those methods look. So the brackets method is pretty straightforward. It's just an instance variable get. We're getting whatever at baz is inside of our instance. And the bracket equals method is where the magic starts to happen. We coerce the key to a symbol. We do an instance variable set. We're setting, in this case, at baz to four. We're setting our key to our value. Again, just standard instance variables. And then we say, OK, if we got here, it's possible that we have to define a new attribute. So do we already have that attribute defined? And if not, then we just add those methods. That's what we saw before, that add methods method on the previous slide. And what's cool is that the next time that you create an instance, those methods are already defined. So in initialize, when we call baz equals, we're just going to have that baz equals method. And it works just like a standard adder writer. So we no longer are relying on this internal hash table. We're just using instance variables. It is a regular class. Just it's dynamic, because on the fly we're defining the adder writers and adder readers that we need. And that's actually a lot faster. It's 40% faster than persistent open struct. It's eight times faster than open struct. And it's still about three times slower than a regular class. But it's close enough at this point, I think, that you can justify using it in your production apps unless they're really, really performant sensitive. It's good for the same purposes as persistent open struct, but it's faster. And to me, what's really important is that it works the way that persistent open struct really always should have. When I wrote persistent open struct, I was very, very focused on the open struct way of doing things. And when I freed myself of that restriction, I realized that there was just a better way to do this and basically keep the API, but have a different underlying way of how it works. OK, let's start to wrap up. Persistent open struct made me happy. It was a really good learning experience. And it also worked really well. Dynamic class made me happier, because I think it was just a much cleaner solution. And to me, that's the bottom line. Maybe people are going to see this talk and start using it in their apps, and that would be great. I'm really happy to help out people. But even if that doesn't happen, even if I'm the only one who ever uses this, that's fine. I had a really great experience and learned a lot creating these solutions. So what have we learned? I would say five things. One, we kind of had this worshipful attitude towards the standard library in the Ruby core. It can be improved. It was written by human beings, and there's always room for improvement. We saw from what Eric Michaels over did, and we saw from what James Golic did, there's room for improvement. Two, optimize for your use case. This is really important in terms of performance work. It doesn't matter how good your solution is in every use case. All that matters is your use case. And sometimes a specialized tool might work a lot better than a standardized tool. Think about knives. If you have to cut watermelons and you have to cut grapes, you could theoretically do them both with the same kind of standard knife, but it'll probably work a lot better if you get specialized tools for each situation. Three, I can't emphasize this enough. You have to benchmark. Okay, don't trust your intuitions. I can tell you my intuitions are wrong all the time, and yours will be too. So make sure that you benchmark to validate your hypotheses. Four, I wanna encourage everybody to experiment. Experiments are awesome. You learn tons of things. It's just a lot of fun. And occasionally you could create something that's actually really useful. So do more experiments. There's little downside, and you always learn something. And here's the last thing. And to me, this is the most important point here that I wanna stress. I had a problem. I profiled to zoom in on the problem, looked at the source code, looked at the solutions that are out there, and thought about it a little bit camp with an idea. Benchmarked to verify that my idea was correct. And then made it into a gem. There's nothing in that whole series of events that any single one of you can't do. You will come into problems. You don't have to be the most brilliant programmer to make a difference.   Or to make improvements to existing solutions that no one else would think of. So, please, don't sell yourself short. You can do it. It only takes one person to invent a really great tool. But if that tool is gonna work for the community, everyone in the community has to be involved. OpenStruct is a really, really nice tool, but it took a lot of different solutions coming from different people in order for it to really work for everybody. There's more work to do on OpenStruct. There's more work to do on a lot of things. Be part of the community and make our community so much richer. Thank you.


Hill City, Northland taking on the third-seated Carlton in the section 5-9, man. Started the second quarter Hill City, Northland with the ball. They had everyone looking left, but Tucker Holm would run it on to the right side for six points. Later Carlton responds. Ryan Gray looking for an opening has time and finds Matthew St. Kyle, who evades the defender. Nice move there for the touchdown. Carlton turns on the heat and they win this one 28-14. If you enjoyed this segment of Lakeland News, please consider making a tax-deductible contribution to Lakeland PBS.