Consecutive calls/evaluations in a form?
Hey guys, simple question...
Working with XLISP to write a program, but I've seemed to run into a simple fundamental problem that I can't seem to work around: perhaps someone has a quick fix.
I'm trying to write an if statement who's then-clause evaluates multiple forms and returns the value of the last.
In example:
(setq POSITION 'DINING-ROOM)
(defun LOOK (DIRECTION ROOM) ... )
(defun SETPOS (ROOM) ... )
(defun WHERE () ... )
(defun MOVE (DIRECTION)
(if (not(equal nil (LOOK DIRECTION POSITION))) ; If there is a room in that direction
( ; Then-block: Go to that room. Return where you are.
(SETPOS (LOOK DIRECTION ROOM))
(WHERE)
)
( ; Else-block: Return error
(list 'CANT 'GO 'THERE)
)
)
The logical equivalent intended is:
function Move (Direction)
{
if(Look(Direction, Room) != null)
{
SetPos(Look(Direction,Room));
return Where();
}
else
{
return "Can't go there";
}
}
(Apologies for the poor web-formatting.)
The problem I have is with:
(
(SETPOS (LOOK DIRECTION ROOM))
(WHERE)
)
I simply want to return the evaluation of WHERE, but I need to execute the SETPOS function first. XLISP开发者_StackOverflow中文版 doesn't like the extra parentheses: if I remove the outer set, my WHERE list becomes my else (I don't want that). If I remove the sets around SETPOS and WHERE, it treats WHERE like an argument for SETPOS; I also don't want that.
So, how do I simply evaluate the first, then the second and then return the values of the last evaluated?
Lisp usually provides something like PROGN. PROGN evaluates a sequence of expressions and the value(s) of the last expression is returned.
(progn
(do-this)
(do-that))
Also look at your code:
(if (not(equal nil (LOOK DIRECTION POSITION)))
(EQUAL NIL (FOO)) is the same as (NULL FOO)
(NOT (NULL FOO)) is the same as FOO.
So you can simply write:
(if (LOOK DIRECTION POSITION) ... ...)
Or if you want to check if there is a room:
(if (ROOM-P (LOOK DIRECTION POSITION)) ... ...)
ROOM-P would be a predicate that returns T if something is a room.
You may also want to use typical Lisp indentation:
(defun MOVE (DIRECTION)
(if (LOOK DIRECTION POSITION)
(progn
(SETPOS (LOOK DIRECTION ROOM))
(WHERE))
(progn
...
(list 'CANT 'GO 'THERE))))
There is also a COND construct:
(defun MOVE (DIRECTION)
(cond ((LOOK DIRECTION POSITION)
(SETPOS (LOOK DIRECTION ROOM))
(WHERE))
(t
...
(list 'CANT 'GO 'THERE))))
I would also propose to switch from XLISP to something like CLISP or ECL. XLISP is old, mostly not maintained and not Common Lisp.
So I found a way of doing consecutive executions (whether its the best means or not):
Changed:
(
(SETPOS (LOOK DIRECTION ROOM))
(WHERE)
)
To:
(let ()
(SETPOS (LOOK DIRECTION ROOM))
(WHERE)
)
Which executed both forms and returned the output of the last.
精彩评论