How to make a Racket macro take an integer argument? - syntax

I've been trying to make a macro for 'wrapping' functions, i.e. if I have a function that will take a list and cons the symbol 'a to the first element, it'd normally be defined as lambda (l) (cons 'a l), but I want a macro that will take a function and a list of integer-expression pairs and 'wrap' that function by making a new function that takes the some arguments of the old function and gets the rest based on the pairs, using the integer as a position and the expression as the value to give the function. Something like this:
(wrap list (0 'blah) (2 'bloo) (4 'blee))
Should expand to:
(lambda (a1 a2 . rest)
(apply list 'blah a1 'bloo a2 'blee rest))
Problem is, I don't know how to get the macro to find the value of the integer in the pair, it only knows it as a syntax object. I'm fairly new to macros and this should be fairly simple, I'm just having trouble with the docs, and I can't find any info on the web other than simple tutorials on macros. Any help would be appreciated.

This seems like a crazy macro to want to write, especially when SRFI 26 is so much more intuitive to use. Instead of (wrap list (0 'blah) (2 'bloo) (4 'blee)), you can just use:
(cut list 'blah <> 'bloo <> 'blee <...>)
That is surely much easier to read.
If you really must write such a macro, here's one way to go about it, by transforming usages of wrap into equivalent usages of cut:
(require (for-syntax syntax/parse) srfi/26)
(define-syntax (wrap stx)
(syntax-parse stx
((_ func:expr (idx:nat expr:expr) ...)
(let* ((alist (map cons
(syntax->datum #'(idx ...))
(syntax-e #'(expr ...))))
(upper (add1 (apply max -1 (map car alist))))
(listfunc (lambda (i)
(cond ((assv i alist) => cdr)
(else #'<>)))))
(with-syntax (((args ...) (build-list upper listfunc)))
#'(cut func args ... <...>))))))
The key to answering your question, about how to get the integers given the syntax objects, is by using syntax->datum (for deep syntax-stripping) or syntax-e (for shallow syntax-stripping).
(P.S. (To Racket experts reading this.) I'm very new to syntax-parse, so I'm sure syntax-parse experts can find better ways to write the above. I originally wrote the macro as a syntax-case macro, then slapped on syntax-parse syntax classes. That's it.)

Related

Does specifying the number of elements on defining a vector in Racket make the program use less time or memory?

For example, can this
#!/usr/bin/env racket
#lang racket/base
(define vector-of-pleasures #6("eating" "cold showers" "swimming" "running" "pullups" "weighlifting"))
(for ((pleasure vector-of-pleasures)) (displayln pleasure))
be more performant because of the optional annotation than this
#!/usr/bin/env racket
#lang racket/base
(define vector-of-pleasures #("eating" "cold showers" "swimming" "running" "pullups" "weighlifting"))
(for ((pleasure vector-of-pleasures)) (displayln pleasure))
?
Methinks it should not matter since in both snippets vector-of-pleasures is immutable.
What are, other than performance, possible reasons for annotating the number of the elements of the vector on its definition?
No, it doesn't. The real use of that syntax is that it lets you write a vector of a bunch of identical things easily: #6(1) is a vector of 6 1s.
But I think it could save space. I can't see why, for instance:
(let ((v #2((1 2))))
(eq? (vector-ref v 0) (vector-ref v 1)))
should not be true. But then this rapidly turns into the question of when similar literals can be folded: can (eq? '(1 2) '(1 2)) return true for instance? I don't know what Racket's rules are on that.

racket: Why doesn't apply work with "bitmap" function?

I have been cautioned against using eval in my code. However, in this bit of racket code, I can get eval working but not something more recommended, like apply. Here is the code:
(require 2htdp/image)
(define (get_img filename)
(let ([img (eval `(bitmap ,filename))])
(image->color-list mask)
))
I tried doing the naive replace of eval with apply:
(require 2htdp/image)
(define (get_img filename)
(let ([img (apply `(bitmap ,filename))])
(image->color-list mask)
))
and when I run it I get:
; apply: arity mismatch;
; the expected number of arguments does not match the given number
; expected: at least 2
; given: 1
; [,bt for context]
I have tried a few permutations of this code, but to no avail. I was hopeful this one
(let ([img (apply bitmap `(filename))])
(image->color-list img)`)
would work, but clearly there's still something I'm not understanding
EDIT:
The first thing I tried, with error message:
> (require 2htdp/image)
> (define (get_img filename)
(let ([img (bitmap filename)])
(image->color-list img)))
; readline-input:6:15: bitmap: expected a path with a / in it
; in: (bitmap filename)
; [,bt for context]
Another failed attempt:
> (define (get_img filename)
(let ([img (apply bitmap (list filename))])
(image->color-list mask)))
; readline-input:16:20: bitmap: bad syntax
; in: bitmap
; [,bt for context]
You're using it wrong. So behind the variable + there is a procedure object which can be applied. These are equal:
(+ (* 2 3) 5) ; ==> 11
(apply + (list (* 2 3) 5)) ; ==> 11
(apply + `(,(* 2 3) 5)) ; ==> 11
In your example you are using bitmap and it isn't a procedure at all but a macro and it seems it is to get bitmaps from a racket package and with strings it expects at least a slash since images should't be in the package root. You should replace it with bitmap/file which is a procedure and takes a file path absolute or relative to current working directory instead.
In your example (apply `(bitmap/file ,filename) you are passing apply a list as first argument instead of a procedure object and a last argument with parameters.
In your example (apply bitmap/file `(filename)) you are applying bitmap with a literal list with a symbol filename which has nothing to do with the variable with the same name. You were so close since I think you wanted (apply bitmap/file `(,filename)) which is a funny way of doing (apply bitmap/file (list filename)). What I don't understand is why can't you just do this:
(define (get_img filename)
(let ([img (bitmap/file filename)])
(image->color-list mask)))
The combination apply and bitmap doesn't work together because bitmap is not a function. Note that the entry in the documentation on bitmap says "Syntax" and not "procedure".
If f is a function, then (apply f (list a b c)) will compute (f a b c).
However, bitmap is not a function, it is a "special form".
You are in luck though, because bitmap/file is a function, so you can use that instead.
I think it's worth understanding what apply is useful for, in Racket or other Lisp-1s. In almost all code it is useful when you have a function and a bunch of arguments but you don't know how many there are, and you want to call the function with those arguments. What that means in practise is:
'you have a function' so in particular you are not trying to evaluate some macro form or something else special;
'you have a bunch of arguments' means you have a list of arguments.
If you know how many arguments you have then there is almost never a reason to use apply unless the arguments are already in a list and you don't want to bother extracting them: (apply cons l) might be easier than (cons (first l) (second l)) say.
In particular if you are trying to call a function with a single argument which you know then apply is definitely not what you want. And similarly it is never what you want if the 'function' is a macro.
In Lisp-2s there is an additional use for apply: calling a function which is the value of a variable. This is needed because, as a silly example, (let ((x (lambda (...) ...))) ... (x ...) ...) won't work in a Lisp-2. Lisp-2s have an additional function, funcall, which does what apply does when you know the number of arguments: you don't need funcall in a Lisp-1.
The cases where eval is useful are even rarer. There are some, but almost all the time it is at best a confusion and at worst a terrifying security problem: what does
(define (terror x) (eval `(list x)))
Do when it is called? Answer: anything at all that the language is capable of doing: (terror '(launch-the-nukes)), say.

Typed Racket - dynamic function calls (string to procedure) revisited

About a year ago, #soegaard provided an answer to an interesting problem - how to take a string and return the procedure named in that string. The solution was simple and elegant.
Enter typed racket and a twist.
I can make it work in typed racket as long as it returns only functions with the same arity, for example (-> Number Number Number), but if I try to have it able to return functions with different arities, such as shown below, I cannot figure out how to make the require/typed call work.
Here is the modified file with my second function with a different arity.
#lang racket
(provide string->procedure add square)
(define (add x y)
(+ x y))
(define (square x)
(sqr x))
(define ns (variable-reference->namespace (#%variable-reference)))
(define (string->procedure s)
(define sym (string->symbol s))
(eval sym ns))
(string->procedure "add")
((string->procedure "add") 1 2)
((string->procedure "square") 5)
And here is the call that only works with the "add" fuction or any other function that takes two numbers and returns one number.
#lang typed/racket
(require/typed "string-procedure.rkt"
[string->procedure
(-> String (-> Number Number Number))]
[add (-> Number Number Number)]
[square (-> Number Number)])
I've tried using case-> and unions to no avail. Using case-> for the return type at least will run but then it fails all calls.
In case you think I'm nuts for trying this, what I'm trying to do is take the result of a database call, a string, and determine the correct procedure to call to access the appropriate data element in a struct. I can do it with a long case statement, but I was hoping for a more elegant solution.
Thank you.
I don't think you want to use eval, or to solve this problem in quite this way. Specifically: what if the database contains a string that refers to a function that doesn't exist, or a function that you didn't want to have called? This is how security problems arise.
I would say that in this case, you'd probably be willing to specify the names of the procedures that are "legal", and you can probably do that easily with a macro that doesn't mangle hygiene too badly:
#lang typed/racket
;; defines the 'db-callable' syntax. Put this in a library file...
(define-syntax (db-callable stx)
(syntax-case stx ()
[(_ fun-name [id ...])
(with-syntax ([(id-strs ...)
(for/list ([id-stx (in-list (syntax->list #'(id ...)))])
(symbol->string (syntax-e id-stx)))])
#'(define (fun-name str)
(match str
[id-str id] ...)))]))
;; here are some functions we want the DB to be able to call
(define (f x) 3)
(define (g x) 4)
;; here's the list of functions we want the db to be able to call:
(db-callable getfun [f g])
((getfun "f") 9)
((getfun "g") 123)

How can I unsplice a list of expression into code?

I have an experiment for my project, basically, I need to embedded some s-expression into the code and make it run, like this,
(define (test lst)
(define num 1)
(define l (list))
`#lst) ; oh, this is not the right way to go.
(define lst
`( (define num2 (add1 num))
(displayln num2)))
I want the test function be like after test(lst) in racket code:
(define (test lst)
(define num 1)
(define l (list))
(define num2 (add1 num)
(displayln num2))
How can I do this in racket?
Update
The reason I would like to use eval or the previous questions is that I am using Z3 racket binding, I need to generate formulas (which uses racket binding APIs), and then I will fire the query at some point, that's when I need to evaluate those code.
I have not figured out other ways to go in my case...
One super simple example is, imagine
(let ([arr (array-alloc 10)])
(array-set! arr 3 4))
I have some model to analyze the constructs (so I am not using racketZ3 directly), during each analyzing point, I will map the data types in the program into the Z3 types, and made some assertions,
I will generate something like:
At allocation site, I will need to make the following formula:
(smt:declare-fun arr_z3 () IntList)
(define len (make-length 10))
Then at the array set site, I will have the following assertions and to check whether the 3 is less then the length
(smt:assert (</s 3 (len arr_z3)))
(smt:check-sat)
Then finally, I will gather the formulas generated as above, and wrap them in the form which is able to fire Z3 binding to run the following gathered information as code:
(smt:with-context
(smt:new-context)
(define len (make-length 10))
(smt:assert (</s 3 (len arr_z3)))
(smt:check-sat))
This is the super simple example I can think of... making sense?
side note. Z3 Racket binding will crash for some reason on version 5.3.1, but it mostly can work on version 5.2.1
Honestly, I don’t understand what exactly you would like to achieve. To quote N. Holm, Sketchy Scheme, 4.5th edition, p. 108: »The major purpose of quasiquotation is the construction of fixed list structures that contain only a few variable parts«. I don’t think that quasiquotation would be used in a context like you are aiming at.
For a typical context of quasiquotation consider the following example:
(define (square x)
(* x x))
(define sentence
'(The square of))
(define (quasiquotes-unquotes-splicing x)
`(,#sentence ,x is ,(square x)))
(quasiquotes-unquotes-splicing 2)
===> (The square of 2 is 4)
Warning: if you're not familiar with how functions work in Scheme, ignore the answer! Macros are an advanced technique, and you need to understand functions first.
It sounds like you're asking about macros. Here's some code that defines test to be a function that prints 2:
(define-syntax-rule (show-one-more-than num)
(begin
(define num2 (add1 num))
(displayln num2)))
(define (test)
(define num1 1)
(show-one-more-than num1))
Now, I could (and should!) have written show-one-more-than as a function instead of a macro (the code will still work if you change define-syntax-rule to define), but macros do in fact operate by producing code at their call sites. So the above code expands to:
(define (test)
(define num1 1)
(begin
(define num2 (add1 num1))
(displayln num2)))
Without knowing the problem better, it's hard to say what the correct approach to this problem is. A brute force approach, such as the following:
#lang racket
(define (make-test-body lst)
(define source `(define (test)
(define num 1)
(define l (list))
,#lst))
source)
(define lst
`((define num2 (add1 num))
(displayln num2)))
(define test-source
(make-test-body lst))
(define test
(parameterize ([current-namespace (make-base-namespace)])
(eval `(let ()
,test-source
test))))
(test)
may be what you want, but probably not.

How do I evaulate a procedure that's returned as a symbol

We are dealing with data representation in my class and we had to represent the integers as diff trees. For my is-zero? class I want to actually evaluate the diff-tree to see if it comes out to 0. However all of my procedures return symbols. I don't know how to make Scheme evaluate the procedures.
diff-tree ::= (one) | (diff diff-tree diff-tree)
(predecessor '(one)) = (diff (one)(one))
So if I have (is-zero? (predecessor '(one))) |note: it has to take it in as a symbol
it will evaluate to (is-zero? '(diff (one)(one)))
how do I get it so that I can actually evaluate the diff as a function?
I already have (define diff -) (define (one) 1) so if I just run (diff (one)(one))
All the other functions, such as predecessor, have to return a symbol.
I'm not very good at explaining but I hope I've done a good enough job for people to understand.
NOTE: I've created another function the recursively runs through the diff tree and evaluates it. It's not as nice as I would have liked it but it will work.
(define evaluate
(lambda (dt)
(if (eqv? (car dt) 'diff)
(- (evaluate (cadr dt))(evaluate (caddr dt)))
1
)))
(define is-zero?
(lambda (dt)
(if (= 0 (evaluate dt))
#t
#f
)))
This is a sketch, No access to a Scheme compiler :).
(define (list-eval l)
(apply (car l) (map list-eval (cdr l))))
(define (is-zero? l)
(= 0 (list-eval l)))
It sure looks to me like the idea of this assignment is for you either to develop an interpreter for diff-trees or (given the "interesting"ness of the specification) to develop functions that perform algebraic manipulations on trees that preserve "meaning."
Assuming that it's all right to just write an interpreter that returns an integer--this is clearly what you have in mind--you need to develop the straightforward (from the appropriate HtDP chapter) "function on a piece of self-referential compound data" (that is, your diff trees). It starts by picking a name and contract for your "interpret" function. Then, how about some test cases?

Resources