This is part one of a series I am sending to some of my friends.
It teaches you how to make a pop-up window using scheme, and change the message of the window, position, size, content, etc.

Part two will teach how to link windows together, make them visible, invisible, and if I figure out how to do graphics, I will post a graphics with scheme tutorial as well. The help desk part of scheme is invaluable, I just made this tutorial to condense the huge amount of information in help desk. :D

Step One: Go to www.drshceme.org and download the full version of scheme.
Step Two: Run the installation program and open Dr Scheme.
Step Three: While in the Dr Scheme window, press ctrl and L at the same time. Click on the arrow next to PLT and select graphical from the list before pressing okay.

Then you can begin programming.
This should be your first program: (Fell free to copy and paste!)

(define mywindow (instantiate frame% ("Your mom")(x 300)(y 300)(height 300)(width 300)))
(define mymsg (instantiate message% ("Is the speed limit" mywindow)))
(instantiate button% () (label "press me")(parent mywindow)
(callback (lambda (button event)(send mymsg set-label "is the best"))))
(send mywindow show #t)

That program will give you a window with a title, a message, and a button.

In the first line of code, mywindow is replaceable by any word you can think of.
your mom is also replaceable, and you can change the x y height and width values to any real positive number.
In the second line, mymsg is replaceable, as is "is the speed limit" but now and forever, you will NEED those quotation marks.
Third line of code: The label is changeable, and in the fourth line, you can change what the message changes to.

Recommended Answers

All 11 Replies

hi ! i am a student and i learning Dr Scheme , i think that is a good programing.
Can you help me have many exercise and solution of Dr Scheme ( i from VIET NAM)

Sure! I do not have very much freetime these days, but I will help in what way I can. I am not a scheme expert, but I will teach you what I know. If you want/need more information, you can go to www.drscheme.org and join the mailing list.

Email me at mister_fett@walla.com if you want me to send you some stuff, and I have a friend who knows more about scheme that may be able to help you.

Sure! I do not have very much freetime these days, but I will help in what way I can. I am not a scheme expert, but I will teach you what I know. If you want/need more information, you can go to www.drscheme.org and join the mailing list.

Email me at mister_fett@walla.com if you want me to send you some stuff, and I have a friend who knows more about scheme that may be able to help you.

Can you make a scheme code for me that will count the number appearance of the number in the list. For example the list contains `(41434) the code will check how many times number 4 appears in list. From the example 4 appears 3 times so the output would be 3. please. help me... i'm kinda noob in scheme prgramming.

Okay, I will try that and get back to you if I make it work.
By the way, my email address has changed, it is now misterfett@gmail.com

Thanks a lot...mr-fetts...

Can you make a scheme code for me that will count the number appearance of the number in the list. For example the list contains `(41434) the code will check how many times number 4 appears in list. From the example 4 appears 3 times so the output would be 3. please. help me... i'm kinda noob in scheme prgramming.

Hi, I'm the guy who taught Mr. Fett about DrScheme. He asked me for help with this (apparently I didn't do a very good job... ;) )

Anyway, I'm assuming that you're using the Textual language and that you mean for that to be a list of 5 integers, not a list of one integer. I'm also assuming you're interested in an explanation, if not just skip to the bottom for the code.

OK, an important thing to know about scheme lists is that they can also be represented as cons cells. The above list can be represented as:
(cons 4 (cons 1 (cons 4 (cons 3 (cons 4 null)))))
The operation car returns the first part of the cons cell, and the operation cdr returns the second part of the cons cell. (I know, there are more precise technical terms, but I'm too lazy to use them.)
For example, (car '(1 2 3 4)) returns 1
(cdr '(1 2 3 4)) returns '(2 3 4)
and (cdr '(1)) returns '() or null

Now, further consider this: given the list null or '(), we know the answer to the question; there are 0 things on the list that match your criteria.

So, here's the process we need to do to get the answer:
if the list is '(), the answer is 0.
if the first item on the list is what we're trying to find, the answer is 1 plus the result of this process applied to the rest of the list.
otherwise, the answer is the result of this process applied to the rest of the list.

in scheme code (the ;... are comments),

; count: list of numbers, number --> number
; to determine how many of some number are on a list
(define (count a-lon n)
  (cond
    [(null? a-lon) 0]
    [(= n (car a-lon)) (+ 1 (count (cdr a-lon) n))]
    [else (count (cdr a-lon) n)]))

So then (count '() 4) returns 0,
(count '(4 1 4 3 4) 4) returns 3,
and (count '(4 1 4 3 4) 3) returns 1.

If you're using Beginning Student instead of Textual, some of the syntax is different, but the idea is the same. Also, if you're working on very large lists, this would result in a very large, inefficient function stack, and there would be a better way to write it. If anyone is interested in the specifics, let me know.

* Apologizes in advance for double-post *

Ok, this is supposed to be a DrScheme tutorial, but I noticed that mister-fett hasn't given too much basic background on DrScheme.
(BAD FETT! BAD!) :lol:

First of all, the link he posted was wrong, it's www.drscheme.org
(BAD FETT! BAD!)

Second of all, some history. Scheme is a programming language based on Lisp. Lisp was a language created in the old days to help with AI programming. It does this by having a remarkable selection of higher level features, most importantly the ability for a program to treat functions as values. Functions can thus be dynamically created, passed to other functions as arguments, and have other things done to them that you'd usually associate with values. The idea was that this would eventaully lead to a computer that could reprogram itself, taking learning AI to new heights. A drawback of all this is, Scheme and LISP have so many high-level features that they don't compile well, and some amount of the code always has to be parsed at run-time. This makes it difficult (but not impossible) to create portable scheme code, and it also makes it a relatively slow langauge.

The basic syntax of scheme is, all expressions are parenthesized. You have an open-parenthesis, then a procedure, then (maybe) some arguments, then a close-parenthesis. The arguments could of course be other expressions.

Now for a brief overview of data types.
Some important data types in scheme are:
number, such as 4, -5, 3.14159265, +inf, 0+5i
symbol, such as 'moo or 'hello. (Essentially just a string)
string, such as "Hello World"
character, such as #\A or #\0
list, such as null or (list 1 2 3) or '(1 2 3) or (cons 1 (cons 2 (cons 3 null). The last three are the same thing, I'm just showing the 3 ways to construct one.
structure, but you're probably not ready for that yet.
boolean, such as #t or #f
void. This value can be produced by the procedure (void) and some other procedures.
vector - constructed with (vector arg...) or (make-vector length [fill]) or (build-vector length fill-proc). This is an array. It works faster than a linked list (which is what the list is), but isn't as flexible.

Next, definitions. Definitions are done as
(define name value)
e.g.: (define bar 4)
Defining a procedure can be done 2 ways, but I'll only get into one now:
(define (name arg...) expression)
e.g.: (define (zig x y) (+ x (* 5 y)))

Some scheme operators include + - * / sqrt expt = eq? string? string=? symbol? symbol=? number? integer? exact? string-append cons list number->string string->number string->symbol symbol->string
Most of these should be self-explanatory, if not, download DrScheme, go to help, say help desk, and look it up.

Here's a sample definition of the distance formula function (which should really use posn structures, but we haven't gotten there yet, so just ignore that):

(define (sqr n) (* n n))
(define (dist x1 y1 x2 y2)
  (sqrt (+ (sqr (- x1 x2)) (sqr (- y1 y2)))))

More detailed tutorials available on demand. Sorry if this one is hard to read, I'll fix it tomorrow if I remember.

Ok, I suppose I ought to handle some special forms next.
Ordinarily, in Drscheme, if I have an expression of the from (proc (subexpr) (subexpr)), the program will execute the subexpressions before the main expression (obviously). However, there are some forms (most notably branching constructs) that don't follow the rules exactly.
The simplest is the if statement. In scheme, if takes the form
(if test-expr true-result [false-result]). This form does test, and if it's true, it does true-result. Otherwise, true-result is never touched. (Same with false-result) I think this should be self-explanatory, but I don't want someone to get lost in the language's semantics.

There are two similar forms, when and unless.
(when test result...)
(unless test result...)
The only reason you would use these instead of if is that you can have multiple expressions after the test, for example:
(when (> pressure 10) (open-valve) (ring-bell) (wait 1.5) (check-pressure))
You could also just define a procedure to do those 4 operations, like so:
(define (high-pressure) (open-valve) (ring-bell) (wait 1.5) (check-pressure))
...
(if (> pressure 10) (high-pressure))
But using when and unless is easier.

Now, lets talk about boolean operations. Scheme provides the usual (and, or, not), and more may be defined depending on your language settings and included libraries (xor, nand, nor...). It is important to note that as far as scheme is concerned, any value that is not false is true, including non-booleans like "hi", 'false (a symbol), and 4. These operations work like if in that they DO short circuit. Thus, the expression
(and (= 4 5) (ring-bell))
will return false without touching the bell. The expression
(and (ring-bell) (= 4 5))
on the other hand, would ring the bell (assuming that that procedure is defined elsewhere), then return false.

Finally (at least for boolean stuff), I'd like to introduce you to cond, scheme's version of switch. The syntax for cond is a bit different than for ordinary expressions:

(cond
  [test result]
  ...)

Basically, what this form does is, it does the first test. If it's true (ie: not the boolean false), the first result is the result of the whole cond statement. If it is false, it goes on to the next test-result pair, and so on. If it gets through all its cond clauses without finding a true test, it returns void. Note that you can use the keyword else instead of a test to make it always do that choice. Example:

(cond
  [(> 4 5) 42]
  [(or (= 4 4) #f) 'moo]
  [else "Hello"])

would return 'moo

Using these forms, we could define a procedure to tell us the number of real roots produced by a quadratic equation:

(define (numRealRoots a b c)
  (cond
    [(> (* b b) (* 4 a c)) 2]
    [(= (* b b) (* 4 a c)) 1]
    [(< (* b b) (* 4 a c)) 0]))

Before I go, I would like to mention one more syntactic form: begin. (begin expr...) takes any number of subexpressions and returns the result of the last one. This can be useful, for example, when you're writing an if statement, as each result can only be one expression.
(begin0 expr...) works the same way, but it returns the result of the FIRST expression, making it marginally useful as a shorthand way to store and retrieve a variable (for example, when popping items off a stack).

Speaking of storing and retrieving values, another form you'll need to know is set! . Although scheme is mainly a functional programming language, it does allow you to mutate variables. The syntax is simple: (set! variable value)
e.g.:

(define x 5)
x
(set! x 4)
x

returns 5 and 4 to the interactions window.

OK, so we can set global variables, now wouldn't it be nice if we could also set local variables? The let form allows us to do that. The syntax is:
(let ([name value]...) body-expr...)
For example, lets say we're defining a function to move a little dude around the screen. Our function will be given his original position and the angle and distance to move him, but we will need to find the x and y offset before feeding it to out graphics and physics engines:

(define (move x y r d)
  (let ([movex (* d (cos r))]
        [movey (* d (sin r))])
    (physics-move x y movex movey)
    (graphics-move x y movex movey)))

As much as I'd love to put some information here about the syntax to do other common tasks in scheme, this post is probably long enough already. Join me next time for information on the fun stuff - structures, lists, input, and output. After that we'll start on scheme's classes, graphics, and GUI toolboxes.

As I said, this is where we start doing the fun stuff. I'll start with structures. To define a new structure type, simply use the syntax:
(define-struct name (field...))
Doing this defines several procedures at once. There's a make-name procedure that takes as many arguments as the structure has fields, and returns a new instance of the structure. There's name? , a predicate that determines if some arbitrary datum is an instance of the structure. Also, an accessor procedure name-field is created for each field, and a mutator procedure set-name-field! is also created. Here's some example code (with comments):

(define-struct plane (speed passengers fuel max-fuel))
(define boeing (make-plane 1000 100 150 200)) ; create a plane
(plane? boeing) ; returns true
(plane? 4) ; returns false
(plane-speed boeing) ; returns 1000
(plane-fuel boeing) ; returns 150
(set-plane-fuel! boeing 200) ; returns void
(plane-fuel boeing) ; now returns 200

Maybe after the lists tutorial we can do something more in depth with this, but for now, that's all there is too it!

Now for I/O. As you proabbly know by now, when an expression executes in the interpreter, it prints the result to the interactions window. However, for a compiles program there is no interactions window, and perhaps you'ld like to communicate with the user without ending the program? You can do it with the display command, like this:
(display "Hello World")
Yes folks, it had to happen sooner or later. I apologize.
Anyway, there are two ways to put in a newline. One is to use the newline procedure, which takes no arguments:
(newline)
The other way is to put a newline character in a string and display it. A newline character is represented as \n .
\ is the usual escape character in scheme strings, with other useful sequences being \" to put a quote mark in the string, or \\ to put in an actual backslash. Here's an example with it's output:
(display "\"Hello, World!\"\nOh no, it's that phrase again!")

"Hello, World!"
Oh no, it's that phrase again!

Reading information from the user can be done with (drumroll) read . Big suprise there. Just use (read) and it will wait for someone to type something into standard output window and return that value. Note that it doesn't always return a string, values read are parsed as scheme expressions. If you are trying to get a string, use read-char or read-line.
Sample:

(display "How many cows do you have? ")
(define cows (read))
(display "You have ") (display cows) (display " cows!")

No discussion of I/O would be complete without talking about files a bit. So how are files handled with scheme?
Well, seeing as I've already written about two pages of tutorials and two more of english essays today, I think I'll just show you.
(define out (open-output-file "test.txt"))
(display 42 out)
(close-output-port out)
That should be fairly self explanatory, hmmm? One thing you'll notice is that display takes an opitional second argument, a "port" to output to. If it's not given one, it just outputs to the current-output-port , which echos everthing to that box in the interactions window (or the Standard Output window if your program is compiled).
Reading files works exactly the same way:
(define in (open-input-file "test.txt"))
(display (read in))
(close-output-port in)
As you can see, read optionally takes one argument, which is an input port.
Of course, there are a lot fo other things you can do with files, but I think this should be enough to get you started with I/O.

Ok, now we're going to get into DrScheme's list commands. A scheme list is represented as a cons cell, a structure with 2 parts, the car and the cdr. The car store a datum, and the cdr stores another cons cell. The last cell in the list has null instead of another cons cell. Here is an example:
(cons 4 (cons 1 (cons 4 (cons 3 null))))
Understanding the nature of lists as cons-cells is often important to write list-processing procedures, but it's a bit tedious to type. Here are two more ways to represent the same list:
(list 4 1 4 3)
'(4 1 4 3)
Note that the last method for making lists, using a single quote, can have unexpected side effects. That's becuase it parses things inside it differently than usual. For instance, if you define a variable x to be 5, then make quoted list that contains x, the list will contain the symbol 'x , not the number 5. This also happens with procedure applications; they are interpreted as sub-lists rather than being executed. Thus, quoted lists should only be used to input atomic constants. In other cases, use list or cons.
So, lets talk about list processing. The command append takes any number of lists and concatenates them, e.g.:
(append '(1 2) '(3 4) '(5 6) '(7 8))
returns '(1 2 3 4 5 6 7 8)
There are also some predicates that can be useful in list processing. null? determines if something is the empty list (note: do NOT use the not procedure for this. null is not the boolean false, therefore it is actually counted as a TRUE value, unlike in some other languages.), and list? determines if the datum given to it is a list of any sort.
The procedures car and cdr that I mentioned earlier are often valuable for creating functions that traverse lists. Here's an example:

(define (echo a-list)
  (unless (null? a-list) (display (car a-list)) (newline) (echo (cdr a-list))))

This function prints all the information on a list to std-out.
However, if you don't plan on using all the elements of a list, you can just skip straight to the one you want with list-ref and list-tail. list-ref takes a list and a number n, and returns the nth item on the list. It's important to note that it numbers the first thing on the list as 0, not 1. Thus,
(list-ref '(a b c d e) 3)
returns 'd rather than 'c as you might expect.
list-tail also takes a list and a number n, and then returns the list sans the first n items.
The procedure reverse takes a list and reverses it. This can be handy sometimes, although its naturally somewhat processor-intensive.
Another important procedure is string->list , which takes a string and returns a list of characters. E.g.:
(string->list "hello world")
returns '(#\h #\e #\l #\l #\o #\space #\w #\o #\r #\l #\d)
There's also a list->string procedure that does the opposite, finally allowing you to get at the guts of strings.
While we're on that topic, there's also a string-append function that appends two or more strings for you.
There's one more procedure I'd like to tell you about that can be very useful. It is build-list. Go ahead and type it into DrScheme. Get an error? That's becuase build-list isn't part of the basic Mzscheme language. To get at it, we'll have to require a library. It's high time you learn to do that.
to require a file, simply say (require "filename"). Scheme will look in the directory where the current file is to find filename. Since we're looking for something in the PLT\Collects folder, though, this won't do us much good. Fortunately, there's an easier way to get to the collects folder than to type "..\..\..\..\Progra~1\Plt\collects", or whatever the path would be on your computer. instead, just use the keyword lib, the filename, and the collection, like so:
(require (lib "etc.ss" "mzlib") (lib "graphics.ss" "graphics") (lib "make.ss" "make"))
(all of those are libraries included with DrScheme)
so, in order to get to build-list, you'll just need to use the first one.
(require (lib "etc.ss" "mzlib"))
how build-list works is, first you define a procedure that consumes an integer, then you call build-list with a number and that procedure as arguments. For example:
(define (double x) (* x 2)
(build-list 8 double)
This will return (0 2 4 6 8 10 12 14).
I think you can see how this works, and how it could be useful.
There's also a build-string procedure that works the same way, except that the procedure you give it must return characters.
I know these procedures that eat other procedures will be very confusing for some people, although others get it right away. If you don't get it, there's not much I can do to help you, so just try to accept that this works for now and move on.
Anyway, I'd like to show you one more thing in this post. It's another one of those "higher-order procedures", which is what they're called. The procedure is map. It's a little tricky to explain, so just look at this and I think you'll get it.
(map + '(1 4 7 10) '(1 1 0 0))
returns '(2 5 7 10)
Get it? It's taking the an element from each list, applying the + procedure to them, and then making that the item on the resulting list. Map can take any number of arguments, the trick is just that they have to match up with the number of arguments that the other procedure takes. For example:
(map expt '(1 2 3))
would return an error, because expt (exponent) takes 2 arguments. Here we're only giving it one at a time.
Once again, adios.

Request moderator help: Is there any way to REPLACE my "tutorial" with Junkbone's tutorial?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.