TABLE OF CONTENTS
LINE 1 - THIS POST
LINE 2 - http://krewgaming.com/threads/10776/#post-185065
I was talking with some Krew members after a match on a1 a few weeks ago and the subject of interests/professions came up. When I mentioned that I'm a developer, someone (my apologies for forgetting who) suggested that I consider writing a series of tutorials for the benefit of members interested in learning how to code.
Of course I was honored by the request since it presumes I have knowledge worth sharing, however *I* don't presume that my presentation of that knowledge would be demonstrably better than any of the many tutorials already out there (and in many cases I'm sure it would be far worse). But, reservations aside, I liked the idea and so have been thinking about it since; looking for some project or example to use as a 'starting point.'
As luck would have it, I found myself wanting a bit of a puzzle last night and the shoutbox thread presented the perfect excuse to write something. Several of you have been able to make use of that work (awesome!) and since I firmly believe that practical examples are the best, it seems to me as though a 'starting point' has fallen into place.
I'd like to use this thread to discuss what's happening, in a line-by-line analysis, in the simplest version of the shoutbox script, and to answer any questions people may have about some aspect of the code. Further, I invite @Kreubs to expand on any points, answer questions, &c. &c. however he sees fit. If there's good interest in this, perhaps another thread can be started to discuss further problems and examples, and other programming languages - let me know.
To begin, here is the JavaScript code that we will be discussing:
You may notice that I have removed the // ==UserScript== section from the top of this: that section is merely added for the benefit of utilities like Greasemonkey and only contains metadata about the script (i.e. no code).
Donald Knuth, a very important CS figure/prof., has a method called 'literate programming' which seeks to define programs using plain English. Here is the above script written literally:
Line 1:
The first word we encounter is function. What does that mean? It is perhaps obvious, but we must first realize that, in addition to there being very many programming languages, there are many ways in which we can write programs - something called 'style.'
Of course different languages elect to use different styles, depending on the preferences and goals of the language's developer(s). So, what are these styles? For the sake of brevity (for there are many), the *main* ones are:
1) procedural
2) functional
3) object-oriented (which we'll talk about another time perhaps?)
I have taken care to present these styles in rough order of increasing complexity (functional languages that delve into recursion theory (which I'd enjoy talking about at some point) can become highly complex). Let's have a look at, at their most basic, these styles mean:
1) Procedural code is written in a way that is meant to be executed line after line, in a perfect, generally non-repeating, sequence from the top of the file to the bottom. The classic example of this is a program written in the BASIC language:
As you can see, we start at the top of the file and clear the screen (CLS). Next, we print the message "HELLO, WORLD" (PRINT) then halt the program (END).
2) So what about functional code? Language designers realized that there may be certain BLOCKS of code that you want to use several times during the course of your program. Now, procedural languages like BASIC address this desire somewhat by implementing a command like GOTO. The problem is that, if you use GOTO a lot, things can quickly become very confusing and cross-referenced (something programmers call 'spaghetti code').
How can we solve that? By using something called a ... function. Put simply, a function contains a block of code that will be executed each time the function is called. Inside of the function the code may still be written procedurally, i.e. start at the first line in the function and proceed to the bottom line, but the function itself can be called at any time. Pretty useful.
So THAT is what function means in our first line! What's about to follow is a block of code that we can execute EVERY time we call it! But how do we call it? How does the code know that we want to use this particular function? "A man needs a name..."
The second word we encounter is taigaRemoveThreads. This is the NAME of our function! Now, every time we want to execute this particular block of code we can simply write 'taigaRemoveThreads()' - very cool!
Hold on, though: What about those parentheses? Are those part of the name? You didn't mention those the first time! No, the parentheses are not part of the name, but they do have a special purpose.
It's very cool that our function can execute a block of code on demand, but what if we want to, say, transform some data by passing it through a function - how can the function 'see' that data? Here again we could delve very deeply into a conversation about scoping - that is to say, what data the various parts of your program have access to.
To keep things simple, however, let's assume that the function can only see what is inside of itself. If we want the function to know about some EXTERNAL data, we have to pass it to the function. THIS is what the parentheses are for: they contain what programmers call 'arguments.'
Let's have an example. Say I'm writing a program that says "HELLO, NAME!". Instead of name, however, I want to actually write my users' names. If I did this procedurally then I'd have to write a line for EVERY user, something like:
Yuck. So let's try using a function instead:
Cool. Now we can just write 'sayHello()' every time we want to say hello to a user...but it only says 'NAME' not the user's name like we want. Okay, you say, we can solve that procedurally...but now we're right back to the BASIC example. We somehow need to *pass* some data INTO the function. Aha! We'll use an *argument*! Let's try that function again:
Okay, now a few things have changed. First of all, we have a new word between the parentheses: 'name'. Now, when we call 'sayHello' we can include external data (i.e. a name) like this: sayHello("KREW");. The value "KREW" will be assigned to the variable 'name' for use INSIDE our function! Nice!
But wait - I thought you said 'name' was an argument but now you're calling it a variable? What gives? When we ASSIGN a value to 'name' by including it in the call to our sayHello function, then it is called an ARGUMENT (arguments are passed). Yet when we USE 'name' within our function, then it is called a VARIABLE (variables are referenced).
What else has changed? In both versions, we have used the 'console.log' command. In JavaScript, this is a command that takes text as an ARGUMENT and writes it out to the console built into your browser (check it out by hitting F12). So, what we're writing in the parentheses is an example of the arguments we were just talking about!
Let's see … we've got quotes - okay, so we're defining what the text is. But then we've got plus signs? What are those? Programming has another concept called 'concatenation' - and that's what's happening here. Put simply, concatenation is taking two or more things and putting them together into one thing. In this case, we know that we want to write "HELLO, KREW!" but the "KREW" part of that is VARIABLE - it is going to change. Therefore, we need to write a FIXED string (in programming a 'string' is a PIECE of data that will be treated as text) and CONCATENATE a variable onto it. Since the exclamation point is similarly fixed, we can concatenate a final string into the end of this structure. Hence: "HELLO, " + name + "!". I.e. write this fixed string, concatenate a variable onto it, then concatenate a final fixed string.
Returning to our main topic, now we know what the parentheses are all about, and we can see that this particular function (taigaRemoveThreads) isn't taking any arguments.
So - what's left on this line? Well, lastly we see a single open curly brace ("{"). Here again we could have a very deep conversation about something called 'syntax' and 'syntactic sugar' - terms that basically refer to the SYMBOLS and FORMATTING a language uses to convey meaning. Once again, each language implements syntax in a way that makes the most sense to its developer(s) or for its purpose (for example Texas Instruments implements a very sparse native BASIC on their calculators because you wouldn't want to type much more on such a little 'keyboard').
JavaScript is a little notorious for its overly-verbose, sometimes inconsistent, syntax. One of the rules is that, to define WHAT is contained WITHIN a function, the code must be enclosed within curly braces. So this opening brace is saying "the code that I want to be executed when this function is called starts here." Correspondingly, then, when we get to the close brace we're saying "the code that I want to be executed when this function is called ends here."
THAT'S LINE 1!
What do you guys think? Should I keep going like this? Was it interesting?
LINE 1 - THIS POST
LINE 2 - http://krewgaming.com/threads/10776/#post-185065
I was talking with some Krew members after a match on a1 a few weeks ago and the subject of interests/professions came up. When I mentioned that I'm a developer, someone (my apologies for forgetting who) suggested that I consider writing a series of tutorials for the benefit of members interested in learning how to code.
Of course I was honored by the request since it presumes I have knowledge worth sharing, however *I* don't presume that my presentation of that knowledge would be demonstrably better than any of the many tutorials already out there (and in many cases I'm sure it would be far worse). But, reservations aside, I liked the idea and so have been thinking about it since; looking for some project or example to use as a 'starting point.'
As luck would have it, I found myself wanting a bit of a puzzle last night and the shoutbox thread presented the perfect excuse to write something. Several of you have been able to make use of that work (awesome!) and since I firmly believe that practical examples are the best, it seems to me as though a 'starting point' has fallen into place.
I'd like to use this thread to discuss what's happening, in a line-by-line analysis, in the simplest version of the shoutbox script, and to answer any questions people may have about some aspect of the code. Further, I invite @Kreubs to expand on any points, answer questions, &c. &c. however he sees fit. If there's good interest in this, perhaps another thread can be started to discuss further problems and examples, and other programming languages - let me know.
To begin, here is the JavaScript code that we will be discussing:
Code:
function taigaRemoveThreads() {
var messages = document.getElementById('taigachat_box').getElementsByTagName('li');
for (var i = 0; i < messages.length; i++) {
if (messages[i].innerHTML.indexOf('internalLink') > 0) {
messages[i].style.display = 'none';
}
} setTimeout(function () { taigaRemoveThreads(); }, 100);
} taigaRemoveThreads();
You may notice that I have removed the // ==UserScript== section from the top of this: that section is merely added for the benefit of utilities like Greasemonkey and only contains metadata about the script (i.e. no code).
Donald Knuth, a very important CS figure/prof., has a method called 'literate programming' which seeks to define programs using plain English. Here is the above script written literally:
Code:
Define a block of code that takes no arguments and can be referenced as taigaRemoveThreads
Create a variable called messages that contains all of the <li> elements in the 'taigachat_box' HTML <div>
For each of the <li> items in the messages variable, do the following:
If the current <li> item contains the text 'internalLink', do the following:
Set the CSS 'display' property of this <li> element to 'none' to hide it.
Move to the next <li> item.
Stop processing the <li> items in messages.
In 100 milliseconds, do the following:
Create a new reference to taigaRemoveThreads, causing the function to execute again.
Stop the timer.
End the taigaRemoveThreads block.
Call the taigaRemoveThreads function, causing it to execute the first time.
Line 1:
Code:
function taigaRemoveThreads() {
The first word we encounter is function. What does that mean? It is perhaps obvious, but we must first realize that, in addition to there being very many programming languages, there are many ways in which we can write programs - something called 'style.'
Of course different languages elect to use different styles, depending on the preferences and goals of the language's developer(s). So, what are these styles? For the sake of brevity (for there are many), the *main* ones are:
1) procedural
2) functional
3) object-oriented (which we'll talk about another time perhaps?)
I have taken care to present these styles in rough order of increasing complexity (functional languages that delve into recursion theory (which I'd enjoy talking about at some point) can become highly complex). Let's have a look at, at their most basic, these styles mean:
1) Procedural code is written in a way that is meant to be executed line after line, in a perfect, generally non-repeating, sequence from the top of the file to the bottom. The classic example of this is a program written in the BASIC language:
Code:
10 CLS
20 PRINT "HELLO, WORLD"
30 END
As you can see, we start at the top of the file and clear the screen (CLS). Next, we print the message "HELLO, WORLD" (PRINT) then halt the program (END).
2) So what about functional code? Language designers realized that there may be certain BLOCKS of code that you want to use several times during the course of your program. Now, procedural languages like BASIC address this desire somewhat by implementing a command like GOTO. The problem is that, if you use GOTO a lot, things can quickly become very confusing and cross-referenced (something programmers call 'spaghetti code').
How can we solve that? By using something called a ... function. Put simply, a function contains a block of code that will be executed each time the function is called. Inside of the function the code may still be written procedurally, i.e. start at the first line in the function and proceed to the bottom line, but the function itself can be called at any time. Pretty useful.
So THAT is what function means in our first line! What's about to follow is a block of code that we can execute EVERY time we call it! But how do we call it? How does the code know that we want to use this particular function? "A man needs a name..."
The second word we encounter is taigaRemoveThreads. This is the NAME of our function! Now, every time we want to execute this particular block of code we can simply write 'taigaRemoveThreads()' - very cool!
Hold on, though: What about those parentheses? Are those part of the name? You didn't mention those the first time! No, the parentheses are not part of the name, but they do have a special purpose.
It's very cool that our function can execute a block of code on demand, but what if we want to, say, transform some data by passing it through a function - how can the function 'see' that data? Here again we could delve very deeply into a conversation about scoping - that is to say, what data the various parts of your program have access to.
To keep things simple, however, let's assume that the function can only see what is inside of itself. If we want the function to know about some EXTERNAL data, we have to pass it to the function. THIS is what the parentheses are for: they contain what programmers call 'arguments.'
Let's have an example. Say I'm writing a program that says "HELLO, NAME!". Instead of name, however, I want to actually write my users' names. If I did this procedurally then I'd have to write a line for EVERY user, something like:
Code:
10 PRINT "HELLO, BOB!"
20 PRINT "HELLO, ALICE!"
30 PRINT "HELLO, EVE!"
Yuck. So let's try using a function instead:
Code:
function sayHello() {
console.log("HELLO, NAME!");
}
Cool. Now we can just write 'sayHello()' every time we want to say hello to a user...but it only says 'NAME' not the user's name like we want. Okay, you say, we can solve that procedurally...but now we're right back to the BASIC example. We somehow need to *pass* some data INTO the function. Aha! We'll use an *argument*! Let's try that function again:
Code:
function sayHello(name) {
console.log("HELLO, " + name = "!");
}
Okay, now a few things have changed. First of all, we have a new word between the parentheses: 'name'. Now, when we call 'sayHello' we can include external data (i.e. a name) like this: sayHello("KREW");. The value "KREW" will be assigned to the variable 'name' for use INSIDE our function! Nice!
But wait - I thought you said 'name' was an argument but now you're calling it a variable? What gives? When we ASSIGN a value to 'name' by including it in the call to our sayHello function, then it is called an ARGUMENT (arguments are passed). Yet when we USE 'name' within our function, then it is called a VARIABLE (variables are referenced).
What else has changed? In both versions, we have used the 'console.log' command. In JavaScript, this is a command that takes text as an ARGUMENT and writes it out to the console built into your browser (check it out by hitting F12). So, what we're writing in the parentheses is an example of the arguments we were just talking about!
Let's see … we've got quotes - okay, so we're defining what the text is. But then we've got plus signs? What are those? Programming has another concept called 'concatenation' - and that's what's happening here. Put simply, concatenation is taking two or more things and putting them together into one thing. In this case, we know that we want to write "HELLO, KREW!" but the "KREW" part of that is VARIABLE - it is going to change. Therefore, we need to write a FIXED string (in programming a 'string' is a PIECE of data that will be treated as text) and CONCATENATE a variable onto it. Since the exclamation point is similarly fixed, we can concatenate a final string into the end of this structure. Hence: "HELLO, " + name + "!". I.e. write this fixed string, concatenate a variable onto it, then concatenate a final fixed string.
Returning to our main topic, now we know what the parentheses are all about, and we can see that this particular function (taigaRemoveThreads) isn't taking any arguments.
So - what's left on this line? Well, lastly we see a single open curly brace ("{"). Here again we could have a very deep conversation about something called 'syntax' and 'syntactic sugar' - terms that basically refer to the SYMBOLS and FORMATTING a language uses to convey meaning. Once again, each language implements syntax in a way that makes the most sense to its developer(s) or for its purpose (for example Texas Instruments implements a very sparse native BASIC on their calculators because you wouldn't want to type much more on such a little 'keyboard').
JavaScript is a little notorious for its overly-verbose, sometimes inconsistent, syntax. One of the rules is that, to define WHAT is contained WITHIN a function, the code must be enclosed within curly braces. So this opening brace is saying "the code that I want to be executed when this function is called starts here." Correspondingly, then, when we get to the close brace we're saying "the code that I want to be executed when this function is called ends here."
THAT'S LINE 1!
What do you guys think? Should I keep going like this? Was it interesting?
Last edited: