I am writing a function annotate that uses match-lambda often with recursive calls to annotate. Here is one of the patterns and matches:
(`(,<param> . ,<params> (lambda (,<args>) ,<stmt> . ,<stmts>))
`(CLOSURE ENV ,(append (append `(,<param>) `(,<params>))`(,<args>)) (lambda (ENV) ,(map annotate `(,<stmt> . ,<stmts>)))))
I am getting a complaint that the first use of "." is illegal -- between "param" and "params" -- but I can't figure out why. This pattern and match doesn't get any complaints and seems very similar with regards to the first ".":
(`(λ (,<param1> . ,<params>) ,<stmt> . ,<stmts>)
`(CLOSURE ENV ,(map annotate `(,<param1> . ,<params>)) (λ (ENV) ,(map annotate `(,<stmt> . ,<stmts>)))))
Any advice is appreciated.
Thanks.
The . needs to be before the last element in the list (except for some Racket-specific syntax that you are not using). Remember that the general form of a list is (a b c . d), meaning (cons a (cons b (cons c d))). You might be able to use ,#<params> to match some elements in the middle of a list, but I am not sure about that.
Related
Can I create a macro so that I can call sequence- functions with a s-? Hence, I should be able to write s-length, s-filter and s-map instead of sequence-length, sequence-filter and sequence-map. Thanks.
You can use filtered-in from racket/require to perform this sort of transformation. Here’s a simple example:
#lang racket
(require racket/require
(filtered-in (λ (name) (regexp-replace #rx"^sequence-" name "s-"))
racket/sequence))
(s-ref '(1 2 3) 1)
If you find yourself using this sort of thing often, it wouldn’t be too hard to write a require transformer that would expand to filtered-in:
#lang racket
(require (for-syntax racket/require-transform
syntax/parse)
racket/require)
(define-syntax reprefix-in
(make-require-transformer
(syntax-parser
[(_ original-prefix:id new-prefix:id require-spec:expr ...)
#:with replacer (string-append "^" (regexp-quote (symbol->string (syntax-e #'original-prefix))))
#:with replacement (symbol->string (syntax-e #'new-prefix))
(expand-import #'(filtered-in (λ (name) (regexp-replace (regexp 'replacer) name 'replacement))
(combine-in require-spec ...)))])))
Then you can use it like this:
(require (reprefix-in sequence- s- racket/sequence))
(s-ref '(1 2 3) 1)
Yes there is. To versing levels of cludgyness.
The way I highly recommend you do, however, is to use rename-in To rename each of these functions on import. So for example, your code would look like:
#lang racket
(require (rename-in racket/sequence
[sequence-length s-length]
[sequence-map s-map]
[sequence-filter s-filter]
...))
There are other more advanced ways to do this that do not require you to explicitly list out each identifier, using module->exports, regexp-match, format-id, and make-require-transformer. But this seems to brittle to me and you're better off being explicit about which names you want to rename.
I'm working through the Programming Languages: Application and Interpretation book chapter 6 http://cs.brown.edu/courses/cs173/2012/book/From_Substitution_to_Environments.html
I've applied a fix as described in the book but the cons is not adding the type to the empty list refered to in the source.
I think it's a pass-by-value/pass-by-ref thing, any clues on how to set the mt-env when it's not being passed in as a parameter?
#lang plai-typed
;; Binding types
(define-type Binding
[bind (name : symbol) (val : number)])
;; some helper functions:
(define-type-alias Env (listof Binding))
(define mt-env empty)
(define extend-env cons)
;; testing function
(define (addBinding [b : Binding] [env : Env])
(extend-env b env)
)
(addBinding (bind 'x 5) mt-env) ;; returns (list (bind x 5))
(display mt-env) ;; returns empty list
Below is a link to the complete code for context if required, the interp function's appC case is the specific location of my problem area, thanks.
https://github.com/MickDuprez/plai/blob/master/Chapter%206/chapter-6.rkt
After re-reading the last part of this chapter a few times I don't think there is a simple solution to this problem. The 'change' only makes the revised interpreter behave the same as the previous 'substitution' interpreter but highlights the problem of scope with a special test case.
This is eluded to in the next part '6.4 Scope' where the author writes:
"The broken environment interpreter above implements what is known as dynamic scope."
I'm sure this will be addressed in future chapters, thanks for looking anyway.
This time my problem is mostly with Racklog. I guess. Could also be the Racket syntax this time.
The idea is rather simple. I have a logic-base made up of places and objects and I just wanted to try out printing all the objects using the %bag-of primitive.
My logic-base looks like this:
(define %contains
(%rel ()
[('bridge 'phaser)]
[('engine_room 'toolkit)]
[('toolkit 'screwdriver)]
[('toolkit 'tricorder)]
[('inventory '(communicator, no_tea))]
)
)
Now I have my predicate which is the following one. It should be simply called with the query "(%which () (%list_objects 'toolkit))" and then give out all the items inside the toolkit for example.
(define %list_objects
(%rel (place)
[(place)
(%which (objects)
(%let (x)
(%bag-of x (%contains place x)
objects)))]
)
)
The weird thing is when I just thake the part from the "%which (objects)...)" onwards and throw it directly into the listener, it works perfectly fine. But if I'm using it inside the predicate, it throws this exception:
"application: not a procedure;
expected a procedure that can be applied to arguments
given: '((objects screwdriver tricorder))
arguments...: [none]"
I tried rearranging the code several times, but right now I'm quite stumped about what I did wrong. I would appreciate a little hint what I as a total newbee to Scheme and Racket missed out here. My thanks in advance!
The problem is that the goal (%which ...) returns an answer (not a new relation). Therefore %list_objects can't be used in the way you want.
Maybe this works for you?
#lang racket
(require racklog)
(define %contains
(%rel ()
[('bridge 'phaser)]
[('engine_room 'toolkit)]
[('toolkit 'screwdriver)]
[('toolkit 'tricorder)]
[('inventory '(communicator, no_tea))]))
(define %list_objects
(%rel (place)
[(place)
(%let (x) (%contains place x))]))
(%which (x) (%list_objects x))
(%more)
(%which (bag) (%let (x) (%bag-of x (%list_objects x) bag)))
(define tools-in-toolkit (map cdar (%find-all (tool) (%contains 'toolkit tool))))
(define %in-toolkit
(%rel (tool)
[(tool) (%member tool tools-in-toolkit)]))
(%find-all (tool) (%in-toolkit tool))
Output:
'((x . bridge))
'((x . engine_room))
'((bag bridge engine_room toolkit toolkit inventory))
'(((tool . screwdriver)) ((tool . tricorder)))
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))
I am writing a function annotate that uses match-lambda often with recursive calls to annotate. Here is one of the patterns and matches:
(`(,<param> . ,<params> (lambda (,<args>) ,<stmt> . ,<stmts>))
`(CLOSURE ENV ,(append (append `(,<param>) `(,<params>))`(,<args>)) (lambda (ENV) ,(map annotate `(,<stmt> . ,<stmts>)))))
I am getting a complaint that the first use of "." is illegal -- between "param" and "params" -- but I can't figure out why. This pattern and match doesn't get any complaints and seems very similar with regards to the first ".":
(`(λ (,<param1> . ,<params>) ,<stmt> . ,<stmts>)
`(CLOSURE ENV ,(map annotate `(,<param1> . ,<params>)) (λ (ENV) ,(map annotate `(,<stmt> . ,<stmts>)))))
Any advice is appreciated.
Thanks.
The "." is used in Racket and in Scheme to represent "improper lists"; that is, sequences of cons pairs that don't end with "empty". So, for instance,
'(3 4 . 5)
is a shorthand for
(cons 3 (cons 4 5))
The 'dot' is used to mean: "I'm done with the list-like part; here's the final value, use this instead of "empty". For this reason, you can't use the dot just anywhere in the list; it has to be just before a single, final element. In your example, the dot in the pattern precedes a bunch of elements, not just one.
Looking at your example, it looks you want to use the "..." syntax here, e.g.:
(match '(a b c d e)
[`(,x ... d e) 'ok])
(Actually, you can also use dots for infix notation in Racket, but I'm pretty sure that's not what you're trying to do, here.)