Skip to content

Instantly share code, notes, and snippets.

@LiberalArtist
Last active May 7, 2020 04:47
Show Gist options
  • Save LiberalArtist/b2ded6f033af2df4368407b2fd6b75bf to your computer and use it in GitHub Desktop.
Save LiberalArtist/b2ded6f033af2df4368407b2fd6b75bf to your computer and use it in GitHub Desktop.
Breaking Cyclic Dependencies with Racket's Units

Breaking Cyclic Dependencies with Racket's Units

This is a responce to a question posted by James Platt to the racket-users email list.

Start with single-file.rkt for an example, then see how the example can be split into multiple files with the entry point main.rkt.

#lang racket/gui
;; See also "single-file.rkt" for the same example
;; in a single file with more comments.
(require "table3-unit.rkt"
"row-edit-menu-unit.rkt"
qresults-list)
;; Invoke the units and introduce the definitions they
;; export into this scope:
(define-values/invoke-unit/infer
(link row-edit-menu@
table3@))
;; Run the demo:
(send table3
setup-column-defs
(let ([column1
(λ (data) (vector-ref data 0))]
[column2
(λ (data) (vector-ref data 1))])
(list (qcolumn "Column1" column1 column1)
(qcolumn "Column2"
(λ (row)
;; allows a cell to be blank
(if (number? (column2 row))
(number->string (column2 row))
""))
column2))))
(send table3 add-row (vector "R1C1" 10))
(send table3 add-row (vector "R2C1" 11))
(send table3 add-row (vector "R3C1" 12))
(send table3 add-row (vector "R4C1" 13))
(send frame3 show #t)
#lang racket/unit
;; See "main.rkt" for an overview.
;; A module in #lang racket/unit implicitly `provide`s
;; a single unit with an inferred name.
;; The module body is like the inside of a `define-unit form`.
;; Note that this module does NOT depend on "table3-unit.rkt"
(require "signatures.rkt"
racket/gui)
(import table3^)
(export row-edit-menu^)
(define row-edit-menu
(new popup-menu%))
(define info-menu-item
(new menu-item%
[label "info"]
[parent row-edit-menu]
[callback
(λ (menu-item event)
(define num-selected
(length (send table3 get-selected-row-indexes)))
(message-box "Info"
(~a "You have selected " num-selected " rows")
#f))]))
#lang racket
;; See "main.rkt" for an overview.
(provide row-edit-menu^
table3^
frame3^)
(define-signature row-edit-menu^
(row-edit-menu))
(define-signature table3^
(table3))
(define-signature frame3^ extends table3^
(frame3))
#lang racket/gui
;; See also "main.rkt" for the same example
;; divided into multiple files.
(require qresults-list)
;; A signatures describes an interface.
(define-signature row-edit-menu^
(row-edit-menu))
(define-signature table3^
(table3))
(define-signature frame3^ extends table3^
(frame3))
;; A unit that exports a signature must
;; implement the definitions it specifies.
;; Units can also import signatures,
;; which allows the body of the unit to
;; refer to definitions from the imported signatures.
;; Before the unit is invoked,
;; it must be linked together with other units
;; that that export the signatures it imports,
;; which will suply the actual implementations.
;; Code in the body of the unit is run when the unit is invoked.
(define-unit row-edit-menu@
(import table3^)
(export row-edit-menu^)
(define row-edit-menu
(new popup-menu%))
(define info-menu-item
(new menu-item%
[label "info"]
[parent row-edit-menu]
[callback
(λ (menu-item event)
(define num-selected
(length (send table3 get-selected-row-indexes)))
(message-box "Info"
(~a "You have selected " num-selected " rows")
#f))])))
(define-unit table3@
(import row-edit-menu^)
(export frame3^)
(init-depend row-edit-menu^)
(define frame3
(new frame%
[label "myTable 3"]
[width 800]
[height 600]))
(define table3
(new (class qresults-list%
(super-new))
[parent frame3]
[pref-tag 'preferences-tag]
[selection-type 'multiple]
[right-click-menu row-edit-menu])))
;; Invoke the units and introduce the definitions they
;; export into this scope:
(define-values/invoke-unit/infer
(link row-edit-menu@
table3@))
;; Run the demo:
(send table3
setup-column-defs
(let ([column1
(λ (data) (vector-ref data 0))]
[column2
(λ (data) (vector-ref data 1))])
(list (qcolumn "Column1" column1 column1)
(qcolumn "Column2"
(λ (row)
;; allows a cell to be blank
(if (number? (column2 row))
(number->string (column2 row))
""))
column2))))
(send table3 add-row (vector "R1C1" 10))
(send table3 add-row (vector "R2C1" 11))
(send table3 add-row (vector "R3C1" 12))
(send table3 add-row (vector "R4C1" 13))
(send frame3 show #t)
#lang racket/unit
;; See "main.rkt" for an overview.
;; A module in #lang racket/unit implicitly `provide`s
;; a single unit with an inferred name.
;; The module body is like the inside of a `define-unit form`.
;; Note that this module does NOT depend on "row-edit-menu-unit.rkt"
(require "signatures.rkt"
qresults-list
racket/gui)
(import row-edit-menu^)
(export frame3^)
(init-depend row-edit-menu^)
(define frame3
(new frame%
[label "myTable 3"]
[width 800]
[height 600]))
(define table3
(new (class qresults-list%
(super-new))
[parent frame3]
[pref-tag 'preferences-tag]
[selection-type 'multiple]
[right-click-menu row-edit-menu]))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment