#lang swindle
(require swindle/misc
swindle/setf
)
(defclass* jacket ()
(size :initvalue 40 :accessor sj)
:printer #t)
(defclass* trousers ()
(size :initvalue 44 :accessor st)
:printer #t)
(defclass* suit (jacket trousers)
If i compile this code and write (make suit) | (make jacket) | make (trousers) into the interpreter, the return is always #<procedure:swindleobj> but it should be sth like #<jacket size=40>.
Did I miss any requires or what am I doing wrong?
Your code is working for me:
#lang swindle
(defclass* jacket () (size :initvalue 40 :accessor sj) :printer #t)
(define x (make jacket))
(displayln x)
=> #<jacket: size=40>
(displayln (slot-ref x 'size))
=> 40
(displayln (sj x))
=> 40
Related
I'm trying to level up on metaprogramming in Racket and realized I don't know how to take a datum and simply "eval" it.
If I have
(for ((x '(("Five" (+ 2 3))
("Twelve" (* 6 2))
("Three" (- (/ 21 3) 4)))))
(displayln (format "~s: ~s" (first x) (second x))))
I get
: "Five": (+ 2 3)
: "Twelve": (* 6 2)
: "Three": (- (/ 21 3) 4)
Which is not actually what I want - I want to actually evaluate that list to get the answer.
I'm sure this is simple (perhaps something I need to involve syntax for?) but I'm just missing the picture now. How do I do that?
Edit:
I want to evaluate the s-exp just before displaying, not in the initial list. This is why I figure I might need syntax since I would (I think) have to inject the current syntax context.
Eval is almost always the wrong choice, but eval is what you are looking for:
#lang racket
(define base-ns (make-base-namespace))
(for ((x '(("Five" (+ 2 3))
("Twelve" (* 6 2))
("Three" (- (/ 21 3) 4)))))
(displayln (format "~s: ~s" (first x) (eval (second x) base-ns))))
Alternative 1: Lambda / thunks
(for ((x `(("Five" ,(thunk (+ 2 3)))
("Twelve" ,(thunk (* 6 2)))
("Three" ,(thunk (- (/ 21 3) 4))))))
;; notice double parentheses to call the thunk
(displayln (format "~s: ~s" (first x) ((second x)))))
A thunk is just syntax sugar for a lambda with no arguments.
I've played a little around having procedures that can print their sources. Thus you can make your own thunk that has the original structure as structure as I demonstrate with my visual lambda:
(struct proc (src obj)
#:property prop:procedure (struct-field-index obj)
#:transparent
#:methods gen:custom-write
[(define (write-proc x port mode)
((case mode
[(#t) write]
[(#f) display]
[else pretty-print])
(proc-src x)
port))])
(define-syntax lambda*
(syntax-rules ()
((_ . rest)
(proc '(lambda* . rest) (lambda . rest)))))
(define test (lambda* (x y) (+ x y)))
test ; ==> #(struct:closure (lambda* (x y) (+ x y)) #<procedure>)
(proc-src test) ; ==> (lambda* (x y) (+ x y))
(proc-obj test) ; ==> #<procedure>
((proc-obj test) 1 2) ; ==> 3
(test 1 2) ; ==> 3
(display test) ; prints (lambda* (x y) (+ x y))
Use backquote together with unquote which is
;; backquote: `
;; unquote: ,
;; there is also splice list: ,#
(for ((x `(("Five" ,(+ 2 3))
("Twelve" ,(* 6 2))
("Three" ,(- (/ 21 3) 4)))))
(displayln (format "~s: ~s" (first x) (second x))))
;; "Five": 5
;; "Twelve": 12
;; "Three": 3
How can I test whether a syntax pattern parameter is an empty list? I am testing in guile.
(define-syntax mkl
(lambda (x)
(syntax-case x ()
[(_ var params code)
(if (null? (syntax->datum #'params)); doesn't match anyway !!!???
#'(lambda (var) code)
#'(lambda (var) (cons 1 code)))])))
;;; try: expecting: (100 200) but got: (1 100 200)
(display
((mkl s '() s) '(100 200)))
(newline)
However, if I test against a number, it works:
(define-syntax mkl2
(lambda (x)
(syntax-case x ()
[(_ var params code)
(if (= (syntax->datum #'params) 0); matches OK
#'(lambda (var) code)
#'(lambda (var) (cons 1 code)))])))
;;; try: expecting: (100 200) and it works OK
(display
((mkl2 s 0 s) '(100 200)))
(newline)
It appears that there's an extra quotation in there. In the macro, you should perform the check like this:
(if (null? (cadr (syntax->datum #'params))) ; access the actual list
Or as a workaround, you could call the macro like this:
((mkl s () s) '(100 200)) ; quote was removed
I am fairly new to Scheme, and I have been struggling with what I think should be a simple problem.
I am trying to convert something like
((qty 30) (name "ham")) to (sandwich "#qty" 30) (sandwich "#name" "ham")
Also, this must be dynamic to allow for extra clauses:
((qty 30) (name "ham") (cheese 'no))
Here is what I have so far:
(define-syntax (make-sandwiches x)
(syntax-case x ()
[(_ ((col val)...) ) #``(sandwich #,(format "#,~a" (caar #'((col val)...))) #,(cadar #'((col val)...)))]
[(_) "make-sandwiches is bad"]))
(make-sandwiches ((qty 30) (name "ham"))) => (param "##(syntax qty)" 30)
So this is kinda close, but it only translates the first clause, so my idea is using map or something similar, but I'm not sure if that is correct either:
(define-syntax (make-sandwiches x)
(syntax-case x ()
[(_ ((col val)...)) (map (lambda (cv) #``(sandwich #,(format "#,~a" (caar cv)) #,(cadar cv))) #'((col val)...))]
[(_) "make-sandwiches is bad"]))
Do you really have to use a macro? and return multiple values? a humble procedure that returns a list will do the trick:
(define (make-sandwiches lst)
(map (lambda (data)
(list 'sandwich
(string-append "#" (symbol->string (car data)))
(cadr data)))
lst))
Or a bit shorter (you seem to be using Racket):
(define (make-sandwiches lst)
(map (lambda (data) `(sandwich ,(format "#~a" (first data)) ,(second data)))
lst))
For example, using the sample input in the question:
(make-sandwiches '((qty 30) (name "ham") (cheese 'no)))
=> '((sandwich "#qty" 30) (sandwich "#name" "ham") (sandwich "#cheese" 'no))
for example I have this game:
This game does is move a bird on keyboard or mouse
(define-struct estado (ANCHO ALTO vel tiempo mov punto))
(define mapa (bitmap "mapa.png"))
(define Projo (bitmap "Projo.png"))
(define mario (bitmap "mario.png"))
(define (crear-mundo estado)
(big-bang estado
[to-draw pintar]
[on-tick tiempo-nuevo]
[on-mouse click]
[on-key cambiar-al-nuevo-mundo-teclado]
[stop-when fin-juego]))
(define (pintar nuevo-mundo)
(cond
[(colisiĆ³n nuevo-mundo area)
(place-image Projo
(posn-x (estado-punto nuevo-mundo))
(posn-y (estado-punto nuevo-mundo))
(place-image (text (string-append "Tiempo: " (number->string (quotient (estado-tiempo nuevo-mundo) 28))) 12 "red") 40 20 mapa)
)]
[else (place-image Projo
(posn-x (estado-punto nuevo-mundo))
(posn-y (estado-punto nuevo-mundo))
;(place-image mario 750 500 (empty-scene 800 600))
;(place-image mario 750 500 mapa)
(place-image (text (string-append "Tiempo: " (number->string (quotient (estado-tiempo nuevo-mundo) 28))) 12 "green") 40 20 mapa)
)]
)
)
create the new state of the game where make-posn is the position of the bird
(crear-mundo (make-estado 800 600 10 0 0 (make-posn 100 100)))
How I can save the state of play with the position of the bird when the game is run and what position changes
The simplest would be to just use standard write and read:
#!racket
(define file "file.rc")
(define (save config)
(with-output-to-file file
(lambda () (write config))
#:mode 'text
#:exists 'truncate)
config)
(define (read)
(with-input-from-file file
(lambda () (read))))
So imagine you have a loop somewhere where you pass the new state to the next iteration. Just wrapping it in (save state) will save a new file over the last. (read) will read that file, perhaps when you start up.
You might need to check if it exists but this is basically what you need to read/store state.
In general I want write code in REPL and sometimes save all defined by myself symbols to file.
For example - after typing in REPL:
]=> (define (square x) (* x x))
]=> (define sizes '(5 10 15))
I need to call something to receive a list of previously defined objects.
In this case it can be represented in this way:
]=> (define get-user-defined-environment
(list (list 'sizes sizes) (list 'square square)))
To be able then call something like this:
]=> (map
(lambda (lst) (begin
(display "(define ")
(pp (first lst))
(pp (second lst))
(display ")\n\n")))
get-user-defined-environment)
(define sizes
(5 10 15)
)
(define square
(named-lambda (square x)
(* x x))
)
And, maybe, save output to file somehow.
So, what could be this get-user-defined-environment ?
There isn't something in standard Scheme that lets you record the environment. You can however define your own define-like syntax that does it for you.
> (define *env* '())
> (define-syntax def&rec
(syntax-rules ()
((_ name init)
(define name
(let ((value init))
(set! *env* (cons (cons 'name value) *env*))
value)))))
> (def&rec foo 1)
> (def&rec bar (lambda (x) x))
> *env*
((bar . #<procedure value>) (foo . 1))
If you intend to write this to a file, like with the expectation of reading it back in, you will want to record the init form, not value in the syntax above. Here is another syntactic form to record the init:
> (define-syntax def&rec2
(syntax-rules ()
((_ name init)
(define name
(let ((value init))
(set! *env* (cons (list 'name value 'init) *env*))
value)))))
> (def&rec2 equal-to (lambda (x) (lambda (y) (equal? x y))))
> *env*
((equal-to #<procedure value>
(lambda (x) (lambda (y) (equal? x y))))
(bar . #<procedure value>) (foo . 1))
Thanks to uselpa pointed to How can find all functions and bounded symbols in an "environment"
(environment-bound-names (the-environment)) - returns a list of user-defined names.
Then (environment-lookup (the-environment) name) - returns value of a name in current environment.
Here is the way:
]=> (define (p1 name env) (begin (display "(define ") (pp name) (pp (environment-lookup env name)) (display ")\n\n")))
]=> (define (p2 lst env) (for-each (lambda (name) (p1 name env)) lst))
]=> (p2 (reverse (environment-bound-names (the-environment))) (the-environment))
(define p1
(named-lambda (p1 name env)
(display "(define ")
(pp name)
(pp (environment-lookup env name))
(display ")\n\n"))
)
(define p2
(named-lambda (p2 lst env)
(for-each (lambda (name) (p1 name env)) lst))
)