It’s like a struct that contains a single value. You can pass them by reference. There are a few occurrences of boxes in some old GUI code (although returning values
would have been better in a few cases). I use them extremely rarely.
I can click to drag in order to draw a rectangle, but when i drag the created rectangle (for position adjustment), a new rectangle is created from the said position. How do i constrain/fix the issue? i have been trying to use key-combination to draw a new rectangle on demand. can you please give a hint? #general #dev ``````
any insight ?
Are you sure this code is correct? my-pasteboard
is a class, not an object, so it looks incorrect to send insert
to it.
Also, you never create an object from my-pasteboard
.
no wait
this is not the code
#lang racket/gui
(define (maybe-set-box! b v)
(when b
(set-box! b v)))
(define rect-snip-class%
(class snip-class%
(inherit set-classname)
(super-new)
(set-classname "rect-snip-class%")
))
(define rect-snip-class (new rect-snip-class%))
(define rect-snip%
(class snip%
(inherit set-snipclass
set-flags get-flags
get-admin)
(init w h)
(super-new)
(set-snipclass rect-snip-class)
(define height h)
(define width w)
(define/override (get-extent dc x y [w #f] [h #f] . _)
(maybe-set-box! w width)
(maybe-set-box! h height))
(define/override (draw dc x y left top right bottom . _)
(send dc draw-rectangle x y width height))
))
(define pb
(new
(class pasteboard%
(super-new)
(inherit insert)
(define start-pos #f)
(define/override (on-default-event event)
(super on-default-event event)
(define x (send event get-x))
(define y (send event get-y))
(cond
[(and (equal? (send event get-event-type) 'left-down)
(send event button-down? 'left)
(not (send event dragging?)))
(set! start-pos (cons x y))]
[(and (equal? (send event get-event-type) 'left-up)
start-pos)
(let ([dx (- (car start-pos) x)]
[dy (- (cdr start-pos) y)])
(define-values (nx nw)
(if (> dx 0)
(values x dx)
(values (+ x dx) (abs dx))))
(define-values (ny nh)
(if (> dy 0)
(values y dy)
(values (+ y dy) (abs dy))))
(define sn (new rect-snip%
[w nw]
[h nh]))
(insert sn nx ny)
(set! start-pos #f))]))
)))
(define f-main (new frame% [label "wireframe"]))
(define cnv-main (new editor-canvas%
[editor pb]
[parent f-main]))
(send f-main show #t)
@sorawee please this is the correct code
One easy change is to add:
(define/augment (on-move-to snip x y dragging?)
(when dragging?
(set! start-pos #f)))
That is, whenever an object dragging event occurs, reset the rectangle construction.
should that be under pasteboard
or snip
?
ok, i’ve added it under pasteboard, it’s good
how do i print the number of drawn rectangle snips ?
you have to keep track of them, and also, since you are using a gui in this case, what do you mean by print? to the console or in a msg box?
whichever, console/message-box for debugging purpose in the future
i think console will be ok for the mean time,
override
insert
in the pasteboard%
subclass. have another variable inside that subclass body that is like all-rectangle-snips
and use (set! all-rectangle-snips (cons new-snip all-rectangle-snips))
the compiler signaled an error of a duplicate methods of a similar name: (define pb
(new
(class pasteboard%
(super-new)
(inherit insert) ;; initially defined
(define start-pos #f)
(define/augment (on-move-to snip x y dragging?)
(when dragging?
(set! start-pos #f)))
(define/override (insert all-rectangle-snips) (set! all-rectangle-snips (cons new-snip all-rectangle-snips))) ;;override
(define/override (on-default-event event)
(super on-default-event event)
(define x (send event get-x))
(define y (send event get-y))
(cond
[(and (equal? (send event get-event-type) 'left-down)
(send event button-down? 'left)
(not (send event dragging?)))
(set! start-pos (cons x y))]
[(and (equal? (send event get-event-type) 'left-up)
start-pos)
(let ([dx (- (car start-pos) x)]
[dy (- (cdr start-pos) y)])
(define-values (nx nw)
(if (> dx 0)
(values x dx)
(values (+ x dx) (abs dx))))
(define-values (ny nh)
(if (> dy 0)
(values y dy)
(values (+ y dy) (abs dy))))
(define sn (new rect-snip%
[w nw]
[h nh]))
(insert sn nx ny)
(set! start-pos #f))]))
)))
i removed the (inherit insert) but *(define/override (insert all-rectangle-snips) (set! all-rectangle-snips (cons
new-snip all-rectangle-snips)))
*what should new-snip
hold ? ``````
no you got it wrong, read the signature in the docs for insert
(signature is a fancy terms for the arguments and the return value type the function, in this case method, supports) when i meant new-snip
i meant the argument for insert
that corresponds to the snip being inserted
all-rectangle-snips
should be inside the class
form, not as a part of a method argument or inside a method
this is what i did (define pb
(new
(class pasteboard%
(super-new)
(define start-pos #f)
(define/augment (on-move-to snip x y dragging?)
(when dragging?
(set! start-pos #f)))
(define/override (insert all-rectangle-snips) (set! all-rectangle-snips (cons snip all-rectangle-snips)))
(define/override (on-default-event event)
(super on-default-event event)
(define x (send event get-x))
(define y (send event get-y))
(cond
[(and (equal? (send event get-event-type) 'left-down)
(send event button-down? 'left)
(not (send event dragging?)))
(set! start-pos (cons x y))]
[(and (equal? (send event get-event-type) 'left-up)
start-pos)
(let ([dx (- (car start-pos) x)]
[dy (- (cdr start-pos) y)])
(define-values (nx nw)
(if (> dx 0)
(values x dx)
(values (+ x dx) (abs dx))))
(define-values (ny nh)
(if (> dy 0)
(values y dy)
(values (+ y dy) (abs dy))))
(define sn (new rect-snip%
[w nw]
[h nh]))
(insert sn nx ny)
(set! start-pos #f))]))
)))
like i said, read the docs, see the signature for the insert
method and override
from the signature,insert
is requesting for a snip
` but i can’t locate the snip to pass to it
it’s a callback, when you override a method, you just expect that argument to be passed
no luck, (define/override (insert all-rectangle-snips snip)(set! all-rectangle-snips (cons snip all-rectangle-snips)) )
insert experts 2 args from the compiler, but passing all-rectangle-snips
and snips
doesn’t work out
look here’s a python-ish equivalent of the above code… can you see what’s wrong with it? class _anonymous_class(Pasteboard):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.start_pos = False
def on_move_to(self, snip, x, y, is_dragging):
if is_dragging:
self.start_pos = False
def insert(self, all_rectangle_snips):
all_rectangle_snips = [snip, *all_rectangle_snips]
# because racket discourages mutation, the above is a direct translation to python
# but idiomatic python would use mutation, like
# all_rectangle_snips.append(snip)
def on_default_event(self, event):
super().on_default_event(event)
x = event.x
y = event.y
if event.get_event_type() == 'left-down'\
and event.is_button_down('left') \
and not event.is_dragging:
self.start_pos = (x, y)
elif event.get_event_type() == 'left-up'\
and self.start_pos:
dx = start_pos[0] - x
dy = start_pos[1] - y
nx, nw = (x, dx) if dx > 0 else (x + dx, abs(dx))
ny, nh = (y, dy) if dy > 0 else (y + dy, abs(dy))
sn = rect_snip(w = nw, h = nh)
self.insert(sn, nx, ny)
self.start_pos = False
these are the signatures of https://docs.racket-lang.org/gui/pasteboard_.html?q=ports#%28meth._%28%28%28lib._mred%2Fmain..rkt%29._pasteboard~25%29._insert%29%29\|insert (send a-pasteboard insert snip) → void?
snip : (is-a?/c snip%)
(send a-pasteboard insert snip before x y) → void?
snip : (is-a?/c snip%)
before : (or/c (is-a?/c snip%) #f)
x : real?
y : real?
(send a-pasteboard insert snip x y) → void?
snip : (is-a?/c snip%)
x : real?
y : real?
(send a-pasteboard insert snip before) → void?
snip : (is-a?/c snip%)
before : (or/c (is-a?/c snip%) #f)
snip
is the first argument thus (define all-rectangle-snips '())
(define/override (insert snip . rest)
(super insert snip . rest)
(set! all-rectangle-snips (cons snip all-rectangle-snips)))
yes, i get it but snips
what should it bound to ? i was expecting to pass to rectangle-snip or rectangle-snip-class
because i have to account for all those signatures, but i dont need to check which case it is, so i just pass it to super, and just use the one argument i care and all signatures have in common snip
from the docs you can read, it’s any snip that is inserted, so yes, you should wrap the set!
in a conditional checking is of type rectangle-snip%
i just wanted to print the rectangle object into string,
for debugging purpose,
oh, i wasn’t paying attention to what you posted earlier, sorry
ok no worries, idk how but we ended talking over two threads
the compiler signaled an error of a duplicate methods of a similar name:
i did not notice that question, sorry when overriding dont use inherit
for the method you are overriding, to call in super use (super <method-id> args ... . rest)
is it different from (super new)
?
that is (super-new)
, super-new
“calls” the body of the superclass, (super <id> arg ... . rest)
or (super <id> arg ...)
call the method with name <id>
from the superclass
noted,
from your code, i have added (define/override (insert snip . rest)
(super insert snip . rest)
(set! all-rectangle-snips (cons snip all-rectangle-snips))
(printf "Items ~a: " all-rectangle-snips)
)
it returns a list containing dots into the console: Items (.): Items (. .): >
you are using typed racket?
??
i don’t get it
oh, you are right, i was using DrRacket,
what is your #lang
no, that you are using drracket has nothing to do with it
swithing to emacs i got this:
wireframer.rkt> Items (#(struct:object:rect-snip% ...)): Items (#(struct:object:rect-snip% ...) #(struct:object:rect-snip% ...)):
#lang racket/gui
ah that’s better
Thanks a lot for your push, i covered a huge milestone, i’m now going to implement on the program
good
whish you luck
is there a way i can comprehensively look at the source code of /racket/gui to get more insight ?
you could thoroughly and calmly read through the racket guide and the guide part of racket/gui, because honestly isn’t as tidy to read the source code
@matthew.smith16 has joined the channel
yes, you are right, the source code is even more confusing than the docs :slightly_smiling_face:
https://docs.racket-lang.org/gui/WXME_Decoding.html\|can you please brief me, when can i use https://docs.racket-lang.org/gui/WXME_Decoding.html ?
iirc it’s discouraged to use WXME, you only need it if you are going to serialize to a file the contents of your stuff… and even then you maybe could have an easier way to write and load from a file
like vector editors? (inkscape/coredraw etc…) ?
you mean file formats that could be used with those?
no, the type of contents that could be deserialized and written to a file,
a content of a file is encoded in a file format
what do you mean
what i mean is, the vector editor write the editing pattern of the vector being worked on, history/layer etc… into a file which could be recover later when opened
okay, a file format that encodes history, layers and the curves being worked on
you want to implement that? that sounds hard
no no no :smile:
not today
Boxes are a good solution for including mutation in a statically typed language. They are also easier to understand and explain than set!
mutation. I can’t comment on their efficiency, but if you are coding for yourself or to learn, you might consider using them.
thanks
I have a question about gensym
. (It may be a very silly question.)
In REPL, I can type: > (define test-symbol 'abc)
> (eq? 'abc test-symbol)
#t
That’s OK!
But when I type: > (define test-symbol (gensym 'abc))
> test-symbol
'abc3372
> (eq? 'abc3372 test-symbol)
#f
> (eqv? 'abc3372 test-symbol)
#f
> (equal? 'abc3372 test-symbol)
#f
> test-symbol
'abc3372
>
Why (eq? 'abc3372 test-symbol)
return #f
? :worried: Thanks.
The gensym
procedure returns symbols that are guaranteed to be unique, but they may print the same as other symbols.
The formal term for such a unique symbol is “uninterned”.
In my understanding, gensym
generates a symbol which is different from all the interned symbol. After the symbol generated, it also be interned. Is that right?
> After the symbol generated, it also be interned. No. The symbol that is generated is uninterned
Why Racket would not generate a symbol like a normal (reader’s) symbol, but the name is different from all the already interned symbol?
The document says that > The two procedures string->uninterned-symbol and gensym generate uninterned symbols, i.e., symbols that are not eq?, eqv?, or equal? to any other symbol, although they may print the same as other symbols.
Anyway, it make sense. Thanks.
PS. I found a workaround: > (define test-symbol (string->symbol (symbol->string (gensym 'abc))))
> test-symbol
'abc1172
> (eq? 'abc1172 test-symbol)
#t
I don’t think it works that way
test-symbol
would not be the same symbol as the result of the gensym
call in that case.
When I run the program:
#lang racket
(gensym)
It prints 'g883
.
So I can simply change my program to:
#lang racket
'g883
(gensym)
Then suddenly gensym
creates a “conflicting” symbol if we use your definition of conflict.
What gensym
does is precisely what the doc says. After the symbol->string
and string->symbol
roundtrip, you lose that guarantee.
OK. So the printed name of gensym
is just a random name, it may still conflict if bad luck. It is unique, just because it is uninterned (and like other Racket object).
So when we need a fresh name (e.g. doing some program transformation) and we want to print the result, we should not use gensym
to generate a fresh variable, right? It will conflict if bad luck.
If I do substitute: (λ (x) (x y)) [(y x)/y]
The formal var x
will capture the x
, so we need rename the formal x
.
For example: (substitute '(λ (x) (x y)) '(y x) 'y)
The result should be '(λ (x8152) (x8152 (y x)))
We need rename the formal var x
, but we should not use gensym
.
You can use generate-temporaries
for that, though note that macros in Racket are hygienic already.
Wait, are you talking about macro transformation, or something else?
No, I am not talking about macro transformation. It is just a standard program. E.g. beta-reduce for lambda-calculus
If you have control over the whole tree already, then it should be easy, right?
One stupid scheme is traversing the whole input tree, find the longest identifier, then generate xxxxxxxxx...xxx
with length of the longest identifier plus 1, then for each new symbol you want to generate, you just keep adding x
or something like that.
Yes, it works, but it is not very convenient. If we have some build-in procedure which can generate a new symbol guaranteed to be distinct from all other symbols.
well, afaik it doesn’t exist.
another easy way is limiting the surface syntax so that some set of identifiers are “reserved”
Like, #%1
, #%2
, … are not considered a valid identifier.
Then you can generate these symbols and use them internally.
And also, gensym
works perfectly fine here too. If you use eq[ual]?
as a way to test for equality, and not how they display.
I think for most practical purposes gensym
should get you the uniqueness you need.
If you’re really paranoid about it you could write your own gensym
and seed it with a random number.
> And also, gensym
works perfectly fine here too. @sorawee gensym
does not work perfectly fine here.
Consider the following case (substitute '(λ (x) ((x y) x85500)) '(y x) 'y)
The correct result may be: (λ (x855) ((x855 (y x)) x85500))
But if the substitute
use gensym
to generate a fresh variable for x
, then the printed result could be (λ (x85500) ((x85500 (y x)) x85500))
;<— captured! If bad luck.
> “If you use eq[ual]? as a way to test for equality, and not how they display.”
That’s right.
@samdphillips It just unique for runtime object, not for display.
@chansey97 The likelihood of a user entering a symbol that prints the same as one made by gensym
is very, very low.
Especially if you provide gensym
with a prefix that stands out.
Yes, it works fine in toy program.
Is there a function to get a sub list from a list? Maybe sublist
or sub-list
.
Use take
and drop
.
Thanks for replying. Wonder why there isn’t one function do it all. I thought it’s a very common operation on lists.
The operation seems to be intrinsically index-based, so if it’s common in your application, you are probably using a wrong data structure.