Page 1 of 1

Intro to PLT Scheme/Racket, Part I

#1 Locke  Icon User is offline

  • Sarcasm Extraordinaire!
  • member icon

Reputation: 520
  • View blog
  • Posts: 5,596
  • Joined: 20-March 08

Posted 19 June 2010 - 01:46 AM

This is an introduction to the PLT Scheme programming language (which is also now known as Racket, which I found out while looking at the website while writing this :rolleyes:).

Pre-tutorial apologies...the tutorial is long. But this stuff can be confusing if it's not clearly explained, so I tried my best.

PLT Scheme/Racket is a mainly functional programming language I was introduced to during my third high-level software programming class in college. It has support for many different paradigms, including object-oriented programming, logic programming, and web applications. If you've never programmed in LISP (or any dialect thereof), then it might be a challenge at first, as the syntax will probably be unfamiliar to you, since it differs a lot from C/C++ and their ilk.


Setup

Alright, well, for this tutorial, you'll need to head over to http://download.plt-scheme.org/ to get the version I'm using (4.2.5). On Racket's website, it says that backwards compatibility is maintained, although I don't have the DrRacket IDE...I have DrScheme, which is the older one. The layout of the IDE might be slightly different, but I can't see it being a HUGE overhaul. DrScheme was a relatively simple IDE as far as IDEs are concerned, so I can't see you having too much trouble if you download DrRacket instead.

If you'd like to be up to date and use DrRacket, head on over to http://racket-lang.org/download/ and get the one for your system. It's a simple installer program.

Setting up the language

When you fire up DrScheme, click the "Language" menu option, select "Choose Language...", then select the top option, which should be "Use the language declared in the source". This will allow you to directly control what language you write your code in by specifying it in the source code file.

Now, you're pretty much all set up. If you've ever worked with Java, you'll be thinking, "What? I didn't set up the classpath (or Scheme/Racket equivalent)!". You don't have to. DrScheme/DrRacket knows where it is, since it was packaged with the install of Scheme/Racket itself. :)

The output from your programs will appear in the bottom window of DrScheme. If there is just one main window, then the bottom window that I'm talking about will probably appear on output.


Writing Code

A quick little note here...comments in PLT Scheme/Racket start with a semicolon. Everything past the semicolon will be ignored as far as the code is concerned. You can also do block comments with #| where you want to start it and |# where you want to end it.

; single line comment

#| multi-line comment
   multi-line comment
|#


When specifying the language in the source code file, you need a special line at the beginning of the file. It looks like this.

#lang scheme


That will let DrScheme/DrRacket know that you're using the Scheme language.

A typical statement, or function call, will ALWAYS be encased in parentheses in PLT Scheme/Racket. This comes from LISP.

Well, now I'll start off with something simple. A little function to output something to the standard output. We're going to use the print function. This function takes one argument, whatever you want to output.

(print "Hello, world!")


Notice now that there is only a space between the function name and the argument(s). This will output "Hello World" to the standard output, INCLUDING THE QUOTES. That is important. When strings are used for output, the quotes come with them.

Now how to declare variables. For this, we use the define keyword.

(define x 5)


You C/C++/Java/C# guys might be thinking, "Hey, he didn't specify a data type!". Well, you don't have to. As a matter of fact, I don't even know if you can. I just know that you don't. This statement will make x equal to 5. Note that this is just like a function call. With the parameters being the name of the variable and the value to give it.

; these are also valid examples

(define x 1)

(define x 3/5) ; set x to .6 (or three-fifths as Scheme will represent it)

(define x "YES!")

(define x 5.284856932)

(define x #t) ; set it to true

(define x #f) ; false


x can be any data type. You can also change the value later with the set! function. You can change it to any type that you require. This can be a blessing or a curse, so watch out and make sure you're not operating on something incorrectly.

The set! function is used exactly like define.

(set! x 5) ; set x to 5


The only stipulation is that whatever variable you're setting is already declared using define.

Now, I'll cover the basic mathematical functions. They're still like any regular function call, just with more argument capabilities.

(+ 5 10) ; yields 15

(- 10 5) ; yields 5

(* 3 4) ; yields 12

(/ 5 10) ; yields 5 over 10, or one half


Notice that there are just spaces between the arguments, no commas, nothing.

Now...these functions have the capability to take an infinite amount of arguments...

Some examples:

(+ 1 2 3 4 5) = 1 + 2 + 3 + 4 + 5 = 15

(- 5 4 3 2 1) = 5 - 4 - 3 - 2 - 1 = -5

(* 2 3 4 5) = 2 * 3 * 4 * 5 = 120

(/ 3 5 6 4) = 3 / 5 / 6 / 4 = 1 / 40

You could have TONS of arguments, but I used 4 or 5 to illustrate how the formula works.

Now, if we wanted to combine what we've learned so far, we can print out the result of a formula.

(print (* 2 3))

; prints 6


It's simply supplying the multiplication function result as a parameter to the print function.

Now let's move on to an example summing up all of the things we've learned so far...

#lang scheme

(define x 5)
(define y 4)

(define z (* x y))

(print z) ; prints 20


As the comment says, this will print 20 by assignment to a variable and then printing said variable.

Each function call will be in its own set of parentheses. That's essentially the key thing to remember. The program comprises several function calls.


Functions

Chances are that you already know what a function is. It's a piece of code that can be used multiple times to perform a task. The way to implement them in Scheme/Racket is as follows. We use the define keyword again.

(define (functionName)
  (print 4))


The design is up to you. You can leave it all on one line, or indent it how you wish. For this, either way is fine, but more complicated functions may get confusing if a proper organization technique isn't met.

As you can probably tell, the functionName would be your function's name. This function actually takes no parameters. It will just print the number 4 whenever it is called. However, note that the entire function declaration and body are encased in the parentheses belonging to define.

The function will return whatever the statement inside it returns. Since the print command returns #<void>, if you had a statement like this -- (define x (function)), x would be set to #<void>, since the print command is used to output, and not to return a useful value.

Now I'll now demonstrate how to define a function that takes two parameters (assumed to be numbers), adds them together and returns the result. There are two ways to write this. Each code box will display one.

(define (add x y)
  (+ x y))


(define (add x y)
  (define result (+ x y))
  result)


x and y are the parameters. You can name them whatever you want. Just know that the syntax uses spaces between each parameter.

Personally, I would use the first way. The only difference between them is that the second one uses a local variable (used the same way as a regular one, however, it can only be used inside of the function).

Control Structures

Most of you are probably familiar with if structures. Based on "if this is true, then do something...otherwise do something else". Scheme has the same type of thing:

(if (condition)
    (return this)
    (return that))


The common comparator functions (less than, greater than, equal, etc.) that return a boolean true/false value are as follows, and are much the same as they are in C/C++:

  • >
  • <
  • >=
  • <=
  • = (for numbers)
  • eq? (similar to .equals() in Java, it's used for comparing objects other than simple data types)
  • null?


The only one of the above functions that doesn't take two arguments for comparison is null?. Other than that, they all take two arguments, and compare them and return the value representing the comparison.

It's a convention to name a boolean function that would be used for something like this with a question mark at the end. This is a flag for the programmer's sake. The function, in this case, is typically called a predicate.

An example:

(if (> 5 4)
   "5 is greater than 4"
   "4 is greater than 5")


The condition is translated to if 5 is greater than 4, return "5 is greater than 4", else return "4 is greater than 5". Needless to say, the "else" portion will never be returned. Whatever you return can be functions and whatever else you want them to be.

Moving to a structure like the if...there's one in Scheme called cond. It's like an if/else if/else if/else type of structure. There can be an infinite number of conditions.

(define x 10)
(define y 5)

(cond ((= x y) "equal") ; one condition/return value
      ((> x y) "x > y") ; another
      ((< x y) "x < y") ; another
      (else "something went wrong")) ; theoretically unreachable


Well, I think that's enough for the first part. I'll get another one up soon going over some other basic things, and possibly some more advanced computation using the syntax of Scheme.

You may be thinking...hey, where's the stuff about loops? Well, there are no loops. You can use recursion and lists, which are a major part of LISP. After all, LISP stands for LISt Processing. You can achieve anything you'd like using lists and recursion (among other things, depending on the needs). It's an odd way of thinking, however, once you get used to it...it's not so bad. You'll probably struggle with the shear amount of parentheses at some point, but you'll be able to see them clearly once you have some experience. ;)

For some practice, you can head over to Martyr2's Mega Project Ideas List for some basic application practice, or over to Project Euler for some practice problems.

Functional programming allows you to write some very elegant solutions to some complex problems.

Thanks for stopping by! Suggestions for any improvements are completely welcome! :)

Is This A Good Question/Topic? 1
  • +

Replies To: Intro to PLT Scheme/Racket, Part I

#2 Raynes  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 611
  • View blog
  • Posts: 2,815
  • Joined: 05-January 09

Posted 24 June 2010 - 10:14 AM

I skimmed through it. Looks like an excellent tutorial. I'm happy you're enjoying Lisp.

I'll write up a Clojure tutorial soon.
Was This Post Helpful? 0
  • +
  • -

#3 Locke  Icon User is offline

  • Sarcasm Extraordinaire!
  • member icon

Reputation: 520
  • View blog
  • Posts: 5,596
  • Joined: 20-March 08

Posted 24 June 2010 - 11:34 AM

View PostRaynes, on 24 June 2010 - 11:14 AM, said:

I skimmed through it. Looks like an excellent tutorial. I'm happy you're enjoying Lisp.

I'll write up a Clojure tutorial soon.


Oh man, I take back all the things I said about Clojure. ;)

I just haven't gotten to dive into Clojure yet. I'm juggling learning Python for my next software class, delving further into Scheme/Racket, and assorted other little projects.

Hopefully, I'll get around to writing the second part, which will cover types, lists and some of their functions (map, foldl, foldr), some cons, and getting user input (I left it out of this one because of the type inferences that go on). More basic stuff like that.
Was This Post Helpful? 0
  • +
  • -

#4 Guest_Xagyg*


Reputation:

Posted 01 July 2010 - 06:27 PM

To "loop", I find the following ".." function useful in conjunction with "for-each" see below (but you don't have to use ".." - there are other functions already in racket, for example "in-range").

Defining "..":

(define (.. x y (z (if (< x y) 1 -1)))
    (if ((if (> z 0) > <) x y) empty (cons x (.. (+ x z) y z))))


Now print the countdown to "blastoff":

(for-each (lambda(x)(display x)(newline)) (.. 10 1))(display "blastoff!")


By the way, there are more "looping" functions such as "for", "for-each", "do" etc. Check out the Racket guide or reference manual on the Racket web site.
Was This Post Helpful? 0

#5 Locke  Icon User is offline

  • Sarcasm Extraordinaire!
  • member icon

Reputation: 520
  • View blog
  • Posts: 5,596
  • Joined: 20-March 08

Posted 06 July 2010 - 09:46 PM

Hm. That's actually fairly interesting. Passing a parameter to the lambda function from the second parameter (list) of the for-each function is necessary, however, it doesn't have to be useful.

I suppose that would be a viable way of looping.
Was This Post Helpful? 0
  • +
  • -

#6 matthewstitt49259  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 08-November 11

Posted 08 November 2011 - 07:15 PM

Thank you for the tutorial. I am very interested in learning Racket not so much for me but for all my classmates that stuggle with programming. I want to find a way to make it a little simpler to put together and I think this might just help.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1