wanpeebaw
2020-7-16 14:43:43

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?


soegaard2
2020-7-16 14:49:52

Did you compile the Racket first? Did you benchmark in the terminal?


samth
2020-7-16 15:11:06

That’s almost certainly all startup time


badkins
2020-7-16 15:24:33

I get 0.005 s on my Macbook Pro 16" (for 3,000) using command line racket count.rkt


spdegabrielle
2020-7-16 15:24:59

debugging is on by default in DrRacket


badkins
2020-7-16 15:26:16

“Python” is slower than Racket, but if you spend enough time in C w/in Python, you can get decent performance.


badkins
2020-7-16 15:29:30

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!


wanpeebaw
2020-7-16 16:32:52

I was refering to the output from tio.run website.


wanpeebaw
2020-7-16 17:03:15

samth
2020-7-16 17:03:54

That’s definitely startup time



soegaard2
2020-7-16 17:09:34

@wanpeebaw use racket/base


badkins
2020-7-16 18:16:01

I’m not familiar with tio.run, but if they have to include startup, maybe crank N to 10M or so.


spdegabrielle
2020-7-16 18:33:53

samth
2020-7-16 18:44:47

@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.


samth
2020-7-16 18:45:28

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.


spdegabrielle
2020-7-16 18:50:04

My mistake- I thought that was the meaning of your comment - and the difference in the ’real time’ value seemed to back that up.


samth
2020-7-16 18:50:45

I do recommend testing these sorts of things before filing bugs


spdegabrielle
2020-7-16 18:52:40

Using racket base give a real time of 0.285 vs 0.020 for the python example


samth
2020-7-16 19:00:28

right, racket is just slow to start


spdegabrielle
2020-7-16 19:13:49

I’ll withdraw the issue


spdegabrielle
2020-7-16 19:20:40

10000001


spdegabrielle
2020-7-16 19:24:02

Thank you @samth for actually doing the work:clap:. I’ll take my foot out of my mouth now.


notjack
2020-7-16 19:35:06

This issue really undermines the whole Zen of Python thing in my opinion. “Only one way to do things” my ass.


chansey97
2020-7-16 19:49:17

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?


samth
2020-7-16 19:51:58

Use (lambda (arg) (get-price arg))


chansey97
2020-7-16 19:51:58

I found a solution. (a-high-order-function (thunk (get-price))))


chansey97
2020-7-16 19:52:53

@samth Yes, but it is very very inconvenient.


samth
2020-7-16 19:57:17

That’s because (get-price arg) is really syntactic sugar for (send this get-price arg)


chansey97
2020-7-16 19:57:38

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.


chansey97
2020-7-16 20:01:19

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.


notjack
2020-7-16 20:06:16

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


samth
2020-7-16 20:08:01

Note that “higher order methods” are somewhat tricky — there’s a lot of questions, for example what to do with this


chansey97
2020-7-16 20:08:17

@notjack What is generic interfaces? I’m sorry, I first heard about this feature in Racket. Is there good material about generic interfaces? Thanks.



chansey97
2020-7-16 20:09:14

@samth What is this in a class? Is the this in Racket are the same thing in Java or C#?


notjack
2020-7-16 20:09:33

they let you have OOP-ish interfaces on plain racket structs


notjack
2020-7-16 20:09:58

you get dynamic dispatch without dealing with all the overriding / inheritance stuff of the full racket/class system


notjack
2020-7-16 20:10:32

@chansey97 this in a racket class is roughly similar to this in java / c#, yes


chansey97
2020-7-16 20:11:30

@notjack Can generic interface encapsulate states?


notjack
2020-7-16 20:16:38

yes


chansey97
2020-7-16 20:17:01

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.


notjack
2020-7-16 20:17:03

when you use the generic interface methods, you don’t have to know what the implementation type is


notjack
2020-7-16 20:17:24

the racket/generic system is roughly similar to java interfaces


chansey97
2020-7-16 20:25:43

(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.


notjack
2020-7-16 20:26:27

Yes


samth
2020-7-16 20:26:38

Yes, the fundamental issue for higher-order methods is treatment of this, which is resolved for generics by not having implicit this


chansey97
2020-7-16 20:28:18

But this approach is more functional way… Yes, it maybe support multiple dispatch, but it’s not what I want.:disappointed_relieved:


notjack
2020-7-16 20:29:37

the racket/generic system is single dispatch


chansey97
2020-7-16 20:29:39

notjack
2020-7-16 20:30:05

@chansey97 c# uses the type system to resolve references to this and close over it properly when using methods in a higher-order way


notjack
2020-7-16 20:30:29

compare it to python for a more realistic example of what would be achievable for racket/class


chansey97
2020-7-16 20:30:47

@notjack but c# does not support mixin…


notjack
2020-7-16 20:31:04

?


chansey97
2020-7-16 20:31:40

C# support mixin now?


chansey97
2020-7-16 20:32:07

I have not used C# for many years.


notjack
2020-7-16 20:34:27

I don’t know, but what do mixins have to do with anything?


chansey97
2020-7-16 20:38:35

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>


chansey97
2020-7-16 20:39:00

Just see Chapter 3


notjack
2020-7-16 20:40:32

I understand what mixins are, but I’m not sure what you’re asking about them.


chansey97
2020-7-16 20:42:20

I mean “c# support high-order method, but not support mixin”, “racket support mixin, but not support high-order method” what a pity…


notjack
2020-7-16 20:43:10

Ah, I see what you mean



chansey97
2020-7-16 20:44:37

@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.


chansey97
2020-7-16 20:47:09

If a language does not support higher-order methods, then it means all global variable style code cannot be seamlessly port to object-oriented.


samth
2020-7-16 20:47:19

Fortunately making methods into functions is a small use of a lambda; adding mixins to C# would be harder


chansey97
2020-7-16 20:52:42

@samth I agree with you


popa.bogdanp
2020-7-16 20:57:14

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 (&amp; 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.


samth
2020-7-16 20:59:39

Yes, that’s what Python does



wanpeebaw
2020-7-17 02:21:29

@samdphillips The code was the same. Wrong link?