Type and object in Racket

Hello,

what is the best way to define a class and to be able to derive a type associated with it? example : creating a matrix object and having a matrix? predicate to check it type.

i want to create a matrix that will be a vector of vector for example #(#(1 2) #(3 4) #( 5 6))

i find many Racket's modules :array, matrice and the class system and the language typed/racket but i do not know what is the best combination of all those Racket feature to do it. For example Guile has a Guile object system called goops that integrate all the features but instead in Racket i can not find the same level of integration.

Regards,

Damien

It depends on what you want.

The most common way of defining a new datatype is to use a struct.

(struct matrix (m n elements))

This will define a predicate matrix? for you.

However structures aren't objects. If you want to use classes and objects, use
the builtin class system: (require racket/class).

https://docs.racket-lang.org/guide/classes.html

In memory the representation of structures are more compact and you avoid the overhead of method calls. On the other hand, with class you can create subclasses, override methods and much more.

If you only need matrices over real numbers, then I'd stick to structures.

Also, consider using a single vector to hold the elements. In your example the matrix
is #(#(1 2) #(3 4) #( 5 6)). It contains 4 vectors. It's much faster to allocate only one vector in a flat representation.

i find that in structure i have a built-in predicate for type like struct-name?
but i want to be able to have method so class is needed but then with class i have no built-in predicate to test the type of class like class-name?
that is a problem ,perheaps i can create a structure that contains a class... but this is strange.

With an object, you have is-a?.

So you can write:

(define (matrix? x)  
    (is-a? x matrix))
1 Like

merçi , i searched but can not find it in the doc, i will use that.

There is a whole set of "interface utilities" here:

https://docs.racket-lang.org/reference/objectutils.html

3 Likes

cool... the doc is here then.thank you Jens.

In this particular case you might look at flomat or math/matrix, unless reinventing the wheel is the point.

(I've found the actual object system that comes with Racket is rarely used or even really needed. Though it does come in handy once in a while.)

flomat seems perfect for numerical computation on matrix, even if i have vectors of vectors it could be used to create the equivalent matrix.

i talked too fast, i can not find a predicate matrix? or flomat? in flomat and can not install it from catalog in the package manager.

1 Like

i find flomat in sci package. the install is ok now.

Jens i see you are one creator of both flomat ant math/matrix, i search a way to have a predicate matrix? for flomat (like it exists in math/matrix) or be able to initialize matrix in math/matrix with vectors of vectors (like it exists in flomat) ,unfortunately i need those two features and they exists each one in one package but never the two features are in the same library :frowning:

From memory: try flomat?

yes :slight_smile: ,flomat? works ,undocumented indeed (only mentionned as types in function definitions)
thank you

Here:

https://docs.racket-lang.org/manual-flomat/index.html#(def._((lib._flomat%2Fmain..rkt)._flomat))

ok i just understand that the struct always define a default predicate to test its type, sorry i'm not so familiar with Racket ecosystem

2 Likes

That bit me a few times. Mostly the accessors like something-size because it's not obvious that is not an independent function. Perhaps the doc system can be improved to show them.

1 Like

Note that searching flomat? does bring you to the struct definition, and clicking struct in the definition clarifies that it binds <name>?. (I agree: when first learning Racket, this confused me. Now, the terseness is actually more helpful. If added, the accessors and such should be collapsible and collapsed by default.)

2 Likes

it could be good to uniformize the API of flomat and math/matrix, for example i wanted to use build-matrix:
7.3 Construction
to construct a flomat matrix given a procedure but it does not exist, in fact it can be done but it is a bit "tricky" (not sure the english word is relevant here...) i can do the same with define-pointwise-unary .
given a 'uniform' function i add a "dummy" argument (initially the function has no arguments as it returns random number);

; return a number in ]-1,1[
(define (uniform dummy) {(random) * (if {(random 2) = 0} ;; we randomly choose the sign of the random number
		         		  1
			        	  -1)})

and i can create the vector of flomat matrices like that (sorry the syntax is a bit Scheme+) using .uniform! :

{M <+ (vector-ec (: n {lnc - 1}) ; vectors by eager comprehension (SRFI 42)
			  ($>
			    (define-pointwise-unary uniform)
			    (.uniform! (zeros {nc[{n + 1}]} {nc[n] + 1}))))} ;; flomat Matrix

the result displayed:

Welcome to DrRacket, version 8.9 [cs].
Language: reader "../Scheme-PLUS-for-Racket/main/Scheme-PLUS-for-Racket/SRFI/SRFI-105-toplevel.rkt", with debugging; memory limit: 8192 MB.

M=#((flomat: ((0.7543054041209455 0.4965469325617333) (-0.3875771629661438 -0.9874318398967905))) (flomat: ((0.23886416495864896 0.9744680851440323 0.11934183859804237) (0.8789191729890156 0.818771282281826 -0.6626255355836153) (-0.6558813612031107 0.15529903334151 -0.29173454425315964))) (flomat: ((-0.40467338640523715 -0.4125675858962485 0.7910669635846114 -0.39687916975255766) (-0.3748689002759595 -0.28853484895435366 -0.37187524427428165 0.8346232833810251) (-0.10089962975753541 -0.06721836467772253 -0.7026817426452885 0.07562557624888604) (0.0017178627562977964 -0.9395939457313021 0.4977632229064476 -0.6135792314597592))))

it is a vector of flomat.

I think i can find all the stuff in flomat to build my program : now i just need to access and modify elements of flomat matrix , i will integrate the accessor and setters in Scheme+ before.

i needed flomat? to do a bit of functional overload of operator in Scheme+:

(define (multiply-flomat-vector M v)
  (flomat->vector (times M (matrix v))))

(overload * multiply-flomat-vector (flomat? vector?) 'operator)

;; vector overload for concatenation

;; {#(1) + #(2 3 4)}
;; '#(1 2 3 4)
(overload + vector-append (vector? vector?) 'operator)

used here:

 ;; create an array with 1 in front for the bias coefficient
{z_1 <- #(1) + z[i]}

{z̃[{i + 1}] <- M[i] * z_1} ; z̃ = matrix * vector , return a vector

(display "z̃[{i + 1}] = ") (display  {z̃[{i + 1}]}) (newline)

z̃[{i + 1}] = #(-0.4839735172378113 -0.40037108475276867 -0.34185694789193694)

works great :slight_smile: (but i need to rewrite overload with hashtable ,for now it is only usable at top-level or in the main module)