The Style Guide is a good place to start for learning Racket
conventions: http://docs.racket-lang.org/style/index.html

Overall, things look good! Your code already uses many Racket idioms.

Some things that caught my attention on first glance:

- The code is wider than typical. Though tastes differ, most Racket
code tries to stay within 80 or 102 columns.

- Use square brackets in certain places to aid readability. For
example, around cond and match clauses and let binding clauses. You
already do this somewhat, so just use it more consistently.

- unless/when already return void, so an explicit subsequent (void) is
unnecessary.

- To reduce code verbosity, utilize pattern matching (more than you
already do), particularly to destructure structs. For example, instead
of:

;; from clockwise-turn?
  (let* ((ax (node-x a))
         (ay (node-y a))
         (bx (node-x b))
         (by (node-y b))
         (cx (node-x c))
         (cy (node-y c)))
    (not (positive? (- (* (- bx ax) (- cy ay)) (* (- cx ax) (- by ay))))))

write:

  (match* (a b c)
    [((node ax ay) (node bx by) (node cx cy))
     (not (positive? (- (* (- bx ax) (- cy ay)) (* (- cx ax) (- by ay)))))]))

- Avoid manually traversing lists. Use "for" list comprehensions
instead of let loops. For example, instead of:

;; from highlight-paths
(let loop : Void
    ([x : (Listof path) (filter path? lst)])
    (cond ((empty? x) (void))
          (else (when (any-entity-highlighted? (path-entities (car x)))
                              (map (lambda ([i : Entity])
(set-entity-highlighted! i #t)) (path-entities (car x))))
                (loop (cdr x)))))

write:

  (for ([p : path (filter path? lst)]
        #:when (any-entity-highlighted? (path-entities p)))
    (for ([i : Entity (path-entities p)]) (set-entity-highlighted! i #t)))


I didnt see anything blatant that should be converted to macros. In
general, you should prefer functions to macros, and I think your code
is organized well in general. That being said, you may want to look
into match expanders:

For example:

(define-match-expander line-pat
  (syntax-rules () [(_ pat1 pat2) (struct* line ([p1 pat1][p2 pat2]))]))

would allow you to write:

               (match i
                 [(line-pat p1 p2) (list (node-x p1) (node-x p2))] ...)

instead of:
;; from canvas-utils.rkt
               (match i
                 [(struct* line  ([p1 p1] [p2 p2])) (list (node-x p1)
(node-x p2))] ..)

And then you could nest a pattern more easily. For example, instead of:

;; from canvas-utils.rkt
  (let ((lx1 (node-x (line-p1 line-struct)))
        (ly1 (node-y (line-p1 line-struct)))
        (lx2 (node-x (line-p2 line-struct)))
        (ly2 (node-y( line-p2 line-struct)))) ...)

you could write:

  (match line-struct
    [(line-pat (node lx1 ly1) (node lx2 ly2)) ...])

Functionality-wise, I tried to open "disk_cover R14.dxf" but got the
following error:

hash-ref: no value found for key
  key: "8"

I was able to open "disk_cover R2004-2006.dxf". It did lag somewhat
when I tried to drag it but I'm not sure if this is due to some parts
of the code or the large image itself. Maybe some others who have more
experience writing gui apps will comment.

On Wed, Jul 8, 2015 at 6:17 AM, copycat <kangren.c...@gmail.com> wrote:
> Hello all,
>
>   feedback is most appreciated. I had a lot of fun writing this small program 
> (see bottom for details and repository link), and i want to improve my skills 
> so i can write idiomatic Scheme/Racket code one day. Particularly helpful 
> would be suggestions as to where i can use macros to reduce the amount of 
> code the program has. There is also some seriously verbose stuff in 
> "lst-utils.rkt" (find-entity-with-starting-node, find-entities-from-node ...) 
> that i'm not sure how to refactor at the moment now.
>
>   Also, I am a new programmer and have only seriously programmed in VB.NET 
> and Racket and am thinking about building on this program to develop a GUI 
> for a gantry robot teaching interface. But i am worried about any roadblocks 
> that i may encounter on the way in using Racket. Please help me clear my 
> doubts.
>
> ------------------------------------------------------------------------
>
> WARNING: bottom is a long description which is as much for me as it for you. 
> Skip to the below for a TL;DR.
>
>   The first part of the GUI will be displaying a large image of a printed 
> circuit board (PCB) consisting of stitched high-resolution images taken with 
> an area-scan camera. The idea is to let the user "draw" on this background 
> image the order of movements (commands) of the gantry robot. More detailed 
> control of the robot movements has to be specified in a spreadsheet/display 
> list of some sort. There will also be some commands involving machine vision 
> for checking position markers (fiducials), and various sort of vision 
> inspections. These commands are then saved as a "program" to be executed in 
> the second part of the GUI.
>
>  Those are the very basics, more fancy features that i can think of might 
> include identifying components on the PCB, so as to facilitate easier 
> teaching of motion commands, recognizing the PCB image so as to "snap" 
> preloaded DXF/CAD files on top of it.
>
>   The second part of the GUI will be the production run of the machine. The 
> start-up involves downloading the program instructions to the motion 
> controller that will read and execute the movements. The interface for 
> communication may be an ActiveX interface or an C API depending on the choice 
> of motion controller. Processes running during production run are:
>
> 1) statistical process control (SPC) logging
> 2) displaying the real-time camera
> 3) waiting on images of fiducials; on receiving it will process it and send 
> the compensation values to the motion controller. This has to be done quickly 
> as the motion controller will change its movement "on the fly", so if the 
> compensation values are received late, it is possible the new position is 
> behind the gantry and force it to "backtrack", which will do bad things to 
> machine cycle times.
>
>   It is also possible that the fiducial processing will be done in a smart 
> camera instead of having to be done on the host environment.
>
> TL;DR:
> My biggest worry is about Racket performance or unexpected bugs when 
> interfacing C libraries that come with the hardware with Racket code. Reading 
> things like "FFI overhead" in the mailing list scares me a little also. I'm 
> also a little fuzzy on the performance/details of implementing a canvas 
> showing a giant high resolution image.
>
> My understanding that Racket should be fine as a high level prototyping 
> language and where performance is needed, we can drop down to C. And the 
> biggest performance bottleneck in the whole application is the image 
> processing speed in the library, which will come down to the image processing 
> libraries. Is there anything i might have overlooked?
>
> ------------------------------------------------------------------------
>
> Current program functionality:
>
>  You drag dxf files in the DXF folder into the main window and interact with 
> the 2d drawing as follows:
>
> ctrl drag to select elements
> esc to unselect elements
> click and drag to pan about
> scroll up and down to zoom in/out
>
> most other features are data processing stuff and not that interesting.
>
> https://github.com/xtrntr/DXF-Converter/tree/one-main-window
>
> --
> You received this message because you are subscribed to the Google Groups 
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to racket-users+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to