I've been doing some calculations on genome mutations and I've been finding myself doing a lot of
if(zero_type(foo) && zero_type(bar) ... && zero_type(gonk)) ...
when checking up on user input that is used to index mappings. So... I was wondering if it is safe to do this? Or perhaps - even make zero_type() do this by default?
int zero_types(mixed ... tt) { if(arrayp(tt)) { foreach(tt, mixed t) if(zero_type(t)) return 1; return 0; }
return zero_type(tt); }
It seems to work alright - but I feel that this might perhaps in some way, I havent thought of, dangerous.
mapping m=(["A":1]); zero_types(m["A"]);
(9) Result: 0
zero_types(m["R"]);
(10) Result: 1
zero_types(m["R"],m["A"]);
(11) Result: 1
zero_types(m["A"],m["A"]);
(12) Result: 0
zero_types(m["A"],m["R"]);
(13) Result: 1
zero_types(m["R"],m["R"]);
(14) Result: 1
making zero_type() do this by default is probably not a good idea, because you could got a similar problem when using ||, a better idea might just be to create a short alias:
function zt=zero_type;
if(zt(foo) || zt(bar) || zt(baz))...
greetings, martin.
How is that? zero_type() would still work the same way on single value arguments.
Well, anyway - I won't push this. It was just a thought. Perhaps a bad one.
/ Peter Lundqvist (disjunkt)
Previous text:
2003-09-28 01:49: Subject: Re: zero_type();
making zero_type() do this by default is probably not a good idea, because you could got a similar problem when using ||, a better idea might just be to create a short alias:
function zt=zero_type;
if(zt(foo) || zt(bar) || zt(baz))...
greetings, martin.
/ Brevbäraren
i realize that, i meant that your function only solves the && case (a && b && c), but you still have the probelm with (a || b || c) or any other combination of a, b and c.
so while the thought may be good, the proposed solution does not go far enough.
greetings, martin.
I've been doing some calculations on genome mutations and I've been finding myself doing a lot of
if(zero_type(foo) && zero_type(bar) ... && zero_type(gonk)) ...
when checking up on user input that is used to index mappings.
Could you explain some more why you land at testing a lot of zero_types? I didn't quite get the reason...
/ Mirar
Previous text:
2003-09-28 01:39: Subject: zero_type();
I've been doing some calculations on genome mutations and I've been finding myself doing a lot of
if(zero_type(foo) && zero_type(bar) ... && zero_type(gonk)) ...
when checking up on user input that is used to index mappings. So... I was wondering if it is safe to do this? Or perhaps - even make zero_type() do this by default?
int zero_types(mixed ... tt) { if(arrayp(tt)) { foreach(tt, mixed t) if(zero_type(t)) return 1; return 0; }
return zero_type(tt); }
It seems to work alright - but I feel that this might perhaps in some way, I havent thought of, dangerous.
mapping m=(["A":1]); zero_types(m["A"]);
(9) Result: 0
zero_types(m["R"]);
(10) Result: 1
zero_types(m["R"],m["A"]);
(11) Result: 1
zero_types(m["A"],m["A"]);
(12) Result: 0
zero_types(m["A"],m["R"]);
(13) Result: 1
zero_types(m["R"],m["R"]);
(14) Result: 1
/ Peter Lundqvist (disjunkt)
Perhaps it's a variant of this fairly common case:
if (a && a->b && a->b->c && ...) ...
There's been talk about introducing a shorthand for that as a "safe" variant of ->.
/ Martin Stjernholm, Roxen IS
Previous text:
2003-09-28 08:09: Subject: zero_type();
I've been doing some calculations on genome mutations and I've been finding myself doing a lot of
if(zero_type(foo) && zero_type(bar) ... && zero_type(gonk)) ...
when checking up on user input that is used to index mappings.
Could you explain some more why you land at testing a lot of zero_types? I didn't quite get the reason...
/ Mirar
But that case is simple, because you don't need to test with zero_type. It's where I get confused; when do you need to test with zero_type?
/ Mirar
Previous text:
2003-09-28 10:08: Subject: zero_type();
Perhaps it's a variant of this fairly common case:
if (a && a->b && a->b->c && ...) ...
There's been talk about introducing a shorthand for that as a "safe" variant of ->.
/ Martin Stjernholm, Roxen IS
I wished for this years ago and suggested the "squiggly pointer" operator ~> so I'm glad to see this idea revived. (The ~> syntax is rather ugly if ~ isn't vertically centered in the current font so perhaps => or ?> works better.)
Any news from the conference regarding this, or were you simply referring to our old discussions?
/ Jonas Walldén
Previous text:
2003-09-28 10:08: Subject: zero_type();
Perhaps it's a variant of this fairly common case:
if (a && a->b && a->b->c && ...) ...
There's been talk about introducing a shorthand for that as a "safe" variant of ->.
/ Martin Stjernholm, Roxen IS
Perhaps it's useful to compare with the let-and macro,
(define-syntax let-and (syntax-rules () ((let-and (expr) clause clauses ...) (and expr (let-and clause clauses ...))) ((let-and (name expr) clause clauses ...) (let ((name expr)) (and name (let-and clause clauses ...)))) ((let-and expr) expr)))
where you'd do
(let-and a (foo (a->foo a)) (foo->bar foo))
which means
If a is false, return false. Otherwise bind foo to (a->foo a). If foo is now false, return false. Otherwise, return (foo->bar foo).
Corresponding pike code would be
a && a->foo && a->foo->bar
so in this example, let-and isn't terribly useful, it makes more sense if you have something more komplext instead of ->foo. A more realistic use could be
(define (match pattern expr) (if (atom? pattern) (if (eq? '* pattern) (list expr) (and (eq? pattern expr) '())) (let-and ((pair? expr)) (op-matches (match (application-op pattern) (application-op expr))) (arg-matches (match (application-arg pattern) (application-arg expr))) (append op-matches arg-matches))))
/ Niels Möller (igelkottsräddare)
Previous text:
2003-09-28 11:43: Subject: zero_type();
I wished for this years ago and suggested the "squiggly pointer" operator ~> so I'm glad to see this idea revived. (The ~> syntax is rather ugly if ~ isn't vertically centered in the current font so perhaps => or ?> works better.)
Any news from the conference regarding this, or were you simply referring to our old discussions?
/ Jonas Walldén
No, it hasn't been mentioned at the conference. Personally I don't think it's really worth a new operator.
/ Martin Stjernholm, Roxen IS
Previous text:
2003-09-28 11:43: Subject: zero_type();
I wished for this years ago and suggested the "squiggly pointer" operator ~> so I'm glad to see this idea revived. (The ~> syntax is rather ugly if ~ isn't vertically centered in the current font so perhaps => or ?> works better.)
Any news from the conference regarding this, or were you simply referring to our old discussions?
/ Jonas Walldén
Well, as long as the compiler eliminates CSEs from the expression
a && a->foo && a->foo->bar && a->foo->bar->fie
I'd be quite happy anyway. Is that true, or does it have to be conservative regarding `->() in each dereferencing step? If so I'd see a performance advantage in a new operator.
/ Jonas Walldén
Previous text:
2003-09-29 01:34: Subject: zero_type();
No, it hasn't been mentioned at the conference. Personally I don't think it's really worth a new operator.
/ Martin Stjernholm, Roxen IS
The compiler doesn't do common subexpression elimination, so the indexings are repeated. If performance is very important one has to do something like this:
mixed tmp; if ((tmp = a->foo) && (tmp = tmp->bar) && (tmp = tmp->fie)) ...
I too see some advantage with an ~> operator, but I still don't think it's really worth extending the operator set for such a special case. We already got three indexing operators, and that's often one too much.
/ Martin Stjernholm, Roxen IS
Previous text:
2003-09-29 09:42: Subject: zero_type();
Well, as long as the compiler eliminates CSEs from the expression
a && a->foo && a->foo->bar && a->foo->bar->fie
I'd be quite happy anyway. Is that true, or does it have to be conservative regarding `->() in each dereferencing step? If so I'd see a performance advantage in a new operator.
/ Jonas Walldén
I get a lot of input with the letters "A"-"V" and "-". I use this input as an index (with a value that is stored in a mapping) to retrive data in some arrays.
I could do something like
if( amino_acid[str1] && amino_acid[str2] ... &amino_acid[strn] )
but this would that I do twice as many lookups in the amion_acid-mapping than I really need too (this is done _a lot_). Oh, and 0 is one of the values returned from the amino_acid-mapping. Of course I _could_ bump the numbers one step and subtract -1 for all indices...
Therefore I do it like this
index1 = amino_acid[str1]; ... indexn = amino_acid[strn]; if( zero_type(index1) && ... && zero_type(indexn) )
//use the indices quite a bit more
/ Peter Lundqvist (disjunkt)
Previous text:
2003-09-28 08:09: Subject: zero_type();
I've been doing some calculations on genome mutations and I've been finding myself doing a lot of
if(zero_type(foo) && zero_type(bar) ... && zero_type(gonk)) ...
when checking up on user input that is used to index mappings.
Could you explain some more why you land at testing a lot of zero_types? I didn't quite get the reason...
/ Mirar
If it's done a lot, do you need the error checking at that point?
It seems like a lot of work that in the normal case isn't necessary...
Does zero_type really work in that context? If you store it in an int variable, is it guaranteed to work?
Also, you could do
if (zero_type(index1 = amino_acid[str1]) || ... zero_type(indexn = amino_acid[strn]))
if you want to, which is probably safer zero-typewise. :)
(Just suggesting options.)
/ Mirar
Previous text:
2003-09-28 14:11: Subject: zero_type();
I get a lot of input with the letters "A"-"V" and "-". I use this input as an index (with a value that is stored in a mapping) to retrive data in some arrays.
I could do something like
if( amino_acid[str1] && amino_acid[str2] ... &amino_acid[strn] )
but this would that I do twice as many lookups in the amion_acid-mapping than I really need too (this is done _a lot_). Oh, and 0 is one of the values returned from the amino_acid-mapping. Of course I _could_ bump the numbers one step and subtract -1 for all indices...
Therefore I do it like this
index1 = amino_acid[str1]; ... indexn = amino_acid[strn]; if( zero_type(index1) && ... && zero_type(indexn) )
//use the indices quite a bit more
/ Peter Lundqvist (disjunkt)
Does zero_type really work in that context? If you store it in an int variable, is it guaranteed to work?
It works for local variables in functions. You might say it's guaranteed since there's a lot of code that uses it.
/ Martin Stjernholm, Roxen IS
Previous text:
2003-09-28 14:27: Subject: zero_type();
If it's done a lot, do you need the error checking at that point?
It seems like a lot of work that in the normal case isn't necessary...
Does zero_type really work in that context? If you store it in an int variable, is it guaranteed to work?
Also, you could do
if (zero_type(index1 = amino_acid[str1]) || ... zero_type(indexn = amino_acid[strn]))
if you want to, which is probably safer zero-typewise. :)
(Just suggesting options.)
/ Mirar
Hm, I've always considered the zero bit lost if stored.
(If someone makes a way of indexing out variables from the local function...)
/ Mirar
Previous text:
2003-09-29 01:39: Subject: zero_type();
Does zero_type really work in that context? If you store it in an int variable, is it guaranteed to work?
It works for local variables in functions. You might say it's guaranteed since there's a lot of code that uses it.
/ Martin Stjernholm, Roxen IS
Yes, me too. But it's still a de-facto behavior that's exploited in various code.
/ Martin Stjernholm, Roxen IS
Previous text:
2003-09-29 08:03: Subject: zero_type();
Hm, I've always considered the zero bit lost if stored.
(If someone makes a way of indexing out variables from the local function...)
/ Mirar
Maybe a warning should be added for zero_type on variables, if possible? I don't think it's a good thing to support indefinately...
/ Mirar
Previous text:
2003-09-29 14:22: Subject: zero_type();
Yes, me too. But it's still a de-facto behavior that's exploited in various code.
/ Martin Stjernholm, Roxen IS
Is that necessary? I doubt we would ever want to make local variables externally accessible since that limits the possible optimizations quite a bit. What could conceivably happen is that the boundary between functions and classes are blurred to the point that the user is trying to do it with class variables without realizing it.
/ Martin Stjernholm, Roxen IS
Previous text:
2003-09-29 15:01: Subject: zero_type();
Maybe a warning should be added for zero_type on variables, if possible? I don't think it's a good thing to support indefinately...
/ Mirar
I can also imagine a stronger type system, that can store ints in smaller slots then what allows for subtypes.
/ Mirar
Previous text:
2003-09-29 16:46: Subject: zero_type();
Is that necessary? I doubt we would ever want to make local variables externally accessible since that limits the possible optimizations quite a bit. What could conceivably happen is that the boundary between functions and classes are blurred to the point that the user is trying to do it with class variables without realizing it.
/ Martin Stjernholm, Roxen IS
That's a possibility. (Probably not integers due to bignums, but other variables could be stored as short svalues.)
/ Martin Stjernholm, Roxen IS
Previous text:
2003-09-29 20:02: Subject: zero_type();
I can also imagine a stronger type system, that can store ints in smaller slots then what allows for subtypes.
/ Mirar
The optimization isn't impossible; you only need a bit to differ from a pointer or an int value, and that could be store otherwhere.
(Unlikely, though. :) )
/ Mirar
Previous text:
2003-09-29 20:15: Subject: zero_type();
That's a possibility. (Probably not integers due to bignums, but other variables could be stored as short svalues.)
/ Martin Stjernholm, Roxen IS
If we get to that, we probably use the lowest bit as a flag: If it's 1 then it's a native integer shifted right one step. If it's 0 then it's a pointer (assuming at least 16 bit alignment should be safe). That would halve the range of native integers, but combined with 64 bit values it shouldn't be much of a problem. It's uncertain if the saved space makes up for the added complexity when handling native integers, though.
/ Martin Stjernholm, Roxen IS
Previous text:
2003-09-29 20:16: Subject: zero_type();
The optimization isn't impossible; you only need a bit to differ from a pointer or an int value, and that could be store otherwhere.
(Unlikely, though. :) )
/ Mirar
It's better to use *zero* in the least significant bit mean that it's an integer.
Then you can do simple add and substract on integers with no extra fuzz. And for pointers, using a small constant offset when dereferencing is free in most cases on most architectures.
/ Niels Möller (igelkottsräddare)
Previous text:
2003-09-29 20:21: Subject: zero_type();
If we get to that, we probably use the lowest bit as a flag: If it's 1 then it's a native integer shifted right one step. If it's 0 then it's a pointer (assuming at least 16 bit alignment should be safe). That would halve the range of native integers, but combined with 64 bit values it shouldn't be much of a problem. It's uncertain if the saved space makes up for the added complexity when handling native integers, though.
/ Martin Stjernholm, Roxen IS
I see. And compilers won't flip out and do funny code from the necessary casts to offset a pointer like that?
foo = ((struct object *) ((char *) ptr - 1))->foo;
/ Martin Stjernholm, Roxen IS
Previous text:
2003-09-29 21:11: Subject: zero_type();
It's better to use *zero* in the least significant bit mean that it's an integer.
Then you can do simple add and substract on integers with no extra fuzz. And for pointers, using a small constant offset when dereferencing is free in most cases on most architectures.
/ Niels Möller (igelkottsräddare)
You' probably use an integer type to represent the objects, and then the code would be
#define pointer2object(p) ((unsigned long) (p) - 1) #define object2pointer(o) ((struct object *) ((o) + 1)
Should work fine on any traditional C implementation, I think. Could break a conservative garbage collector pretty hard, though.
Anyway I'd prefer to let the machine code generator handle it ;-)
/ Niels Möller (igelkottsräddare)
Previous text:
2003-09-29 21:21: Subject: zero_type();
I see. And compilers won't flip out and do funny code from the necessary casts to offset a pointer like that?
foo = ((struct object *) ((char *) ptr - 1))->foo;
/ Martin Stjernholm, Roxen IS
Perhaps something you were aware of, but your code implements
if(zero_type(foo) || zero_type(bar) ... || zero_type(gonk)) ...
rather than
if(zero_type(foo) && zero_type(bar) ... && zero_type(gonk)) ...
/ Johan Sundström, Lysator
Previous text:
2003-09-28 01:39: Subject: zero_type();
I've been doing some calculations on genome mutations and I've been finding myself doing a lot of
if(zero_type(foo) && zero_type(bar) ... && zero_type(gonk)) ...
when checking up on user input that is used to index mappings. So... I was wondering if it is safe to do this? Or perhaps - even make zero_type() do this by default?
int zero_types(mixed ... tt) { if(arrayp(tt)) { foreach(tt, mixed t) if(zero_type(t)) return 1; return 0; }
return zero_type(tt); }
It seems to work alright - but I feel that this might perhaps in some way, I havent thought of, dangerous.
mapping m=(["A":1]); zero_types(m["A"]);
(9) Result: 0
zero_types(m["R"]);
(10) Result: 1
zero_types(m["R"],m["A"]);
(11) Result: 1
zero_types(m["A"],m["A"]);
(12) Result: 0
zero_types(m["A"],m["R"]);
(13) Result: 1
zero_types(m["R"],m["R"]);
(14) Result: 1
/ Peter Lundqvist (disjunkt)
Oh.. sorry. I'm quite aware of that. It's not a bug - it's a feature =)
It's only me beeing utterly stupid again ;-)
/ Peter Lundqvist (disjunkt)
Previous text:
2003-09-28 12:41: Subject: zero_type();
Perhaps something you were aware of, but your code implements
if(zero_type(foo) || zero_type(bar) ... || zero_type(gonk)) ...
rather than
if(zero_type(foo) && zero_type(bar) ... && zero_type(gonk)) ...
/ Johan Sundström, Lysator
pike-devel@lists.lysator.liu.se