In terms of performance, there is one thing that surprised me. I thought Python is much slower than Racket. But in this case, Python seems a lot faster than Racket.
Python takes Real time: 0.020 s Racket takes Real time: 0.534 s
Python solution runs 26.7x faster! Any reasonable explanation?
Did you compile the Racket first? Did you benchmark in the terminal?
That’s almost certainly all startup time
I get 0.005 s
on my Macbook Pro 16" (for 3,000) using command line racket count.rkt
debugging is on by default in DrRacket
“Python” is slower than Racket, but if you spend enough time in C w/in Python, you can get decent performance.
It’s one of the things I really dislike about Ruby, Python, etc., that you can sometimes cobble together a big chain of functions that are executing code mostly in C to get good performance, but if you code up something that’s a more natural expression in the language, runtime can be ridiculously high, so there’s a lot of counter-intuitiveness. So, having more of Racket be in Chez Scheme is a plus for me!
I was refering to the output from tio.run website.
That’s definitely startup time
@wanpeebaw use racket/base
I’m not familiar with tio.run, but if they have to include startup, maybe crank N to 10M or so.
Thank you @wanpeebaw - I have reported the bug at https://github.com/TryItOnline/tryitonline/issues/82\|https://github.com/TryItOnline/tryitonline/issues/82
@spdegabrielle why do you think that’s not including startup time for Python? Those times are very much like what I get timing the whole python startup process.
I don’t think there are any bugs here — Racket has relatively slow startup, and if you use #lang racket
instead of #lang racket/base
it’s slower.
My mistake- I thought that was the meaning of your comment - and the difference in the ’real time’ value seemed to back that up.
I do recommend testing these sorts of things before filing bugs
Using racket base give a real time of 0.285 vs 0.020 for the python example
right, racket is just slow to start
I’ll withdraw the issue
10000001
Thank you @samth for actually doing the work:clap:. I’ll take my foot out of my mouth now.
This issue really undermines the whole Zen of Python thing in my opinion. “Only one way to do things” my ass.
Why I can not pass a method as an argument in class? For example: (define my-class-interface (interface () pay))
(define my-class-mixin
(mixin () (my-class-interface)
(init price)
(super-new)
(define current-price price)
(define/public (get-price)
current-price)
(define/public (pay)
(a-high-order-function get-price)) ; <---error
(define/private (a-high-order-function func)
(func))
))
The compiler tell me class: misuse of method (not in application) in: get-price
I read the Racket document, it says: > Within a class, attempting to use a method name in any way other than a method call results in a syntax error. https://docs.racket-lang.org/guide/classes.html#%28part._methods%29
Is there way to work around it?
Use (lambda (arg) (get-price arg))
I found a solution. (a-high-order-function (thunk (get-price))))
@samth Yes, but it is very very inconvenient.
That’s because (get-price arg)
is really syntactic sugar for (send this get-price arg)
But it’s very inconvenient. For example, Suppose I have some code which be written in global way (i.e. using global variable). Now I want use object-oriented approach to re-factory it, i.e. encapsulate global variables to fields in a class. Everything is OK, except all the high-order-methods need eta expansion.
I think this feature should be added to Rhombus. I hope “next version of Racket” can support high-order-methods. I remember C# support this sort of thing.
FWIW, if you use generic interfaces instead of classes, you do get higher order methods - the generic interface methods become ordinary functions that work like any other function does
Note that “higher order methods” are somewhat tricky — there’s a lot of questions, for example what to do with this
@notjack What is generic interfaces? I’m sorry, I first heard about this feature in Racket. Is there good material about generic interfaces? Thanks.
@samth What is this
in a class? Is the this
in Racket are the same thing in Java or C#?
they let you have OOP-ish interfaces on plain racket structs
you get dynamic dispatch without dealing with all the overriding / inheritance stuff of the full racket/class
system
@chansey97 this
in a racket class is roughly similar to this
in java / c#, yes
@notjack Can generic interface encapsulate states?
yes
Thanks, I will look into it. But are there similar equivalents in other languages? I’m sorry, I don’t know what is generic interface, because generic usually means different thing in different context. I use class, because class can encapsulate states (make global to local) and the mixin system is very appealing.
when you use the generic interface methods, you don’t have to know what the implementation type is
the racket/generic
system is roughly similar to java interfaces
(define-struct num (v)
#:methods gen:printable
[(define/generic super-print gen-print)
(define (gen-print n [port (current-output-port)])
(fprintf port "Num: ~a" (num-v n)))
(define (gen-port-print port n)
(super-print n port))
(define (gen-print* n [port (current-output-port)]
#:width w #:height [h 0])
(fprintf port "Num (~ax~a): ~a" w h (num-v n)))])
(define x (make-num 10))
(gen-print x)
This is an example of generic interface. It seems that, when call a method (e.g. gen-print), we must pass a object x
explicitly.
Yes
Yes, the fundamental issue for higher-order methods is treatment of this
, which is resolved for generics by not having implicit this
But this approach is more functional way… Yes, it maybe support multiple dispatch, but it’s not what I want.:disappointed_relieved:
the racket/generic
system is single dispatch
@samth C# support this kind of higher-order methods https://stackoverflow.com/questions/2082615/pass-method-as-parameter-using-c-sharp
@chansey97 c# uses the type system to resolve references to this
and close over it properly when using methods in a higher-order way
compare it to python for a more realistic example of what would be achievable for racket/class
@notjack but c# does not support mixin…
?
C# support mixin now?
I have not used C# for many years.
I don’t know, but what do mixins have to do with anything?
Mixin is very powerful. In Racket, we can compose mixins to generate a class, or just compose mixins to get a new mixin. It can implement multiple inheritance in more natural (correct) way. Detail see <https://cs.brown.edu/~sk/Publications/Papers/Published/fkf-classes-mixins/|Classes and Mixins>
Just see Chapter 3
I understand what mixins are, but I’m not sure what you’re asking about them.
I mean “c# support high-order method, but not support mixin”, “racket support mixin, but not support high-order method” what a pity…
Ah, I see what you mean
@soegaard2 yes, exactly this paper tell me : > Within a class, attempting to use a method name in any way other than a > method call results in a syntax error.
If a language does not support higher-order methods, then it means all global variable style code cannot be seamlessly port to object-oriented.
Fortunately making methods into functions is a small use of a lambda; adding mixins to C# would be harder
@samth I agree with you
I haven’t used racket/class
much, but is it a bad idea to hide the lambda-ification behind a macro like
(define-syntax-rule (& name)
(lambda args
(send this name . args)))
?
It seems like this would be roughly similar to what Python does under the hood when you access a method on an instance of a class.
Yes, that’s what Python does
@samdphillips The code was the same. Wrong link?
Yeah, didn’t realize the site didn’t update the url. https://tio.run/##TZDBDoIwDIbvPMWfeNkOBNCz8UGMh8mKWYQSy@bBl8cxJnjZurbf3/4T0z7Jz4fe8AOSHtXdTDQrS51jgmrHwP4I1gWwJYVsaAmMVF1KWDrZpgi4qg/JeInU2nH75amfKMc/tfJt@kAT1Aui4xlG74h9JTQYx5YkjmlqrTcsD39BuQ7qjGPijLVNXidf@pagfdlFpNg9hNVTN0o1hQHqylGRS4lfQTjVdRMF/vwn2Lsho3qevw