1 00:00:00,600 --> 00:00:01,640 Hello, everyone. 2 00:00:01,800 --> 00:00:04,400 Today we're talking about errors frequently made 3 00:00:04,560 --> 00:00:08,360 by Pharo developers including myself. 4 00:00:08,520 --> 00:00:12,520 We'll see how to find and fix common mistakes faster. 5 00:00:13,560 --> 00:00:16,280 Here we have a bit of code. 6 00:00:16,440 --> 00:00:20,000 When it's executed, a debugger opens 7 00:00:21,080 --> 00:00:24,880 and tells us that the message "self" has been sent to an object 8 00:00:25,040 --> 00:00:27,680 and this object doesn't understand the message "self". 9 00:00:27,840 --> 00:00:32,400 We might say that "self" isn't a message that's sent very often, 10 00:00:32,560 --> 00:00:36,120 so there's probably a mistake somewhere in the code. 11 00:00:36,280 --> 00:00:38,680 Taking a little look at it, 12 00:00:39,840 --> 00:00:41,800 we see there's a period missing, 13 00:00:42,760 --> 00:00:45,800 and so the execution is happening as though 14 00:00:45,960 --> 00:00:50,360 "self" was a message sent as a result of "DiceHandle new". 15 00:00:50,520 --> 00:00:53,640 Since the DiceHandle class doesn't have a "self" method, 16 00:00:53,800 --> 00:00:56,000 the debugger opens. 17 00:00:57,560 --> 00:01:02,240 So the solution is to add this period at the end of the first line. 18 00:01:03,720 --> 00:01:06,600 Another problem we often see 19 00:01:06,760 --> 00:01:11,920 is messages that shouldn't theoretically be combined that are combined. 20 00:01:12,080 --> 00:01:16,280 So here we have an error saying that "includes:ifTrue doesn't exist". 21 00:01:16,440 --> 00:01:19,400 "Includes" exists,"ifTrue" exists, "Includes:IfTrue" doesn't. 22 00:01:19,560 --> 00:01:21,560 Looking closer, 23 00:01:21,880 --> 00:01:24,720 we realise that indeed 24 00:01:24,880 --> 00:01:27,240 the message is being sent "includes:ifTrue" 25 00:01:27,720 --> 00:01:32,120 to receiver "x" with 2 parameters, "33" and a block, 26 00:01:32,320 --> 00:01:34,320 and that doesn't work. 27 00:01:34,480 --> 00:01:36,600 When Pharo sees a key word, 28 00:01:36,760 --> 00:01:39,120 it tries to see all the subsequent key words. 29 00:01:39,280 --> 00:01:41,880 It takes them all and considers it as one message. 30 00:01:42,040 --> 00:01:44,160 So what's missing here 31 00:01:44,320 --> 00:01:45,920 is a pair of parenthesis to say 32 00:01:46,080 --> 00:01:49,480 that the message "ifTrue" is sent as a result of "x includes:33". 33 00:01:50,520 --> 00:01:54,440 In the same way, "assert:includes does not exist", 34 00:01:54,600 --> 00:01:57,760 what we wanted to do was "assert on the result of includes", 35 00:01:57,920 --> 00:02:01,440 so the parentheses are missing here. 36 00:02:02,040 --> 00:02:05,680 Don't hesitate to put parentheses when you have 37 00:02:05,880 --> 00:02:09,280 multiple keyword messages in the same expression, 38 00:02:09,440 --> 00:02:13,200 to delimit them, because Pharo will try to group keywords together 39 00:02:13,360 --> 00:02:16,160 and consider it to be one message. 40 00:02:16,400 --> 00:02:18,600 In this example, 41 00:02:19,080 --> 00:02:23,320 we want to have a collection of numbers in Numbers, 42 00:02:23,480 --> 00:02:27,720 and for the moment, there's only one number there, 35. 43 00:02:27,880 --> 00:02:33,000 However, if we see what's in numbers, its not a collection, it's the number. 44 00:02:33,160 --> 00:02:35,840 It's the number 35, so there's a problem. 45 00:02:37,200 --> 00:02:41,240 In the same way, in this code, 46 00:02:41,400 --> 00:02:45,120 if I send the message "new" to the Dice class 47 00:02:45,280 --> 00:02:47,400 I get the number 6 48 00:02:47,600 --> 00:02:49,200 rather than a 6-sided die. 49 00:02:49,600 --> 00:02:52,200 It's the same problem in both examples. 50 00:02:52,360 --> 00:02:54,360 If we look more closely, 51 00:02:54,520 --> 00:02:57,880 adding "yourself" after "add" 52 00:02:58,040 --> 00:02:59,520 will correct the problem. Why? 53 00:02:59,720 --> 00:03:02,280 Because "add" returns its settings. 54 00:03:03,000 --> 00:03:05,560 So "OrderedCollection new add: 35" 55 00:03:05,720 --> 00:03:07,920 returns 35. 56 00:03:08,080 --> 00:03:12,000 If we add the string to "yourself" we're sure to get the receiver at the end 57 00:03:12,160 --> 00:03:14,200 and Numbers will be a collection of numbers. 58 00:03:14,840 --> 00:03:15,960 So the solution here 59 00:03:16,160 --> 00:03:20,640 is to add "yourself" at the end of each message. 60 00:03:21,560 --> 00:03:22,680 Here's another problem. 61 00:03:22,880 --> 00:03:26,000 Here we have a Book class in "Borrow" method. 62 00:03:26,160 --> 00:03:29,200 When we execute, we get the message 63 00:03:29,360 --> 00:03:32,040 that "nil does not understand ifFalse". 64 00:03:32,200 --> 00:03:35,960 So we send the message "ifFalse" here to nil. 65 00:03:36,120 --> 00:03:38,440 What does that mean? It means that in library 66 00:03:38,600 --> 00:03:41,360 at the value nil, which has the default value of all the variables, 67 00:03:41,520 --> 00:03:46,360 we can say that probably "inLibrary" has never been initialized. 68 00:03:46,520 --> 00:03:51,440 We have to put a default value in that variable. 69 00:03:51,600 --> 00:03:53,960 It's pretty easy to correct 70 00:03:54,120 --> 00:03:56,240 by adding the method "initialize", 71 00:03:56,400 --> 00:04:01,880 which from the creation of each instance of the Book class 72 00:04:02,040 --> 00:04:04,480 will put the value "True" 73 00:04:04,640 --> 00:04:07,280 in the instance variable in Library. 74 00:04:07,640 --> 00:04:09,680 Except that if we execute this code now, 75 00:04:09,880 --> 00:04:12,280 we'll get another error message, 76 00:04:12,440 --> 00:04:16,800 "Class True does not understand ifFalse". 77 00:04:17,520 --> 00:04:21,200 Where does this come from? It's because, what we put here, 78 00:04:21,360 --> 00:04:23,040 is a class. 79 00:04:23,200 --> 00:04:25,400 It's not a Boolean, it's a class. 80 00:04:26,040 --> 00:04:29,360 The Boolean is "true" with a small "t". 81 00:04:30,480 --> 00:04:34,880 Classes generally have a capital letter, 82 00:04:35,040 --> 00:04:37,280 so "True" with a capital is a class, 83 00:04:37,440 --> 00:04:41,240 and "true" with a small "t" is the unique instance of the True class. 84 00:04:42,000 --> 00:04:43,920 Here's another problem. 85 00:04:44,240 --> 00:04:46,840 In the "roll" method in the Dice class we expect, 86 00:04:47,000 --> 00:04:49,760 when we roll a Dice, to get a number 87 00:04:49,920 --> 00:04:52,520 between 1 and the number of faces on the die, 88 00:04:52,680 --> 00:04:56,280 except that here, when we roll the die we get a die 89 00:04:56,440 --> 00:05:00,200 and not the face we landed on. 90 00:05:01,200 --> 00:05:05,520 The method I just showed you is equivalent to the method below. 91 00:05:05,800 --> 00:05:10,760 This means that by default, a method that returns nothing returns "self". 92 00:05:11,680 --> 00:05:15,680 This means our "roll" method, when executed, returns the die 93 00:05:15,840 --> 00:05:18,360 and not the result of sending "roll"... 94 00:05:20,040 --> 00:05:24,120 Not the result of sending "atRandom" to the "faces" collection. 95 00:05:24,920 --> 00:05:27,360 So the same problem in a slightly different example. 96 00:05:27,800 --> 00:05:31,200 Here, we're creating a new method, 97 00:05:31,360 --> 00:05:33,400 in the Dice class, 98 00:05:33,560 --> 00:05:35,080 so in Dice class, 99 00:05:35,240 --> 00:05:39,400 we want to make a new method to create instances in the Dice class, 100 00:05:39,560 --> 00:05:43,120 which initializes by default the number of faces at zero. 101 00:05:44,120 --> 00:05:46,880 If we send the message "new" to the Dice class, 102 00:05:47,040 --> 00:05:49,480 what we'll get is the Dice class itself 103 00:05:49,640 --> 00:05:52,120 rather than a new instance of the Dice class. 104 00:05:53,040 --> 00:05:54,080 So in both cases, 105 00:05:54,280 --> 00:05:56,760 the fact that there's no return in "return self" 106 00:05:56,920 --> 00:06:01,240 and "self" by default is the receiver, in the case of a class method 107 00:06:01,400 --> 00:06:02,760 "self" is the class. 108 00:06:03,200 --> 00:06:04,920 To correct these 2 problems, 109 00:06:05,560 --> 00:06:09,520 we just have to add the caret ^ to return to a specific value. 110 00:06:11,200 --> 00:06:12,160 Next problem, 111 00:06:12,600 --> 00:06:15,480 if this code is executed, 112 00:06:15,640 --> 00:06:20,520 the system seems to be frozen and nothing else happens. 113 00:06:20,680 --> 00:06:23,360 It's impossible to interact with Pharo. 114 00:06:23,960 --> 00:06:25,120 What causes this problem? 115 00:06:25,440 --> 00:06:29,000 It comes from the fact that we're implementing a new method 116 00:06:29,160 --> 00:06:31,920 in Dice class. 117 00:06:33,200 --> 00:06:36,280 "Self" is Dice 118 00:06:36,440 --> 00:06:40,960 and so "self new" will call itself recursively. 119 00:06:41,320 --> 00:06:42,680 The intention here 120 00:06:43,280 --> 00:06:46,640 is to use the creation of instance by default 121 00:06:46,800 --> 00:06:48,560 defined in the Dice superclass, 122 00:06:48,720 --> 00:06:51,400 and then add things in relation to that. 123 00:06:51,560 --> 00:06:53,920 By writing like this, we have an infinite loop, 124 00:06:54,640 --> 00:06:57,680 so we need to replace "self" with "super" 125 00:06:57,840 --> 00:07:01,720 to request the implementation of the superclass. 126 00:07:03,000 --> 00:07:04,880 What you should know, 127 00:07:06,520 --> 00:07:08,360 we all make lots of mistakes. 128 00:07:08,520 --> 00:07:11,600 The ones I've shown you are very frequently made 129 00:07:11,760 --> 00:07:13,800 by all Pharo developers, 130 00:07:13,960 --> 00:07:17,880 so there are things we find very frequently: 131 00:07:18,040 --> 00:07:20,360 missing periods, 132 00:07:20,520 --> 00:07:22,240 parentheses, 133 00:07:22,400 --> 00:07:24,480 missing carets ^, 134 00:07:24,640 --> 00:07:26,160 and "yourself". 135 00:07:26,840 --> 00:07:29,800 Try to use the debugger as much as you can to find 136 00:07:30,000 --> 00:07:33,280 the root of problems. It will really help you. 137 00:07:33,440 --> 00:07:36,040 Don't close it as soon as it opens. 138 00:07:36,200 --> 00:07:39,520 You'll be missing out on a way to fix problems.