I have searched the documentation for Racket (the language; non-typed) and have been unable to decide if it is possible to have optional arguments for a non-mutable struct. I would like to be able to do:
(struct q-a-website (name interest-value #syntax? some-optional-field))
... (q-a-website "stack-overflow" 42 "My name is Jon Skeet") ...
... (q-a-website "quora" -inf.0) ...
In this pseudo-example, #syntax?
is just a placeholder for where I suspect some special syntax might reside to make the following field optional. Is there a way to make your everyday, immutable, run-of-the-mill struct have optional arguments in base Racket?
Clarification: If a struct is created without the optional parameter, it is filled in with a default value that must be supplied at creation time. In this instance, that information would have to be contained inside of the (perhaps poorly named) #syntax?
block.
(Note: I have reservations regarding the inclusion of the struct
tag to this question as it mentions the C family of languages to which Racket does not belong...)
I think the easiest way to do what you want is to create a "constructor" that has an optional argument, like this:
#lang racket
(struct q-a-website (name interest-value optional-field))
;; make a q-a-website
(define (make-q-a-website name interest-value [optional-field #f])
(q-a-website name interest-value optional-field))
;; try making it with and without the optional argument:
(make-q-a-website "stack-overflow" 42 "My name is Jon Skeet")
(make-q-a-website "quora" -inf.0)
Racket also has a full-blown class system, with ... pretty much everything you can imagine. For this use, though, I think I'd just do it like this.
If the default value of the optional field is meaningful, then I'd do what John suggested in his comment -- simply define a custom constructor:
(struct s (a b opt))
(define (make-s a b [opt #f])
(s a b opt))
(make-s "a" "b")
(make-s "a" "b" "opt")
However if the default value of opt
really means N/A, then I might instead define two struct
s: The general case, and the specialized one derived from the special one:
(struct general (a b))
(struct special general (opt))
(define g (general "a" "b"))
(define s (special "a" "b" "opt"))
Code that only knows/cares about general
can treat instances of general
and special
as such:
(general? g) ; #t
(general? s) ; #t
Code that cares specifically about special
can check for that:
(special? g) ; #f
(special? s) ; #t
I would probably only do this for a real "is-a" ("is a kind of") relationship -- if it sounds natural to say that "special
is a kind of general
".
Of course if you're really getting into this kind of OOP territory, you could use racket/class
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With