Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optional struct field

Tags:

struct

racket

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

like image 749
BlackVegetable Avatar asked Feb 20 '14 21:02

BlackVegetable


2 Answers

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.

like image 163
John Clements Avatar answered Oct 28 '22 03:10

John Clements


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 structs: 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.

like image 3
Greg Hendershott Avatar answered Oct 28 '22 04:10

Greg Hendershott