Thread overview | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
August 25, 2012 Lazy range of hashes? | ||||
---|---|---|---|---|
| ||||
I could use something like this: void main() { int[string] x = ["foo":1]; int[string] y = ["bar":1]; assert("bar" in lazyHash(x, y)); } Essentially it would turn into lazy 'in' checks, meaning first opIn_r would be called for 'x', and then for 'y'. Otherwise it might be expensive to have to create a new hash that has all the keys and values of other hashes. Has anyone ever implemented this? |
August 26, 2012 Re: Lazy range of hashes? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | Andrej Mitrovic:
> void main()
> {
> int[string] x = ["foo":1];
> int[string] y = ["bar":1];
> assert("bar" in lazyHash(x, y));
> }
>
> Essentially it would turn into lazy 'in' checks, meaning first opIn_r
> would be called for 'x', and then for 'y'.
This seems to work:
import std.algorithm;
void main() {
auto x = ["foo": 1];
auto y = ["bar": 2];
//assert("bar" in lazyHash(x, y));
assert(any!(h => "bar" in h)([x, y]));
}
Recently I have seen a lazy range struct able to replace that
[x,y]. I don't know if it's in Phobos already.
Bye,
bearophile
|
August 26, 2012 Re: Lazy range of hashes? | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On 8/26/12, bearophile <bearophileHUGS@lycos.com> wrote:
> This seems to work:
It seems it's as simple as defining a struct:
struct LazyHash(T...)
{
T hashes;
bool opIn_r(X)(X x)
{
foreach (hash; hashes)
{
if (x in hash)
return true;
}
return false;
}
}
auto lazyHash(T...)(T t)
{
return LazyHash!T(t);
}
void main()
{
auto x = ["foo" : 1];
auto y = ["bar" : 2];
assert("bar" in lazyHash(x, y));
assert("barx" !in lazyHash(x, y));
}
I didn't even have to define a ctor since field assignment works.
|
August 26, 2012 Re: Lazy range of hashes? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | On 08/25/2012 05:30 PM, Andrej Mitrovic wrote:
> On 8/26/12, bearophile<bearophileHUGS@lycos.com> wrote:
>> This seems to work:
>
> It seems it's as simple as defining a struct:
>
> struct LazyHash(T...)
> {
> T hashes;
>
> bool opIn_r(X)(X x)
> {
> foreach (hash; hashes)
> {
> if (x in hash)
> return true;
> }
>
> return false;
> }
> }
>
> auto lazyHash(T...)(T t)
> {
> return LazyHash!T(t);
> }
>
> void main()
> {
> auto x = ["foo" : 1];
> auto y = ["bar" : 2];
>
> assert("bar" in lazyHash(x, y));
> assert("barx" !in lazyHash(x, y));
> }
>
> I didn't even have to define a ctor since field assignment works.
Cool! :) If the operator returns the pointer to the element, then the callers can access its value as well:
auto opIn_r(X)(X x)
{
foreach (hash; hashes)
{
auto p = x in hash;
if (p)
return p; // <-- return the pointer
}
return null;
}
// ...
import std.stdio;
auto p = "foo" in lazyHash(x, y);
if (p) {
writeln(*p); // <-- the user can access the value
}
Ali
|
August 26, 2012 Re: Lazy range of hashes? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Sunday, 26 August 2012 at 07:29:13 UTC, Ali Çehreli wrote:
> Cool! :) If the operator returns the pointer to the element, then the callers can access its value as well
Reminds me, although not for you Ali, but as a pointer return a question came up. I've wondered and haven't tested this but hypothetically:
Due to that you can call structures and class members even from a pointer (transparently compared to C/C++), does it automatically convert from a pointer to a non-pointer type if the return calls for it? In a class that's irrelevant (it's already a reference type and should auto-fix itself); But a struct or non-class?
//just to get the idea
//potentially ref int, rather than int* as well
int getSomeValue(int[string] x, string someValue) {
auto sv = someValue in x;
return x ? x : 0; //auto convert? Or error? If not, why?
}
Rather than auto could ref work? Or if it's a exact valueType (with postblitz) or (known to be relocatable) would it make a new copy? I can see the importance of both, but depending on the return type in cases, having it throw an error seems like the best policy if it's a non-built in, since it's trivial changing return x, with return *x; Also as a built in type it could automatically do the copy/conversion for you.
|
August 26, 2012 Re: Lazy range of hashes? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Era Scarecrow | On 08/26/2012 12:55 AM, Era Scarecrow wrote: > On Sunday, 26 August 2012 at 07:29:13 UTC, Ali Çehreli wrote: >> Cool! :) If the operator returns the pointer to the element, then the >> callers can access its value as well > > Reminds me, although not for you Ali, but as a pointer return a question > came up. I've wondered and haven't tested this but hypothetically: > > Due to that you can call structures and class members even from a > pointer (transparently compared to C/C++), It has been argued that the -> operator has not been needed for C anyway. Interestingly, it has some value in C++ because if a type has defined operator->() (rather, for this discussion, operator.(), which does not exist in C++ today), then the following would cause confusion for types that worked like smart pointers: class P { /* hypothetical operator */ T * operator.(); void foo(); }; P p = bar(); p.foo(); // foo() of the pointer type or the 'pointed to type'? D does not have that question because the dot operator may not be overloaded. (opDot() has been (will be?) deprecated.) > does it automatically convert > from a pointer to a non-pointer type if the return calls for it? No: The dot does not convert the type. The dot has different meanings on structs vs. classes. With structs, it always operates on the struct object: o.sizeof // The size of the struct object o.foo() // The member of the struct object With classes, it operates sometimes on the reference and sometimes on the referenced object: o.sizeof // The size of the class reference o.foo() // The member of the class object That's D's way of confusing on this topic. > In a > class that's irrelevant (it's already a reference type and should > auto-fix itself); But a struct or non-class? > > //just to get the idea > //potentially ref int, rather than int* as well > int getSomeValue(int[string] x, string someValue) { > auto sv = someValue in x; > return x ? x : 0; //auto convert? Or error? If not, why? You meant sv: return sv ? sv : 0; That is still a compilation error for a statically-typed language like D. The types of sv and 0 don't match. But the line should always be like this anyway: return sv ? *sv : 0; Because sv is always a pointer: // For a struct pointer: *sv // a reference to the struct object // For a class reference: *sv is another reference to the actual class object > Rather than auto could ref work? You mean, 'ref' on the return type, right? For opIn_r, it better not be 'ref', because then it would be returning a reference to a local pointer: // Note ref return. I think this is a bug. ref opIn_r(X)(X x) { foreach (hash; hashes) { auto p = x in hash; if (p) return p; // <-- return a reference to the local pointer } return null; } I think that is a bug but the compiler does not give a warning about returning a reference to the local pointer. > Or if it's a exact valueType (with > postblitz) or (known to be relocatable) would it make a new copy? I can > see the importance of both, but depending on the return type in cases, > having it throw an error seems like the best policy if it's a non-built > in, since it's trivial changing return x, with return *x; Also as a > built in type it could automatically do the copy/conversion for you. As you said, returning *x would return a copy of the value if it were a struct. Ali |
August 26, 2012 Re: Lazy range of hashes? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On 08/26/12 17:28, Ali Çehreli wrote: > On 08/26/2012 12:55 AM, Era Scarecrow wrote: >> On Sunday, 26 August 2012 at 07:29:13 UTC, Ali Çehreli wrote: >>> Cool! :) If the operator returns the pointer to the element, then the callers can access its value as well >> >> Reminds me, although not for you Ali, but as a pointer return a question came up. I've wondered and haven't tested this but hypothetically: >> >> Due to that you can call structures and class members even from a pointer (transparently compared to C/C++), > > It has been argued that the -> operator has not been needed for C anyway. > > Interestingly, it has some value in C++ because if a type has defined operator->() (rather, for this discussion, operator.(), which does not exist in C++ today), then the following would cause confusion for types that worked like smart pointers: > > class P > { > /* hypothetical operator */ > T * operator.(); > void foo(); > }; > > P p = bar(); > p.foo(); // foo() of the pointer type or the 'pointed to type'? > > D does not have that question because the dot operator may not be overloaded. (opDot() has been (will be?) deprecated.) opDispatch lets you write the equivalent in D [1]. The 'local' member always has to take precedence over any 'remote' ones (you can hide (rename/wrap etc) the local one if you want, doing it the other way wont work). >> does it automatically convert >> from a pointer to a non-pointer type if the return calls for it? > > No: The dot does not convert the type. The dot has different meanings on structs vs. classes. With structs, it always operates on the struct object: > > o.sizeof // The size of the struct object > o.foo() // The member of the struct object > > With classes, it operates sometimes on the reference and sometimes on the referenced object: > > o.sizeof // The size of the class reference > o.foo() // The member of the class object > > That's D's way of confusing on this topic. The dot means the same thing, you just have to remember that a class reference is actually a pointer to the class instance. IOW 'o.whatever' for classes works just like 'p.whatever' does for structs. What is confusing is the wrong reference_type-to-pointer model, but fixing it up right now is too late. Or maybe not, given the tiny amount of D code out there and the fact that only code dealing with pointers-to-classes would be affected. Such code is probably so rare that the cost could still be acceptable. artur [1] Well, almost - there are things like dealing with '@property' which need improvements. And of course 'alias this' can be used, sometimes. |
August 26, 2012 Re: Lazy range of hashes? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Sunday, 26 August 2012 at 15:28:17 UTC, Ali Çehreli wrote: > On 08/26/2012 12:55 AM, Era Scarecrow wrote: > Interestingly, it has some value in C++ because if a type has defined operator->() (rather, for this discussion, operator.(), which does not exist in C++ today), then the following would cause confusion for types that worked like smart pointers: > D does not have that question because the dot operator may not be overloaded. (opDot() has been (will be?) deprecated.) Since D wouldn't ever have a need to emulate pointers (like Iterators for C++) the -> and . overloading seem moot. Some features are best not to be implemented as they would give more trouble than they're worth. > No: The dot does not convert the type. The dot has different meanings on structs vs. classes. With structs, it always operates on the struct object: > > o.sizeof // The size of the struct object > o.foo() // The member of the struct object > > With classes, it operates sometimes on the reference and sometimes on the referenced object: > > o.sizeof // The size of the class reference > o.foo() // The member of the class object > > That's D's way of confusing on this topic. Only if o.sizeof may refer to the pointer size and not the class object. > You meant sv: > > return sv ? sv : 0; Ack! bad typo! Bad bad typo! > That is still a compilation error for a statically-typed language like D. The types of sv and 0 don't match. But the line should always be like this anyway: > > return sv ? *sv : 0; > > Because sv is always a pointer: Gotcha. > > Rather than auto could ref work? > > You mean, 'ref' on the return type, right? For opIn_r, it better not be 'ref', because then it would be returning a reference to a local pointer: And here i thought it would refer the reference (from in's case) to the original object. Mmmm. > // Note ref return. I think this is a bug. > ref opIn_r(X)(X x) > { > foreach (hash; hashes) > { > auto p = x in hash; > if (p) > return p; // <-- return a reference to the local pointer > } > > return null; > } > > I think that is a bug but the compiler does not give a warning about returning a reference to the local pointer. I've actually had this problem before. Ended up having to use ref on the input and then force a pointer to get my code elsewhere to work (without copying). But that's kinda unimportant; If the compiler issues a warning than all the better now :) > As you said, returning *x would return a copy of the value if it were a struct. K. Glad to get that out of the way. |
Copyright © 1999-2021 by the D Language Foundation