diff --git a/resources/public/javascript/tryclojure.js b/resources/public/javascript/tryclojure.js index 4e04303..1e0256c 100644 --- a/resources/public/javascript/tryclojure.js +++ b/resources/public/javascript/tryclojure.js @@ -166,8 +166,8 @@ var controller; $(document).ready(function() { controller = $("#console").console({ - welcomeMessage:'Enter some Clojure code to be evaluated.', - promptLabel: 'Clojure> ', + welcomeMessage:'Give me some Clojure:', + promptLabel: '> ', commandValidate: onValidate, commandHandle: onHandle, autofocus:true, diff --git a/resources/public/tutorial/page1.html b/resources/public/tutorial/page1.html index 7ffd325..4654fcb 100644 --- a/resources/public/tutorial/page1.html +++ b/resources/public/tutorial/page1.html @@ -1,15 +1,7 @@

- This tutorial isn't entirely complete yet. More fun content is to be written. Stay tuned. + I'll take you on a 5-minutes tour of Clojure, but feel free to experiment on your own along the road!

- Above, you have your REPL. Please try the examples as we go along, and by all means experiment - with concepts independently. Should you refuse, you will promptly be IP banned from this - website, and a teddy bear will eat your candies. ctrl+v to paste and ctrl+c to copy like you - would normally expect, but you can't paste with your browser's right-click menu. -

- -

- You can type 'next' to move forward, 'back' to go back to the previous step, and 'restart' to - restart the tutorial. Go ahead and type 'next' to begin + You can type next to skip forward, back to return to the previous step, and restart to get back to the beginning. Let's get started: type next.

diff --git a/resources/public/tutorial/page10.html b/resources/public/tutorial/page10.html index f19c97b..f1e2228 100644 --- a/resources/public/tutorial/page10.html +++ b/resources/public/tutorial/page10.html @@ -1,30 +1,35 @@ -

Awesome. Now you can call this function just like we called the old square function.

+

+ Success! Now you can call this new square function just like you called the old square function. +

- Clojure has a great set of immutable and persistent data structures. Vectors, lists, maps, sets, - I get chills. + By now, you know that lists are quite important in Clojure. + But Clojure also has other data structures:

Vectors: [1 2 3 4]
Maps: {:foo "bar" 3 4}
- Lists: '(1 2 3 4)
Sets: #{1 2 3 4}
- Vectors and lists are sequential and ordered collections. You'll see vectors used much more than lists. - Maps are typical hash-maps - unordered collections indexed by keys. The keys can be any object. Here, - we've used a keyword, :foo as a key. Keywords make excellent keys. We also used a number. - Sets are mathematical sets.

- Clojure's collections are one of the most imporant parts of Clojure. Being a functional language, Clojure - encourages immutability and as little state as possible. Therefore, instead of for loops mutating variables - and such, most of the time you'll see higher order functions doing transformations on immutable data and - returning new collections rather than ever modifying the old one. + Vectors and lists are sequential and ordered collections. + Sets are not ordered, and they cannot contain duplicate elements. + Maps are key-value collections, where the keys can be any object. + Here, we've used what Clojure calls a keyword (:foo) for one of the keys, and a number for the other key. +

+ +

+ Now I'll tell you another thing that may surprise you: Clojure collections are immutable - they can never change. + When you do anything on a list, including adding and removing elements, you actually get a brand new list. + (Fortunately, Clojure is amazingly efficient at creating new lists). + In general, Clojure encourages you to have as little mutable state as possible. + For example, instead of "for" loops and other state-changing constructs, most of the time you'll see functions doing transformations on immutable data and returning new collections, without changing the old one.

- A prime example of this is map. We can use map, a higher order function (which is a function - that takes functions as arguments or returns functions), to 'map' a function to every element of a sequence. - Let's use this to increment each number in a vector. Type (map inc [1 2 3 4]) to continue. + A prime example of this is map. map is a higher order function, which means that it takes another function as an argument. + For example, you can ask map to increment each number in a vector by passing it the inc function, followed by the vector. + Try it for yourself: type (map inc [1 2 3 4]) to continue.

diff --git a/resources/public/tutorial/page11.html b/resources/public/tutorial/page11.html index da67d0a..726fe3c 100644 --- a/resources/public/tutorial/page11.html +++ b/resources/public/tutorial/page11.html @@ -1,8 +1,11 @@ -

Excellent work.

+

Great job!

- Well, that's all there is right now. This tutorial is still a work in progress, and I'm working on more - steps. If anybody wants to contribute, you can find a link to the Github repository on the 'about' page. - Furthermore, if you're just a brand new Clojure developer looking for some learning experiences, check - out the 'links' page. You'll find links to some tutorials and such there. + We've only scratched the surface of Clojure and its mind-bending power. + This tutorial is still a work in progress, and I'm working on more steps. + Meanwhile, you can learn more about Clojure by visiting the 'links' page. +

+ +

+ Welcome to your adventures in Clojure, and be prepared to be surprised and delighted every step of the way!

diff --git a/resources/public/tutorial/page2.html b/resources/public/tutorial/page2.html index acd317f..1d11c62 100644 --- a/resources/public/tutorial/page2.html +++ b/resources/public/tutorial/page2.html @@ -1,6 +1,7 @@

- I bet you're curious to find out what Clojure code looks like, aren't you? Sure you are. - Well, I've give you a hint: it's made up of lists. Let's do some arithmetic. + The first thing you may notice about Clojure is that common operations look... strange.

-(+ 3 3) +

+ For example, try typing (+ 3 3) in the REPL. +

diff --git a/resources/public/tutorial/page3.html b/resources/public/tutorial/page3.html index 925f30e..ae8cc9b 100644 --- a/resources/public/tutorial/page3.html +++ b/resources/public/tutorial/page3.html @@ -1,12 +1,13 @@

- Excellent work! There are other arithmetic functions. + That was a strange way to say "three plus three", wasn't it?

-* -- -/

- Try them out. Save / for last (don't worry, I have a reason!). + A Clojure program is made of lists. + (+ 3 3) is a list that contains an operator, and then the operands. + Try out the same concept with the * and - operators.

-

Once you're finished playing around, try (/ 10 3).

+

+ Division might surprise you. When you're ready to move forward, try (/ 10 3). +

diff --git a/resources/public/tutorial/page4.html b/resources/public/tutorial/page4.html index 0d06d50..991dc20 100644 --- a/resources/public/tutorial/page4.html +++ b/resources/public/tutorial/page4.html @@ -1,8 +1,4 @@

- I bet that caught you by surprise, didn't it? Don't fear! Clojure simply has a built in Rational type. - We can prove that we've got a rational by running (type (/ 10 3)). Rationals are more - concise and precise than floating point numbers. However, we can force Clojure to do floating point - division by just making one of our numbers floating point. + Now, that was a bit surprising: Clojure has a built in Rational type. + You can still force Clojure to do floating point division by making one of the operands floating point: type (/ 10 3.0) to continue.

- -

Type (/ 10 3.0) to continue.

diff --git a/resources/public/tutorial/page5.html b/resources/public/tutorial/page5.html index 5f40ebb..1788c09 100644 --- a/resources/public/tutorial/page5.html +++ b/resources/public/tutorial/page5.html @@ -1,11 +1,6 @@

Awesome!

- Another neat thing about Clojure is that functions can take an arbitrary number of arguments. - Functions are allowed to specify a 'catch-all' to put an optional and arbitrary number of arguments - into. Because of this, a lot of Clojure's core functions have interesting capabilities. For example - the arithmetic functions we've already played with are not limited to two arguments! No sir, they can - take any number of arguments they wish. + Many Clojure functions can take an arbitrary number of arguments. + Try it out: type (+ 1 2 3 4 5 6) to continue.

- -

Try it out. Type (+ 1 2 3 4 5 6) to continue.

diff --git a/resources/public/tutorial/page6.html b/resources/public/tutorial/page6.html index 0b55ee3..daa7698 100644 --- a/resources/public/tutorial/page6.html +++ b/resources/public/tutorial/page6.html @@ -1,7 +1,8 @@ -

Alright, that's enough math. Let's do some fun stuff, like write functions.

-

- You can define functions in Clojure with defn + That's enough math. Let's do some fun stuff, like defining functions. + You can do that in Clojure with defn.

-

Type (defn square [x] (* x x)) to continue!

+

+ Type (defn square [x] (* x x)) to define a "square" function that takes a single number and squares it. +

diff --git a/resources/public/tutorial/page7.html b/resources/public/tutorial/page7.html index cf0f574..e6c58c0 100644 --- a/resources/public/tutorial/page7.html +++ b/resources/public/tutorial/page7.html @@ -1,12 +1,13 @@ -

Oh boy! We wrote our very own function! It's a lovely one, isn't it?

+

Congratulations - you just defined your first Clojure function. Many more will follow!

- Our square function takes a single argument -- a number -- and squares it. + defn takes the name of the function, then the list of arguments, and then the body of the function. + I told you that a Clojure program is made of lists, right? + The entire defn is a list, and the function body is also a list. + (Even the arguments are collected in a vector, which is similar to a list - we'll talk about vectors soon).

- Take a look at how our defn form looks. First comes the name of the function, then the argument list - (which is a vector, and not an actual list), then the body of the function. + Oh, sorry for talking so long - you probably want to try out your brand new function! + Type (square 10).

- -

But wait! We don't even know if our function works or not! Let's try it out. Type (square 10).

diff --git a/resources/public/tutorial/page8.html b/resources/public/tutorial/page8.html index 075857f..d3a26cf 100644 --- a/resources/public/tutorial/page8.html +++ b/resources/public/tutorial/page8.html @@ -1,17 +1,20 @@

Yay! It works!

- You know, Clojure is a functional programming language. As such, it has first-class and - anonymous functions. Let's write our square function as an anonymous function. + By now, you probably think that Clojure is very different from the programming languages you already know. + Indeed, it belongs to a different family than most popular languages' - the family of "functional" programming languages. + Like most functional languages, Clojure can define a function without even giving it a name:

+ (fn [x] (* x x)) +

- If you run this in the REPL above (as you should), you'll note that some very weird and - cryptic thing is printed. Functions are just normal values like a number, a string, or - anything else. The cryptic thing is simply how they look when printed. + If you run this code, you'll see some cryptic output. + In Clojure, functions are just normal values like numbers or strings. + fn defines a function and then returns it. + What you're seeing is simply what a function looks like when you print it on the screen.

- Our anonymous function isn't very useful if we don't call it. Let's do it. Type - ((fn [x] (* x x)) 10) + But wait - an anonymous function isn't very useful if you can't call it. Try to define a new anonymous function and call it straight away: ((fn [x] (* x x)) 10).

diff --git a/resources/public/tutorial/page9.html b/resources/public/tutorial/page9.html index d6e81da..8679f37 100644 --- a/resources/public/tutorial/page9.html +++ b/resources/public/tutorial/page9.html @@ -1,12 +1,16 @@

- Yay! Notice how we called our anonymous function? We just wrapped the function in parentheses, - placing it as the first element in this new list and passing it arguments just like we did earlier - with the arithmetic functions. Awesome, huh? + Let's see what you just did: you evaluated a list where the first element is the function itself, defined on the spot - and the other elements are the arguments that you pass to the function. + That's exactly the same syntax that you used earlier on to call functions like square or even +. + The only difference is that now you defined the function in the same place where you called it.

- You may not know this, but defn is actually just a bit of sugar around def - and fn to create named functions. We can create named functions without defn + Remember defn? + Now I can tell you a secret: defn is actually just a bit of syntactic sugar around def and fn. + You've just seen fn at work: it defines a new function. + def binds the newly defined function to a name.

-

Type (def square (fn [x] (* x x))) to continue.

+

+ If you want, you can create a named functions without using defn: type (def square (fn [x] (* x x))) to continue. +

diff --git a/src/tryclojure/views/home.clj b/src/tryclojure/views/home.clj index 0f2b03b..54909be 100644 --- a/src/tryclojure/views/home.clj +++ b/src/tryclojure/views/home.clj @@ -15,26 +15,28 @@ (defpartial about-html [] [:p.bottom - "Please note that this REPL is sandboxed, so you wont be able to do everything in it " - "that you would in a local unsandboxed REPL. Keep in mind that this site is designed for " - "beginners to try out Clojure and not necessarily as a general-purpose server-side REPL."] + "Welcome to Try Clojure - a quick tour of Clojure for absolute beginners." + ] [:p.bottom - "One quirk you might run into is that things you bind with def can sometimes disappear. " - "The sandbox wipes defs if you def too many things, so don't be surprised. Furthermore, " - "The sandbox will automatically be wiped after 15 minutes and if you evaluate more after that," - "It'll be in an entirely new namespace/sandbox."] + "Here is our only disclaimer: this site is an introduction to Clojure, not a generic Clojure REPL. " + "You won't be able to do everything in it that you could do in your local interpreter. " + "Also, the interpreter deletes the data that you enter if you define too many things, or after 15 minutes."] [:p.bottom - "TryClojure is written in Clojure and JavaScript (JQuery), powered by " - (link-to "https://github.com/flatland/clojail" "clojail") - " and Chris Done's " - (link-to "https://github.com/chrisdone/jquery-console" "jquery-console")] - [:p.bottom "Design by " (link-to "http://apgwoz.com" "Andrew Gwozdziewycz")]) + "TryClojure is written in Clojure and JavaScript with " + (link-to "http://webnoir.org" "Noir") ", " + (link-to "https://github.com/flatland/clojail" "clojail") ", and Chris Done's " + (link-to "https://github.com/chrisdone/jquery-console" "jquery-console") ". " + " The design is by " (link-to "http://apgwoz.com" "Andrew Gwozdziewycz") "." + ]) (defpartial home-html [] [:p.bottom - "Welcome to Try Clojure. See that little box up there? That's a Clojure repl. You can type " - "expressions and see their results right here in your browser. We also have a brief tutorial to " - "give you a taste of Clojure. Try it out by typing " [:code.expr "tutorial"] " in the console!"]) + "Welcome to Clojure! " + "You can see a Clojure interpreter above - we call it a REPL." + ] + [:p.bottom + "Type \"tutorial\" in the REPL to begin." + ]) (defn root-html [] (html5 @@ -65,9 +67,7 @@ [:a#about.buttons.last "about"]] [:div#changer (home-html)]] [:div.footer - [:p.bottom "©2011-2012 Anthony Grimes and numerous contributors. Built with " - (link-to "http://webnoir.org" "Noir") - "."]] + [:p.bottom "©2011-2012 Anthony Grimes and numerous contributors."]] (javascript-tag "var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-27340918-1']);