Scheme (or maybe Lisp) Programming Question from Newbie

Here’s a question for Scheme (or, I think, Lisp) programmers.

I’m learning to program the “text user interface” in Fluent software (which calculates fluid flow problems), and it is based on Scheme, a dialect of Lisp. Scheme is new to me, nor do I know Lisp, and I’m using Web references from schemers.org, a book by Dybvig, and other tidbits to pick my way along, but have hit a hitch. AFAIK this is a basic Scheme programming issue I don’t understand, maybe the same in Lisp too.

Fluent provides a Scheme procedure called ti-menu-load-text that passes text strings to a text menuing system (which I gather is just a Scheme loop evaluating input anyway). So for instance

(ti-menu-load-string “/display/close-window 1”)

will close the first Graphics Display Window. I note also that it seems to leave a #t (boolean “true” value) behind. That is, what I see at the prompt when I do this is:

> (ti-menu-load-string “/display/close-window 1”)
/display/close-window 1#t

>

All that is fine. The problem is that defining a procedure to do this and then running the procedure (this is all done by reading in a little text file of the code) doesn’t work right. What it does is close the graphics window, and then give me an error message, to wit:

> (define shell
(ti-menu-load-string “/display/close-window 1”)
)/display/close-window 1shell

> (shell)
Error: eval: invalid function
Error Object: #t

Moreover, subsequent lines in the text file don’t get processed either. This is just a guess, but I wonder if what is going on is that the ti-load… procedure returns a boolean, and if you just run the procedure by itself the boolean gets displayed, but if you put it inside another procedure (what I named "shell), the eval procedure tries to operate on the boolean and chokes. So I guess I’d need to not return that boolean, or to nest the ti-load… procedure inside some other thing that will consume the boolean, or some such. Does this sound right? Or do I misunderstand entirely?

try
>shell
instead of
>(shell)

works for me.


1 ]=> (define blah (= 1 1))

;Value: blah

1 ]=> (blah)

;The object #t is not applicable.
;To continue, call RESTART with an option number:
; (RESTART 2) => Specify a procedure to use in its place.
; (RESTART 1) => Return to read-eval-print level 1.

2 error> blah

;Value: #t

I agree with mic84: You didn’t define a function called shell, you created a variable named shell with the return value of the function you did call. The two are very, very different things.

As far as learning Scheme, you are very lucky. There are two really good books that teach standard Scheme, both of them available free online: Teach Yourself Scheme in Fixnum Days is a book that out-and-out teaches the Scheme language to someone with minimal programming experience, while The Structure and Interpretation of Computer Programs is a good theoretical text that uses (and teaches) Scheme in its examples. If you wonder about these books, note that the second one is used by MIT in its introductory programming courses.

And, finally, if you decide you really love Scheme and wish to join me in Schemey goodness, download DrScheme, a graphical environment for Scheme development.

Thanks - this has set me right.

What I had to change was to say (define (shell) … instead of (define shell … and this was just the newness of it all - I was doing this right elsewhere. However, writing shell instead of (shell) at the prompt didn’t fix it - see below. I have added lines of my own comments in {braces} to the Fluent window in which I am trying things:
Welcome to Fluent 6.1.22

 Copyright 2003 Fluent Inc.
 All Rights Reserved

Loading “C:\Fluent.Inc\fluent6.1.22\lib\fl_s117.dmp”
Done.

>
{Program is started, so I load a text file}
> (define (shell1) (ti-menu-load-string “/display/open-window 1”))shell1
{Create one function definition to open graph window, and get its name echoed back}
> (define (shell2) (ti-menu-load-string “/display/close-window 1”))shell2
{Create another to close graph, it’s echoed back too}

> (shell1)
/display/open-window 1#t
{Execute the function and the window opens, plus my boolean is returned (?)}

> (shell2)
/display/close-window 1#t
{Likewise but window closes}

> shell1
invalid command [shell1]
{Typing the function name without paren just gives an error, no graph window}

> shell2
invalid command [shell2]
{Similar disappointment}

>

OK, now about books - what’s a good book for a scientist experienced at programming in a variety of languages, but new to Scheme and Lisp, who’s never been a professional programmer per se? Amazon’s reader’s comments don’t point to any really good ones. I will try your two suggestions, Derleth, and probably DrScheme too - any other comments?

As mentioned already, you didn’t properly define a procedure. What you want to do is either this:



(define shell (lambda () (ti-menu-load-string "/display/close-window 1")))


or this:



(define (shell) (ti-menu-load-string "/display/close-window 1"))


On preview I see you fixed this. Ah well.

In addition to the recommendations already made, I’ll add The Scheme Programming Language — ANSI Scheme by R. Kent Dybvig, whose college course I actually took back at I.U., many years ago.

Also, The Little Schemer is an interesting tutorial approach to the language. It takes them forever though to make a simple point, so I lost patience with it. But it’s certainly a good introduction to the language for those who, having programmed mostly in imperative languages (Fortran, C, C++, and the like), find Scheme to be completely alien at first.