超出范围的索引 returns 来自在 chibi 方案中创建的矢量的正确值
Out of bounds index returns correct values from vector created in chibi scheme
我已将 chibi 方案嵌入到我的 C++ 应用程序中,并尝试在方案中创建一个大小为 3 的浮点向量,然后将该向量的各个值返回到我的 C++ 程序中,但是当我尝试为此,如果我使用超出向量大小的索引,我只会得到正确的结果。正如您在下面看到的,我验证了向量的大小。
test.scm
(define (test-vec in-a in-b)
(let ((vec (vector (* 3.1 in-a) (* 4.1 in-b) 5.0)))
(display "From Scheme: ")
(display vec)
(display "\n")
vec))
test.cpp
#include <iostream>
#include <chibi/eval.h>
int is_defined(sexp ctx, const char *sym)
{
sexp_gc_var1(ret);
sexp_gc_preserve1(ctx, ret);
ret = sexp_eval_string(ctx, sym, -1, NULL);
int defined = sexp_procedurep(ret);
sexp_gc_release1(ctx);
return defined;
}
int main()
{
float returnA, returnB, returnC, returnD, returnE, returnF;
sexp_scheme_init();
sexp ctx = sexp_make_eval_context(NULL, NULL, NULL, 0, 0);
sexp_load_standard_env(ctx, NULL, SEXP_SEVEN);
sexp_load_standard_ports(ctx, NULL, stdin, stdout, stderr, 1);
// Load the scheme file and create temp variables to pass the values to chibi
sexp_gc_var6(inAVal, inASym, inBVal, inBSym, returnedVector, filePath);
sexp_gc_preserve6(ctx, inAVal, inASym, inBVal, inBSym, returnedVector, filePath);
filePath = sexp_c_string(ctx, "test.scm", -1);
sexp_load(ctx, filePath, NULL);
// Ensure our procedure is defined
if(is_defined(ctx, "test-vec"))
std::cout << "test-vec is defined" << std::endl;
// Create the values and create the symbols
inAVal = sexp_make_flonum(ctx, 1.0);
inASym = sexp_intern(ctx, "a", -1);
inBVal = sexp_make_flonum(ctx, 2.0);
inBSym = sexp_intern(ctx, "b", -1);
// Bind the values to the symbols and pass them to chibi
sexp_env_define(ctx, sexp_context_env(ctx), inASym, inAVal);
sexp_env_define(ctx, sexp_context_env(ctx), inBSym, inBVal);
// Evaluate the expression and store the result
returnedVector = sexp_eval_string(ctx, "(test-vec a b)", -1, NULL);
std::cout << "Vector size: " << sexp_vector_length(returnedVector) << std::endl;
// I would expect this to return the expected results?
returnA = sexp_flonum_value(sexp_vector_ref(returnedVector, 0));
returnB = sexp_flonum_value(sexp_vector_ref(returnedVector, 1));
returnC = sexp_flonum_value(sexp_vector_ref(returnedVector, 2));
std::cout << "Vector[0] = " << returnA << "\nVector[1] = " << returnB << "\nVector[2] = " << returnC << std::endl << std::endl;
// If I index outside of the range of the vector, it gives me the correct results?
returnD = sexp_flonum_value(sexp_vector_ref(returnedVector, 0));
returnE = sexp_flonum_value(sexp_vector_ref(returnedVector, 3));
returnF = sexp_flonum_value(sexp_vector_ref(returnedVector, 4));
std::cout << "Vector[0] = " << returnD << "\nVector[3] = " << returnE << "\nVector[4] = " << returnF << std::endl;
sexp_gc_release6(ctx);
}
这给了我输出:
test-vec is defined
From Scheme: #(3.1 8.2 5.0)
Vector size: 3
Vector[0] = 3.1
Vector[1] = 3.1
Vector[2] = 8.2
Vector[0] = 3.1
Vector[3] = 8.2
Vector[4] = 5
为什么超出向量长度的索引会给我正确的值?
解决了问题。这是因为 sexp_vector_ref(vec, i)
的计算结果为
#define sexp_vector_ref(x,i) (sexp_vector_data(x)[sexp_unbox_fixnum(i)])
和 sexp_unbox_fixnum(i)
的计算结果为
#define sexp_unbox_fixnum(n) (((sexp_sint_t)((sexp_uint_t)(n) & ~SEXP_FIXNUM_TAG))/(sexp_sint_t)((sexp_sint_t)1<<SEXP_FIXNUM_BITS))
当我们只传递整数时
std::cout << "Unboxed fixnums: " <<
sexp_unbox_fixnum(0) << " " <<
sexp_unbox_fixnum(1) << " " <<
sexp_unbox_fixnum(2) << " " <<
sexp_unbox_fixnum(3) << " " <<
sexp_unbox_fixnum(4) << std::endl;
给我们输出
Unboxed fixnums: 0 0 1 1 2
但是如果我们首先将它们转换成 chibi 期望的正确类型,就像这样
std::cout << "Fixnum: " <<
sexp_unbox_fixnum(sexp_make_fixnum(0)) << " " <<
sexp_unbox_fixnum(sexp_make_fixnum(1)) << " " <<
sexp_unbox_fixnum(sexp_make_fixnum(2)) << " " <<
sexp_unbox_fixnum(sexp_make_fixnum(3)) << " " <<
sexp_unbox_fixnum(sexp_make_fixnum(4)) << std::endl;
我们得到正确的输出
Fixnum: 0 1 2 3 4
解决方法:索引时使用正确的类型
我已将 chibi 方案嵌入到我的 C++ 应用程序中,并尝试在方案中创建一个大小为 3 的浮点向量,然后将该向量的各个值返回到我的 C++ 程序中,但是当我尝试为此,如果我使用超出向量大小的索引,我只会得到正确的结果。正如您在下面看到的,我验证了向量的大小。
test.scm
(define (test-vec in-a in-b)
(let ((vec (vector (* 3.1 in-a) (* 4.1 in-b) 5.0)))
(display "From Scheme: ")
(display vec)
(display "\n")
vec))
test.cpp
#include <iostream>
#include <chibi/eval.h>
int is_defined(sexp ctx, const char *sym)
{
sexp_gc_var1(ret);
sexp_gc_preserve1(ctx, ret);
ret = sexp_eval_string(ctx, sym, -1, NULL);
int defined = sexp_procedurep(ret);
sexp_gc_release1(ctx);
return defined;
}
int main()
{
float returnA, returnB, returnC, returnD, returnE, returnF;
sexp_scheme_init();
sexp ctx = sexp_make_eval_context(NULL, NULL, NULL, 0, 0);
sexp_load_standard_env(ctx, NULL, SEXP_SEVEN);
sexp_load_standard_ports(ctx, NULL, stdin, stdout, stderr, 1);
// Load the scheme file and create temp variables to pass the values to chibi
sexp_gc_var6(inAVal, inASym, inBVal, inBSym, returnedVector, filePath);
sexp_gc_preserve6(ctx, inAVal, inASym, inBVal, inBSym, returnedVector, filePath);
filePath = sexp_c_string(ctx, "test.scm", -1);
sexp_load(ctx, filePath, NULL);
// Ensure our procedure is defined
if(is_defined(ctx, "test-vec"))
std::cout << "test-vec is defined" << std::endl;
// Create the values and create the symbols
inAVal = sexp_make_flonum(ctx, 1.0);
inASym = sexp_intern(ctx, "a", -1);
inBVal = sexp_make_flonum(ctx, 2.0);
inBSym = sexp_intern(ctx, "b", -1);
// Bind the values to the symbols and pass them to chibi
sexp_env_define(ctx, sexp_context_env(ctx), inASym, inAVal);
sexp_env_define(ctx, sexp_context_env(ctx), inBSym, inBVal);
// Evaluate the expression and store the result
returnedVector = sexp_eval_string(ctx, "(test-vec a b)", -1, NULL);
std::cout << "Vector size: " << sexp_vector_length(returnedVector) << std::endl;
// I would expect this to return the expected results?
returnA = sexp_flonum_value(sexp_vector_ref(returnedVector, 0));
returnB = sexp_flonum_value(sexp_vector_ref(returnedVector, 1));
returnC = sexp_flonum_value(sexp_vector_ref(returnedVector, 2));
std::cout << "Vector[0] = " << returnA << "\nVector[1] = " << returnB << "\nVector[2] = " << returnC << std::endl << std::endl;
// If I index outside of the range of the vector, it gives me the correct results?
returnD = sexp_flonum_value(sexp_vector_ref(returnedVector, 0));
returnE = sexp_flonum_value(sexp_vector_ref(returnedVector, 3));
returnF = sexp_flonum_value(sexp_vector_ref(returnedVector, 4));
std::cout << "Vector[0] = " << returnD << "\nVector[3] = " << returnE << "\nVector[4] = " << returnF << std::endl;
sexp_gc_release6(ctx);
}
这给了我输出:
test-vec is defined
From Scheme: #(3.1 8.2 5.0)
Vector size: 3
Vector[0] = 3.1
Vector[1] = 3.1
Vector[2] = 8.2
Vector[0] = 3.1
Vector[3] = 8.2
Vector[4] = 5
为什么超出向量长度的索引会给我正确的值?
解决了问题。这是因为 sexp_vector_ref(vec, i)
的计算结果为
#define sexp_vector_ref(x,i) (sexp_vector_data(x)[sexp_unbox_fixnum(i)])
和 sexp_unbox_fixnum(i)
的计算结果为
#define sexp_unbox_fixnum(n) (((sexp_sint_t)((sexp_uint_t)(n) & ~SEXP_FIXNUM_TAG))/(sexp_sint_t)((sexp_sint_t)1<<SEXP_FIXNUM_BITS))
当我们只传递整数时
std::cout << "Unboxed fixnums: " <<
sexp_unbox_fixnum(0) << " " <<
sexp_unbox_fixnum(1) << " " <<
sexp_unbox_fixnum(2) << " " <<
sexp_unbox_fixnum(3) << " " <<
sexp_unbox_fixnum(4) << std::endl;
给我们输出
Unboxed fixnums: 0 0 1 1 2
但是如果我们首先将它们转换成 chibi 期望的正确类型,就像这样
std::cout << "Fixnum: " <<
sexp_unbox_fixnum(sexp_make_fixnum(0)) << " " <<
sexp_unbox_fixnum(sexp_make_fixnum(1)) << " " <<
sexp_unbox_fixnum(sexp_make_fixnum(2)) << " " <<
sexp_unbox_fixnum(sexp_make_fixnum(3)) << " " <<
sexp_unbox_fixnum(sexp_make_fixnum(4)) << std::endl;
我们得到正确的输出
Fixnum: 0 1 2 3 4
解决方法:索引时使用正确的类型