Vickenty Fesunov
http://github.com/vickenty/perl-xs
AV* array = get_av("array", 0);
SV** item = av_fetch(array, 0);
SV** item = av_fetch(array, 0);
av_clear(array);
char *buf = SvPV_nolen(*item);
char *buf = SvPV_nolen(*item);
sprintf(buf, "%d", rand());
- uninitialized variables
- sequence points
- integer overflows
- aliasing rules
- data races
SSize_t av_len(AV* array_ptr);
XPUSHs(av_fetch(array, 0))
// but
XPUSHs(sv_2mortal(av_delete(array, 0)))
FILE *f = fopen("output", "w");
fprintf(f, "%d", SvIV(value));
fclose(f);
We must do better.
— Bjarne Stroustrup, 2015
- prevents segfaults
- compatible with c
- can do unsafe code if needed
- safe abstractions
xs! {
package Array::Util;
sub sum_array(ctx, array_ref: SV) {
let mut sum = 0.0;
xs_return!(ctx, sum);
}
}
xs! {
package Array::Util;
sub sum_array(ctx, array_ref: SV) {
let mut sum = 0.0;
let array: AV = array_ref.deref_av();
xs_return!(ctx, 0.0);
}
}
xs! {
package Array::Util;
sub sum_array(ctx, array_ref: SV) {
let mut sum = 0.0;
let array: AV = array_ref.deref_av();
// ERROR: AV expected, but have Option<AV>
xs_return!(ctx, 0.0);
}
}
xs! {
package Array::Util;
sub sum_array(ctx, array_ref: SV) {
let mut sum = 0.0;
let array: AV = array_ref.deref_av().expect("an array reference");
xs_return!(ctx, 0.0);
}
}
xs! {
package Array::Util;
sub sum_array(ctx, array_ref: SV) {
let mut sum = 0.0;
let array: AV = array_ref.deref_av().expect("an array reference");
for index in 0..array.top_index() + 1 {
}
xs_return!(ctx, sum);
}
}
xs! {
package Array::Util;
sub sum_array(ctx, array_ref: SV) {
let mut sum = 0.0;
let array: AV = array_ref.deref_av().expect("an array reference");
for index in 0..array.top_index() + 1 {
sum += array.fetch(index);
}
xs_return!(ctx, sum);
}
}
xs! {
package Array::Util;
sub sum_array(ctx, array_ref: SV) {
let mut sum = 0.0;
let array: AV = array_ref.deref_av().expect("an array reference");
for index in 0..array.top_index() + 1 {
sum += array.fetch(index); // ERROR
}
xs_return!(ctx, sum);
}
}
xs! {
package Array::Util;
sub sum_array(ctx, array_ref: SV) {
let mut sum = 0.0;
let array: AV = array_ref.deref_av().expect("an array reference");
for index in 0..array.top_index() + 1 {
sum += array.fetch(index).unwrap_or(0.0);
}
xs_return!(ctx, sum);
}
}
xs! {
package Array::Util;
sub sum_array(ctx, array: AV) {
let sum
xs_return!(ctx, sum);
}
}
xs! {
package Array::Util;
sub sum_array(ctx, array: AV) {
let sum: NV = array.iter()
xs_return!(ctx, sum);
}
}
xs! {
package Array::Util;
sub sum_array(ctx, array: AV) {
let sum: NV = array.iter()
.map(|v| v.unwrap_or(0.0))
xs_return!(ctx, sum);
}
}
xs! {
package Array::Util;
sub sum_array(ctx, array: AV) {
let sum: NV = array.iter()
.map(|v| v.unwrap_or(0.0))
.sum();
xs_return!(ctx, sum);
}
}
Perl | 1.003s | 100% |
Rust loop | 0.645s | 64% |
Rust iter | 0.637s | 63% |
XS | 0.164s | 16% |
- reference counting
- no hot path inlining
- exception handling
file:xcpt-2.svg
file:xcpt-4.svg
- it works
- it is safer
- it is slower
- Booking.com
- p5pclub
- #rust and the Rust community
xs! {
package Array::Util;
sub sum_array(ctx, array: AV) {
let sum: NV = array.iter()
.map(|v| v.unwrap_or(0.0))
.sum();
xs_return!(ctx, sum);
}
}