Consider the following racket code to get a list of accessors of a given struct:
#lang racket
(require (for-syntax syntax/parse racket/struct-info racket/list))
(struct point [x y])
;; get the list of accessors from a struct
;; ex. (get point) = '(point-x point-y)
(define-syntax (get stx)
(syntax-parse stx
[(_ struct)
(define struct-info (extract-struct-info (syntax-local-value #'struct)))
(define accessors-list (map syntax-e (fourth struct-info)))
#``(#,#accessors-list)]))
(get point)
Using syntax-local-value, we can extract the value of the identifier bound by the pattern variable struct.
Using extract-struct-info, we can extract the structure type information in a list form (it has 6 elements). From here the accessors list can be extracted (it's the fourth element in the list).
Question
How can I access the information about a struct (as shown in Structure Type Transformer Binding) at the non-macro level? The two functions above cannot be used directly on structs outside a transformer because the struct is a procedure at that point (and extract-struct-info takes in a struct-info).
You cannot use syntax-local-value and extract-struct-info at run time. You must use run-time struct introspection instead.
If you make your struct transparent, like this:
(struct point [x y] #:transparent)
then you can get analogous values from a point instance using struct-info and struct-type-info:
(define a-point (point 3 4))
(define-values (type skipped?) (struct-info a-point))
;; type = #<struct-type:point>, skipped = #f
(define-values (name inits autos acc mut imms super super-skipped?)
(struct-type-info type))
(acc a-point 0) ;; => 3
The value of type above is the same as struct:point (implicitly defined by the struct definition), so if you know you're dealing with a point struct specifically, you coud use that instead. You still need #:transparent (or you need a sufficiently powerful inspector) to use struct-type-info, though.
Related
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.
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)
I am new to Lisp-scheme and fairly new to the functional paradigm as a whole, and am currently doing an assignment which requires me to overload a function with the same name, but different sets of parameters in racket. Below is an example of what I'm trying to achieve:
#lang racket
(define (put-ball-in-box two-by-fours nails ball)
... )
(define (put-ball-in-box box ball)
... )
These are not the actual functions, but close enough. As implied, both functions would put a ball in a box, but one would assemble the box from its components first, then call the other. Obviously, when I try the above in DrRacket or using the command line, I get a module: duplicate definition for identifier ... error.
Is there a way to achieve this in racket?
Maybe the answer is right in front of me, but I have spent the last two hours searching for this and couldn't find anything, so would appreciate any pointers.
Thank you.
It doesn't in the usual sense of "writing another definition somewhere else."
It allows shadowing, which is defining a procedure with the same name as an imported procedure. Thus you can (define + ...) and your definition of + will hide the + from racket/base. If you want the original procedure, then you can do something like the following, where I define + to be either addition or string-appending.
#lang racket/base
(require (rename-in racket/base (+ base:+)))
(define (+ . args)
(if (andmap string? args)
(apply string-append args)
(apply base:+ args)))
Another thing you can do is use racket/match to have different behavior based on the shape of the argument.
#lang racket/base
(require racket/match)
(define (fib . arg)
(match arg
[(list n) (fib n 1 0)]
[(list 1 a b) a]
[(list 0 a b) b]
[(list n a b) (fib (sub1 n) (+ a b) a)]))
This second example still doesn't quite do what you want since you have to go to the original definition point and modify the match clauses. But it might be sufficient for your purposes.
A more complicated example would be to use custom syntax to create a define/overload form. But I think you'll find the racket/match solution to be best.
You have the concept of default values as in JS and PHP:
(define (fib n (a 0) (b 1))
(if (zero? n)
a
(fib (sub1 n) b (+ a b))))
(fib 10) ; ==> 55
Now if you had 5 optional parameters you need to order them and even pass some values just to be able to add a later one. To avoid that you can use keywords:
(define (test name #:nick [nick name] #:job [job "vacant"])
(list name nick job))
(test "sylwester" #:job "programmer")
; ==> ("sylwester" "sylwester" "programmer")
Now Racket has classes. You can call a method like (send object method args ...).
(define circle%
(class object%
(super-new)
(init-field radius)
(define/public (area)
(* radius radius 3.1415))))
(define cube%
(class object%
(super-new)
(init-field side)
(define/public (area)
(* side side))))
(define circle (new circle% [radius 7]))
(define cube (new cube% [side 7]))
(map
(lambda (o) (send o area))
(list circle cube))
; ==> (153.9335 49)
Notice that the two classes hasn't really commited to a joint interface with area so this is pure duck typing. Thus you can make a function that expects a class that implements a message and it doesn't need to worry about other aspects of the class at all.
I have a macro that extends the racket syntax, and at some point accepts a sequence of bog standard racket expressions. This looks something like this, the relevant syntax variable being body:
(syntax-parse stx
[(_ some-id:id
body:expr ...+)
This macro generates a racket class with a generated method like so:
#'(<class stuff>
(define/public (some-id some-formal-parameter)
body ...)
As I said the body is plain racket code, except for one expression that can be used exclusively in the body, for example:
(define-syntax-rule (tweet identifier value)
(send this publish-tweet (quote identifier) value))
But this does not allow me to use some-formal-parameter because it is not defined. Is there some proper way in which I can define something that can exclusively be used in the body, and can still bind to variables in the context after expansion? Maybe via a splicing syntax class? Reusability is a big bonus, since this "type of body" may exists in multiple (similar) macros.
Some code for testing:
#lang racket
(require (for-syntax syntax/parse))
(define-syntax (define-something stx)
(syntax-parse stx
[(_ some-id:id
body:expr ...+)
#'(define some-id
(new
(class object%
(super-new)
(define/public (displ arg)
(displayln arg))
(define/public (tick some-formal-parameter)
body ...))))]))
(define-syntax-rule (tweet value)
(send this displ value))
(define-something derp
(define a 'not-derp)
(tweet a))
(send derp tick 'derp)
To reformulate the original question now that I know (and can answer) what I wanted to ask: how can I define a macro that can only be used in a certain context (for me: in the body of a method of a racket class), and how can I use dynamically bound variables. In the original code above: when using the expression (tweet a) not only do I want the value of a, but also the value of some-formal-parameter which is bound in the context of the code where the tweet macro is expanded (not where it is defined).
Chris Jester-Young kindly pointed me to syntax parameters, which indeed seem to solve both the issue of dynamic binding and "can only be used in certain contexts". A paper by Eli Barzilay, Ryan Culpepper, and Matthew Flatt helped me understand syntax parameters.
With respect to the original example code I posted, this is the solution I have come up with:
#lang racket
(require
racket/stxparam
(for-syntax syntax/parse))
(define-syntax-parameter tweet
(lambda (stx)
(raise-syntax-error 'tweet "use of an actor keyword outside of the body of an actor" stx)))
(define-syntax (define-something stx)
(syntax-parse stx
[(_ some-id:id
body:expr ...+)
#'(define some-id
(new
(class object%
(super-new)
(define/public (tick some-formal-parameter)
(syntax-parameterize
([tweet
(syntax-rules ()
[(_ value)
(begin (displayln some-formal-parameter)
(displayln value))])])
body ...)
))))]))
(define-something derp
(define a 'not-derp)
(tweet a))
(send derp tick 'derp)
The three key points of attention are the following.
Because of the definition of the tweet macro, whenever it is used outside of the context of a syntax-parametrize statement (that changes the definition of tweet) it will throw an appropriate error.
In the body of the public method tick of our class we change thedefinition of tweet to a macro that matches a pattern of the form (_ value) (which is the value we supply to tweet)
The tweet macro can expand to something that both uses the bound value value, and the value of some-formal-parameter, whatever that may be.
I do not know if this is the proper way to deal with such a situation, but it seems good.
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>) ...))