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)
Related
I'm trying to match against a hash table in typed racket, but I keep getting the following error. The code works fine in untyped racket and I've tried changing it up some to no effect. The error looks like it's happening somewhere after the match macro gets expanded but I'm not familiar enough with racket to understand where or how to debug the issue.
Is is possible to use the hash-table pattern in typed racket?
(match (make-hash '((a . 2) (b . 3) (c . 2)))
[(hash-table _ ...) #t])
Type Checker: Polymorphic function `hash-map' could not be applied to arguments:
Domains: HashTableTop (-> Any Any c) Any
HashTableTop (-> Any Any c)
(HashTable a b) (-> a b c) Any
(HashTable a b) (-> a b c)
Arguments: (Mutable-HashTable Symbol Integer) (All (a) (-> a * (Listof a)))
it's impossible.
in the match macro, the hash-table form expands to syntax that includes the hash-map function, viz (lambda (e) (hash-map e list)). this is correct but its type is too abstract for typed racket to infer it. for the type checker to be satisfied, we'd need:
(lambda #:forall (k v) ([e : (HashTable k v)])
(hash-map e
(λ ([k : k] [v : v])
(list k v))))
there's no practical way to specify this, so the hash-table matcher is unusable in typed racket.
if a for loop is usually best, e.g.
(for ([(k v) (make-hash '((a . 2) (b . 3) (c . 2)))] #:when (even? v))
(printf "~a and ~a~n" k v))
or else something like (hash-keys m)
otherwise, positional matching requires advanced knoweldge of typed racket. for example, the following function, hash-set/cond, takes a hash table and arguments of the form (flag k v) ... and updates (if key already in table) or inserts (if key not already in table) each k/v pair if its associated flag is truthy:
(: hash-set/cond (∀ (k v) (->* ((HashTable k v))
#:rest-star (Any k v)
(HashTable k v))))
(define (hash-set/cond ht . args)
(let loop ([ht : (HashTable k v) ht]
[args : (Rec r (U (List* Any k v r) Null)) args])
(if (null? args)
ht
(loop (if (car args)
(hash-set ht (cadr args) (caddr args))
ht)
(cdddr args)))))
e.g.
(hash-set/cond (hash 'a 20 'b "yes")
(even? 3) 'a 10 ; 3's not even, so 'a isn't modified
#t 'b "canary" ; necessarily set 'b to "canary"
'im-a-truthy-value! 'c 'new-value) ; ditto
returns #hash((a . 20) (b . "canary") (c . new-value)).
so if you end-up using typed racket a lot and want to use this kind of functionality, then it can be very useful in certain places! still, typed racket's type system can represent—but not handle—certain recursive hash table types. this is because, when checking the type of the value, hash? cannot refine the type of the hash table beyond it being a hash table with some type of key and value, i.e. hash? : (-> Any Boolean : HashTableTop) instead of (-> Any Boolean : (HashTable k v)). this makes recursing over particular recursively defined JSON schemata impossible. in these cases you must use untyped racket, though the saving grace here is that racket contracts can handle such complex definitions.
if your project is heavily based on complex hash tables, then clojure or janet are likely better language choices.
I want to make user-program which extract elements a which have element b (given by parameter) as pair in list.
Like, if I give c as parameter and list ((c a) (c b) (d f) (d g)),
result should be 'a' 'b';
So I define a function as below,
(defun myr (b a) (if (= CAAR(a) b) CDAR(a) 'nope myr(b CDR(a))));
and call like this
myr(b ((b a) (b c) (a d) (a f)))
But result is like variable myr has no value
Its my first time in Lisp, So just tell me what keyword should I search for will be great help for me.
Thank you for reading.
You really need to start with a good lisp book, e.g., PCL or ACL.
You will save yourself a lot of time.
Lisp syntax is different from C.
In C, you call a function f with arguments х and y like this: f(x,y).
In Lisp, you do it like this: (f x y).
When you invoke your function myr(...), you put the symbol myr in the variable position, not function position, which causes the error you reported.
You also need to use quote as appropriate.
I'm trying to capture the expanded forms by defining my own module-begin:
(define-syntax-rule (my-module-begin e ...)
(#%module-begin
e ...
(foo e ...)))
Am I correct that foo here gets the original forms? If so is there a way for foo to get the expanded forms instead?
To get the expanded forms you'll need to use local-expand in some way.
Part 1, an incomplete solution
You might think to call local-expand separately on every expression like this:
#lang racket
(require syntax/parse/define
(for-syntax syntax/stx))
(define-simple-macro (my-module-begin e ...)
; define a function that expands it
#:do [(define (expand/mod-ctx e)
(local-expand e 'module '()))]
; get the expanded versions by calling that function on the e's
#:with (e-expanded ...) (stx-map expand/mod-ctx #'(e ...))
; use the expanded versions inside foo
(#%module-begin
e-expanded ...
(foo e-expanded ...)))
This works when the e forms are expressions like (+ 1 2) or (let ([x 3] [y 4]) (make-list x y)). However, it doesn't work when the e forms can be definitions.
Part 2, getting the expanded versions from Racket's #%module-begin
One way to support using local-expand with these module-level definitions is to wrap it in racket's #%module-begin form before expanding. This allows it to process all the es together in one call to local-expand.
(define-simple-macro (my-module-begin e ...)
; get the expanded versions by calling that function on a
; *constructed* module-begin form
#:with (_ e-expanded ...) (local-expand #'(#%module-begin e ...) 'module-begin '())
; use the expanded versions inside foo
(#%module-begin
e-expanded ...
(foo e-expanded ...)))
This gets Racket's #%module-begin to handle the definitions, and when it's done, you can pattern match on it with (_ e-expanded ...).
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>) ...))
actually i am trying to perfectly understand clojure and particularly symbols
(def a 1)
(type a)
;;=>java.lang.Long
(type 'a)
;;=>clojure.lang.Symbol
I know that type is a function so its arguments get evaluated first so i perfectly understand why the code above work this way .In the flowing code i decided to delay the evaluation using macro
(defmacro m-type [x] (type x))
(m-type a)
;;==>clojure.lang.Symbol
and i am fine with that but what i fail to uderstand is this:
(m-type 'a)
;;=>clojure.lang.Cons
why the type of 'a is a cons
the character ' is interpreted by the clojure reader as a reader-macro which expands to a list containing the symbol quote followed by whatever follows the ', so in your call to (m-type 'a) the 'a is expanding to:
user> (macroexpand-1 ''a)
(quote a)
then calling type on the list (quote a) which is a Cons.
This may be a bit more clear if we make the m-type macro print the arguments as it sees them while it is evaluating:
user> (defmacro m-type [x] (println "x is " x) (type x))
#'user/m-type
user> (m-type 'a)
x is (quote a)
clojure.lang.Cons