Returning a Rebol TRIPWIRE (TRASH!)

When I created the MySQL extension, the way to return a void value from a function was to do a simple

return rebTripwire();

Now I am dealing with the GTK3 extension and I suspect something about this has changed. Multiple occasions where I return a tripwire like this appear to be resulting in a segfault and quitting the console as a result as well.

Was this method indeed changed? Or could it be that it is just unintentionally broken?

Should the

return rebTripwire();

be replaced by

return Init_Tripwire(OUT);

now?

grep -r "rebVoid()" .
./extensions/crypt/mod-crypt.c:    return rebTripwire();
./extensions/crypt/mod-crypt.c:        return rebTripwire();
./extensions/crypt/mod-crypt.c:        return rebTripwire();
./extensions/odbc/mod-odbc.c:    return rebTripwire();
./extensions/mysql/mod-mysql.c:        return rebTripwire();
./extensions/mysql/mod-mysql.c:        return rebTripwire();
...

grep -r "Init_Tripwire(" .
./extensions/process/mod-process.c:    return Init_Tripwire(OUT);
./extensions/process/mod-process.c:    return Init_Tripwire(OUT);
./extensions/event/mod-event.c:    return Init_Tripwire(OUT);
./extensions/event/mod-event.c:    return Init_Tripwire(OUT);
...

I replaced my return rebTripwire(); 's with the return Init_Tripwire 's
Alas, this did not resolve the segfault when closing the window.

I take it that both methods to return a void are actual and functional.

So....

It appears I resolved the segfault issue now!

Of course it was my own stupid mistake(*), not connecting the right information in the signal-connect function.

I can now exit the window and return to a working console again.

Next step up is get a Rebol function to act as a valid callback function. (**)

(*) The stupid mistake only to be taking up this work :smile:
(**) Check for the latest update on this the ever growing GTK3 GUI thread ( Just moving ahead now with GTK3 - #18 by iArnold )

Sounds like you got it working, but the first API (the rebXXX() routines) are what are supposed to be the public API routines... the ones most people use.

Think of this as the "libRenC", it would be analogous to what Red calls "libRed".

The other API Init_Xxx(OUT) is not something you should need to concern yourself with. That's internal to the implementation. It is currently exposed to institutions to be able to make a choice which to use, but the correct choice for 99% of the people is the rebXXX routines.

If you have a crash that is something that should not happen, so if it is reproducible please report what you were doing that made it crash. That's useful feedback.

But also interesting is if you're able to get things done, which indicates that the API design is making sense to you. Feedback there is important.

1 Like

Thanks @hostilefork .
Yes I can safely re-place the rebTripwire()'s.
I got to doubt because I did not see many rebTripwire()'s in the rest of the code base, only a few which might have been missed or not in active used code. And there is often a lot of philosophy going about how to handle NULL, None, Void, Blank resulting in perhaps a slight different approach and I could easily have missed something. But this is not the case here.

It would be a nice to have to get the API docs available

A few years down the road... there's another answer: return can just return code to run.

So you can say return "x + y"; and it will run, looking up those variables in the current "scope" (e.g. it can find the native's arguments, or definitions in an extension's MODULE!)

If you want to return VOID, you can say return "~"; or return "()"

And so if you want a TRASH! like a "tripwire" you can just say return "~<?>~";

:smiling_face_with_sunglasses:

1 Like

There's a feature in modern Ren-C which is that if you use arity-0 return, you get a TRASH! which has the name of the function.

>> foo: func [] [return]

>> foo  ; will have no console output, because it returns TRASH!

>> lift foo
== ~<foo>~

The same happens for PROCEDURE / PROC when you don't use a return:

>> foo: proc [] []

>> lift foo
== ~<foo>~

I'll point out that if you pass an actual TRASH! to a function's RETURN, this will be taken verbatim and its name not changed.

>> bar: func [] [return foo]

>> bar  ; no console output, returns TRASH!

>> lift bar
== ~<foo>~

So you get different behavior from bar: func [] [foo, return] (or bar: proc [] [foo]) which would give you a ~<bar>~ trash.

Not twisting an explicit value you're passed makes sense to me. (If you happen to be piping some other function's return result and want a TRASH! return to be twisted into the name of the function doing the piping... that is possible to write, but I don't think the system needs to offer a pattern for doing that out of the box. It's rare to want to do that--and even rarer to care what the symbol in the trash is.)

C doesn't let you write return in a function that is supposed to return a value, you have to return something. And when you say return and pass it a particular TRASH! value, that will return the literal trash you specified... hence not getting the "use the name of the function" feature.

We could say that return ""; means arity-0 return, and it could thus generate a TRASH! with the name of the native.

I've speculated on this question before regarding what should transcode of an empty string be. If we say that transcode of an empty string is legitimately an empty block, that might suggest that return "" would have to do the same thing as return "eval []".

This shows some actual value in considering emptiness "out of band" for transcoding, which may be worth revisiting my decision and saying that there's a special result for transcode of an empty string. Maybe that result shouldn't be NULL, but some other signal that would be differentiable from the null you'd get from try transcode when it's an error?

I'll have to think about it.

(Sidenote: JavaScript allows you to leave off the return value in any function (there's no 'return type' concept and hence no distinction of void and non-void functions). But you can't tell the difference between return and return undefined;)

2 Likes