how to specify that a method argument is a list of (e.g.) string - lisp

In CLOS, how to specify that a method argument is a list of (e.g.) strings?
e.g. something like:
(defmethod m1 ((x (every 'string)))
(dolist (y x) (print (char y 0))))

You can't. Methods can only be specialized on classes, not types. You could manually define the type list-of-strings with deftype and satisfies, but it would still be invalid to use it as a specializer in a defmethod.
From the defmethod entry of the CLHS:
Only required parameters can be specialized. If parameter-specializer-name is a symbol it names a class.

Related

Error for defining class method as expression

I am trying to define a class method like so:
#lang racket
(define foo% (class object%
(super-new)
(define/public plus-one (curry + 1))))
But this code produces the following error:
eval:2:0: class: bad form for method definition
According to the Racket documentation, it should be possible to define a method using the syntax (define/public id expr), so I don't understand why this isn't working.
There is an easy workaround by using the (define/public (id . formals) body ...+) syntax, of course, but I would like to understand why the current code isn't accepted.
In the documentation for class*, see the nonterminals named method-definition and method-procedure. They describe the constraints on a legal method definition. A paragraph later in the class docs says that each private, public, etc declaration must correspond to a method-definition. So it isn't a bug, it's the intended behavior.
The reason behind the behavior, by the way, is that Racket's class macro implements methods by rewriting the method's lambda (or case-lambda) expression(s) to add an implicit argument for this. The same argument is also implicitly used to access the object's public and private fields. Restricting method definitions to certain shapes makes it possible to find the right lambda expressions to adjust.
Here's one way of rewriting your example:
#lang racket
(define do-plus-one (curry + 1))
(define foo% (class object%
(super-new)
(define/public (plus-one n) (do-plus-one n)))
This has the following nice properties: do-plus-one is computed only once, and it doesn't take a field slot in each foo% object.
It might be a bug. Imagine we have the usuall way:
(define/public (plus-one n) (+ 1 n))
The define way with name and arguments in parentheses are sugar for a id and lambda and that works:
(define/public plus-one (lambda (n) (+ 1 n)))
I'm getting that (curry + 1) returns a similar lambda and that that object should be working, but it isn't.
The whole point with a class method is using the private fields from the object and none of them do that, however only curry version makes it obvious that it will not be able to since the resulting procedure won't be having the scope of the object.
If you imagined we used a private variable for the increment you couldn't use curry since it would cache it. eg. you can't replicate this:
(define increaser%
(class object%
(init inc)
(define increment inc)
(super-new)
(define/public (set-inc inc)
(set! increment inc))
(define/public (increase n)
(+ increment n))))
(define test (new increaser% [inc 2]))
(send test increase 1) ; ==> 3
(send test set-inc 3)
(send test increase 1) ; ==> 4
(define test2 (new increaser% [inc 21]))
(define value 13)
(map (lambda (obj) (send obj increase value)) (list test test2))
; ==> (16 34)

Specialize Generic Function (Multimethod) on Two Arguments

I am trying to build a binary search tree in common lisp. I have defined the binary search class using the CLOS like this:
(defclass bst ()
((root :type node
:accessor tree-root
:initform nil
:initarg root)))
I am trying to define a generic function that takes in the tree object and a key and returns a boolean true if the tree contains the key and nil if the tree does not contain the key.
Right now I have the following definition of a generic function:
(defgeneric contains ((tree bst) (key))
(:documentation "returns boolean of whether the given tree contains a particular key)
I get the following error when I load the file into the REPL (I am using SBCL):
Required argument is not a symbol: (TREE BST)
Am I misunderstanding how generic functions work? I can't seem to define the function properly.
Yes, defgeneric defines a generic function. You can either specify methods in the call to defgeneric or by using defmethod.
You need one of:
(defgeneric contains (tree key)
(:documentation "returns boolean of whether the given tree contains a particular key")
(:method ((tree bst) key) ...))
or:
(defgeneric contains (tree key)
(:documentation "returns boolean if a given tree contains a given key"))
(defmethod contains ((tree bst) key)
...)

Why are there two parentheses after `let` in emacs lisp?

I'm doing a tutorial on emacs lisp, and it's talking about the let function.
;; You can bind a value to a local variable with `let':
(let ((local-name "you"))
(switch-to-buffer-other-window "*test*")
(erase-buffer)
(hello local-name)
(other-window 1))
I don't understand the role of the double parentheses after let in the first line. What are they doing that a single set wouldn't do? Running that section without them, I get an error: Wrong type argument: listp, "you".
You can introduce multiple variables there. The outer parentheses delimit the list of bindings, the inner the individual binding form.
(let ((foo "one")
(bar "two"))
(frobnicate foo bar))
There are not "double parens".
Presumably, you are thinking of (let ((foo...)...)), and you mean the (( that come after let? If so, consider this:
(let (a b c) (setq a 42)...)
IOW, let declares local variables. It may also bind them. In the previous sexp, it declares a, b, and c, but it doesn't bind any of them, leaving it to the let body to give them values.
An example that declares two variables but binds only one of them (a):
(let ((a 42) b) ... (setq b ...) ...)
According to gnu.org, it looks like you can construct and initialize multiple variables with one let statement, so the double parenthesis is there to allow the separation between the variables.
If the varlist is composed of two-element lists, as is often the case, the template for the let expression looks like this:
(let ((variable value)
(variable value)
…)
body…)
The let special form takes a list of bindings: (let (<binding-form> ...) <body>).
The binding form is one of <symbol> (denoting a variable bound to the value nil) or a list (<symbol> <value>) (where value is computed when the let is entered).
The difference between let and let* is how the "value" bits are executed. For plain let, they're executed before any of the values are bound:
(let ((a 17)
(b 42))
(let ((a b) ; Inner LET
(b a))
(list a b)))
Whereas let* executes the binding forms one after another. Both have their places, but you can get by with only using let since (let* (<form1> <form2>...) is equivalent to (let (<form1>) (let (<form2>) ...))

How to use `apply-partially`?

I'm trying to use apply-partially in a local context:
((apply-partially '+ 1) `(1))
This give me the following error: eval: Invalid function: (apply-partially (quote +) 1)
similarly:
(let ((addone (apply-partially #'+ 1)))
(addone 2))
Why any of this example doesn't work?
That's because Emacs Lisp has separate namespaces for variables and functions. A function that has been defined using defun can be called by putting its name first in a list and evaluating that, but if you have a function as a value (as returned by apply-partially) you need to use funcall or apply.
The difference between funcall and apply is that funcall just calls the function with the arguments given, while apply treats its last argument as a list that should be appended to the argument list. Thus, your first example needs to be written with apply, since + doesn't work with lists:
(apply (apply-partially '+ 1) `(1))
For your second example, use funcall, since the function argument is not wrapped in a list:
(let ((addone (apply-partially #'+ 1)))
(funcall addone 2))

Specifying multiple options in a structure's constructor?

I tried defining a structure with a custom print function and constructor like so:
(defun print-test (a-test stream depth)
(format stream "#<TEST-STRUCT ~A>" (test-struct-a a-test)))
(defstruct (test-struct (:print-function print-test
:constructor create-test
(&key a (b a) c)))
a
b
c)
But on evaluation I get:
Bad defstruct option (:PRINT-FUNCTION PRINT-TEST :CONSTRUCTOR
CREATE-TEST (&KEY A B C)).
[Condition of type CCL::SIMPLE-PROGRAM-ERROR]
But specifying either keyword alone works just fine. How can I fix this?
According to the grammar, options must be parenthesized individually. The defstruct form therefore needs to look like this:
(defstruct (test-struct (:print-function print-test)
(:constructor create-test (&key a (b a) c)))
a
b
c)