This code works as I want, except for the warning message. In GNU Common Lisp, how do I suppress that message without suppressing other possible warning messages?
1 (defgeneric zang (x y)
2 (:documentation "they want you to put documentation here"))
3 (defmethod zang ((a number) (b string))
4 (format t "got to zang ((~s number) (~s string))~%" a b))
5 (defmethod zang ((a integer) (b string))
6 (format t "got to zang ((~s integer) (~s string))~%" a b)
7 (when (evenp a)
8 (format t "passing control to the other guy~%")
9 (call-next-method (1+ a) "hoo boy")
10 (format t "returned control from the other guy~%")))
11 (defmethod no-applicable-method (zang &rest args)
12 (format t "no applicable method for (zang ~{~s~^ ~})~%" args))
13 (zang 3.5 "hi")
14 (zang 3 "hi")
15 (zang 4 "hi")
16 (zang "hello" "world")
WARNING: Replacing method #<STANDARD-METHOD (#<BUILT-IN-CLASS T>)> in
#<STANDARD-GENERIC-FUNCTION NO-APPLICABLE-METHOD>
got to zang ((3.5 number) ("hi" string))
got to zang ((3 integer) ("hi" string))
got to zang ((4 integer) ("hi" string))
passing control to the other guy
got to zang ((5 number) ("hoo boy" string))
returned control from the other guy
no applicable method for (zang "hello" "world")
EDIT in response to Vatine's kind reply:
I tried that, and the situation escalated from a warning to a fatal error:
(defgeneric zang (x y)
(:documentation "they want you to put documentation here"))
(defmethod zang ((a number) (b string))
(format t "got to zang ((~s number) (~s string))~%" a b))
(defmethod zang ((a integer) (b string))
(format t "got to zang ((~s integer) (~s string))~%" a b)
(when (evenp a)
(format t "passing control to the next guy~%")
(call-next-method (1+ a) "hoo boy")
(format t "returned control from the next guy~%")))
;(defmethod no-applicable-method (zang &rest args)
; (format t "no applicable method for (zang ~{~s~^ ~})~%" args))
(defmethod no-applicable-method ((zang eql #'zang) &rest args)
(format t "no applicable method for (zang ~{~s~^ ~})~%" args))
(zang 3.5 "hi")
(zang 3 "hi")
(zang 4 "hi")
(zang "hello" "world")
*** - DEFMETHOD NO-APPLICABLE-METHOD: Invalid specialized parameter in method
lambda list ((ZANG EQL #'ZANG) &REST ARGS): (ZANG EQL #'ZANG)
You need to provide a correct argument list for NO-APPLICABLE-METHOD.
If you use a compiler (even the CLISP implementation can compile via COMPILE-FILE), you also should get an error message at compile time about the incorrect argument list.
The LispWorks compiler for example says:
**++++ Error between functions:
An argument is not an atom or list of two elements : (ZANG EQL (FUNCTION ZANG))
Fixed version:
(defgeneric zang (x y)
(:documentation "they want you to put documentation here"))
(defmethod zang ((a number) (b string))
(format t "got to zang ((~s number) (~s string))~%" a b))
(defmethod zang ((a integer) (b string))
(format t "got to zang ((~s integer) (~s string))~%" a b)
(when (evenp a)
(format t "passing control to the next guy~%")
(call-next-method (1+ a) "hoo boy")
(format t "returned control from the next guy~%")))
;(defmethod no-applicable-method (zang &rest args)
; (format t "no applicable method for (zang ~{~s~^ ~})~%" args))
(defmethod no-applicable-method ((zang (eql #'zang)) &rest args)
(format t "no applicable method for (zang ~{~s~^ ~})~%" args))
Example:
(defun test ()
(zang 3.5 "hi")
(zang 3 "hi")
(zang 4 "hi")
(zang "hello" "world"))
CL-USER 1 > (test)
got to zang ((3.5 number) ("hi" string))
got to zang ((3 integer) ("hi" string))
got to zang ((4 integer) ("hi" string))
passing control to the next guy
got to zang ((5 number) ("hoo boy" string))
returned control from the next guy
no applicable method for (zang "hello" "world")
NIL
I think you want to define a method on no-applicable-method as:
(defmethod no-applicable-method ((zang (eql #'zang)) &rest args)
...)
As-is, you're declaring a method that applies to all generic functions and that's why clisp is telling you that you're replacing an already-defined method.
Related
I found myself calling lots of methods whose first argument is a complex object from a given class.
Whilst with-slots and with-accessors are useful, generic methods cannot be bound in this way. So I thought: if we could locally curry any functions, slots + accessors + generic functions + functions could all be addressed with the same construct.
Example of code I want to clean up:
(defun clox-string (scanner)
"Parse string into a token and add it to tokens"
(loop while (and (char/= #\" (peek scanner))
(not (at-end-p scanner)))
do
(if (char= #\Newline (peek scanner)) (incf (line scanner))
(advance scanner)))
(when (at-end-p scanner)
(clox.error::clox-error (line scanner) "Unterminated string.")
(return-from clox-string nil))
(advance scanner) ;; consume closing "
(add-token scanner 'STRING (subseq (source scanner)
(1+ (start scanner))
(1- (current scanner)))))
This would be cleaner (I'm imitating this in CL https://craftinginterpreters.com/scanning.html#reserved-words-and-identifiers but I often end up with more verbose and less readable code than in Java - specially when using this classes a lot). As in CL methods don't belong to classes you end up declaring such arguments over and over. This would be a bit better:
(defun clox-string (scanner)
"Parse string into a token and add it to tokens"
(let-curry scanner (peek at-end-p line source start current advance add-token)
(loop while (and (char/= #\" (peek))
(not (at-end-p)))
do
(if (char= #\Newline (peek)) (incf (line))
(advance)))
(when (at-end-p)
(clox.error::clox-error (line) "Unterminated string.")
(return-from clox-string nil))
(advance) ;; consume closing "
(add-token 'STRING (subseq (source)
(1+ (start))
(1- (current)))))
sketch of macro (not working):
;; Clearly not as I don't understand macros very well :) non-working code:
(defmacro let-curry (obj functions &body body)
"Locally curry all functions"
(let ((fn (gensym)))
`(flet (loop
for ,fn in ,functions
collect (list ,fn (&rest args)
(funcall ,fn ,obj args)))
,#body)))
EDIT (ADD): Notice that scanner is a class; start, source, line, etc., accessors to the slots with the same name; add-token a generic function of more than one argument, advance a generic method of one argument:
(defclass scanner ()
((source
:initarg :source
:accessor source)
...
(...)))
(defmethod advance ((scanner scanner)) ...)
(defmethod add-token ((scanner scanner) token-type) ...)
Simpler Example with error:
;; With
(defun add (x y) (+ x y))
(defun mul (x y) (* x y))
;; I want to have this:
(let-curry 1000 (add mul)
(print (add 3))
(print (mul 3)))
;; expanding to:
(flet ((add (y) (add 1000 y))
(mul (y) (mul 1000 y)))
(print (add 3))
(print (mul 3)))
;; but instead I'm getting:
Execution of a form compiled with errors.
Form:
(FLET (LOOP
FOR
#1=#:G777
IN
(ADD MUL
)
COLLECT
(LIST #1#
(&REST ARGS)
(FUNCALL #1# 1000 ARGS)))
(PRINT (ADD 3))
(PRINT (MUL 3)))
Compile-time error:
The FLET definition spec LOOP is malformed.
[Condition of type SB-INT:COMPILED-PROGRAM-ERROR]
Thanks! The basic question is: is it possible to make such macro work?
Your version didn't expand to what you wanted but:
(flet (loop for #:g8307 in (add mul) collect (list #:g8307 (&rest args) (funcall #:g8307 1000 args)))
(print (add 3)) (print (mul 3)))
Now the loop needs to be done at macro expansion time.
Here is a working version:
(defmacro let-curry (obj (&rest functions) &body body)
"Locally curry all functions"
`(flet ,(loop for fn in functions
collect `(,fn (&rest args)
(apply #',fn ,obj args)))
,#body))
;; test it using add and mul from OP
(macroexpand-1 '(let-curry 10 (add mul) (list (add 5) (mul 5))))
;; ==>
(flet ((add (&rest args) (apply #'add 10 args))
(mul (&rest args) (apply #'mul 10 args)))
(list (add 5) (mul 5)))
(let-curry 10 (add mul) (list (add 5) (mul 5)))
;; ==> (15 50)
Using gensym is only needed if you are in danger of shadowing/colliding something or to ensure evaluation order is least surprising, but in your case you actually want to shadow the original names with the curried version so it makes sense to just use the original name.
If you want to have more than one argument you should use apply
since you know the function is in the function namespace you need to call #'symbol instead of symbol.
I've done (&rest functions) instead of functions in the prototype that with bad usage (not a list) you get a compile time error and it is more preciese.
This is my lisp code.
(DEFUN F (A B)
(SETF C (* 4 A))
(SETF D (* 2 (EXPT B 3)))
(SETF RES (+ C D))
(IF (AND (TYPEP A 'INTEGER) (TYPEP B 'INTEGER))
(list 'Final 'value '= res)
'(YOUR INPUTS ARE NOT NUMBERS)))
For example, (f 5 9) works well.
But (f 'w 'q) doesn't work with the following error message:
(ERROR TYPE-ERROR DATUM W EXPECTED-TYPE NUMBER FORMAT-CONTROL
~#<~s' is not of the expected type~s'~:#> FORMAT-ARGUMENTS
(W NUMBER))
Error: W' is not of the expected typeNUMBER'
I want to make if A,B is integer calculate 4A+2B^3.
Else if at least one is not an integer print error message.
I try to the code shown above.
But how can I make this error handling using if statements?
First, you should use LET or LET* to define local variables.
(defun f (a b)
(let* ((c (* 4 a)) ; You need LET* instead of LET because
(d (* 2 (expt b 3))) ; RES depends on the previous variables.
(res (+ c d)))
(if (and (typep a 'integer) (typep b 'integer))
(list 'final 'value '= res)
'(your inputs are not numbers))))
The actual problem is that you're doing the calculations before you check that the arguments are integers. You should move the calculation inside the IF.
(defun f (a b)
(if (and (integerp a) (integerp b))
(let* ((c (* 4 a))
(d (* 2 (expt b 3)))
(res (+ c d)))
(list 'final 'value '= res))
'(your inputs are not numbers)))
Returning lists like that is kind of strange. If you intend them as output for the user, you should instead print the messages and return the actual result.
(defun f (a b)
(if (and (integerp a) (integerp b))
(let ((result (+ (* 4 a)
(* 2 (expt b 3)))))
(format t "Final value = ~a~%" result)
result) ; Return RESULT or
(format t "Your inputs are not integers.~%"))) ; NIL from FORMAT.
In most cases you should signal an error if the arguments are not correct type. Printing output from a function that does the calculation is usually a bad idea.
(defun f (a b)
(check-type a integer "an integer")
(check-type b integer "an integer")
(+ (* 4 a)
(* 2 (expt b 3))))
(defun main (a b)
(handler-case
(format t "Final value = ~a~%" (f a b))
;; CHECK-TYPE signals a TYPE-ERROR if the type is not correct.
(type-error () (warn "Your inputs are not integers."))))
(main 12 1)
; Final value = 50
;=> NIL
(main 12 'x)
; WARNING: Your inputs are not integers.
;=> NIL
Common Lisp condition system also allows you to use restarts to fix errors. CHECK-TYPE establishes a restart named STORE-VALUE, which you can invoke to supply a correct value for the place. In this case it probably doesn't make sense, but you could do something like use 1 as a default.
(defun main (a b)
(handler-bind ((type-error (lambda (e)
(store-value 1 e))))
(format t "Final value = ~a~%" (f a b))))
(main 12 1)
; Final value = 50
;=> NIL
(main 12 'x)
; Final value = 50
;=> NIL
Notice that conditions/error handlers do add some overhead, so for performance critical functions you might not want to use them and instead check your arguments before calling the function.
(declaim (ftype (function (integer integer) integer) f))
(defun f (a b)
(declare (optimize (speed 3) (safety 0) (debug 0)))
(+ (* 4 a)
(* 2 (expt b 3))))
(defun main (a b)
(if (and (integerp a)
(integerp b))
(format t "Final value = ~a~%" (f a b))
(warn "Your inputs are not integers.")))
My program is supposed to convert a given temperature from Fahrenheit to Centigrade or the other way around. It takes in a list containing a number and a letter. The letter is the temperature and the letter is the unit we are in. Then I call the appropriate function either F-to-C or C-to-F. How do I call the functions with the given list that was first checked in my temperature-conversion function. Here is my code.
(defun temperature-conversion (lst)
(cond
((member 'F lst) (F-to-C))
((member 'C lst) (C-to-F))
(t (print "You didn't enter a valid unit for conversion"))
)
)
(defun F-to-C ()
;;(print "hello")
(print (temperature-conversion(lst)))
)
(defun C-to-F ()
(print "goodbye"))
;;(print (temperature-conversion '(900 f)))
(setf data1 '(900 f))
You have infinite recursion: temperature-conversion calls F-to-C which calls temperature-conversion again.
I would do this:
(defun c2f (c) (+ 32 (/ (* 9 c) 5)))
(defun f2c (f) (/ (* 5 (- f 32)) 9))
(defun temperature-conversion (spec)
(ecase (second spec)
(C (c2f (first spec)))
(F (f2c (first spec)))))
(temperature-conversion '(32 f))
==> 0
(temperature-conversion '(100 c))
==> 212
(temperature-conversion '(100))
*** - The value of (SECOND SPEC) must be one of C, F
The value is: NIL
The following restarts are available:
ABORT :R1 Abort main loop
I think this example is generally used to demonstrate how functions are first-class values.
With a little modification to sds's answer, you can have an ECASE statement that selects the appropriate function, which is then used by a surrounding FUNCALL.
(defun temperature-conversion (spec)
(destructuring-bind (temperature unit) spec
(funcall
(ecase unit (C #'c2f) (F #'f2c))
temperature)))
I added a DESTRUCTURING-BIND in case you don't know yet what it is.
I can't figure, is there any way to put something like _ in erlang, for "unused value" in destructuring-bind?
For example there we have something like that:
(destructuring-bind ((_SNIPPET
(_TITLE . title)
(_DESCRIPTION . description)
_RESOURCE-ID (_VIDEO-ID . video-id)))) entry
(declare (ignore
_SNIPPET _TITLE _DESCRIPTION _RESOURCE-ID _VIDEO-ID))
(list video-id title description)))
It'll be great not to put specific variable for every unused value, and write something like that:
(destructuring-bind ((_
(_ . title)
(_ . description)
(_ (_ . video-id)))) entry
(list video-id title description)))
Is there any way to get such behavior with standart destructuring-bind or any other standart macros? Or I have to use some ML-like pattern matching library, and if so - which one?
It's not possible with DESTRUCTURING-BIND (you can't use a variable more than once, some compiler will complain). You can enumerate the variables, _1, _2, ... But then you have to ignore each of them.
LOOP can do it:
CL-USER 23 > (loop for ((a b nil c) nil d) in '(((1 2 3 4) 5 6)
((1 2 3 4) 5 6))
collect (list a b c d))
((1 2 4 6) (1 2 4 6))
NIL is used as the wildcard variable.
You can reuse the LOOP macro:
(defmacro match-bind (pattern object &body body)
`(loop with ,pattern = ,object
while nil
finally (return (progn ,#body))))
CL-USER 37 > (match-bind ((a b nil c) nil d)
'((1 2 3 4) 5 6)
(list a b c d))
(1 2 4 6)
You can use some LET-MATCH from some library. For example: https://github.com/schani/clickr/blob/master/let-match.lisp
There are probably more fancy versions.
There's nothing built into the language for this. Rainer Joswig's answer points out that loop can do some destructuring, but it doesn't do nearly as much. In an earlier version of this answer, I suggested traversing the destructuring lambda list and collecting a list of all the symbols that begin with _ and adding a declaration to the form to ignore those variables. A safer version replaces each one with a fresh variable (so that there are no repeated variables), and ignores them all. Thus something like
(destructuring-bind (_a (_b c)) object
c)
would expand into
(destructuring-bind (#:g1 (#:g2 c)) object
(declare (ignore #:g1 #:g2))
c)
This approach will work OK if you're only using the "data-directed" described in 3.4.4.1.1 Data-directed Destructuring by Lambda Lists. However, if you're using "lambda-list-directed" approach described in 3.4.4.1.2 Lambda-list-directed Destructuring by Lambda Lists, where you can use lambda-list keywords like &optional, &key, etc., then things are much more complicated, because you shouldn't replace variables in some parts of those. For instance, if you have
&optional (_x '_default-x)
then it might be OK to replace _x with something, but not _default-x, because the latter isn't a pattern. But, in Lisp, code is data, so we can still write a macro that maps over the destructuring-lambda-list and replaces only in locations that are patterns. Here's somewhat hairy code that does just that. This takes a function and a destructuring lambda list, and calls the function for each pattern variable in the lambda list, along with the type of the argument (whole, required, optional, etc.).
(defun map-dll (fn list)
(let ((result '())
(orig list)
(keywords '(&allow-other-keys &aux &body
&key &optional &rest &whole)))
(labels ((save (x)
(push x result))
(handle (type parameter)
(etypecase parameter
(list (map-dll fn parameter))
(symbol (funcall fn type parameter)))))
(macrolet ((parse-keyword ((&rest symbols) &body body)
`(progn
(when (and (not (atom list))
(member (first list) ',symbols))
(save (pop list))
,#body)))
(doparameters ((var) &body body)
`(do () ((or (atom list) (member (first list) keywords)))
(save (let ((,var (pop list)))
,#body)))))
(parse-keyword (&whole)
(save (handle :whole (pop list))))
(doparameters (required)
(handle :required required))
(parse-keyword (&optional)
(doparameters (opt)
(if (symbolp opt)
(handle :optional opt)
(list* (handle :optional (first opt)) (rest opt)))))
(when (and (atom list) (not (null list))) ; turn (... . REST)
(setq list (list '&rest list))) ; into (... &rest REST)
(parse-keyword (&rest &body)
(save (handle :rest (pop list))))
(parse-keyword (&key)
(doparameters (key)
(if (symbolp key)
(handle :key key)
(destructuring-bind (keyspec . more) key
(if (symbolp keyspec)
(list* (handle :key keyspec) more)
(destructuring-bind (keyword var) keyspec
(list* (list keyword (handle :key var)) more)))))))
(parse-keyword (&allow-other-keys))
(parse-keyword (&aux)
(doparameters (aux) aux))
(unless (null list)
(error "Bad destructuring lambda list: ~A." orig))
(nreverse result)))))
Using this, it's pretty easy to write a destructuring-bind* that replaces each pattern variable beginning with _ with a fresh variable that will be ignored in the body.
(defmacro destructuring-bind* (lambda-list object &body body)
(let* ((ignores '())
(lambda-list (map-dll (lambda (type var)
(declare (ignore type))
(if (and (> (length (symbol-name var)) 0)
(char= #\_ (char (symbol-name var) 0)))
(let ((var (gensym)))
(push var ignores)
var)
var))
lambda-list)))
`(destructuring-bind ,lambda-list ,object
(declare (ignore ,#(nreverse ignores)))
,#body)))
Now we should look at the expansions it produces:
(macroexpand-1
'(destructuring-bind* (&whole (a _ . b)
c _ d
&optional e (f '_f)
&key g _h
&aux (_i '_j))
object
(list a b c d e f g)))
;=>
(DESTRUCTURING-BIND
(&WHOLE (A #:G1041 &REST B) C #:G1042 D
&OPTIONAL E (F '_F)
&KEY G #:G1043
&AUX (_I '_J))
OBJECT
(DECLARE (IGNORE #:G1041 #:G1042 #:G1043))
(LIST A B C D E F G))
We haven't replaced anywhere we shouldn't (init forms, aux variables, etc.), but we've taken care of the places that we should. We can see this work in your example too:
(macroexpand-1
'(destructuring-bind* ((_ (_ . title)
(_ . description)
_
(_ . video-id)))
entry
(list video-id title description)))
;=>
(DESTRUCTURING-BIND ((#:G1044 (#:G1045 &REST TITLE)
(#:G1046 &REST DESCRIPTION)
#:G1047
(#:G1048 &REST VIDEO-ID)))
ENTRY
(DECLARE (IGNORE #:G1044 #:G1045 #:G1046 #:G1047 #:G1048))
(LIST VIDEO-ID TITLE DESCRIPTION))
This program produces an error:
define: unbound identifier;
also, no #%app syntax transformer is bound in: define
When pasted into the REPL (to be exact, the last line: (displayln (eval-clause clause state))), it works. When run in definition window, it fails. I don't know why.
#lang racket
(define *state* '((a false) (b true) (c true) (d false)))
(define *clause* '(a (not b) c))
(define (eval-clause clause state)
(for ([x state])
(eval `(define ,(first x) ,(second x))))
(eval (cons 'or (map eval clause))))
(displayln (eval-clause *clause* *state*))
This too:
(define (eval-clause clause state)
(eval `(let ,state ,(cons 'or clause))))
produces
let: unbound identifier;
also, no #%app syntax transformer is bound in: let
This was my attempt to translate the following Common Lisp program: Common Lisp wins here?
; (C) 2013 KIM Taegyoon
; 3-SAT problem
; https://groups.google.com/forum/#!topic/lisp-korea/sVajS0LEfoA
(defvar *state* '((a nil) (b t) (c t) (d nil)))
(defvar *clause* '(a (not b) c))
(defun eval-clause (clause state)
(dolist (x state)
(set (car x) (nth 1 x)))
(some #'identity (mapcar #'eval clause)))
(print (eval-clause *clause* *state*))
And in Paren:
(set *state* (quote ((a false) (b false) (c true) (d false))))
(set *clause* (quote (a (! b) c)))
(defn eval-clause (clause state)
(for i 0 (dec (length state)) 1
(set x (nth i state))
(eval (list set (nth 0 x) (nth 1 x))))
(eval (cons || clause)))
(eval-clause *clause* *state*)
eval is tricky in Racket. As per Racket Guide, 15.1.2, you need to hook into the current namespace as follows
(define-namespace-anchor anc)
(define ns (namespace-anchor->namespace anc))
and then add ns to every call to eval:
(define (eval-clause clause state)
(for ([x state])
(eval `(define ,(first x) ,(second x)) ns))
(eval (cons 'or (map (curryr eval ns) clause)) ns))
Note that this is not necessary in the REPL, as explained in the document referenced above.
However, it's probably a better idea to create a specific namespace for your definitions so that they don't get mixed up with your own module's definitions:
(define my-eval
(let ((ns (make-base-namespace)))
(lambda (expr) (eval expr ns))))
(define *state* '((a #f) (b #t) (c #t) (d #f)))
(define *clause* '(a (not b) c))
(define (eval-clause clause state)
(for ([x state])
(my-eval `(define ,(first x) ,(second x))))
(my-eval (cons 'or (map my-eval clause))))
(displayln (eval-clause *clause* *state*))
or, if you want to continue using true and false from racket/bool, define my-eval as follows;
(define my-eval
(let ((ns (make-base-namespace)))
(parameterize ((current-namespace ns))
(namespace-require 'racket/bool))
(lambda (expr) (eval expr ns))))
I would write the Common Lisp version slightly simpler:
(defun eval-clause (clause state)
(loop for (var value) in state
do (set var value))
(some #'eval clause))
The LOOP form is more descriptive (since we can get rid of CAR and NTH) and EVAL can be directly used in the SOME function.