nails says, "And the log begins." nails says, "I'd first like to start out by saying I've made a very tasty sandwich. That said, the topic of today's talk is MUSH softcode." nails says, "Today's session is meant as a second run and/or followup to the talk we had on Wednesday night (see http://puggy.mushpark.com/talk for a log), but as was the case last time, the focus can be adjusted depending on our audience and the interests." nails says, "Lets start out with the meet'n'greet. Who's here and why?" Sponge is here to try to contribute. Wine is an advanced coder and figured she could help answer questions The Lecture Hall - Museon You stand in a colonnaded gallery of smooth white stone, lit during the day by clear glass skylights set into the high arched ceiling; by night, torches in high mounts illuminate the hall. The floor is carpeted in dark blue, and low benches arranged in a cresent ring an open area. While ornately decorated, this place has an indisputable air of utilitarian purpose. Contents: Rippah Wine Ros nails RatFink Sponge Noisy McLoudface(#1820V) Mark Boo Tape(#1033V) The Archives (TA) The Forum (O) nails says, "Looks like we've got a small crowd today, and more instructors than instructees :)" RatFink is a newbie to code and is here to learn. :) nails says, "Excellent. :)" Rippah is software engineer in real life, and is currently working on a project in mushcode. :) nails says, "You poor creature." nails says, "I mean..." nails has often found that 'real' programmers tend to get more frustrated by the limitations of MUSH softcode than newbies do trying to learn how it all works. "Hopefully that's not too much of an issue for you :)" Announcement: nails shouts, "The Softcode talk is happening now. Just FYI." Rippah shakes his head, "It's moderately entertaining at the moment to do something elegant within the limitations of MUSHcode. Software engineering principles still apply, like fragmenting, using descriptive function names and the like." PyritePyro has arrived. nails says, "Welcome, welcome." nails says, "We may have a few more stragglers showing up." PyritePyro says, "thank you." nails says, "We were just doing the meet-n-greet part, talking about our interest in coding, etc." PyritePyro says, "Well, MUSH code looks like even more of gobbeldygook than any other lanugage to me." PyritePyro says, "even lisp" Rippah happens to be a Lisp fan. RatFink doesn't know any programming languages like at all. :( RatFink is really very illiterate as far as programming goes. nails thinks ignorance, in that regard at least, may actually be bliss. Rippah smiles, "It is." Boo is a vetran builder that would like to be able to code -and- build. And one of my main goals through this is learn the lingo so I can understand what's being said when code is discussed -and- be able to talk to the coders and debug and such in a lingo that makes the problem clear to them. I hate saying things like, The thingie that does the whatchitmacalled needs a tweaking in its whozimahwhati." PyritePyro says, "Lisp is a very nice language. But trying to read someone else's lisp code is a pain." nails says, "Well, lets ruin it for you, RatFink :) I guess we should get started here." RatFink says, "lol boo" nails nods at Boo. the 'thingie' thing isn't really that useful as a diagnostic :) nails says, "So. MUSH code! softcode!" Ide has connected. nails says, "First off, let me specify what I mean when I say MUSH. It is a general term for a family of MU* codebases that includes TinyMUSH, TinyMUX, PennMUSH and RhostMUSH, and any close relatives of these. There are variants (such as CobraMUSH, a modified version of Penn), but those first four are the primary MUSH-style codebases in use and most likely the ones you'll end up coding on." nails says, "Each one of them is different, which is why they get to have separate names, but the fundamental structure that makes them a type of MUSH is the same amongst them, and code written for one can in many cases be modified to work on another." Ide goes home. Ide has left. nails says, "And yes, MUX is a type of MUSH." Chameleon has arrived. nails says, "A MUSH is essentially a database and a command parser. The database holds all the info and the parser lets you do stuff with the info." nails says, "Obviously it's a little more involved than that, but that's the basic idea." RatFink says, "So a parser is like a program then?" PyritePyro says, "A parser is a part of a program that chunks strings into commands and arugments." nails says, "You interact with the MUSH via commands and functions, and most of the time you interact with objects. The bulk of the MUSH database is made up of objects." Sponge says, "A parser takes the text that you (hopefully) understand and breaks it into pieces that the MU can (hopefully) understand." nails says, "Consider the parser to be your interface to the MUSH program as a whole. It's the part that listens to what you say, interprets it, and does what you ask." nails says, "(in this case 'say' is 'type')" PyritePyro says, "Hehe." nails says, "When you type a command, it goes into a queue with all the other commands being entered, and the parser goes through them one at a time, reads them, figures out what to do, and then does it. If what you typed doesn't make sense, or you're not allowed to do, it'll give you an error instead of performing the action." nails says, "It's kind of like the Ship computer on Star Trek." nails says, "Or HAL 9000." nails says, "Only, it's not that smart or that psychotic (although some people might argue the latter point)" RatFink says, "lol" nails says, "Consider the say command. you type 'say blah'. The Parser takes your input, grabs the first piece to see if its a valid command (say is), then looks up what say is supposed to do. It checks your location, checks what other objects are in your location, and it takes the rest of what you typed in and sends the message out." nails says, "It even figures out to send you a different version, prefixed with 'You say' instead of 'RatFink says'." nails says, "Even seemingly simple commands have involved stuff going on under the surface." nails says, "Also, just as English grammar has certain rules, the parser has certain expectations when you type in a command. The very first thing you enter on a line *must* be a valid command. Consider this example." Muse enters from the Forum. Muse has arrived. nails says, "type: time()" nails says, "Then type: think time()" RatFink says, "Ok I see." nails says, "The first example will give you an error message, whereas the second will give you the current time." RatFink says, "So you have to type in a command first in order for it to work?" nails says, "this is because time() is a function. It evaluated into a string of text, so it was as if you had taken that text and entered it as a command." nails says, "Which has the same result as if your cat walks across your keyboard." nails nods. nails says, "The parser house rules." nails says, "command first." RatFink says, "How do you learn all the commands?" nails says, "This is a fairly important lesson when it comes to softcode, because there are many instances where you need to supply a command, and people often start out throwing in functions with no command to process them." nails says, "time." nails says, "Not time(), actual time. :)" RatFink says, "lol" nails says, "Every command and every function is documented in the help system. It's just a matter of finding the ones you need and reading the topic." nails says, "type: help think" Wine says, "see also 'help commands'" RatFink says, "That's a lot of commands." nails says, "There are as many or more functions as well." RatFink says, "What is the difference between a function and a command?" nails says, "It is very crucial to understand the difference betwen commands a-" Wine says, "Many or them are also actually attributes" nails says, "There's several ways to look at it, but the way I put it is that commands are 'active' and functions are 'passive'." Sponge says, "A command does something in the world... changes something, sends a message to someone, etc. A function transforms one piece of information to another." nails says, "Functions are used to derive or generate information, often dynamically." nails says, "This information, or data, is used by commands, but it does not specify an action in and of itself." RatFink says, "I understand command but I'm not sure that I understand what a function is." nails says, "Commands are like verbs. They tell the parser what it is you want to do. Often commands require arguments, or additional information." Wine says, "A command is a casserole you feed into the oven (the parser). Functions are the peas, and carrots and beans that go into the casserole." nails says, "Are you familiar with @desc?" Wine has disconnected. Sponge says, "So with the 'time()' function... when the MU parser sees 'time()' it looks up the current time, erases the 6 letters t-i-m-e-(-) with current time." RatFink knows the @desc nails says, "Okay, so @desc is a command, or an action. It is telling the parser: Set the 'desc' attribute on an object." nails says, "You have to supply two arguments: What object, and what the description should be." nails says, "I could do: @desc here=This is a very nice room." nails says, "Or, I could use functions." nails says, "help loc()" nails types -=> loc(me) nails says, "err. :)" nails types -=> think loc(me) nails says, "that returns #399. Which is this room." nails says, "So I could do: @desc loc(me)=This is a very nice room." nails says, "Functions are therefore a way of generating data or information dynamically, by using the parser to do some work for you." nails says, "Let me give you another example." nails says, "take a look at Noisy McLoudface here" nails points Noisy McLoudface(#1820V) If it was intentional, you'd think Noisy's wardrobe was his clown outfit from his job at the circus. Mostly he's just round, brightly colored, and 'jolly' in that way that is mostly done not out of personal happiness but spite at the world. What is up with people like that anyway? nails types -=> &foof noisy=I added this attribute now. nails says, "This sets an attribute named 'foof' on the object noisy, with the contents of 'I added this attribute now'." nails says, "Are you familiar with setting attributes?" RatFink nods nails says, "You can examine noisy's foof attrib with: exa noisy/foof" PyritePyro says, "I am. That one is pretty easy." nails says, "so every time I type that command, it'll have the exact same result." nails says, "Lets use a function." RatFink says, "Yup I examined noisy foof. :)" Psyche has connected. nails types -=> &foof noisy=I added this attribute at: [time()] nails says, "Hmm. train doesn't help me there." nails types -=> @fo me= &foof noisy=I added this attribute at: [time()] nails says, "exa noisy/foof again." PyritePyro says, "heh" FOOF: I added this attribute at: Sat Mar 24 16:57:01 2007 Sponge suggests, "For the benefit of the uninitiated, I suggest using the full commands, 'examine', '@force', etc." nails nodnods. Good point. nails says, "exa is an abbreviation of examine. @fo is an abbreviation of @force." RatFink nods "Okie doke" nails says, "Not all commands can be abbreviated in all ways, particularly if there's two commands with similar names. Trial and error will help on that front." nails says, "Error is often a good learning tool :)" nails says, "So lets try it again." PyritePyro says, "yeah, I should have known that setting an attribute doesn't parse. I've got a char that has several attributes that are function calls, so that when certain commands check them it'll dynamicaly call the function." Sponge notes, "I've found that the information that stuck with me the best was that which I learned by pounding it through my forehead by way of my desk." nails types -=> @force me= &foof noisy=I added this attribute at: [time()] nails says, "I've just typed the same command as before (although I used @force instead of @fo)" nails says, "examine noisy/foof again" FOOF: I added this attribute at: Sat Mar 24 17:00:20 2007 nails says, "Tada! the time has changed." RatFink says, "Very cool :)" nails says, "This is a very small and simple example of what functions can do." nails says, "Lets try another one." nails types -=> say first(lwho()) nails says, "#1816" nails says, "Here we have one function given as the argument to another function. This is sometimes called 'nesting', because one is inside another." Sponge says, "You should explain arguments." nails says, "#1816 #844 #1478 #1814 #203 #1827 #1733 #7 #1231 #1826 #1321 #1821 #1121 #866 #44 #324 #4 #693 #1426 #901 #317 #492 #1146 #883 #2 #1419 #1162 #1765 #1090 #925 #632 #389 #437 #11 #885 #1587 #840 #142 #9 #12 #8, which means 'list who' returns a list of the database reference numbers (or dbrefs) of the connected players." nails says, "doh" nails says, "lwho(), which means 'list who' returns a list of the database reference numbers (or dbrefs) of the connected players." PyritePyro smirks and gives nails a hug. PyritePyro says, "how do you supress parsing for that?" nails says, "There's some quirks to the way the parser handles things." nails says, "Let me cover the arguments piece first." nails says, "Both commands and functions can take arguments. An argument is basically a piece of information that the command uses to know how to do what it needs to do." nails says, "In the case of @desc, there were two arguments. The object to be described was the first argument. The second argument was the description to give that object." RatFink says, "How do you know which argument is first and which argument is second?" nails says, "The syntax of each command is listed in the help topic, but they usually follow a similar pattern." nails says, "if you take a look at help @desc, it says: COMMAND: @describe = " PyritePyro says, "Yeah, it's almost always command, target, option." nails says, "There are a number of commands whose primary job is to set attributes on objects." PyritePyro says, "What geeks call prefix order" nails says, "In these cases, it'll be =" nails says, "This also goes for other commands that modify objects in some way." nails says, "Tell it what you want to do, what object to do it to, and how to do it." nails says, "Not all commands follow this pattern, so checking the help topic is key." nails says, "Consider the @doing command. This sets a message that displays across from your name in the output of WHO." nails says, "Many people often mistakenly type @doing me=, but this results in the 'me=' showing up in the WHO output." nails says, "This is because only you can set your @doing, and you can't set it for any other objects. Therefore, specifying the object serves no purpose, and the command syntax varies accordingly." nails says, "Does that make sense?" nails says, "Any questions on using arguments with commands?" RatFink noddles, "Makes sense." :) nails says, "Functions take arguments as well, and very much in the same fashion, but the syntax is different. No = signs with functions." nails says, "When supplying an argument to a function, you put it inside the parentheses." RatFink says, "So in @desc me=I like purple. @desc is the command me and I like purple are the arguments?" nails nods. RatFink says, "Ok :)" nails says, "Lets play with names. Try this: think name(me)" nails says, "In this case, name() is the function, and 'me' is the argument." RatFink says, "Ok I see." PyritePyro says, "why do some commands use / as the seperator for the arugments and some use =?" nails says, "This gets into a more complex discussion of command syntax, but basically the /blah portion of command usage is supplying a 'switch', not an 'argument'." RatFink says, "Isn't it just because how the person codes it?" nails shakes his head. nails says, "When talking about built-in MUSH commands, the syntax is pretty structured across most commands." nails says, "A switch is a specific modifier to how a given command will function, and is part of the hardcode definition of the command itself." nails says, "It's not user supplied data, but a variation of the command itself." PyritePyro nods in limited understanding. nails says, "Here's an example." nails types -=> say time() nails says, "Sat Mar 24 17:20:05 2007" nails types -=> say/no_eval time() nails says, "err" nails types -=> say/noeval time() nails says, "time()" Sponge says, "The difference between / and = is programmer choice, really. When someone writes the command they decide how arguments should be broken up. Good programmers try to follow good/common practices and do things the same way. If you're assigning a value to something (like a description) then = is the common way to do it. A / is usually used to give a 'more specific' argument..." nails says, "In this case 'say' is the base command /noeval is a 'switch' to the command, and 'time()' is the argument." Sponge says, "It's all convention, most coders do things the same way so that players know what to expect when using unfamiliar commands." nails says, "If you read the help topics for commands, switches will be listed and it will be explained how they modify the core behavior of the command." Psyche says, "Before you go on nails, I'm just not exactly sure what noeval and eval are supposed to do themselves. If you don't mind" nails is explaining nails says, "read: help say" SAY COMMAND: say[/noeval] nsay " Says out loud to everyone in your current location (usually a room). If you use say/noeval or nsay, the message is not evaluated. Example: > say Where is the movie theater? Player says, "Where is the movie theater?" Related Topics: page, pose, whisper, :, ;, ". Psyche ah's. nails says, "the /noeval switch modifies the behavior of say in that it prevents it from evaluating the functions and percent substitutions in the supplied argument." nails says, "So in the context of MUSH parser syntax, a switch really is different than an argument." nails says, "When people write softcoded commands, they often mimic the syntax of the built-in MUSH commands, and in that case the line between switch and argument can become blurred, but that's another matter entirely." nails pokes at PyritePyro. "Does that clarify things?" PyritePyro says, "somewhat. I still don't entirely understand the way that @mail/quick works though, because it uses one of it's /es for user data." RatFink says, "So if I wanted to do the eval command in this case in a code I would use it to get rid of the percet R's and T's in a description to make it look all nice and pretty in paragraph form becasue it's evaluating the code?" RatFink says, "er percent that is." nails says, "Heh. @mail is highly convoluted beast. It's syntax is straining the capability of MUSH standards." Sponge agrees, "If you're confused about @mail, it's because it's confusing." nails isn't clear on the question, Rat? PyritePyro says, "Fink. I'm going to cut and paste some code I use, and modify to do what I think you want." RatFink says, "Okie doke" PyritePyro says, "[u(*me/desc)]" Sponge says, "I think RatFink was just trying to verify understanding of eval." nails says, "We've kind of veered off course here." RatFink nods to what Sponge says. Sponge looks to Rat, "I believe that you do understand and you'll see what's going on when nails gets to substitution." RatFink says, "okie doke" nails says, "So, command syntax (mostly) covered. MUSH syntax is a lot like English in that there are exceptions to every rule, and you'll find odd things if you look deep enough. But for the most part it's pretty straightforward." nails says, "Lets get back to functions." nails says, "Some functions require no arguments, some need one, or need two. Some can take range of arguments. Ususally if you use them with the wrong number of arguments they'll tell you (quite loudly) what the correct format is. And each functions' help topic will lay out the syntax." nails says, "In the case of think name(me), name() takes one argument, an object you want to get the name of." nails says, "When a function takes multiple arguments, there's generally two ways they are specified: either they are separated with commas, or in some cases they are separated by a /" RatFink says, "How do you know when they are separated with a comma or a /?" RatFink says, "Help is the answer again? :)" PyritePyro says, "help ?" nails will get there, guys. Sponge says, "Unfortunately, the only way to know is the help command." nails says, "The majority of arguments in functions will be separated by commas. The specific case where you will see a / is almost always a case of specifying an object/attribute pair. Consider this:" nails types -=> say get(noisy/foof) nails says, "I added this attribute at: Sat Mar 24 17:00:20 2007" nails says, "This is one of those situations where we get into semantics. Technically 'noisy/foof' is one argument." nails looks for another good example function. nails says, "Lets go back to the lwho()." nails says, "This function can take one argument but generally doesn't, so I tend to think of it as a no-argument function. It spits out a list of dbrefs, one for each of the connected players in WHO, and in that order." nails says, "so the first dbref in the list will be the dbref of the person who connected most recently, and the last in the list will be the person who has been connected the longest." nails says, "Then we have the first() function. When given a list of items, first() will take the first one on the list and just give you that one." nails says, "So, try: say first(lwho())" PyritePyro says, "#1816" PyritePyro says, "#-1" nails peers PyritePyro says, "I tried it with the arugment. too." nails grins. PyritePyro says, "#-1 PERMISSION DENIED" nails says, "Generally you need to be a wizard to see people's ports." Sponge shows off his port all the time, you don't have to be a Wizard. PyritePyro says, "ok. I'm just a compuslive hacker. If I see an option, I have to try it" nails checks on Rat and Psyche. nails says, "You guys have any questions on how first() or lwho() work?" Psyche is getting it so far. RatFink says, "Got #1816" nails says, "Lets try another version of that." Psyche says, "First gets the first object dbref and lwho gets a dbref of the who list, right?" nails says, "lwho generates a list, and first() takes the first item in that list." nails says, "for example" nails types -=> say first(eeny meeny miney moe) nails says, "eeny" nails says, "there's an equivalent function 'last()'." nails types -=> say last(eeny meeny miney moe) nails says, "moe" nails says, "and there is one called 'rest()' which will give you everything *but* the first" nails types -=> say rest(eeny meeny miney moe) nails says, "meeny miney moe" PyritePyro says, "I'm getting flashbacks to lisp now." Rippah says, "Yay lisp." nails says, "MUSH softcode is based on something that was based on something that was based on lisp." Sponge wonders why it isn't called lithp. PyritePyro says, "Spooge, gimme a sec." Boo covers a giggle. nails says, "Uh." Sponge says, "It stands for litht prothethor." nails says, "Anyway." nails says, "Another example for the Future Coders of MU*dom." nails types -=> say first(shuffle(lwho())) nails says, "#693" nails types -=> say first(shuffle(lwho())) nails says, "#437" nails says, "shuffle() is a function that takes a list of items that are in a particular order, and... shuffles them; ie, it randomizes the order." nails types -=> say shuffle(one two three four five) nails says, "four five two three one" nails types -=> say shuffle(one two three four five) nails says, "five one four two three" nails says, "It'll come out different each time." RatFink says, "Is there a random function?" PyritePyrorabd nails says, "There are several." PyritePyro says, "rand" PyritePyro says, "and others." nails says, "rand is only one of them, and it depends on what you want to randomize and how." nails says, "the rand() function will generate a random number, depending on the arguments you give it." nails says, "for example: say rand(50)" nails says, "That will give you a random number between 0 and 49." nails says, "Or you can do: rand(1,50) which will give you a random number between 1 and 50." nails says, "Alternately, you can use die(5,10), which will generate a random number between 5 and 50; it simulates 5 rolls of a 10 sided die." nails says, "When working with strings and lists, there is shuffle, pickrand, scramble..." nails says, "If you want to spam yourself, you can get a list of all available functions by typing: @list function" Sponge says, "I much prefer going throught 'help function classes'" nails says, "That serves a different purpose." RatFink just did: think die(1,10) :) nails says, "What'd you roll?" nails got 4. RatFink got 6 :) nails says, "you win!" RatFink says, "hehe" nails says, "Do you have a sense now of how functions are used to generate data?" RatFink noddles RatFink says, "This has cleared up a /lot/ of stuff for me. :) Thank you!" nails says, "And how using the same function at different times or in different contexts will give different results?" RatFink nods :) nails says, "The other key thing is that by nesting functions on top of each other, you're essentially creating a new super-function." RatFink will have to mess around with the help files to explore now. hehe nails says, "try: say name(first(shuffle(lwho())))" nails types -=> say name(first(shuffle(lwho()))) nails says, "Brazil" RatFink says, "I got sinnsyk :)" Boo says, "Draken-Korin" PyritePyro says, "Rippah" Psyche says, "nam(first(shuffle(lwho())))" Sponge says, "Narilka" nails says, "What you've got is essentially a function that grabs a random dbref from the WHO and gets the name of that object." Psyche says, "cHia" nails says, "What would you call that? randwhoname?" Sponge says, "I like long names: random_logged_on_player" nails hates names like that. :) Sponge explains, "Well, my memory for detail sucks but I can type fast." nails doesn't like typing underscores, either. Waste of a shift key press. Sponge suggests, "randplayer" PyritePyro says, "I think I'd call it pracFunc1" nails will compromise. rand.wholist.name nails fires PyritePyro. RatFink says, "hehe" PyritePyro says, "you don't like camelback format?" nails types -=> &f.rand.wholist.name noisy=name(first(shuffle(lwho()))) Sponge says, "And this illustrates an important point. There are lots of ways to name stuff and lots of ways to accomplish the same thing. try 'think name(pickrand(lwho()))'" nails says, "camelback format doesn't work well when the function name becomes an attribute name and is forced into all uppercase." nails nods. PyritePyro says, "Ahh, so it's not appropriate for the environment." nails says, "pickrand() is a more efficient version of first(shuffle()), but it is unfortunately MUX specific. first(shuffle()) should work on all MUSH codebases." nails says, "So, I've set the code on Noisy. examine noisy/f.rand.wholist.name" nails says, "Or if you are lazy like me: examine noisy/f.rand*" nails says, "I showed you the get() function earlier. try: think get(noisy/f.rand.wholist.name)" nails says, "Now, Rat." nails says, "On the subject of evaluation. What is evaluation?" RatFink says, "An evaluation is when you modify a certain part of a code?" nails says, "Evaluation is what the parser does when it takes functions and percent substitutions and processes them to get the results." nails says, "When you type 'think time()' and you get the actual time, the parser is evaluating the argument to the think command." nails says, "and PyritePyro, you had a question earlier about preventing evaluation." nails says, "This is a weird quirk of the parser:" nails types -=> say time() nails says, "Sat Mar 24 18:16:39 2007" PyritePyro says, "ok." nails types -=> say the time is time() nails says, "the time is time()" nails says, "In the first example, it evaluated. In the second, it didn't. Weird." nails says, "It does this." PyritePyro says, "how do we force evaluation also?" nails says, "basically, the argument to the 'say' command is just a string." nails says, "In the context of code, when you provide a string to the parser and it /starts/ with a function? that function gets evaluated. If it starts with just random text? it doesn't." nails types -=> say time() is a function nails says, "Sat Mar 24 18:18:12 2007 is a function" nails types -=> the string 'time()' is a function. nails says, "err" nails types -=> say the string 'time()' is a function. nails says, "the string 'time()' is a function." nails says, "This is just how the parser is, and it has always been this way." nails says, "If you want to start a string with a function but /not/ have it evaluate, you can use \s to escape it." nails says, "Put a \ in front of each paren that you do not want to evaluate." nails says, "time()" nails types -=> say time\(\) nails says, "time()" nails says, "Note that if you want to ever say a \, you need to double them up." nails types -=> say one backslash: \ nails says, "one backslash: " nails types -=> say two backslashes: \\ nails says, "two backslashes: \" nails says, "The same goes for %s. to make one show up, you need to type two in a row." nails says, "The alternate scenario: You have a function in the middle of a string and you want it to evaluate. For this you use square brackets: []." RatFink is lost. :( nails types -=> say time is time() - that's time. nails says, "time is time() - that's time." nails backs up a bit. nails says, "Rat, you know how the parser is taking in everything that you type?" RatFink got lost on the: "basically, the argument to the 'say' command is just a string." nails says, "In the context of code, when you provide a string to the parser and it /starts/ with a function? that function gets evaluated. If it starts with just random text? it doesn't." RatFink nods nails says, "when I say 'string', that means a 'string of text" RatFink says, "Okie doke" nails says, "a string of characters. abcdefg." nails says, "So I type: say blah blah blah. The parser reads 'say' command, followed by 'blah blah blah'. That's the argument." RatFink says, "Ok" nails says, "The argument is a bunch of text characters." nails says, "The trick with evaluation is that if you use functions in your text, well... functions /are/ text." nails says, "commands are text, too." nails says, "if I type: say say, it doesn't run two commands. it runs the 'say' command with the argument being the text 'say'." nails says, "The parser has its rules." nails says, "Once you give it a command, it stops looking for commands. :)" nails says, "And the parser is not very smart." Psyche says, "But then what would happen if you type, like, say/say" nails says, "It'd give you an error :)" nails says, "Because '/say' is not a valid switch to the command 'say'" nails types -=> say/say foo Psyche erms and meant [ nails says, "you mean: say [say]?" Psyche says, "I meant say[say]" nails points to the space. Psyche nods. nails thinks. nails says, "When I talk about evaluation, I'm talking mostly about 'function' evaluation." nails says, "The evaluation that happens to the arguments of commands." Psyche nods. nails says, "Once you move past the command and onto its arguments, you're no longer working with commands." nails says, "(this is not always the case and depends on the command in question)" nails is oversimplifying. nails checks to see where Rat is. RatFink is getting to the escaping thing. RatFink says, "With the /" nails says, "the \." RatFink says, "er yeah lol" nails says, "The parser is notoriously unforgiving when it comes to typoes ;)" Sponge says, "The parser has a one track mind. When it sees any of the special symbols it is trained to recognize, it wants to do substitution on them." nails says, "Get one perenthesis out of place and 10 lines of code will break." RatFink eeps Sponge says, "You know how when you do 'think time()' it shows you the time?" RatFink nods Sponge says, "Well, what if you wanted to actually see t-i-m-e-(-)? You know, the literal word time followed by the ()?" PyritePyro says, "try typing think time()" Who enters from the Forum. Who has arrived. PyritePyro says, "try typing think time\(\)" nails waves to Who PyritePyro mumbles at himself for making such a n00b mistake. Sponge says, "Every time you type it in, the parser, like a loyal dog, sees time() and thinks you want the time." Psyche says, "Well a think time() would also work." Psyche says, "erm think time(\)" RatFink says, "So every time you put in the backslash the parser literally takes it for what it is?" Psyche says, "As would think time\(), you don't actually need to add in both \(\)." nails nods. RatFink says, "So how would that be useful in code?" PyritePyro says, "but if you only put in one \ it evaluates it with the next char." nails says, "If you're in the middle of complex code, you want to do both so that the other half doesn't get misinterpreted as part of a function several nesting levels out." nails says, "Rat, sometimes when you've got functions inside functions inside functions, the parser will have to evaluate the code multiple times." nails says, "Sometimes you can delay a piece of it from evaluating until a later pass." Sponge shrugs, "Sometimes you just want some darn parenthesis, but that parser won't let you have them." Swift has arrived. RatFink says, "Ok I see." nails says, "So, the first time it passes over, it'll turn the \(\) into (), and the next time through it'll evaluate the function." RatFink says, "Okie doke" nails says, "Also, what Sponge said. Sometimes you're making something like +finger code, and you want to put something like Name (alias), but the parser keeps thinking the parens are part of a function." nails says, "So that is how you prevent the parser from evaluating a function when it goes to evaluate stuff." PyritePyro says, "so you have to use even more \'s so that you delay evaluation until you want it." nails says, "Lets look at the opposite case." nails says, "You use a function in the middle of some text, and the parser ignores it. hiss!!" nails types -=> say the time is now: time() nails says, "the time is now: time()" Sponge says, "To get somethings right I've had to use like eight of them. That being said, there was probably a smarter way to do it." nails tries to keep moving. we're almost 3 hours in now :) nails says, "the square brackets - [] - will tell the parser while it's reading through text to start evaluating what's inside." nails types -=> say the time is now: [time()] nails says, "the time is now: Sat Mar 24 18:42:17 2007" RatFink says, "Ahh ok so that's what the square brackets are for." nails says, "Note that the brackets are snugly wrapped around the function. You want to place them just so, and not around the whole string, or it'll confuse the parser." nails examples nails types -=> say the time [is now: time()] nails says, "the time #-1 FUNCTION (is now: time) NOT FOUND" nails says, "Not pretty." nails says, "Questions about brackets?" RatFink says, "nope" nails says, "So, lets backtrack." Psyche says, "Wait quickie question!" nails grins. Yeah? Psyche says, "I know this is similar to a different question I asked last seminar, but now a different topic, heh, does it matter how many functions you nest within each other in square brackets?"" nails says, "Same rules of limits apply." nails says, "The one qualification I'd point out is that if you are using functions in two different parts of the text, you want to bracket them separately." Sponge says, "The parser will only keep track of nesting to a certain depth and after that it will give you an error.." Psyche nods, "So except for those limits of 2500 and bracketing different functions seperatly, it won't be much of a concern/problem, right?" nails says, "Most people never hit that limit. If you do, you are either writing some gnarly code, or you have unleashed demons." PyritePyro says, "How deep will it parse? or is that implementation specific?" nails says, "It's a configuration setting." nails says, "The function invocation limit in TinyMUX defaults to 2500." PyritePyro says, "Ahh, ok." nails says, "Many games increase this. YMMV." nails says, "But again, in most cases you're not doing 100 function invocations." Sponge says, "I hit the limit last night. Of course, that could could use some clean up." nails says, "gnarly code or demons?" Sponge points, #-1 FUNCTION INVOCATION LIMIT EXCEEDED nails says, "What codebase, and what's your limit set to?" nails notes that the most common cases where you hit the function invocation limit is when you are dealing with global softcode commands such as +who and +where; code that runs several functions for each player connected. Sponge says, "Mux2.4... I'm looking for the limit." nails says, "If you do that on a game that has *many* players connected, you jack up your invocation count." nails points at: think config(function_invocation_limit) nails says, "5000" Swift raises a hand nails says, "5000 here on Puggy." nails says, "Ja, Swiftmeister?" Sponge says, "2500" nails says, "Many people consider the default to be fairly conservative." Swift would take a moment to note that really complex systems can get really function invocation hairy really fast. WE's first CGen system demanded a limit of just over 40000. That's Forty thousand ;). nails says, "We's code == gnarly demons." nails says, "WE's, even." Swift says, "Way gnarly" nails says, "Way demonic." PyritePyro says, "Damn, 100k on shang. And I know you have other servers on that machine too." nails says, "But in a good way." Swift says, "Sorry for interrupting there nails, just wanted to comment that it can happen if you're heavy into complex systems and arcane parent relationships" Who ponders giving up already as greek doesnt even begin to reach him Sponge says, "I know the code in question to be inefficient so I'd rather clean it up that up the limit." nails grins at Who. nails nods to Sponge. PyritePyro says, "Who, where did you get lost?" nails says, "Who came in a bit late." Sponge shares what he noted to Rat, "One can set that limit arbitrarily high. You can set to to 4 billion if you want. If you run code that gets high enough, your MU will crash. That limit is a protective measure." Who laughs. "trudge on, im hopeless for coding...I only recently figure out ansi RatFink says, "Hey man...I feel your pain. I was there once too. :)" nails nods. Shangrila's case is unique, as it's really the only MUX out there that routinely hits 500-600 connected players. nails says, "In any case, I wanted to do a quick little exercise with some code on Noisy here." nails says, "For reference, examine noisy/f.rand.wholist.name" F.RAND.WHOLIST.NAME: name(first(shuffle(lwho()))) nails says, "The last thing we did with this was to think get(noisy/f.rand.wholist.name)" nails says, "The get() function 'gets' the contents of an attribute from an object. You tell it what object, and what attribute on that object." nails says, "It does not evaluate, so if there is code in the attribute, you see that code." nails says, "The get() function has a sibling: get_eval(). This works just like get() except it evaluates the contents of the attribute before giving it to you." nails types -=> say get(noisy/f.rand.wholist.name) nails says, "name(first(shuffle(lwho())))" nails types -=> say get_eval(noisy/f.rand.wholist.name) nails says, "name(first(shuffle(lwho())))" nails says, "err." PyritePyro says, "maybe if you put it inside []s inside the attribute?" nails tries that. nails is surprised it is behaving like that, though. Swift says, "maybe u() instead?" nails says, "We shouldn't need to use u(), as it's overkill for this." nails says, "Bear with me one moment." Swift thought so too, but get_eval() seems to be a little weird atm. nails says, "Bear with me one moment." PyritePyro says, "U works" Sponge changes into a bear and mauls members of the audience, looking for food in trash bags. Rippah chuckles wryly, as he's beating his head against his desk, trying to code up a poker table. :) nails says, "Intersting. I expected get_eval to act differently. I learned something today :)" Psyche should say something witty like, "Live and learn and then get_eval" but...well, isn't that witty. PyritePyro says, "no, it's not." nails says, "PyritePyro's suggestion worked. I updated the attribute on noisy to include []s on the outside." nails says, "Now we can demonstrate the difference between get and get_eval" nails types -=> say get(noisy/f.rand.wholist.name) nails says, "[name(first(shuffle(lwho())))]" nails types -=> say get_eval(noisy/f.rand.wholist.name) nails says, "sinnsyk" nails says, "People will often use u() instead of get_eval() simply because it's easier to type. It's really not just a replacement, it's a much more complex function." PyritePyro says, "I have a little Voodoo code. Just because I didn't understand it when I copied and pasted it, doesn't mean with such an excelent instructor I can't pick it up." nails says, "There is a whole family of functions whose purpose is to get the contents of an attribute, including v(), get(), get_eval(), u(), udefault(). Each one has different behavior and a different purpose, and can be used accordingly." nails says, "So! another interesting detour." nails says, "We've got a little bit of function code that we can now call. Lets make it into a command." Sponge says, "Some of those will be have the same in some situations and different in others. This is important to be aware of because something may work fine when you're testing because you're only using get_eval() in certain ways. When you make your code available to players, they may throw different arguments at it and make it behave in unexpected ways." nails types -=> &c.randy noisy=$randy:say I think [get_eval(me/f.rand.wholist.name)] is feeling randy! nails says, "I've just set another attribute on Noisy. This one is called 'c.randy', and the contents of this attribute are a little special." PyritePyro says, "so how do we invoke it?" nails says, "It defines a ssoftcoded command." Noisy McLoudface says, "I think empowered Eratl is feeling randy!" nails says, "The way you do this is that you create an attribute on an object where the contents start with a $, then you specify the command name, a colon, and the code that the command will run." RatFink says, "hehe" nails says, "ie: $:" Noisy McLoudface says, "I think Psyche is feeling randy!" Noisy McLoudface says, "I think empowered Eratl is feeling randy!" Sponge asks, "Who's Randy?" nails slaps knee. Psyche doesn't want to knee! Sponge nyuck nyucks. nails says, "Lets tweak this slightly..." Psyche erms and thought she typed know. nails types -=> &c.randy noisy=$randy:say Hey, %n! I think [get_eval(me/f.rand.wholist.name)] is feeling randy! nails types -=> randy Noisy McLoudface says, "Hey, nails! I think Grey is feeling randy!" nails introduces the use of percent substitutions. Noisy McLoudface says, "Hey, PyritePyro! I think Phaser is feeling randy!" nails says, "examine noisy/c.randy" C.RANDY: $randy:say Hey, %n! I think [get_eval(me/f.rand.wholist.name)] is feeling randy! nails says, "We've got a softcoded command, sometimes called $commands, dollar sign commands, or arbitrary commands." nails says, "We're using functions, we're calling code from another attribute, and we're using percent substitutions." nails says, "Questions?" Sponge says, "WHat's the difference between a 'command' and a '+command'?" RatFink says, "What are all the character substitutions?" RatFink says, "Like percent N and such?" nails isn't going to list them all. :) check: help substitutions RatFink says, "ok :)" Swift has a question, for clarity's sake nails says, "+command is a somewhat ambiguous term. the 'plus' commands are in most cases softcoded commands, and the use of + as a prefix to softcoded commands is a common convention, but is not a technical distinction." Sponge says, "So, it's safe to say that the + is meant to make it obvious that it's a soft-coded command." nails says, "No, not exactly." Swift says, "nails, can you please explain the importance of the difference between a command and a function - especially with regards to softcoded versions of each?" nails says, "To confuse matters, many games use a hardcoded implementation of +help, and PennMUSH comsys/channels use + as a prefix even though that is a hardcode implementation." nails says, "Furthermore, the assumption that +commands are all softcoded sometimes leads to the assumption that any command without a + is hardcoded, and this is even more often not the case." nails says, "So it's safe to say that it's true, except when it isn't." PyritePyro says, "Ahh, clear as my grand pappy's fishing pond!" nails grins. RatFink says, "lol" Swift withdraws his question, btw. nails says, "The problem with human-enforced conventions vs hardcode-enforced conventions. :)" PyritePyro says, "We haven't gotten to user defined functions yet." nails says, "Let me actually touch on the commands vs function issue again." nails says, "User defined functions via @function are a little out of the scope of this discussion." Swift nods and meant, more of the way of ufun's nails says, "We've talked about commands and their arguments, and functions and their arguments." nails says, "There are cases where a command will take another command as its argument. Consider the @wait command." PyritePyro runs afk to scrounge up some food. will get caught up when he gets back. nails types -=> @wait 10=say Ten seconds have passed since I started the @wait. nails taps his foot. nails picks his nose. nails yawns. nails says, "Ten seconds have passed since I started the @wait." nails says, "The @wait command takes two arguments: a number of seconds to wait, and another command. In this case '10' and 'say blah blah' were the two arguments to @wait" nails says, "Functions can take other functions as their argument, as we see in the nesting of functions." nails says, "commands can take functions as their arguments, as in the case of think time()." nails says, "But." nails says, "This is the important part." nails looks at Rat. nails looks at Psyche. Swift hehs nails looks at Swift. RatFink says, "uh oh :)" nails says, "Functions CANNOT take commands as arguments." Psyche is following along fine so far. nails says, "You CANNOT put commands INSIDE functions." nails uses CAPS to EMPHASIZE his POINT. nails settles down. RatFink says, "lol!" Rippah was beaten over the head by nails when he did ... Swift nods and forgot one time...haven't lived it down since, but hasn't forgotten anymore either. Sponge grins, "You can put a command inside a function, it just won't work." Swift says, "ever" Sponge says, "think get(say Hi)" nails says, "Sometimes you're working on a piece of code and you've got a function, and you are looking for something that'll do what you need to have happen next. You won't see the function for it, but you'll find a command." nails says, "So you think, a little spackle, a little tape, we'll be right as rain." nails says, "No!" nails says, "We won't be." Swift says, "Be thou not mislead? :P" nails says, "Yeah, that." RatFink grins nails says, "So, at the point you find yourself doing that, it is time to rethink your grand strategy." nails says, "Questions?" Swift says, "Nein" RatFink says, "Nope" Sponge notes, "After a while you get used to it and don't really think about using commands inside of functions." nails nods. nails says, "Having your code work the way you want is a good incentive. :)" nails says, "Percent substitutions." nails is tired. Who wants to explain these? Sponge volunteers. nails says, "tag, Sponge is it :)" Sponge says, "Percent substitutions are also called percent subs, substitutions, subs, or sometimes just subs." Sponge says, "When the parser looks at arguments, it looks for special symbols. One such special symbol is the sign." Sponge hahs. Sponge says, "Percent substitutions are also called percent subs, % substitutions, % subs, or sometimes just subs." Swift hands Sponge another % Sponge prefers backslash. Sponge says, "When the parser looks at arguments, it looks for special symbols. One such special symbol is the % sign." Sponge kicks the parser. Sponge says, "Consider the following problem: You want to have multiple paragraphs in your @desc. At the end of a paragraph you hit to start a new one. Unfortunately, the MU thinks that means that you're done with your command." Sponge says, "To solve this problem, there is a special symbol that the parser looks for and interprets it to mean . This is %r." Sponge says, "When the parser looks through your desc, it sees the % and nows that it means a special symbol. It looks through the special symbols that it knows of and finds 'r'. I knows that 'r' means so it goes back to your argument and replaces your %r with an ." Sponge asks, "Is anyone fuzzy on the concept?" Sponge corrects, "The parser *knows*, it doesn't *nows*." RatFink is good. Sponge continues, "There are lots of these. Another common one is %t which gives you a tab. If you want the first line of a desc or message to be indented, you can start it off with a %t." Sponge adds, "...and there are other ones that do weirder, more interesting things. Everyone try 'think %n'." Sponge says, "Next, try 'say %N'" nails screams. PyritePyro smirks. RatFink says, "lol" RatFink says, "You broke Nails. :)" PyritePyro says, "come on nails, try it" Sponge quirks. nails says, "%N is an abomination and should never be used." PyritePyro says, "PyritePyro" Sponge says, "Oh, I thought I had done something wrong. Someone put nails back in the straightjacket." nails says, "%n is vastly superior in all ways at all times." Psyche says, "Whyssat?" Sponge says, "So, what do %n and %N do?" Swift says, "return the name and the Capitalized Name of the enactor, respectively." PyritePyro says, "because PyritePyro forces capitolisation of the first character." nails says, "%N forces the capitalization of names. %n displays them exactly as they are, caps intact or non." Psyche says, "The same exact thing, put in the name of whoever triggered them." nails types -=> say %n %N nails says, "nails Nails" PyritePyro says, "because %N forces capitolisation of the first character." nails screams! Psyche oh's....got that difference now. Sponge says, "Nails is very particular about the case of 'nails'." nails screams! pyritepyro hides. Swift says, "Moving on..." Sponge says, "Now, Swift brought up an interesting word... 'enactor'...." Noisy McLoudface says, "Hey, pyritepyro! I think Quartz is feeling randy!" pyritepyro offers an example. Sponge says, "The enactor is the person who triggered the running code. When you use '%n' in a say, pose, etc, *you* are the enactor." nails nods. RatFink grins Sponge says, "When the code exists on some other object and you trigger that code, you are *still* the enactor." nails says, "The randy command demonstrates this well. Even tho the code is stored in an attribute on the Noisy Mcloudface? /you/ typed the command." nails says, "You did it. You're responsible." Sponge says, "When there is a command on you, and someone else triggers that code, *they* are the enactor." Sponge asks, "Clear as mud?" RatFink says, "So who is responsible for the +who command?" nails says, "If you type +who, you are the enactor." Sponge says, "When you type +who, YOU are the enactor." nails says, "if the softcode for the +who command included %n at the top, it'd show your name when you typed it." Sponge gets out the voodoo doll, "Or %N." RatFink waits for the scream. nails cracks his knuckles. Sponge says, "A similar concept that is close enough to be confusing is 'me'." Swift gets out the thorazine and waits. Sponge says, "This is where it gets confusing. Sometimes 'me' is the same as the enactor, sometimes 'me' is something else." Sponge says, "The 'me' refers to whatever object contains the code being run." Swift coughs nails says, "The Unbearable Lightness of 'me'." Rippah adores 'me' that changes in context. Sponge says, "So, if the +who command has a 'me' somewhere, 'me' refers to whatever object the +who command lives on." Rippah also adores the fact that some functions require it, like set(). nails says, "Is 'me' the same as Executor?" Sponge says, "What is Executor?" nails has never been clear on that. nails says, "%! vs %#" Sponge isn't familiar with the term. Sponge says, "Not sure." nails says, "We're probably getting into deeper water." nails says, "Lets check if Rat is still swimming :)" RatFink sunk. :) nails gets the paddles RatFink grins nails shakes Psyche. "You awake?" RatFink says, "What's an executor? :)" Sponge says, "So, quiz. If noisy has a 'me' and you run some code on noisy, to what does 'me' refer?" Psyche nods and has been clear on this stuff for a while. RatFink says, "the enactor." Swift says, "The database number of the object holding the message or running the action list." Swift says, "'me' on noisy refers, generally, to noisy." Sponge says, "'me' refers to object that the code lives on. Since the code lives on noisy, 'me' is noisy." nails types -=> &c.whoami noisy=$whoami: say Who am I? I'm [name(me)]!! Noisy McLoudface says, "Who am I? I'm Noisy McLoudface!!" Sponge asks nails, "Add one for the enactor, too please?" Swift says, "Question...what if you have something like $whoami: think Who am I?;@fo #1426=think I'm Swift" nails types -=> &c.whoami noisy=$whoami: say Who am I? I'm [name(me)]!! You, [name(%#)]? You can call me [first(name(#!))] Noisy McLoudface says, "Who am I? I'm Noisy McLoudface!! You, nails? You can call me #-1" Swift says, "Question...what if you have something like $whoami: think Who am I?;@fo %#=think I'm [name(me)]" nails says, "interesting" nails types -=> &c.whoami noisy=$whoami: say Who am I? I'm [name(me)]!! You, [name(%#)]? You can call me [first(name(%!))] nails fixes Noisy McLoudface says, "Who am I? I'm Noisy McLoudface!! You, nails? You can call me Noisy" nails says, "So %! appears to be 'me'. Which makes 'me' the Executor." Sponge addresses Swift, "@force makes everything confusing is outside the scope of this session... at least so far." Swift nods, "Knew that was a big monkey wrench, but had to throw it anyways. Psyche says, "Actually question now." Psyche says, "Why would you use first?" nails says, "Also, I'd have to give noisy more power than I dare to allow him to force you. :)" Swift hehs nails did that for style reasons, Psyche. Sponge says, "Like I said, I don't know what %l (Executor) is... I don't think it's 'me' and I don't think it's enactor." nails says, "It's not enactor. It's acting more like me." Sponge says, "Executor may be a formal way of saying 'me'." Sponge says, "But this is getting outside the range of beginner." nails nods Sponge says, "So, recap." Noisy McLoudface says, "Who am I? I'm Noisy McLoudface!! You, pyritepyro? You can call me Noisy" nails says, "Swift, go make something on your game that can force you and test it out." Swift knows the answer Sponge says, "The enactor is whoever triggered some code, ran a command. They're the one who started the ball rolling." Swift says, "The @fo passes the code to the enactor before parsing it so 'me' in that case 'resides' on the enactor, not the executor." Sponge says, "'me' is the object that the code lives on." nails would add one thing. nails says, "'here' is the location where 'me' is, whoever 'me' happens to be." Sponge says, "It's your house." Sponge was getting to that too. nails grins. Sponge says, "Usually, in code you care about the enactor more than 'me'." Swift says, "Hrrrrmm...I'm wrong. Me resides as the executor of the code all the time, not the enactor." nails muffles Swift. Sponge says, "So there are more things to deal with that. The %n and %N get the name of the enactor. There's something even more useful. %#. Can someone figure out what %# (that doesn't already know)?" Sponge corrects, "What %# is" nails asks: does anyone not know what #9 is? nails doh nails fires himself. RatFink says, "hehe" RatFink says, "It's your dbref #?" Swift does, but remains muffled ;) Sponge says, "Almost correct. It is the dbref of the enactor." Who has disconnected. Sponge says, "In your code, you might want to find someone's location. The loc() function will get the dbref of the location of an object." Sponge says, "Everyone do 'say loc(Sponge)'" Sponge says, "#399" nails types -=> loc(%#) Boo says, "#399" nails types -=> say loc(%#) nails says, "#399" Sponge says, "Now, try 'say loc(Gem)'" Psyche says, "#-1 NOT FOUND" Swift types -=> say [loc(*Gem)] Swift says, "#875" Sponge says, "Referring to things by name only works if they're in the same room. But you can refer to something by dbref it it's anywhere." nails types -=> say num(*gem) nails says, "#8" Sponge says, "As Swift demonstrated, using a * in front of the name causes the MU to try and find them but it doesn't always work." Swift says, "In my experience, only on players :(" Sponge says, "It does only work on players. And if it's only given part of the name (like 'j') and there's more than one match (there's a john and a jason logged on) it doesn't know who you mean and it will error." nails nods. Swift nods, "Uniqueness factor plays in to it." Sponge says, "So getting the dbref is very handy. You can get the dbref of the enactor by doing %#." nails says, "dbrefs are unique to each object. No two objects in a database will have the same dbref." Sponge says, "Again, we can do 'say loc(%#)' but this isn't a good demonstration since we're all in the same room." RatFink says, "If everyone has a different dbref number, then why can't they have the same name?" nails says, "Because." nails says, "In the end." Swift says, "You could only log in by dbref then." Sponge says, "The MU enforces players to have unique names for clarity. That's it." nails says, "there can be only one!!" RatFink says, "hehe" nails settles down. nails says, "So, you can't do loc(Gem)." nails says, "But Gem's dbref is #8." Sponge says, "So, we can do loc(%#) but there's an even easier way: %l. %l is the dbref of the location of the enactor." Sponge says, "It gets even more funky... there's %- which is the dbref of the location of the enactor's cousin's second character's sphere wiz." Sponge says, "...or not." nails hehs. Sponge says, "You can get a list of the % substitutions in 'help subs'" RatFink grins nails says, "Okay. That's 4 hours." Sponge trails off, "and, I think nails was looking to wrap this up." nails says, "Lets switch over to Q&A before full on brain meltage." Sponge solicits, "Any questions?" RatFink says, "Nope" nails says, "Oh c'mon." Sponge notes that some different things were covered between this session and the last so if you came here to learn it would behoove you to read the log from Wednesday evening. nails says, "There have got to be questions." Swift says, "What, you guys weren't gonna make this an all nighter and try and explain iter() at 4 am?!?" Swift grins Psyche is still unsure as to exactly what the differences between u(), get_eval() and v() are Psyche says, "Cause I know you said they can be interchanged at times but are definatly not the same thing." nails says, "All of them are functions to get the contents of attributes. They differ in level of complexity." Sponge says, "We know get(/)... it goes to and retrieves if you have permission..." Sponge says, "Well, v() is essentially shorthand for get(me/)" Sponge says, "Neither get() or v() do evaluation." nails says, "the simplest, most streamlined one is v(). The trick with v() is that you do not even specify the object. it is just v(attrib) and it pulls off of the object using the code." nails says, "At the other end of the spectrum, u() is like get_eval() on crack." Rippah nods and has been using v() where pertinent. Sponge says, "Next, get_eval(/) gets from and performs substitution on the contents of " Swift says, "nails, can't you get the same effect with % ?" nails says, "Not only will u() evaluate the contents of the attribute you're getting, but it will allow you to pass arguments to it before it is eval'd and returned." nails says, "No, Swift." nails says, "There is %va-vz, which is the same as v(a) or the like." Psyche is stuck at the pass arguments part. Swift says, "ahhh" nails says, "but v(foo) works, %foo doesn't." Swift nods Sponge says, "And u()... we didn't cover some % subs that are used when writing your own functions and commands." nails says, "Let me give you a u() example" Sponge says, "The subs we didn't cover are %0 through %9" nails types -=> &u.ilike noisy=I like %0 nails types -=> say u(noisy/u.ilike,ice cream) nails says, "I like ice cream" nails says, "I pass two(ish) arguments to u(). the obj/attr, and 'ice cream')" Sponge says, "As nails demonstrated, u() takes the form of u(/,,,...,)" nails says, "It returns the contents of u.ilike, which is 'I like %0', but it evaluates the %0 like get_eval would" Sponge corrects himself... nails says, "only, it takes the second argument to u() and puts it in the code where %0 is." Sponge says, "As nails demonstrated, u() takes the form of u(/,,,...,)" Psyche thinks she got it now. nails says, "let me tweak it a little" nails types -=> &u.ilike noisy=I like [ansi(rh,ucstr(%0))] nails types -=> say u(noisy/u.ilike,ice cream) nails says, "I like ICE CREAM" Psyche says, "ucstr?" Sponge says, "Uppercase string" nails says, "uppercase string" Psyche nods. nails types -=> ucstr(hello) nails types -=> say ucstr(hello) nails says, "HELLO" nails says, "try say u(noisy/u.ilike,) where you put in whatever you want for blah" Psyche says, "I like FUDGE" nails grins. Psyche is getting it now, shakes a fist at helpfiles which keep confussing her. nails says, "So it's not just spitting back what you typed. It's processing it through the code in the attribute first, then returning the end results." nails says, "For you kids reading the log, FUDGE is printed in red text. Go get a marker and fix your monitor." nails says, "Any other questions?" Swift says, "Yeah" Psyche says, "Yea how do you get red marker off of your screen?" Psyche sniggers Swift says, "When are the intermediate talks?" pyritepyro says, "I like WOMANSES" nails says, "I don't know. When are they?" nails says, "Psyche, you need to lick it off." nails says, "When you start seeing spots, you can eat those. They're candy." Psyche eeeks and will keep it red! nails says, "When we have more classes, they will be posted here on puggy on the Talk Night board (puggy.mushpark.com port 9033) and up on Electric Soup (www.electricsoup.net)" nails says, "Feedback as to when these classes should be held will help make them happen." Swift nodnods, "Thank you nails" nails says, "Also, this log will be posted on the Puggy website." pyritepyro says, "yay" Sponge says, "There's some chance I'll be doing something more advanced but I'm not quite sure what people want to learn about." nails says, "You should start a topic on ES" nails is going to shut the log down now. It's long enough as it is. Sponge ahs, "Good idea, Oh Lord!"