
Ugh that sound frustrating. :frowning: Thank you for pursuing it so doggedly!

The last pair of screenshots is interesting — how it starts midway through the racket
.

Unfortunately. I don’t have any quick theories of the bug. And I’m up to my eyeballs in some other issues atm. But I want to capture your report/research in a GitHub issue so it doesn’t get lost. So I’ll do some copy/paste for now….


Is there a way for a message%
to receive a mouse event? I tried overriding on-subwindow-event
without success. Is it related to the fact that a message%
can’t have the focus, and on-traverse-char
does not forward key events to them? (It seems different to me though)

@badkins What version of Racket are you using?

Does it pass events straight to the underlying container?

A button%
in the same panel does receive clicks (left or right) when overriding the aforementioned method

(but I would like a message%
because there’s not button-like border and I want to customize the behaviour)

I seem to remember something about controls that don’t handle events(unlike button) passing them to the parent object. I’m not sure where in the docs - I could be wrong. And I’m not sure how to determine the position/area of the child message% obj.

Looks like I can cheat, by enclosing the message% into a dedicated panel%, and overriding the event methods works for the latter

It’s weird though

Welcome to Racket v8.2.0.8 [cs].

That is exactly what I did for my app. I used a subclass of horizontal-panel% to handle the events.

I am trying to define a macro that shortens the definition of an generic method:
(define-syntax (const-method stx)
(syntax-parse stx
[(_ method:id)
#:with args
(datum->syntax stx
(for/list [(i (in-range (procedure-arity method))]
(string->symbol (format "arg~a" i)))
#'(define (method args ...) 'constant-value)]))

There are probably other problems with this but the main one is that it doesn’t let me use a pattern variable outside a template

This (procedure-arity method)
should probably be (procedure-arity #'method)
.

But from method:id
we know that method
is an identifier, so (procedure-arity #'method)
doesn’t work, since procedure-arity
expects a function.

right… so how do I get arity of the function corresponding to method
?

I don’t know how generic methods are implemented. But maybe a method definition also stores some information at compile time that can be used?

Is it this type of “generic method” ? https://docs.racket-lang.org/reference/ivaraccess.html#%28form._%28%28lib._racket%2Fprivate%2Fclass-internal..rkt%29._generic%29%29

I was trying to implement this https://docs.racket-lang.org/reference/struct-generics.html but it looks like its the same thing right?

It may be helpful to provide a concrete usage of the macro, and what you think it should expand to.

It’s not the same thing. One is for objects and the second is for structures.
The docs on define-generics
say: Defines the following names, plus any specified by keyword options.
gen:id as a transformer binding for the static information about a new generic interface;
So at compile time, you’ll need to lookup the information in gen:id
. I think the information is stored as one of the structs mentioned at the end in that section of the documentation.

ok lets forget about structs for a minute because I can’t get it to work even for normal functions:
(define-syntax (macro-arity stx)
(syntax-parse stx
[(_ fn:id) #:with args (datum->syntax stx (procedure-arity #'fn))
#'args]))

calling (expand (macro-arity +))
sais #%app: missing procedure expression

What do you want (macro-arity +)
to expand to?

(FWIW, it probably should be (expand #'(macro-arity +))
)

ideally (arity-at-least 0)

Why do you need a macro for that? Can’t you just use procedure-arity
?

I need to use that information to build the expansion of another macro

in particular I want to build a function that has the same arity as the one provided

I see. IIUC, this is not possible with procedure-arity
. The information is only available at run-time.

What you can do is, you can create your own variant of define
that records its arity at compile-time, and then extract it later.

ok, I can live with that. What would be the RightWay of recording compile time information?

Also, side-question, how could you tell that procedure-arity
doesn’t read compile-time information?

it is sligtly surprising to me that the arity is not known at compile time since the racket compiler should be able to produce efficient code based on that information..

Something like this:
#lang racket
(require syntax/parse/define)
(begin-for-syntax
(struct fun-info (arity proc)
#:property prop:procedure
(λ (si stx)
(syntax-parse stx
[x:id (fun-info-proc si)]
[(_ args ...)
#:with p (fun-info-proc si)
#'(p args ...)]))))
(define-syntax-parse-rule (fun name (xs ...) body ...+)
#:with arity (length (attribute xs))
(begin
(define (the-function xs ...) body ...)
(define-syntax name (fun-info 'arity #'the-function))))
(define-syntax (find-arity stx)
(syntax-parse stx
[(_ x:id)
(printf "~a has arity ~a\n"
(syntax->datum #'x)
(fun-info-arity (syntax-local-value #'x)))
#'(void)]))
(fun test (a b)
(+ a b))
(test 1 2)
(define f test)
(f 5 6)
(find-arity test)

IIUC, the arity is inferred later in the Chez Scheme level. But it’s not known at the macro expansion level

thanks very much for putting in the time!

At compile time, what should the compiler do when it sees: (define f (if (random 1) list cons)

The point is that the value of which you would like to know the arity hasn’t been computed yet. That’s why the arity is known at runtime and not at compile time.

Sometimes the compiler might have a chance, but not in general.

good point

in my case I would like the macro to fail when something like that happens

Dybvig and others have a series of papers on “flow analysis” which has the goal of determining that type of information at compile time. It’s not as easy as it looks at first sight.

I am realising that…

I think, sorawee’s suggestion is the best practical solution.

Unless … define/generics
saves the same information somewhere.