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
.
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.
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.
+
- 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)
.
+
- 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.
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.
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.
+
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)
.
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)
.
- 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.
+