probably an easy question: I want to wrap the "(format ..)" function of Scheme in order to handle my debugging output (including the wrapping of the format-string).
As "format" takes a variable number of arguments my wrapper would need to do that too yielding the question on how I tell scheme to have an ellipsis-parameter and how to reference it.
I thought of something like this:
(define debugPrint
(lambda (formatString ELLIPSIS_PARAMETER)
(if debug
(format #t (string-append "<!--" formatString "-->") ELLIPSIS_PARAMETER)
()
)
)
)
Thank You for your help in advance!
There is dot notation for this:
(define (debugPrint formatString . params)
(if debug
(apply format #t (string-append "<!--" formatString "-->") params)
'()))
Take note on apply as dot notation wraps all parameters in list and when you use (debugPrint "~a: ~a" key name), the formatString will be bound to "~a: ~a" and params will be bound to (key name) (sure the values of key and name, not symbols ;).
Related
I'm making a random sentence generator using Scheme (Pretty Big), and I'm having trouble defining temporary variables. I want to make something like this:
<NOUN1> <VERB1> <NOUN2> <but> <NOUN2> <VERB1> <NOUN2> <also>
Example: Sharks eat fish, but fish eat fish also.
I have word lists, and functions to choose a word from said list. Then, I use append to create a function. I am able to do:
(define (sentence)
(append (getNoun) '(and) (getNoun) (getVerb)))
However, I am unable to figure out a way to temporarily define a variable.
I have this so far:
(define (sentence1)
(append (getNoun)
(lambda (verb getVerb)
(noun getNoun))
(verb) (noun) '(but) (noun) (verb) (noun)))
Hints/Help please?
You are looking for let.
http://docs.racket-lang.org/reference/let.html
Here is an example usage:
(define (my-proc age)
(let ([age-plus-10 (+ age 10)])
(printf "age is ~a" age)
(printf "age-plus-10 is ~a" age-plus-10)))
Notice how we can temporarily define age-plus-10 and then use it later.
I will describe my problem on example.
I'll get (play '(left nothing right left)). Some of the names in the list are real procedures, others i want to skip.
(define (left)
'left
)
I need to interpret procedures with names in the list. What is the solution?
When I try ( (car '(left nothing right left))) I get error : procedure application: expected procedure, given: left (no arguments)
(car '(left nothing right left)) evaluates to the symbol left, which is the name of a procedure, but not actually a procedure, so you can't call it.
You'll want to build an association list mapping symbols to procedures:
(define actions `((left . ,(lambda () 'left))
(right . ,(lambda () 'right))
(nothing . ,(lambda () (display "I'm staying put")))))
then you can call the appropriate function for the first element in your list as
((cdr (assoc (car '(left nothing right left)) actions)))
You can also use quasiquoting to construct a list containing a mixture of symbols you want evaluated and others you don't, e.g.
(play `(,left nothing nothing ,right nothing))
left and right will expand to whatever you've defined them as (such as a procedure) while nothing is not un-quoted so it will be left as a symbol. play would then have to test each member to see if it's a procedure, something like:
(define (play xs)(for-each (lambda (x)(if (procedure? x)(x) x)) xs))
(define bootstrap-c-code
(define (from-file file-name)
(let* ((ip (open-input-file file-name))
(res (read-text-file-from-input-port ip)))
(close-input-port ip)
res))
(from-file "llvm.c"))
Error : define: bad syntax (multiple expressions after identifier)
But I can't see anything wrong with it. Can someone explain / fix it please.
It's not clear what you intended with the above code. If you were trying to load a text file and leave the loaded value in a variable called bootstrap-c-code, then try this:
(define bootstrap-c-code
(let ((from-file
(lambda (file-name)
(let* ((ip (open-input-file file-name))
(res (read-text-file-from-input-port ip)))
(close-input-port ip)
res))))
(from-file "llvm.c")))
Of course, the from-file definition will only be visible inside the let, if you need to use it outside, define it outside of the whole expression. If you only need the functionality of from-file inside the let, you can obtain the same result in a much simpler way:
(define bootstrap-c-code
(let* ((ip (open-input-file "llvm.c"))
(res (read-text-file-from-input-port ip)))
(close-input-port ip)
res))
On the other hand, if what you intended was to create a procedure called bootstrap-c-code, then the correct syntax would be:
(define (bootstrap-c-code)
(define (from-file file-name)
(let* ((ip (open-input-file file-name))
(res (read-text-file-from-input-port ip)))
(close-input-port ip)
res))
(from-file "llvm.c"))
According to R5RS, internal definitions can occur only at the beginning of the of a bunch of forms like let, let*, lambda etc. In the case of your code, that is not the case since you have an internal definition inside a non-procedural define. You could fix it by making `bootstrap-c-code' bind to a procedure.
In Exercise 35.4.2 from HtDP, I've implemented the GUI and have a button called "Remove" which invokes a callback function. Here it is:
(define (cb-remove x)
((lambda (name result)
(cond
[(number? result) (remove-name name address-book)]
[else (draw-message msg "Not found")]))
(string->symbol (text-contents label-name))
(lookup (string->symbol (text-contents label-name)) address-book)))
When I run this, I get the following message: button-callback: result of type <Boolean> expected, your function produced #<set!-result>. The problem is that I have to call set! in order to change the address book. However, the result of set! is (void), which cannot cannot be combined with a Boolean type. How can I avert this problem? Thanks for any insight.
Simple:
(begin (set! foo bar) #t)
(defspel game-action (command subj obj place &rest rest)
`(defspel ,command (subject object)
`(cond ((and (eq *location* ',',place)
(eq ',subject ',',subj)
(eq ',object ',',obj)
(have ',',subj))
,#',rest)
(t '(i cant ,',command like that.)))))
Thats the code from http://www.lisperati.com/actions.html for the 'macro defining macro'. I can't seem to convert it appropriately to scheme. Can someone explain to me the process of creating this same sort of thing in Scheme?
This kind of macro is actually much simpler in Scheme, since you can do it all with define-syntax-rule (in standard Scheme code you will need define-syntax + syntax-rules). You basically do the same thing, minus the whole quote/unquote mess.
(defspel (game-action command subj obj place rest ...)
(defspel (command subject object)
(cond [(and (eq? *location* 'place)
(eq? 'subject 'subj)
(eq? 'object 'obj)
(have 'subj))
rest ...]
[else '(i cant command like that.)])))
And since this is actually most of the code, I ported the whole thing to PLT -- see the post on the mailing list.