Common Lisp: Passing an object to a method - common-lisp

I have a problem with the behaviour of objects (class instances).
A code sample:
(defclass game-cards ()
((card-symbol :initarg :card-symbol :accessor card-symbol)
(colour :initarg :colour :accessor colour)))
(defvar *king-hearts* (make-instance 'game-cards
:card-symbol 'King
:colour 'hearts))
(defvar *ace-spades* (make-instance 'game-cards
:card-symbol 'Ace
:colour 'spades))
(defclass game-states ()
((my-cards :initarg :my-cards :accessor my-cards)
(other-cards :initarg :other-cards :accessor other-cards)))
(defparameter *state-1*
(make-instance 'game-states
:my-cards '(*king-hearts* *ace-spades*)
:other-cards ()))
(defmethod play-game ((state game-states))
(some-job (first (my-cards state))))
(defmethod some-job ((card game-cards))
(colour card))
When some-job is used with a game-cards object in the parameter list, it works like I expected.
CL-USER> (some-job *king-hearts*)
HEARTS
CL-USER>
Also this works:
CL-USER> (first (my-cards *state-1*))
*KING-HEARTS*
CL-USER>
When I try this:
(some-job (first (my-cards *state-1*)))
I get the following error message:
There is no applicable method for the generic function
#<STANDARD-GENERIC-FUNCTION COMMON-LISP-USER::SOME-JOB (1)>
when called with arguments
(*KING-HEARTS*).
[Condition of type SIMPLE-ERROR]
When I define some-job as a function:
(defun some-job-1 (card)
(colour card))
the same behaviour occurs.
The error message is now:
There is no applicable method for the generic function
#<STANDARD-GENERIC-FUNCTION COMMON-LISP-USER::COLOUR (1)>
when called with arguments
(*KING-HEARTS*).
[Condition of type SIMPLE-ERROR]
It seems that *king-hearts* is now not distinguished as an instance of game-cards by some-job and colour.
What is the reason? Tank you for your answers.

Quoted data is not evaluated. That's a basic Lisp evaluation rule:
CL-USER 1 > pi
3.141592653589793D0
CL-USER 2 > 'pi
PI
CL-USER 3 > '(pi pi)
(PI PI)
CL-USER 4 > (list pi pi)
(3.141592653589793D0 3.141592653589793D0)
CL-USER 5 > (list 'pi 'pi)
(PI PI)
Here PI is a symbol and not a number:
CL-USER 6 > (type-of 'pi)
SYMBOL
CL-USER 7 > (type-of pi)
DOUBLE-FLOAT
Thus we can define a method for a number:
CL-USER 8 > (defmethod square ((n number)) (* n n))
#<STANDARD-METHOD SQUARE NIL (NUMBER) 402005F60B>
CL-USER 9 > (square pi)
9.869604401089358D0
But the call for a symbol does not work, since there is only a method for a number:
CL-USER 10 > (square 'pi)
Error: No applicable methods for #<STANDARD-GENERIC-FUNCTION SQUARE 4060010C1C> with args (PI)
1 (continue) Call #<STANDARD-GENERIC-FUNCTION SQUARE 4060010C1C> again
2 (abort) Return to top loop level 0.
Type :b for backtrace or :c <option number> to proceed.
Type :bug-form "<subject>" for a bug report template or :? for other options.
We can define a method for a symbol in the debugger:
CL-USER 11 : 1 > (defmethod square ((n symbol))
(let ((n (symbol-value n)))
(* n n)))
#<STANDARD-METHOD SQUARE NIL (SYMBOL) 4020285ED3>
And then we re-invoke the call:
CL-USER 12 : 1 > :c 1
9.869604401089358D0
How to solve your problem:
Either create a list of CLOS objects using LIST
or retrieve the CLOS objects from the global variable using SYMBOL-VALUE.
The latter usually makes less sense.

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^^

Lisp variable using itself in definition

I am building a window application in Lisp using the LTK library. I want a button that does an action and, possibly, hides itself. However, this code:
(let* ((left (button 0 0 f "←" #'(lambda ()
(decf start page-length)
(funcall redraw)
(if (>= start page-length)
(ltk:configure left :state :visible))
(ltk:configure left :state :hidden))))))
claims that "left" is an undefined variable (the rest is defined in code beyond the scope of this problem).
Worst case scenario, I avoid the "button" function I wrote and rework the code for this particular situation, but the scenario begs a general solution. Is there any way in Lisp to use a variable in a function in the definition of the variable?
A let* with only one binding is the same as a let binding. A let binding does not exist until the body is executed. During the execution of button the reference for left must be from an earlier closure or global as left is created after the expression is evaluated. You can do this:
(let ((left nil))
(setf left (button 0 0 f "←" #'(lambda ()
(decf start page-length)
(funcall redraw)
(if (>= start page-length)
(ltk:configure left :state :visible)
(ltk:configure left :state :hidden))))))
NB: There was a bug in the if such that the lambda always would execute (ltk:configure left :state :hidden)
For what it's worth here is a version of letrec in CL:
(defmacro letrec (bindings &body decls/forms)
(assert (and (listp bindings)
(every (lambda (b)
(or (symbolp b)
(and (consp b)
(symbolp (first b))
(null (cddr b)))))
bindings))
(bindings) "malformed bindings")
(multiple-value-bind (names values)
(loop for b in bindings
collect (etypecase b
(symbol b)
(cons (first b)))
into vars
collect (etypecase b
(symbol nil)
(cons (second b)))
into vals
finally (return (values vars vals)))
`(let ,names
(psetf ,#(loop for name in names
for val in values
collect name
collect val))
(locally
,#decls/forms))))
Then
> (letrec ((x (lambda (y)
(if (null y)
'done
(funcall x (cdr y))))))
(funcall x '(1 2 3)))
done

Write a function that behaves like car, cadr, caddr etc

I'm new to lisp (i'm experimenting with sbcl and ccl), i came across the use of car and cdr that can be chained arbitrarily within a single function call like (caddr).
I was wandering how one would write functions that behave like this...
Say for example i'd like my-eval to eval the input s-exp 3 times if i invoke it like (my-evaaal '(+ 2 1))
I've hacked my way around with a macro like
(my-ev $$$$ '(...)) where the behavior is dictated by the number of '$' in the first argument by transforming it into char sequence (coerce (symbol-name x) 'list) and the evaluate and recurse until the list is nil...
basic need:
;; if
(defvar *foo* 1)
(eval '*foo*) ;; => 1
(eval ''*foo*) ;; => *foo*
(eval '''*foo*) ;; => '*foo*
;; then
(eval (eval (eval '''*foo*))) ;; => 1
desired syntax
(my-eval '''*foo*) ;; => '*foo*
(my-evaal '''*foo*) ;; => *foo*
(my-evaaal '''foo) ;; => 1
Functions like CAAR, CADR are just regular functions; you can define a macro to help you define them easily if you want to.
 Macros
(defpackage :so (:use :cl :ppcre))
(in-package :so)
(defmacro eval%% (count form)
(case count
(0 form)
(1 `(eval ,form))
(t (check-type count (integer 2))
`(eval%% ,(1- count) (eval ,form)))))
For example, the following :
(eval%% 3 '''most-positive-fixnum)
expands successively as:
(EVAL%% 2 (EVAL '''MOST-POSITIVE-FIXNUM))
(EVAL%% 1 (EVAL (EVAL '''MOST-POSITIVE-FIXNUM)))
(EVAL (EVAL (EVAL '''MOST-POSITIVE-FIXNUM)))
Then, you can define custom eval functions as follows, or even with another macro:
(defun evaal (x) (eval%% 2 x))
(defun evaaal (x) (eval%% 3 x))
Handler and restarts
Alternatively, note that you can catch calls to undefined functions:
(block nil
(handler-bind ((undefined-function
(lambda (e)
(return
(values (cell-error-name e)
(compute-restarts e))))))
(evaaaaaal 'a)))
=> EVAAAAAAL
(#<RESTART CONTINUE {7FD5F5F8CE43}> #<RESTART USE-VALUE {7FD5F5F8CE03}>
#<RESTART SB-KERNEL::RETURN-VALUE {7FD5F5F8CDC3}>
#<RESTART SB-KERNEL::RETURN-NOTHING {7FD5F5F8CD83}>
#<RESTART SWANK::RETRY {7FD5F5F8DA13}> #<RESTART ABORT {7FD5F5F8DEC3}>
#<RESTART ABORT {7FD5F5F8EB03}>)
You can also use the standard USE-VALUE restart to provide a different function to call:
(defun multi-eval-handler (condition)
(let ((name (cell-error-name condition)))
(when (eq (symbol-package name) (find-package :so))
(register-groups-bind ((#'length count)) ("EV\(A+\)L" (string name))
(invoke-restart 'use-value (make-repeated-evaluator count))))))
You need an auxiliary function that computes an evaluation N times:
(defun make-repeated-evaluator (count)
(case count
(0 #'identity)
(1 #'eval)
(t (check-type count (integer 2))
(lambda (form)
(loop
for value = form then (eval value)
repeat count
finally (return value))))))
For example:
(funcall (make-repeated-evaluator 3)
'''most-positive-fixnum)
=> 4611686018427387903
And then, you can have arbitrarily long eval functions:
(handler-bind ((undefined-function #'multi-eval-handler))
(evaaaaaaaaaaaaaal '''''''''''''0))
Now, if you compile the code, you'll have warnings at compile-time about the unknown function, when then you can muffle warnings.

Why is this lisp vector not extending?

I am trying to make a node object in Common Lisp using SBCL that is initialized with its text element and then has links to other nodes. My function link is supposed to take node "from_node", get its member links (which should be a mutable/extendable vector) and push in the node "to_node".
I compile say.lisp, create 2 global variables that represent nodes and then try to link the two nodes. I am getting an error
Here is say.lisp
(defclass node ()
((text
:initarg :text)
(links
:initform (make-array 1 :adjustable t))))
(defun link (from_node to_node)
(vector-push-extend to_node (slot-value from_node 'links)))
And then in the REPL
* (load "say.lisp")
T
* (defvar *x* (make-instance 'node :text "hello world"))
*X*
* (defvar *y* (make-instance 'node :text "bye world"))
*Y*
* (link *x* *y*)
debugger invoked on a TYPE-ERROR in thread
#<THREAD "main thread" RUNNING {1003016593}>:
The value #() is not of type (AND VECTOR (NOT SIMPLE-ARRAY)).
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.
(VECTOR-PUSH-EXTEND #<NODE {10031D3983}> #() NIL)
0]
Originally I thought that I was making an immutable vector, but ":adjustable t" should allow this to work.
What is wrong?
VECTOR-PUSH-EXTEND requires that the vector argument is a "vector with a fill pointer." Passing :adjustable t to the make-array makes it adjustable, but doesn't give it a fill pointer. For instance, without a fill pointer:
CL-USER> (defparameter *x* (make-array 1 :adjustable t))
*X*
CL-USER> *x*
#(0)
CL-USER> (vector-push-extend 3 *x*)
; Evaluation aborted on #<SIMPLE-TYPE-ERROR expected-type:
(AND VECTOR (SATISFIES ARRAY-HAS-FILL-POINTER-P))
datum: #<(VECTOR T 1) {100464C57F}>>.
With a fill pointer:
CL-USER> (defparameter *x* (make-array 1 :adjustable t :fill-pointer 0))
*X*
CL-USER> *x*
#()
CL-USER> (vector-push-extend 3 *x*)
0
CL-USER> (vector-push-extend 4 *x*)
1
CL-USER> (vector-push-extend 5 *x*)
2
CL-USER> *x*
#(3 4 5)
It's an important difference because you can have adjustable arrays without fill pointers, as you've seen. These can be resized, but always appear to have as many elements as there is space. (E.g., in the first case, *x* has length one. You can also have arrays will fill pointers that are not adjustable. These would still allow you to use vector-push and vector-push-extend until they were filled up, but couldn't be resized afterward.

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.

Resources