Generics
Generics provide a way to create definitions for types and methods that can be parameterized over other types. This improves code reuse, type-safety and performance (e.g. avoid run-time casts). Consider the following example of a generic type that adds a timestamp to any value. However, JavaScript does not have the concept of generics.
class Timestamped {
constructor(value) {
this.Timestamp = new Date();
this.Value = value;
}
}
C does not have built-in support for generics. In C, preprocessor macros or void pointers are typically used to achieve a similar effect.
Here's a simplified example in C that mimics the Rust code using a void pointer to achieve a generic-like behavior:
#include <stdio.h>
#include <time.h>
typedef struct {
void* value;
time_t timestamp;
} Timestamped;
Timestamped new(void* value) {
Timestamped ts;
ts.value = value;
ts.timestamp = time(NULL);
return ts;
}
int main() {
int intValue = 42;
Timestamped intTimestamped = new(&intValue);
char charValue = 'A';
Timestamped charTimestamped = new(&charValue);
return 0;
}
Generic type constraints
JavaScript has no concept of generics, and it is a weakly typed scripting language that makes it impossible to add type constraints to it.
class Timestamped {
constructor(value) {
this.value = value;
this.timestamp = Date.now();
}
equals(other) {
return this.value === other.value && this.timestamp === other.timestamp;
}
}
The same can be achieved in C:
#include <stdio.h>
#include <time.h>
typedef struct {
void* value;
time_t timestamp;
} Timestamped;
Timestamped new(void* value) {
Timestamped ts;
ts.value = value;
ts.timestamp = time(NULL);
return ts;
}
int equal(Timestamped* ts1, Timestamped* ts2) {
return ts1->value == ts2->value && ts1->timestamp == ts2->timestamp;
}
int main() {
void* val = NULL;
Timestamped ts1 = new(val);
Timestamped ts2 = new(val);
if (equal(&ts1, &ts2)) {
printf("Timestamped values are equal.\n");
} else {
printf("Timestamped values are not equal.\n");
}
return 0;
}