GSPredicate

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

GSPredicate

amon
NSArray refers to GSPredicate, but I cannot seem to find any
documentation of it outside of the include file that defines it.

In the NSArray man page... er html/whatever page...

indexOfObjectWithOptions: passingTest:
- (NSUInteger) indexOfObjectWithOptions: (NSEnumerationOptions)opts
passingTest: (GSPredicateBlock)predicate;

It is referenced but never defined.

--
+---------------------------------------------------------------+
|   Dale Amon                  Immortal Data                    |
|   CEO             Midland International Air and Space Port    |
| [hidden email]       "Data Systems for Deep Space and Time"     |
+---------------------------------------------------------------+

_______________________________________________
Discuss-gnustep mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/discuss-gnustep
Reply | Threaded
Open this post in threaded view
|

Re: GSPredicate

Fred Kiefer
You are referring to GSPredicateBlock not GSPredicate and this type gets defined on line 177 in  NSArray.h. It is an  NSBlock that can be used to filter the elements of an NSArray. The way this is done is a bit complex as GNUstep tries to support compilers (GC) that don‘t have build in support for NSBlock.

Hope this helps,
Fred

Unterwegs

> Am 16.06.2018 um 06:54 schrieb amon <[hidden email]>:
>
> GSPredicateBlock


_______________________________________________
Discuss-gnustep mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/discuss-gnustep
Reply | Threaded
Open this post in threaded view
|

Re: GSPredicate

amon
In reply to this post by amon
Yes, I found the macro. What is missing is a usage example
for the user documentation.

Without having to decompile the macro, how would a user figure
out how to actually use it?

I'd love to be pointed at some example code. I'm much more
likely to use a feature that doesn't require me to reverse
engineer and guess from source.

--
+---------------------------------------------------------------+
|   Dale Amon                  Immortal Data                    |
|   CEO             Midland International Air and Space Port    |
| [hidden email]       "Data Systems for Deep Space and Time"     |
+---------------------------------------------------------------+

_______________________________________________
Discuss-gnustep mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/discuss-gnustep
Reply | Threaded
Open this post in threaded view
|

Re: GSPredicate

Fred Kiefer
I was hoping for someone with a working knowledge of blocks to step in here. But currently I seem to be the only one operating this mailing list :-)

If you have a look in the file Tests/base/NSArray/blocks.m you will find examples on how to write an NSBlock for a compiler that supports it. A very simple one would be this:
^() { return YES; }

You should also be able to simulate blocks with gcc, but I am not sure how to do this :-(

> Am 16.06.2018 um 08:18 schrieb amon <[hidden email]>:
>
> Yes, I found the macro. What is missing is a usage example
> for the user documentation.
>
> Without having to decompile the macro, how would a user figure
> out how to actually use it?
>
> I'd love to be pointed at some example code. I'm much more
> likely to use a feature that doesn't require me to reverse
> engineer and guess from source.


_______________________________________________
Discuss-gnustep mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/discuss-gnustep
Reply | Threaded
Open this post in threaded view
|

Re: GSPredicate

David Chisnall-7
On 17 Jun 2018, at 22:48, Fred Kiefer <[hidden email]> wrote:
>
> I was hoping for someone with a working knowledge of blocks to step in here. But currently I seem to be the only one operating this mailing list :-)
>
> If you have a look in the file Tests/base/NSArray/blocks.m you will find examples on how to write an NSBlock for a compiler that supports it. A very simple one would be this:
> ^() { return YES; }
>
> You should also be able to simulate blocks with gcc, but I am not sure how to do this :-(

You can, in theory, simulate blocks with any C compiler, but in practice it’s too hard. A block is a structure that contains pointers to other structures that describe all of the captured variables and how to copy them.  For anything beyond a simple function written as a block, the compiler is generating a load of helper code for copying the captures.

The GSBlock stuff allows a legacy compiler to *call* blocks (by casting them to a compatible structure type and calling the invoke function with a pointer to the struct as the first argument) but it doesn’t make any attempt to allow compilers for pre-2007 dialects of Objective-C to generate blocks.  The logic in the compiler for doing so is several hundred lines of code and integrates with understanding of object lifetimes - replicating this in C macros is not feasible.

David


_______________________________________________
Discuss-gnustep mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/discuss-gnustep
Reply | Threaded
Open this post in threaded view
|

Re: GSPredicate

amon
In reply to this post by amon
Just to bring this back to my original question:

NSUInteger i;
NSMutableArray *a;
NSEnumerationOptions opts;
GSPredicateBlock      predicate;

i = [a indexOfObjectWithOptions: opts passingTest: predicate];

What is the code to set up predicate using the GSBlock macro?
Can someone show me what the above would look like as a working
bit of code?

--
+---------------------------------------------------------------+
|   Dale Amon                  Immortal Data                    |
|   CEO             Midland International Air and Space Port    |
| [hidden email]       "Data Systems for Deep Space and Time"     |
+---------------------------------------------------------------+

_______________________________________________
Discuss-gnustep mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/discuss-gnustep
Reply | Threaded
Open this post in threaded view
|

Re: GSPredicate

Fred Kiefer


> Am 18.06.2018 um 17:32 schrieb amon <[hidden email]>:
>
> Just to bring this back to my original question:
>
> NSUInteger i;
> NSMutableArray *a;
> NSEnumerationOptions opts;
> GSPredicateBlock      predicate;
>
> i = [a indexOfObjectWithOptions: opts passingTest: predicate];
>
> What is the code to set up predicate using the GSBlock macro?
> Can someone show me what the above would look like as a working
> bit of code?

Just replacing predicate with the one example I gave should work.

_______________________________________________
Discuss-gnustep mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/discuss-gnustep
Reply | Threaded
Open this post in threaded view
|

Re: GSPredicate

David Chisnall-7
In reply to this post by amon
On 18 Jun 2018, at 16:32, amon <[hidden email]> wrote:

>
> Just to bring this back to my original question:
>
> NSUInteger i;
> NSMutableArray *a;
> NSEnumerationOptions opts;
> GSPredicateBlock      predicate;
>
> i = [a indexOfObjectWithOptions: opts passingTest: predicate];
>
> What is the code to set up predicate using the GSBlock macro?
> Can someone show me what the above would look like as a working
> bit of code?

You cannot create blocks with a compiler that does not support blocks.

If you look at the declaration of this, or Apple’s documentation, you will see that it expects a block of the form:

        BOOL(^)(id obj, NSUInteger idx, BOOL *stop)

You must therefore write such a block.  For example:

```objective-c
GSPredicateBlock predicate = ^()(id obj, NSInteger idx, BOOL *stop)
{
        if ([obj passesSomeTest])
        {
                // Include this one
                return true;
        }
        else if (idx = 32)
        {
                // Unconditionally include the thing at index 32, even if it fails the test.
                return true;
        }
        if ([obj isInvalid])
        {
                // If we find any invalid objects, then give up completely.
                *stop = YES;
        }
        return false;
}
```

David


_______________________________________________
Discuss-gnustep mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/discuss-gnustep
Reply | Threaded
Open this post in threaded view
|

Re: GSPredicate

amon
In reply to this post by amon
So you are saying this would be good to go?

NSUInteger i;
NSMutableArray *a;
NSEnumerationOptions opts;
GSPredicateBlock      predicate = ^() { return YES; }

i = [a indexOfObjectWithOptions: opts passingTest: predicate];


--
+---------------------------------------------------------------+
|   Dale Amon                  Immortal Data                    |
|   CEO             Midland International Air and Space Port    |
| [hidden email]       "Data Systems for Deep Space and Time"     |
+---------------------------------------------------------------+

_______________________________________________
Discuss-gnustep mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/discuss-gnustep
Reply | Threaded
Open this post in threaded view
|

Re: GSPredicate

David Chisnall-7
On 18 Jun 2018, at 16:49, amon <[hidden email]> wrote:
>
> So you are saying this would be good to go?
>
> NSUInteger i;
> NSMutableArray *a;
> NSEnumerationOptions opts;
> GSPredicateBlock      predicate = ^() { return YES; }
>
> i = [a indexOfObjectWithOptions: opts passingTest: predicate];

No, because that block does not take the correct number of arguments.  It might compile, but it would be undefined behaviour.  You must define a block that takes three arguments:

- The object being inspected
- The index of the object.
- A pointer to a BOOL that is used to stop early

You can see these types here:

https://github.com/gnustep/libs-base/blob/6c388830dac190452dd3bce617139a552d78519e/Headers/Foundation/NSArray.h#L177

       

        DEFINE_BLOCK_TYPE(GSPredicateBlock, BOOL, GS_GENERIC_TYPE(ElementT),
  NSUInteger, BOOL*);

BOOL is the return type of the block.

GS_GENERIC_TYPE(ElementT) is an ugly macro that allows us to use generic types with modern compilers and fall back to id for older ones.  The type of the first argument to the block is therefore either id (for older compilers or for arrays that don’t use generics) or the generic type of the NSArray (e.g. NSString for NSArray<NSString>).

NSInteger and BOOL* are the types of the next two arguments.

David


_______________________________________________
Discuss-gnustep mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/discuss-gnustep
Reply | Threaded
Open this post in threaded view
|

Re: GSPredicate

Fred Kiefer


> Am 18.06.2018 um 17:59 schrieb David Chisnall <[hidden email]>:
>
> On 18 Jun 2018, at 16:49, amon <[hidden email]> wrote:
>>
>> So you are saying this would be good to go?
>>
>> NSUInteger i;
>> NSMutableArray *a;
>> NSEnumerationOptions opts;
>> GSPredicateBlock      predicate = ^() { return YES; }
>>
>> i = [a indexOfObjectWithOptions: opts passingTest: predicate];
>
> No, because that block does not take the correct number of arguments.  It might compile, but it would be undefined behaviour.  You must define a block that takes three arguments:

I might be wrong here, but I think that with all compilers that I know about that code should work. The compiler will complain about the type mismatch but if you do not access the arguments you should be able to have them on the stack with any issue.
Of course your example is a lot more correct (and actually useful!) but the code above should basically work, although I didn’t try it.


_______________________________________________
Discuss-gnustep mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/discuss-gnustep