World: r3wp
[!REBOL3]
older newer | first last |
Ladislav 26-May-2011 [8880] | How can that "confuse" anybody? Something may confuse you only if it suggests something that proves wrong later, which is not the case of two datatypes being used instead of just one you seem to prefer. |
Geomol 26-May-2011 [8881] | It confused me, because they are called differently, so as a programmer, I think "ok, this is two different things, so I have to use time to learn the differences between e.g. functions and natives, or natives and actions, and how to use them correctly". And in fact, as a programmer I can very well ignore the differences, because the 3 types works exactly the same in my programs. |
Ladislav 26-May-2011 [8882] | But the difference between functions and natives is obvious - speed |
Geomol 26-May-2011 [8883] | :) I badly written native might be slower than a well written function. |
Ladislav 26-May-2011 [8884] | You can certainly invent any number of generalizations, but you will not be able to find any example, I bet |
Geomol 26-May-2011 [8885] | I think, it was Bertrand Meyer, who wrote, that a datatype is recognized by the methods, you can use on it. In REBOL terms, what you can do with a datatype specify it. If you can do the same with a native! and a function!, they're the same datatype. |
Ladislav 26-May-2011 [8886x2] | OK, then, how do you get the body of a native? |
But, the fact is, that, seen from the Meyer's perspective, there should not be any distinction between actions and natives... | |
Geomol 26-May-2011 [8888x2] | That is up to the implementor/designer to deside. :-) Maybe it should be a number, like actions returns in R2, or none as R3 do. |
We can still try to get the body of a native and action, like we can with functions. So we can use them exactly the same way. | |
Ladislav 26-May-2011 [8890] | There is not "body of a native" you get. Both in R2 as well as in R3 you get just a "replacement value" |
Geomol 26-May-2011 [8891] | Correct! But that doesn't remove the fact, that I can use the method to get bodies on natives and actions, just like I can on functions. The methods define the datatype. |
Ladislav 26-May-2011 [8892x5] | Aha, so you are saying, that it does not matter whether you get a #[none!] or a block? |
I see it as a huge difference. | |
It is actually the same difference as a difference between causing an error or obtaining a block. | |
(a "caused error" can be considered a "special value" as well) | |
...and that is not my invention, you can find that principle in descriptions of many programming languages | |
Geomol 26-May-2011 [8897x2] | Good point. |
>> type? 10 / 2 == integer! >> type? 10 / 3 == decimal! I guess, that's two different divide operators in use then? :) | |
Ladislav 26-May-2011 [8899] | Actually, the above behaviour is unacceptable for many programming language designers (or users). |
Henrik 26-May-2011 [8900] | I wonder what happens in there. I would assume it would be slower to divide, if you have to make a check afterwards that it can be converted to integer, or is there something else fancy going on? |
Ladislav 26-May-2011 [8901] | Yes, certainly it is slower. |
Geomol 26-May-2011 [8902x2] | You need to something like: case INTEGER_T: { double r1 = (double) rb->value.i / (double) rc->value.i; int64_t i1 = (int64_t) r1; if (i1 == r1) { ra->value.i = i1; ra->type = INTEGER_T; } else { ra->value.r = r1; ra->type = REAL_T; } break; } |
But I guess, it's convenient, it works this way, as we think this way as humans. 10 / 2 is an integer, 10 / 3 is a real. | |
Ladislav 26-May-2011 [8904x2] | >> i: to integer! #{8000000000000000} == -9223372036854775808 >> i / -1 ** Math error: math or number overflow ** Where: / ** Near: / -1 |
is that consistent? And, if yes, why? | |
Geomol 26-May-2011 [8906x3] | My code works this way with your example: w> i: -9223372036854775808 == -9223372036854775808 w> i / -1 == 9.22337203685478e+18 |
So it returns a real. | |
Is it crazy to make the rule, that DIVIDE always returns a decimal! ? POWER always returns a decimal!, even if the inputs are integers and the output could be an integer. It would make DIVIDE faster. | |
Henrik 26-May-2011 [8909] | perhaps it is somewhat convenient for integer based datatypes, like pair or tuple, but consistency overrules it. |
Geomol 26-May-2011 [8910] | Hm, I may take that back. It may be compiler optimization, but always giving a real as output seem to be slower in my test. Or it could be, that giving the result involve slower cpu circuity, when it's a real compared to an integer. |
Henrik 26-May-2011 [8911x2] | it also works on R3 pairs: >> 3x1 / 3 == 1x0.3333333 |
But: >> a: 3x1 / 3 == 1x0.3333333 >> a/1 == 1.0 | |
Geomol 26-May-2011 [8913x4] | Hah! :) |
Ah, pairs are always decimals. >> first 1x1 == 1.0 | |
So he does in pairs in R3, kinda the same thing Lua does with its numbers. They're always reals internal, but is presented as integers, if they can. | |
Why was REFLECT introduced? Couldn't SELECT be used? Did Carl write about REFLECT anywhere? (I tried search the blogs.) | |
onetom 26-May-2011 [8917] | i just discovered reflect by looking at the source of body-of spec-of and stuff. can't recall reading about it anywhere else |
Henrik 26-May-2011 [8918] | Geomol, objects have series abilities now, so SELECT wouldn't work. |
Geomol 26-May-2011 [8919x2] | ah, I see. (I even think, this was discussed somewhere.) Hm, not an easy call. |
so you are saying, that it does not matter whether you get a #[none!] or a block? If natives and actions were called functions (datatype function!), then getting their bodies could also just return an empty block instead of none (if that's a problem from a language technical view). But it can't be a big problem, as so many functions in REBOL return a value different from none, if success, else none. Like PICK, SELECT, ... | |
Ladislav 26-May-2011 [8921x2] | ...it can't be a big problem... - this is not about any "big problem". This is "only" a problem of a definition. You seem to be saying, that, formally, you can get the "body" of a native. Of course, you can define the BODY-OF function however you want. But, that is a "super-formal" approach, since, in fact, you are unable to get the body of a native no matter how much you pretend "it is not a big problem". In the same "super-formal" way you can evaluate BODY-OF 1 and say, that it (formally) is possible too, "yielding" a "triggered error". What I am trying to note is, that a part of the definition should be when we can we reasonably "can get the body" and when not. |
Reasonable definitions are of advantage over some non-reasonable I would say. | |
BrianH 26-May-2011 [8923x4] | Geomol: "Why bother?" The reason that this kind of question is asked is because a lot of people seem to forget that REBOL is any more than its built-in dialects. I have to answer to remind people that the point of these syntax types is for users to use when creating their own dialects. Given that, a feature being useless for the built-in dialects is not a suffcient reason to restrict it. In order to justify restrictions the feature has to be actively harmful, as opposed to just passively unused, because it could be useful to user-level dialects. |
Ladislav, thanks for looking up the /local blog and getting the actual numbers - I didn't have the time. I think that the only votes against the change were by gurus, while the rest of the responding gurus abstained like me. | |
Geomol, about native-op!, native-closure! and native-action!, these won't be necessary. Functions of the native! type don't need to bind their bodies to contexts, so they don't need the feature that makes closures closures. Ops and actions both redirect to the actual implementing function, which in the case of actions is an internal native associated with the type of the first argument, and in the case of op is a (at the moment only native) function provided at op creation time. If you wanted to allow the creation of user-defined datatypes with function!, closure! or command! implementations of the type's actions, the regular action! functions would still redirect to these implementations. Similarly, the regular op! type could be extended to support redirecting to other function types without needing the creation of a new function type. | |
Why was REFLECT introduced? - REFLECT was my idea, as a way to get metadata about a type without overloading the ordinal functions. This was a security measure so that you could make the ordinal functions available to untrusted code safely, and not make REFLECT and the *-OF functions available, which would make untrusted code potentially more useful. Couldn't SELECT be used? >> select context [body: 1] 'body == 1 >> reflect context [body: 1] 'body == [ body: 1 ] | |
Geomol 26-May-2011 [8927] | Aha, so that's how it got in there ... and for security reasons! So you're the one, we should beat up, when times come. ;) |
Ladislav 26-May-2011 [8928x2] | I think that the only votes against the change were by gurus, while the rest of the responding gurus abstained like me. - that *very much* depends on who you consider gurus |
Functions of the native! type don't need to bind their bodies to contexts - in that sense, natives behave both as functions and as closures at the same time. That is not as a big of an exception, as it may look, e.g.: f: func [][] behaves as a closure, similarly as g: func [x y][add :x :y] , simply because in such simple cases it is not discernible whether the given "function" is a function or a closure | |
older newer | first last |