Undefined variable on sbcl, not on clisp - common-lisp

Loading the following 2 functions on clisp goes successful.
(defun func1 (l)
(defvar *count* nil)
(setq count 1)
(cond ((null l) 0)
((atom l) (+ count 1))
((atom (car l)) (+ count (func1 (cdr l))))
((listp (car l)) (+ (func1 (car l)) (func1 (cdr l))))
(t nil)) )
(defun func2 (l)
(defvar *resLis* nil)
(setq resLis '((0 0)))
(anotherFunc l resLis)
)
However, sbcl causes error:
warning: undefined variable: COUNT
warning: undefined variable: RESLIS
Compilation failed.
I prefer using sbcl (since my slime only goes well with it) but what's wrong with the codes above?
Environment: Ubuntu 11.10, GNU CLISP 2.49, SBCL 1.0.50.0.debian

SBCL does not 'causes error'. The compiler prints a warning. CLISP may not warn, if you use its interpreter and not its compiler. SBCL uses the compiler by default.
What's wrong?
DEFVAR is a top-level form defining a global variable. Using it in a function is possible, but not recommended.
count is simply undefined. As SBCL says. You have nowhere a variable count defined.

First, note that *count* and count are two different things. Same goes for *resLis* and resLis.
Second, what's that : doing in the middle of func1?
Third, where's anotherFunc?
Fourth, don't use defvar in a function; those are for globals!
Once you work these out, you should find it easier to get going.

Related

In Common Lisp, how to use lexical scope and funcall to make another function be passed as an argument?

I am using SBCL, Emacs, and Slime. Hence, I can do:
CL-USER> (defvar example #'(lambda (x) (* x 20)))
EXAMPLE
CL-USER> (funcall example 10)
200
Ok. It works as expected. Using the library Dexador, I can also so:
CL-USER> (ql:quickload :dexador)
To load "dexador":
Load 1 ASDF system:
dexador
; Loading "dexador"
.......
(:DEXADOR)
CL-USER> (dex:get "http://www.paulgraham.com")
"big HTML ommited"
200
#<HASH-TABLE :TEST EQUAL :COUNT 11 {10029F1443}>
#<QURI.URI.HTTP:URI-HTTP http://www.paulgraham.com>
#<SB-SYS:FD-STREAM for "socket 10.0.0.193:44936, peer: 74.6.52.135:80" {1002681F73}>
Now, I am trying to make the argument to be passed be a function! More specifically, the dex:get function. I tried different approaches, but none of them worked out:
CL-USER> (defvar example-failing #'(lambda (x) (x "http://www.paulgraham.com")))
; in: DEFVAR EXAMPLE-FAILING
; (LAMBDA (X) (X "http://www.paulgraham.com"))
;
; caught STYLE-WARNING:
; The variable X is defined but never used.
; in: DEFVAR EXAMPLE-FAILING
; (X "http://www.paulgraham.com")
;
; caught STYLE-WARNING:
; undefined function: COMMON-LISP-USER::X
;
; compilation unit finished
; Undefined function:
; X
; caught 2 STYLE-WARNING conditions
EXAMPLE-FAILING
CL-USER> (funcall example-failing dex:get)
; Evaluation aborted on #<UNBOUND-VARIABLE GET {1002C57103}>.
CL-USER> (funcall example-failing 'dex:get)
; Evaluation aborted on #<UNDEFINED-FUNCTION X {1002DEA263}>.
CL-USER> (funcall example-failing #'dex:get)
; Evaluation aborted on #<UNDEFINED-FUNCTION X {1002F906C3}>.
CL-USER> (funcall example-failing (function dex:get))
; Evaluation aborted on #<UNDEFINED-FUNCTION X {1003147F83}>.
I managed to do it with:
CL-USER> (defvar hacky-eval #'(lambda (x) (eval x)))
HACKY-EVAL
CL-USER> (funcall hacky-eval (dex:get "http://www.paulgraham.com"))
"big html omitted"
But, this feels as bad practice. Is there another way to fix this?
Thanks
I am confused by your question although not as confused as you seem to be. You already seem to know that, to call a function which is the value of a variable, you need either
funcall if you have all the arguments as individual things;
apply if you have only a list of arguments;
and that to get the function value of something you need (function thing) or equivalently #'thing[1].
But then you forget that in your function, and pay no attention to the copious warnings from SBCL.
So
(defvar *example* (lambda (f) (funcall f "http://www.paulgraham.com")))
...
(funcall *example* #'dex:get)
Note that none of this (and nothing in your question) relies on lexical scope: this would all have worked in any historical Lisp.
[1]: you don't need #' for (lambda ...) only because lambda is a macro which expands into (function (lambda ...)). Very old code sometimes uses the explicit #'(lambda ...) form since this macro did not always exist in CL.
Your code:
(defvar example-failing
#'(lambda (x)
(x "http://www.paulgraham.com")))
This makes no sense in Common Lisp. x is a variable. You can't use a variable as a function as in (x arg). In Common Lisp there are different namespaces for functions and variables. For example LET introduces a local variable and FLET introduces a local function.
The ways to call a function bound to a variable are:
(funcall x arg)
(apply x (list arg))
Thus correct examples would be:
(defvar example-failing
#'(lambda (x)
(apply x (list "http://www.paulgraham.com"))))
or
(defvar example-failing
#'(lambda (x)
(funcall x "http://www.paulgraham.com")))
Your solution is no solution
This is your example:
CL-USER> (defvar hacky-eval #'(lambda (x) (eval x)))
HACKY-EVAL
CL-USER> (funcall hacky-eval (dex:get "http://www.paulgraham.com"))
"big html omitted"
This does not work as you think.
(funcall hacky-eval (dex:get "http://www.paulgraham.com"))
is just the same as
(funcall hacky-eval "big html omitted")
and then
(eval "big html omitted")
and then
"big html omitted"
All your call to eval does is to evaluate a string to itself.
You really need to understand basic evaluation rules in Lisp:
(defun foo (arg)
(eval arg))
(foo (+ 3 4))
is simply the same as:
(defun foo (arg)
arg)
(foo (+ 3 4))
which is the same as
(identity (+ 3 4))
Note: if you pass just self evaluating data to EVAL, then all it does is to return the data
A function call (foo (+ 1 2)) works like this:
Lisp sees that FOO is a function
Lisp evaluates the arguments. (+ 1 2) -> 3
Lisp calls the function FOO with the evaluated argument: (funcall #'foo 3)
Lisp computes the function FOO: (EVAL 3) -> 3
Lisp returns the value(s) from FOO -> 3
Start by using a proper defun:
(defun request (url)
(dex:get url))
CL-USER> (request "http://…")
Now you want to use something else than dex:get? Well… write another function, because their argument handling, headers, return values… might be different.
(defun request-drakma (url)
(drakma:… url))
Maybe in later code you want to reference to either function?
(defun do-request (url &optional (get-fn #'request))
(funcall get-fn url))
(defvar example #'(lambda (x) (* x 20)))
Here you are giving a name to an anonymous function… just use defun^^

How to compile s-expression at runtime and then execute it in Common Lisp

I am working on a program that generates program (Genetic Programming). I build at runtime an s-expression and today I use eval like this:
(defvar *program* '(+ x 1))
(defvar x 10)
(eval *program*) ;; returns 11
Evaluation is done for multiple x and I want to compile the s-expression into a function at runtime and then call it for multiple x to improve performance.
I can't figure out how to do it and I will appreciate some help. Here is what I have:
;;;; This is not working code
(defmacro compile-program (args &body body)
(compile nil `(lambda (,#args)
(declare (ignorable ,#args))
(progn ,#body))))
(funcall (compile-program (x) *program*) 10) ;; returns (+ X 1)
(funcall (compile-program (x) (+ x 1)) 10) ;; returns 11
Edit:
Thx to #RainerJoswig I made the following modifications and it works:
;;;; Working Code
(defvar *program* '(+ x 1))
(defun compile-program (args program)
(compile nil `(lambda ,args
(declare (ignorable ,#args))
,program)))
(funcall (compile-program '(x) *program*) 10) ;; returns 11
Thx to #RainerJoswig and #coredump I made the following modifications and it works:
;;;; Working Code
(defvar *program* '(+ x 1))
(defun compile-program (args program)
(compile nil `(lambda ,args
(declare (ignorable ,#args))
,program)))
(funcall (compile-program '(x) *program*) 10) ;; returns 11

I working through little lisper. The function lat? checks whether all elements of list are atoms or not

(defun lat
(lambda (l)
(cond ((null l) t)
((atom (car l))(lat (cdr l))
(t nil))))
The function takes a list as an argument. It is a recursive function that checks every element in the list. Whether it is atom or not. If every element is an atom, then it returns true else false.
Following is the error displayed
While compiling LAT :
Bad lambda list : (LAMBDA (L)
(COND ((NULL L) T) ((ATOM # #)) (T NIL)))
[Condition of type CCL::COMPILE-TIME-PROGRAM-ERROR]
Just like Hal Abelson called Scheme "lisp" in the SICP videos this book does the same, however the language in the book is a predecessor to Scheme and not Common Lisp. When you see:
(define name
(lambda (arg ...)
body ...)
This is the same as this in CL:
(defun name (arg ...)
body ...)
The reason is that in Scheme it's the same namespace for operator as well as operand bindings. A lisp-2 like Common Lisp can split it up like this:
(setf (fdefinition 'name)
(lambda (arg ...)
body ...))
This probably won't happen since you can always use defun, but in the event you return a function from a function you can do this or you must rely on funcall or apply to use the returned value:
;; This is a function that creates a function
(defun get-counter (from step)
(lambda ()
(let ((tmp from))
(incf from step)
tmp)))
When using this you might want to bind it globally:
(setf (fdefinition 'evens) (get-counter 0 2))
(evens) ; ==> 0
(evens) ; ==> 2
Or in functions you get it bound to normal variables and need to funcall or apply:
(defparameter *odds* (get-counter 1 2))
(funcall *odds*)
; ==> 1
Which one do you prefer?
(list (funcall *odds*) (evens))
; ==> (3 4)
The ? in lat? inidicated predicate and in CL a p in the end does the same. Your function latp is suppose to return nil or t so it should not return a function at all. Thus:
(defun latp (list)
(cond ((null list) t)
((atom (car list)) (latp (cdr list)))
(t nil)))
This of course is the same as:
(defun latp (list)
(or (null list)
(and (atom (car list))
(latp (cdr list)))))
Unlike Scheme using the name list as the argument does not affect the function call to list.

LispWorks program will not build as application

This is my second proper attempt at a Lisp program, as a dice-roller for Mythender (a freely distributed tabletop RPG). It has a couple of problems though:
When it's loaded I get a prompt to confirm creation of the package. Surely this file should be creating it?
When I try to build it standalone with the LispWorks application builder it gives an error saying that I am trying to invoke a CAPI function at compile-time, but I don't see where that is.
I've gotten negative comments from some lisp folks I spoke to about the (the null ()) sections which are meant to indicate a function has no return so no point leaving anything on the stack - is this proper or not? Is there a better way to do it?
Any general suggestions would also be welcome.
(defpackage :mythender (:add-use-defaults t) (:use "CAPI"))
(in-package :mythender)
(defun d6 () (the fixnum (+ 1 (random 6))))
(defun d6s (count)
(declare (type fixnum count))
(the list (loop for x from 1 to count collecting (d6))))
(defun d6over (count threshold)
(declare (type fixnum count threshold))
(the fixnum (count-if
(lambda (x) (> threshold x))
(d6s count))))
(defvar *storm* 3)
(defvar *thunder* 3)
(defvar *lightning* 0)
(declare (ftype (function) printstate))
(defun printstate ()
(print *storm*)
(print *thunder*)
(print *lightning*)
(the null ()))
(defun roll ()
(incf *lightning* (d6over *thunder* 3))
(incf *thunder* (d6over *storm* 3))
(the null ()))
(defun damage (threshold)
(setf *thunder* (d6over *thunder* threshold))
(the null ()))
(defun doroll (&rest args)
(roll)
(update-interface)
(the null ()))
(define-interface mythender-interface () ()
(:panes
(roll-button push-button :data "Roll" :callback #'doroll)
(damage-button push-button :data "Damage")
(storm-pane display-pane :title "Storm:" :title-position :left)
(thunder-pane display-pane :title "Thunder:" :title-position :Left)
(lightning-pane display-pane :title "Lightning:" :title-position :left))
(:layouts
(main-layout column-layout '(storm-pane thunder-pane lightning-pane buttonlayout))
(buttonlayout row-layout '(roll-button damage-button))))
(defvar *interface*)
(defun update-interface-slot (slotname value)
(declare (type string slotname) (type fixnum value))
(setf (display-pane-text (slot-value *interface* slotname)) (write-to-string value))
(the null ()))
(defun update-interface ()
(update-interface-slot 'storm-pane *storm*)
(update-interface-slot 'thunder-pane *thunder*)
(update-interface-slot 'lightning-pane *lightning*)
(the null ()))
(defun start ()
(setf *interface* (make-instance 'mythender-interface))
(display *interface*)
(the null (update-interface)))
An answer to your build problem has to wait until you tell us the build statement and the error message.
Your last question:
(declare (ftype (function) printstate))
(defun printstate ()
(print *storm*)
(print *thunder*)
(print *lightning*)
(the null ()))
It's known that it is a function. No need to declare that. Declaring types like that, have in plain Common Lisp only the purpose of optimization hints to the compiler, which the compiler may ignore. Only CMUCL (and derived compilers like SBCL and SCL) actually does more with declared types.
Nobody writes such code in Lisp. Better omit the types. Remember: Lisp is not a statically typed language.
(defun printstate ()
(print *storm*)
(print *thunder*)
(print *lightning*)
(values))
Using (values) causes the function to not return a value. That's usually preferred, not returning NIL.
If you want to actually check types in a meaningful way at runtime, then make use of ASSERT, CHECK-TYPE and/or DEFMETHOD.
(defun d6s (count)
  (declare (type fixnum count))
  (the list (loop for x from 1 to count collecting (d6))))
Is just:
(defmethod d6s ((n integer))
"Returns a list of n dice rolls."
(loop repeat n collect (d6)))
Don't forget to describe the semantics of your function in human readable form.

Get minimum num recursively from a list

I'm new to lisp and trying to write a recursive function that returns minimum number from a list. It also wants to detect atom. The following code returns error:
(defun minFromList (l)
(cond ((null l) nil) ; Causes error shown below
; (cond ((null l) ) ; Causes the same error
; (cond ((null l) 0) ; It causes always 0 to be the final return val.
((numberp l) l)
((numberp (car l)) (min (car l) (minFromList(cdr l))))
((listp (car l)) (min (minFromList (car l)) (minFromList (cdr l))))
(t nil) ; if all condition doesn't hold just return nil.
)
)
Error:
*** - MIN: NIL is not a real number
Apparently the problem lies in where it returns nil/0 when the given list is null. What's possible workarounds? Thank you.
Environment) Ubuntu 11.10, clisp 2.49
Update) Although I already picked up this as the answer, I welcome if there are other ways especially w/o making new functions if any.
Here's the simplest code I made inspired by the chosen answer.
(defun minNum (a b)
(cond ((null a) b)
((null b) a)
(t (min a b)))
)
Apparently you get an error message because you try to use the result of your function as a number, and said result is nil when the function is called with an empty list as argument, so the evaluation that tries to use the result fails. This is not a Common Lisp problem - you have to decide what to return when the argument is empty. Maybe 0 is a good value, maybe some approximation of minus infinity - only you (or whoever uses your function) can tell.
As for getting the the minimum (or the sum or any other 'reduction') of a list, this is a pattern already handled by the reduce Common Lisp standard function. So min-from-list could look something like:
CL-USER> (defun min-from-list (list &optional (default 0))
(reduce #'min list :initial-value default))
MIN-FROM-LIST
CL-USER> (min-from-list '(1 2 -3))
-3
CL-USER> (min-from-list '(1 2 -3) -7)
-7
CL-USER> (min-from-list '())
0
CL-USER> (min-from-list '() -3)
-3
(the user can specify what the minimum of an empty list is - if none specified, it's 0).
When comparing two numbers, you need to deal with the nil case in some way. This is easy to do. Define your own version of min that satisfies
(min2 nil <x>) = <x>
(min2 <x> nil) = <x>
(min2 <x> <y>) = (min <x> <y>) if <x>, <y> non-null
and use that.
The simplest approach I can think of is to wrap an application of min.
(defun min-or-nil (num-list)
(when num-list (apply #'min num-list)))

Resources