Write a C preprocessor macro that automates the definition of a simple class with three instance variables of user-specified types. Each variable should be declared "private" with the proper type, there should be a public constructor that takes in values for all three variables and assigns them appropriately, and there should be a getter method for each of the three variables. For example,
DEFCLASS(Person, firstName, std::string, lastName, std::string, age, int)should produce something like the following code:
class Person { private: std::string firstName; std::string lastName; int age; public: Person (std::string firstName_arg, std::string lastName_arg, int age_arg) { firstName = firstName_arg; lastName = lastName_arg; age = age_arg; } std::string get_firstName () { return firstName; } std::string get_lastName () { return lastName; } int get_age () { return age; } };
This problem is motivated by section 16.1.5 of the Racket Macro
Guide, which includes (among other things) definitions of a
get-clock
and put-clock!
function, which share
a hidden variable that nobody else can see.
Define a macro defvar
which takes in
two function names, creates a hidden variable, and defines the two
function names to be a getter and a setter for that variable,
respectively. Since the variable itself is hidden, there is no way to
get at it other than through these getter and setter functions.
For example,
> (defvar get-x set-x!) > (defvar fnord-getter fnord-setter!) > (set-x! "hello") > (get-x) "hello" > (fnord-setter! "glerp") > (set-x! "goodbye") > (get-x) "goodbye" > (fnord-getter) "glerp"
You need this macro to expand into a local definition of a variable
and definitions of a getter and setter function that get at that variable.
But since the getter and setter need to be defined inside the scope of
the variable, which itself should be hidden, you have the problem of how
to get the functions from inside the local
, where they're
defined, to the global scope where you can give them globally-visible
names. There are at least two ways to do this.
One way is the way it's done in section 16.1.5, which uses a Racket
feature you haven't seen called "values". (It has nothing to do with
macros, it just happens to be used in this one.) The values
form allows a function to return not one value, but several at once.
The define-values
form allows you to give names to the
several values thus returned simultaneously.
The other way is to basically simulate values
and
define-values
with lists:
locally define the variable, return a two-element list containing its getter
and setter functions, store the result in a global variable, then define
the desired getter and setter names globally as the first and second
elements of this list respectively. A little more complicated, but
doesn't require learning values
and
define-values
.
Write a Racket macro that provides a "list comprehension" capability similar to what we had in Haskell. (I'm still working out the details of this one myself.) See this paper.