 This is Matt, sorry for the connection trouble. The programming language is a hot topic among the developers. Some people like Ruby, some people like Python, and then some fight each other, like Emux in the game. But for most of the people, the programming language to study, you know, you study programming language to implement your application, so that you study C, Java, Python, or Ruby to implement your application. But for some people, programming language to create. For those people, including me, the language design matters. And I believe it matters to you too. Oh, I'm sorry. Could you wait for a second? I made a mistake in my slides. So because the learning, the design of the programming language makes you a better programmer so that you have a better programming skill. And then you will understand the rationale behind the language design so that you don't have to worry about the random choice in the programming language. Sometimes you wonder why this method or this language feature design like this, but if you understand the design of the programming language, probably you can understand the design philosophy or policy behind the design in Ruby, Python, whatever. And then there's no one side game so that programming language designers make some kind of compromise each day so that we have trade-off. When we focus on the performance, maybe we have to sacrifice the usability toward the programmer. The programmer has to write more to achieve the performance in some cases. Or if you want to write your program in very concise way like doing the metaprogramming, you have some kind of side effect of some kind of hiccups or something like that. By learning the design of the programming language, you can understand the trade-off in the design of the languages and the design of your application. So the trade-off is our friend so that we have to face trade-off each day as a programmer. But by learning, studying the design of the programming language, you can learn some kind of case study of the trade-offs. Then not everyone but some of you might try creating your own programming language. Maybe your programming language may not be popular but designing your own programming language itself is a very valuable experience and I believe it will make you better programmer. In this presentation, I'm talking about the design of Ruby language through the reserve words and the source of inspiration of design Ruby. Ruby has 41 reserve words. That's kind of many. Each reflects the early design decisions of the language. The story behind those reserve words. Ruby is kind of famous for using the beginning and end so that unlike other programming languages like Java or JavaScript or C, they use braces to create the code blocks. But instead of using braces, Ruby used the end keyword. Ruby program will see a lot of the ends. But it's kind of intentional. It is called Algol style. In ancient time, we had a programming language named Algol that created right after the Fortran. Most of the current programming languages are influenced somehow by Algol. Then Algol used the beginning and end to note the code blocks. But the programming language like Algol or Pascal or those languages used the beginning and end as code parentheses, code blocks. The code blocks begin with the keyword begin and end with the end like braces. But in Ruby, we don't use begin that much because Ruby used the second generation of the begin and end style, which is a comb style indentation. Like we have if, then code blocks, then else, then code blocks, and end. This is kind of like a comb, hair comb. So we call them the cold style indentation. That style is inherited from the programming language named Eiffel. Eiffel is a less popular programming language, less famous programming language designed in the 80s. But it's a kind of interesting programming language. Even though it's created in the 80s, it has the JIT compiler. It has the multiple inheritance. And then it is quite an interesting approach to the object-oriented programming language. So back then, the only major object-oriented programming language is C++ or Smalltalk. Then back then, Eiffel came in as a very unique programming language. It's kind of modern things. But unfortunately, Eiffel didn't get the popularity that much. So very few people still use Eiffel. But in the late 80s, I was a university student, and I bought a book about the programming language Eiffel, and I influenced a lot. I inherited those com style indentation from Eiffel, and those key was rescued and ensured and we tried. Those key words are inherited from Eiffel, from a little bit different way though. Okay, next. In Ruby, we have the key words reserved for us like a break. Next, we do, which controls the loop execution. So the break time is a loop. Next, skip the execution of the loop into the next iteration. And we do restart the execution of the loop from the start. And then we don't use continue as in C or other languages. Next is inherited from Perl. And then because it's shorter than continue. The very early stage of the Ruby design, the Ruby was influenced heavily from the language named Perl. Because I started developing Ruby in 1993. Back then, Python is not that popular. Java is not popular. Java didn't exist at all. And as a scripting language, the Perl is the major thing. So I try to mimic Perl. I try to, my programming language as a replacement to the Perl programming language. Actually, I confess that I regret mimicking too much. But that tells you that it is quite difficult to foresee the future. For me, 25 years ago, mimicking Perl is a good strategy. It seems to be a good strategy. But two decades later, the Perl is nearly gone. And Python is popular. So probably I should have mimicked more Python than Perl. But actually, I stole some ideas from Python. For example, the class and death is a stone from Python. And the idea of module is from Lisp. Actually, the old object-oriented Lisp is named Flavors. So that object system, Flavor object system, invented the idea of the mixing, which is the base of the idea of the module in Ruby. Next. We have very usual if, else, and else if. This is quite usual. But else if is kind of a controversy. Some people prefer else if. And some people use else if. Some other languages like Python and Shell use else if. What do you choose? It's arbitrary. So else if you feel okay, else if, else if. I pick else if because that is the shortest-pronounceable combination. But else if is not really a short, not the same pronunciation of else if. It's different. Actually, it's the reverse of the file. But else if is unpronounced e is not really comfortable. So I pick else if. Then we don't use then in Ruby, but it's kind of a stop-word. Actually, we have the dem method and the class method in Ruby. That allows me that if it is clear, you can use the method with the same name of the reserved first. This is unusual for the programming languages. But if you want to retrieve the class of the object, you want to call the method what the method name should be. Class. But the class is a reserved word. So in many programming languages. So it has a zero. But the class method is so natural so that I allowed using the key method name with the reserved word. Unless, yeah, it's from Pearl. Maybe we didn't need it. And then it's, you know, reverse was sometimes difficult. But putting not in the front of the conditions and wrapping in the parentheses, it's kind of agree. So we sometimes use the unless. But we don't provide the else if or else unless class. Because that kind of thing is too complex. Okay, just use F statement for those cases. It gets confusing. While is while. Every language has a while loop. For loops. I don't remember, but probably it's from Python. Until. It's a loop thing. Yeah, you get it. It's from Pearl. And then in condition, we use the true, false, and no. And then that's indicated that the concept of the truthy and falsely in Ruby. Unlike other languages. Nail and false are false. It's kind of confusing. Nail and false are falsely. And everything else is truth. In other languages, like a zero is a, is a false. And empty array or empty hash is a false. But you know, it's one thing. It's confusing. So that it should be clear. Then in addition, it's kind of costly. Okay, I have this string. Okay, this must be true or false if the length is zero. So that we have to look into the structure of the strings and check the length of the strings. Or if the value is the array, we have to look into the inside of the array structure, then check the length if the length is zero or something. It's kind of costly. And the condition, the loop condition is checked so many times so that I want to optimize the truth checking. Actually, in Ruby implementation, the truth and false decision is only one bit checking. It is quite lightweight operation. But if I allow the empty array to be false, we have to check using the functions or something. Or maybe if I allow the object to be overlaid at two Boolean or something, and if two Boolean returns true, the value is true, or if two Boolean returns new, it should be new or something like that. We have to call method implicitly every time in every conditionals. That is costly. I know Ruby is slow compared to C++ or something. I want Ruby to be even slower so that I just skip that kind of things to optimize the conditional checking. In addition, by using false and new, we can implement the three-value logic. The implicit false for the false value and then new for in-existing value or something like that. In some language like SQL, we have three-value model, three-value checking. They are non-existence and are considered as a false, and then everything else is true. Then almost accidentally Ruby can provide a three-value model. It's inspired by the traditional list. Traditional list has both false and new. Then I inherited this idea from this, and or not. Ruby has the operator named alphabetical and or not. These are taken from Pro, and it's there for only four procedures. Having a large operator or two vertical bars operator has kind of the precedence issue. When in doubt, we have to put parentheses around the expression. This and or not has a very low precedence so that you don't have to worry about breaking the expression. In Ruby and or, these two logical operators have the very low same precedence. Because in English, we don't have precedence over the and or. When you use the and or in the English sentence, you have to worry about confusion. That's why these two precedence are the same. It's called block. In Ruby, you can put the fragment of code after the method code, which is called block. The idea is taken from the language named clue, which is invented in MIT in the 70s. It's kind of modified from clue because in clue, these kind of blocks, they called iterators, are only used for loops. But in Ruby, you can use blocks for loops, callbacks, and code blocks, scopes, in many use cases. That kind of enhancement, I believe, is the biggest invention of Ruby. Actually, it's kind of similar to the higher order function in other programming languages like Lisp, Haskell, and those functional programming languages. In one survey, 98% of the higher precedence function, higher order function, takes one function. That means that for most of the cases, except very few cases, taking one function is sufficient. That means that if taking one function is sufficient, the restricting method to be taking one functional argument, and then take a special syntax for that kind of one function, a higher order calling, is good and very usable and easy to read in the language. That's why the method called block is the biggest invention of Ruby. Actually, the modern programming language like Swift, or Groovy, or Elixir, takes this idea from Ruby. This is kind of a neat idea. Rescue and share, we try. These are exceptions. In some languages, they use the word try and try except or something like that. I don't want to use that term try because exception is usual, so that every method is usual. I don't want to, okay, this method might raise error, so that should I try or something like that? This is kind of weak-minded. I want to be, okay, this method may cause, this region may cause exception. I want to handle exceptions in those methods so that just begin is good enough to say the region. Okay, shall I try? No, just begin. Then, okay, it's okay except this error. No, something bad happens. We have to rescue them. This was taken from IFL as I told you before, but I don't regret the choice of the words. Actually, in the early stage of Ruby design, there are languages named icon, which is not the icon in the screen, but it predates the term icon. That language has the success-failure model. Every function can success with value or failure. For the user of the modern programming language, every method can return an option, or maybe in, for example, Swift. Those modern programming languages use the value of the success-failure model. But in the ancient programming language named icon, everything was a success-failure model. I tried to use this model in Ruby in a very early design, but it's too different from other programming languages. So I just gave up and then used the exception instead. Return is return. It's from C, but in Ruby, the return takes multiple values using the array in Ruby. Ruby used the keywords named self and super, which is inherited from smalltalk. It's a parent of the object system of Ruby. If you had a chance to look into the Ruby source code, and in the file named object.c, which has some weird diagram of the class hierarchy, you have object, object has a class, and the class is the instance of a class class, and the class is the instance of an object, but the object itself is a class. It is kind of a loop. So this kind of the weird object model is inherited from smalltalk. Actually, class has its own class named metaclass, and the metaclass itself is a class. Kind of confusing, but those whole object system is inherited from smalltalk. alias and and death. Unlike other programming languages, Ruby put the alias of the method, and then you can even remove the method from a class. This is kind of a weird idea. According to the basic design principle of the object-oriented design, there are the basic principles of the LISC of replacement principle. The LISC of is the professor of MIT, which she happened to invent a language named Clue, which is the source of the block, the idea of a block. The LISC of replacement principle is that subclass must satisfy the role of the superclass. Using and death is clearly a contradiction to the principle. But the idea is taken from the language named the CESAR, which is invented in the 1980s in the University of California Berkeley. CESAR is the mimic language of the Eiffel, but it implemented its own ideas. When I stole the idea of the alias and the death, the version of the CESAR was the version of 0.8. And then the CESAR is totally gone. After the designer was graduated from the UCB, he stopped developing it, and they gradually disappeared in the history of the internet. But when you Google it, you can find the documentation of the version named the CESAR version 1.2, which is the latest version, which doesn't have alias and the death. Actually, I regret a little bit about putting and death to the language. Begin and end in capital. You may not know that, but if you put the begin in your program and put a brace around that, those codes will be executed in the beginning of your program. And if you put the capital in and put a brace around the code, those programs will be executed at the end of your program. It's the idea is taken from... Oh, taking a picture? The idea is taken from AUK. Remember, Ruby was invented as a scripting language, and AUK is one of the scripting languages. I assumed it was a good idea, but nowadays, people don't use Ruby as a scripting language. You use Ruby as a web programming language, a general-purpose programming language, so that probably we don't no longer need to begin and end no more, so that it's not recommended anymore, but it's still there. File and line, so that you can get the file of the program and the line number of that particular line. It's from C. In addition, Ruby has the encoding, which is the file encoding from 1.9. Let me tell you a little bit about that. In the 80s and early 90s, we didn't have Unicode, so that each country has its own character encoding. The English-speaking people are OK because ASCII can express everything, but an unfortunate country like Japan or China, so that we need more characters, actually thousands of characters, so that we have to invent our own character encoding, and then we have to handle those encodings in our program. To handle those characters, there are two ways to handle it. One is the universal character set approach, which is basically the Unicode. The other one is a character set independent approach. The easiest approach is to process the text data, first convert everything into Unicode, then process the text, then convert back into the legacy encoding and write in the file. This is natural, but it has a problem. Because character set encoding is legacy, there's no way to predict which encoding is correct, because, for example, in Japan, we have a character encoding scheme named as ShiftChess, which can describe the Japanese character set. But we have tons of dialects. IBM has its own dialect, Microsoft has its own dialect, and adding a little bit more characters for their own companies or something like that. There's no way to tell the difference between the IBM encoding and the Microsoft encoding. When you try to convert the ShiftChess text into Unicode, it really was an IBM encoding. The data was lost. When the text processing data is wrong and you convert it back to ShiftChess, you will have the broken text. Or, maybe by some errors, maybe the character is broken, the total conversion will collapse and the whole text might be lost. That kind of thing would happen if you have tons of the legacy text. Repeatedly, English-speaking people are OK. Most premium language designed by the English-speaking people or European language, very limited character set. For them, the byte encodings are good enough. That's OK, but for us Asian people, we have very huge trouble. That's why Ruby people picked the call set independent approach. In Ruby, you don't have to convert anything. For ShiftChess text, you can process it as a ShiftChess. For the Unicode text, you can handle them as a Unicode, UTF-8 or UTF-16 even. Or maybe in the legacy Chinese encoding or legacy Taiwanese encoding, you can handle them without any conversion. It was designed in the 90s. These days Unicode is almost taken over the world. Maybe the future programming language will no longer handle the legacy encoding. But for us, especially in that age, 10 years ago, 15 years ago, it is quite important for us to handle legacy encoding. These are Ruby's reserved words. Those words are taken from other programming languages, and we think very carefully to which language to steal the ideas, that concept. In addition, let me explain something new. Chaining operators. In languages like Fsharp from Microsoft and Elixir, we have something named PipelineOperator, like this. By PipelineOperator, you can combine two functions in diverse ways. In Ruby, you can write like this. It's almost similar. The original idea of PipelineOperator is invented in Fsharp and ML-like family language. Its definition is this. This is the PipelineOperator definition. ML-like language, by wrapping in the parentheses, you can define the function name with the operator names. It takes two arguments, X and F. Then you can call the second argument as a function. Then the first argument is operand. That means that you can add the primary argument at the last of the arguments. For example, the map function. Map function in Fsharp and ML languages. Map function takes an array and a function and applies each element in an array in a collection to the function. Then in ML family language, the function comes last of the arguments. The array is the first argument of the map function because map is very important. We call them primary arguments. The primary argument comes first, function comes last. In Elixir, PipelineOperator is defined as a macro and it adds primary argument as the first argument of the function call. The map function in Elixir, the array comes first. I'm sorry, I made a mistake. The first argument comes first. The collection comes first. The function comes last. I made a mistake. The primary argument in ML language, Fsharp, function comes first. Then the array comes last. In Elixir, it's reverse. It's now no wonder. The basic culture behind the language is different so the function argument order is different. That's okay. The concept of the PipelineOperator is the primary argument to the call. That's important. No matter which order of the function call, the PipelineOperator has the primary argument of the left-handed expression put to the call in the proper place of the language. If I add the PipelineOperator in Ruby, I add the primary argument to the call. Then remember, in Ruby, the map method takes the primary argument, which is the array, as a receiver of the call. Unlike Fsharp or Elixir, we don't put it into the usual argument, but the receiver. As a result, the PipelineOperator in Ruby becomes the alternative syntax of the method call .operator. In Ruby, the different operator precedence already exists, like blocks. We have two forms of the blocks, like do and end and braces. It has the different precedence for that. By using the PipelineOperator, we have less parentheses, like an example above. Like this and this. This and this. Little bit less parentheses. I thought it was a good idea. I thought it was a good idea. But let's see. We experimented. We put in the master of the development branch of Ruby. Let's Ruby. Unfortunately, people don't understand. For them, the concept of the PipelineOperator is adding the left-hand side expression as a usual argument of the method call. That is crucial for them. I explained about the primary operator. In Ruby, as a culture, the primary operator comes as a receiver. The natural consequence is adding the primary operator as a receiver. Still, people don't understand. The language design is built upon the common sense, the shared knowledge between users. This fact indicates that we don't share the same concept of the PipelineOperator. Even after explaining it, many users stick to the previous idea of adding left-hand side expression into the ordinary argument. It's kind of a recognition problem. If I were very stick with this idea, if I strongly opinionated about this idea, I would try to proceed with the community with years ahead. I'm not that passionate about this idea. Having a few less percentages is okay. It's a little bit very beautiful. But if not, it's okay. I gave up. It's before the 2.7 final release. It was just an experiment. I had to experiment. Unlike the early stage of Ruby, it's quite difficult to change Ruby language because even the slightest backward compatibility makes many, many, many calls. We have to experiment heavily before making any changes. We usually take a one-year cycle between releases because we have the time slot to experiment the ideas. As a community, we have to keep moving forward. But at the same time, we cannot break the code. It's kind of contradiction whether we, the core developers have to take this kind of a narrow path. At least through this discussion, we get some ideas. In the past, we cannot allow the comments between the method chain like this. When RubyProser sees this comment, it stops the method chain. But it's kind of the bad things. It's kind of against our expectation that we fix our parsers to allow this comment between the method chain. This is one good thing. And we are aware of the requirement for the right assignment. When we have to write the assignment, the resulting value from this method chain, this method chain, you have to go back to the top and assign to the variable. But it's against our eye movement. Go like this, left to right, top to bottom. Then when you assign it, you have to go back to the top then assign to the variable. But if we allow the right assignment like this, I process this, then that, then that, then that, then assign to the variable. It's kind of natural. We are still experimenting with this idea, but we might see it in the future. Making this decision is quite tough. We need a scope of it. Every change has its scope so that you cannot break the existing code and your change might affect the unexpected region. Every change has its background, like I say. The pipeline operator has this policy or something like that, but this policy and recognition might not be accepted by the major members of the community. And then we need the motivation behind the change. Maybe by using these changes, the Ruby code will be more readable or more easy to write or something like that. And then this is kind of tough choice. The making decision, especially the language design, is tough choice. Then we use the way we call it BDFL, Venomol and the Data for Life. Taking one person to make every decision, trying to be consistent, trying to be better. But some other languages take a committee style. For example, PHP takes a committee style. Every change is voted. Then every change is decided by some kind of a democratic way voting. But I'm not sure. I don't think that would work well with the programming language because I see it with Climb and Mountain with many captains or too many cook spoils. So the language design has very many issues and consideration. In summary, we took many ideas from the pre-existence, foreigners, and combined them in harmony. That is good. We have a lot of contradiction between language features, but we have to resolve it and we have to make trade-offs. The toughest part in the language design is making decisions. I think it is the same to the software design. The toughest part in the software development is making decisions. Programmers are the biggest role in making decisions. Serving pre-existence or taking ideas from others, and adopting the ideas into the current software. Once you make a decision to go through it with confidence, that kind of leadership and making decisions is a crucial part of the software design. This is all my talk. Thank you for listening. Thank you.