| If there are extra things, the test doesn't match. Mark Guzdial |
| Sorry, let me answer that better. If there's a POSSIBLE match, take it. If there's a way of making it true, take it. Mark Guzdial |
| That is my understanding of the assignment also. -DR |
| Folks, the reason why I had you make Who's Who pages was so that you could sign your messages. Please do so! There's a fudge factor in the grading scheme based on participation. How do I figure out participation if you don't sign your notes? |
| Your interpretation is mostly correct, except for a vocabulary problem. You're going to create a class WordMatcher. The INSTANCES of WordMatcher will accept rules and strings and do a match returning true, false, or a Dictionary. No, there's no transcript or "terminal" interaction here. Mark Guzdial |
| There are examples there. If your rule has "I am" then you should match "I AM" or "i am" – simply lowercase the matching tokens. But if your rule has "!name" in it, then you should match either "Mark" or "eric" or "WhATeVeR" and retun the variable's value mixed-case. Mark Guzdial |
| My guess is that it's just saying to compare against the rule case insensitively, but when we add words to our dictionary we should preserve the case that the user passed in. That was just my interpretation though. |
| Yes, there may be multiple variable declarations in a single rule. That will be necessary to handle indirect objects, such as "put the sword into the troll." Mark Guzdial |
| You can use whatever you want inside the instances. Remember that this is a class on Design – we're not going to specify the problems as much as in past classes, leaving it up to you to figure it out. (Mohammad, please reference your Who's Who page by putting your names in asterisks) Mark Guzdial |
| '39' asNumber – not too complex. But you're right that the variables should be Strings, so I'll update the problem. Mark Guzdial |
| First, don't change the title of the Questions and Discussions page! Second, ask questions about assignments on assignment pages, e.g. Questions on Fall2001 P1 Milestone Please, sign your messages. We'll explain "new" tomorrow (Tuesday). You need to give me some idea of what "Squeak crashed" means. Did you get an error notifier? What was the error? Mark Guzdial |
| If you assume that the input is a string of whatever matched, and that the input string could contain spaces and other tokens, then it could work for others, too. Mark Guzdial |
| Yes – that can be more than one token with special matching characters per rule. And yes, there may be cases, then, when it can be ambiguous, e.g., where you have two match-more-than-one next to one another. Resolve the ambiguity best you can. We don't plan to test you on ambiguous cases, but you need to make your matcher work for the rest of the assignments. Mark Guzdial |
| See above, Graham – resolve it as you'd like it to work for the rest of your milestones. For multiple or zero matched variables, separate by space and toss them into a single string. (Think about how you're going to use this: "Take the blue key" vs. "Take the red key" You're going to want a single string with "blue key" or "red key" in it.) Mark Guzdial |
| Assume that you're getting a String as input and let other cases generate message not understood errors. Mark Guzdial |
| I strongly suggest NOT to use TGEN. This is much closer to a regular expression matcher than to a parser. Mark Guzdial |
| Unfortunately there is no "asBlock" message for String, nor is there a "BlockContext fromString:" available either! So, what the heck, how come you can just "do-it" on the block in the workspace? its okay - you can invoke the compiler from workspace anyway, so think about passing your string of a block off to the compiler (Compiler evaluate: —).Webb |
| Like Webb says. Only call the Compiler evaluate: when you know that you have a block inside the string. "thirty-nine" isn't a number from Squeak's perspective. If you want to support that, you can, but it's not necessary. Mark Guzdial |
| yeah - it certainly is a problem - I didn't see it at first, sorry. Okay the Compiler evaluate: part is not screwing up - its when you actually test the block with whatever junk comes through match:, right? (i hope i'm on the same page) – okay so you need to wrap this failing part in another block — see p.106 for a way to prevent that pink box from popping up! working yet? Webb |
| Hang on – I wouldn't pass in the "value:" into the Compiler evaluate:. Instead, only use Compiler evaluate: to create the block, e.g., b := Compiler evaluate: '[:x|x asNumber]'. . Now, you can call b value: someInput. Yes, you do need to test if someInput is a string before you pass it in. In general, we're only going to test your code with blocks that will work with Strings. BTW, there is a way to capture the notifiers – see ifError: in Chapter 2. Mark Guzdial |
| String -> ArrayedCollection -> SequenceableCollection Eureka! all three answer (xCollection = yCollection)-Webb |
| Not that I'm aware of. There might be something there that could be used for that, but nothing obvious springs to mind. Mark Guzdial |
| Return true if there's a match but there are no variables. Return a dictionary if there are variables. Mark Guzdial |
| See my answer above – Compiler evaluate: '[some block]' will return a BlockContext object. Mark Guzdial |
| Booleans understand and: and or:. They also understand ampersand and pipe (and and or) but without short-circuiting. This is in Chapter 2. (Please do sign your messages.) |
| Yup – we plan on only testing with valid rules. Mark Guzdial |
| Answering a good question in class: '#name' allButFirst gives you 'name'. Mark Guzdial |
| Christopher sent me a nice piece of code that always works, and that's currently what's up there. Mark Guzdial |
| Basically. It can also be shared between classes. Don't use them. Mark Guzdial |
| Good question, Robert! Here's the point: There are GOBS of cool String/Array methods already implemented. Use those, don't write your own. Use detect:/collect:/reject:. Use first/allButFirst. Don't do everything with for loops and at:put: I'm trying to get you to dig around and find things to use. Mark Guzdial |
| typo I believe a Dictionary('name'->'Mark') Webb |
| Typo, like the WebbMan said. Mark Guzdial |
| Then look for uses of the Dictionary in the image, in order to get examples. That's why I did that shtick in class on how to take an example and generalize it. See if you can figure out where Dictionaries are used for examples. Mark Guzdial |
| Aren't there any number of variables allowed in a rule? Andy Foster |
| Oh, my suggestion is to keep the handling very simple and don't waste much time trying to be elegant or clever - memory and processors are cheap and Squeak cleans up after us. Andy Foster |
| Like Andy said, and remember "Dictionaries are your friends" Mark Guzdial |
| good question, because I don't think its possible right now, but you can at least look at the version history of the page and see what files have been uploaded. Right now there is no downloading because other students could come along and take your completed work! Webb |
| Every class understands the "class" message so you could do something like this. ( ( var class) = "Dictionary") ifTrue: [.... ]. Jared Parsons |
| Everything also understand isKindOf:, e.g., var isKindOf: Dictionary Be sure not to use double quotes as in Jared's example, but otherwise, sending class is a darn good idea. Mark Guzdial |
| Page 71 in the Squeak book has a very good explination of how alter the "new" class message Jared Parsons |
| I am not a TA. But one way to do this would be something like : |
| Ahmed is right. Jennifer, if what you wanted to write was something like "match: 'fred', 'ginger', 3" – well, you can't in Squeak. Parameters must be separated by methodname/selector markers, each ending with ":". Mark Guzdial |
| Each time you create an instance of WordMatcher, the new instance should have its own copy of OrderedCollection. If you declear your OrderedCollection as class variable, all instances will end up sharing one OrderedCollection. Why would you want do that? What won't work w/out it? Donghan Li |
| Well said, Donghan! Mark Guzdial |
| I'm just another student, but I think that that is an invalid match, Webb. in the rule you had "forever looking for an" that you did not match with the matching text. I'd interpret a valid match here to be only Dictionary ('claim' -> 'i spent' 'answer' -> 'answer!'). Correct me if I'm wrong though Chris Church |
| That is the exact point I mean. Why should "one or more" stop with just 'i spent'? Its much easier to just take more more more all the way to the end of the matched input. You aren't "wrong" though because it is entirely up to your interpretation to resolve the ambiguous variables the way you wish- make sense? Webb |
| Actually, it is wrong to match this way in this case because the match would fail. And as Guzdial mentioned above (very first post), if there's a possible way to avoid returning false, you cannot choose the case that would return false. if #claim ate the entire sentence, than the rest of the rule ("forever looking..") would not match the query, and so it would return false. However, As Chris mentioned above, there is a way to match it without returning false, so that's what your parser would have to do. I'm not a TA or anything, but I'm pretty sure about that. -DR |
| I disagree - this is parallel processing. It matches BOTH acceptable final states. You refer to: "if there's a possible match, take it". Ok, well if you can match it then what is to prevent the machine from entering an accept all state for that variable token (i'd really like to know a formal reason if you know -cause i'm just learning theory myself)? And then the other symbols proceed with their corresponding rules as well. It may not be the formally correct solution to an NFA - but I don't think the match is "wrong", especially under the leisure that is allowed in personal design. Webb |
| Actually, I think our discrepancy is simpiler than that. I agree that the # operator can consume the entire sentence.. however, that would cause it to return false. Lets look at the example again.. addRule: '#claim forever looking for an !answer' match: 'i spent forever looking for an answer!' Now "claim" can eat 0 or more words and "answer" has to eat exactly one word. Between those two, the words "forever looking for an" must appear unmatched. In otherwords, if they are matched in a dictionary then they cannot be used to fulfill the rest of the rule. Of course I might be wrong, but that at least is my understanding.. It'd be really great to have an official response to this.. *wink wink nudge nudge* -DR |
| Like David said: Find a match if one exists and return true. Ambiguity is up to you how you want to handle it. Mark Guzdial |
| Although I'm just a student, my understanding is that you should be able to handle that rule or any combination of variables and strings, despite positioning. Aaron Drew |
| "I am the Greatest!" doesn't have a variable or match token in it. "I am the Greatest !" (note the space) does, and it would match "I am the Greatest Butterfly!" Mark Guzdial |
| 'I am called !name and I am the Greatest!' does have a variable name, and name should be matched. If you look through the assignment, you'll see example with variables in the middle of strings (the block one is an example of it, but there are others too). Just a sample of what would match is 'I am called Steve and I am the Greatest!'. Aaron Drew |
| I think it depends on when you have class. As copied from the assignment page: "In class, please turn-in well-documented, hardcopy source code (at least two lines of comments for each non-accessor method, in-line comments at significant portions) with your name and student number on it. In addition, before class time, turn-in your code using the Fall 2001 Turnin Information with the code 'P1'." Hope that helps. Aaron Drew |
| Like Aaron said. (Gee, Aaron, you want a job? :-) Mark Guzdial |
| methodName: firstParam descriptorForSecond: secondParam descriptorForThird: thirdParam and so on. For example, to draw a point that needed a color, x coordinate, and y coordinate you could do drawPoint: color xCoordinate: x yCoordinate: y, and the variables in the method would be x, y, and color. Aaron Drew |
| The reason 'my name is Mark Guzdial' returns false is because the rule is 'my name is !name'. !name can only store one word, so there's nothing to store or match the Guzdial. Since it isn't stored or matched, the whole strng can't be match and is therefore false. Aaron Drew |
| I'm pretty sure each time you call match: you are returning a different Dictionary. When you did match: 'My name is John.', name should be John in the returned Dictionary. When you match: 'My name is Doe', the returned Dictionary has name with Doe. The two Dictionaries you return are unrelated to each other. Aaron Drew |
| Is this what you are saying. That everytime i add something to a dictionary it is a different dictionary. That would not make sense. The impression that i got was that everytime you make a new WordMatcher, you have one dictionary where everything is stored. So any matches that you get are entered in one dictionary. As far as i know, we are trying to build a game. So i would think within the game the dictionary would hold any information we want it to hold. And so only one dictionary would exist for each wordMatcher. If everytime we matched something and put it into a new dictionary, thus in the game.. we would have like hundreds of dictionary's. Is my thinking correct on this? So the question remains.. would it be "John", "Doe" or just "Doe". Thanks again. Shehzad Ashfaq |
| I agree with Aaron Drew's view, that each time you run match you are returning a new instance of a Dictionary. Otherwise, if you had multiple rules that had identifiers with the same name, when your dictionary instance is returned you don't necessarily know whether the keys contained in it are there from THAT "match:" method call, or from a previous "match:" method call, so you wouldn't really know whether the call succeeded. Furthermore, it wouldn't be difficult to merge small dictionaries into a bigger game dictionary, if you decided you needed to do that in the future. -DR |
| If you're using findTokens to get the OrderedCollection, each Token in the OrderedCollection is a string by default. Aaron Drew |
| You could use the , operator strings have to add them together. Just add a ' ' to them too and it should work fine. That help at all? Aaron Drew |
| Try using the at: message in String. 'string' at: 3 would return $r. |
| beginsWith: takes a character, not a string. Also, Strings understand "first" Mark Guzdial |
| It's one of the classic Smalltalk gotchas. "The other one being fighting a land war in Asia." (Never mind...:-) Mark Guzdial |
| I was of the impression that each call to match returned a new instance of a dictionary, but at least one other person had your perspective too. There's a small discussion about that a bit up from here, but there's no response from a TA or Guzdial yet. -DR |
| Folks, COME TO CLASS! This was asked explicitly in class last Thursday, and I answered it there as well. You return ONE Dictionary with all the matches in it. Mark Guzdial |
| Based on how a Dictionary works, I would think you should put every variable matched during one call to the match: string method into one Dictionary, then return that as the result. On top of just how the Dictionary works, it wouldn't be possible for one call to match: string to return multiple Dictionaries (unless you stuffed them into a Collection, but that's not returning a Dictionary then). As a side note, if you call match twice, each call should return it's own Dictionary or boolean value independent of the other calls made to match. Not a TA, but that's how I interpret it. Aaron Drew |
| Yes Matt, I'm pretty sure that you return (^) true, false, dictionary with no output to the transcript like you said since the assignment uses the word 'return' all over the place and says no word about the transcript. [Not a TA] Glenn Calvert |
| Like Glenn says. Mark Guzdial [Not a TA] |
| That's the way I understood it to work. However - I think once you have a Dictionary matched it should be preserved until its replaced - so false matches won't wipe out your old one (false matches to a Block condition). Webb |
| if you can't get multiple rules don't panic. Webb |
| I'm not a TA, but it seems most logical for that to be true. The ? signified that there could be nothing there, so you shouldn't have to evaluate the block at all Jesse Shieh |
| I agree with Jesse. While it seems like an ambiguous case (are symbols are blocks evaluated first?), think about using this to code a game. If you used ? instead of ! you obviously wanted it to be able to pass in the event there is no word there. If the block caused it to always fail because an empty string does not evaluate correctly that ruins the usefulness of ? here. Looking at it the other way allows you the power to say "only match this if it meets these requirements or it doesn't exist." My interpretation could be wrong, it's merely my evaluation based upon usefulness, and since we're using this code in later Milestones, that should be a deciding factor.Chris Church |
| you're not goofy - see above posts for how to avoid this crash Webb |
| catch the error by enclosing it with a block, [...] and then pass it the ifError: message - see the text for details :) Webb |
| The only answer I see is to set everything to lowercase EXCEPT the block Jesse Shieh |
| don't set everything to lowercase. The examples store 'my name is Mark' Dictionary, 'name'->'Mark' — you just need to lowercase the string when you are comparing the tokens for a match. I wouldn't lowercase the input for the block and certainly not the block itself. Webb |
| you can always say '=' ifFalse or whileFalse if you want the negation Webb |