On 13 December 2012 08:16, Ciprian Teodorov <[email protected]> wrote: > > > On Thu, Dec 13, 2012 at 3:11 AM, Igor Stasenko <[email protected]> wrote: >> >> On 13 December 2012 03:08, Igor Stasenko <[email protected]> wrote: >> > On 11 December 2012 20:33, Ciprian Teodorov <[email protected]> >> > wrote: >> >> Hi guys, >> >> >> >> today I have commited to the NativeBoost repository a new core class, >> >> the >> >> NBExternalEnumerationType, >> >> which reifies the enum declarations in C and offers a nice interface >> >> (especially in terms of debug/inspect). >> >> >> >> To use it just subclass the NBExternalEnumeration and add an #enumDecl >> >> method to the class side such as: >> >> >> >> NBExternalEnumeration subclass: #NBTestEnumeration >> >> instanceVariableNames: '' >> >> classVariableNames: '' >> >> poolDictionaries: '' >> >> category: 'NativeBoost-Tests' >> >> >> >> NBTestEnumeration class>>enumDecl >> >> ^ {(#AAA -> 1). >> >> (#BBB -> 2). >> >> (#CCC -> 3). >> >> (#DDD -> 2400)} asDictionary >> >> >> > just one comment: imo, it would be better to not force users to >> > remember that they should use >> > complicated syntax in this method. >> > >> > i propose following syntax: >> > >> > NBTestEnumeration class>>enumDecl >> > ^ #( >> > #AAA 1 >> > #BBB -> 2 >> > #CCC -> 3 >> > #DDD -> 2400 >> > ) >> > >> oops, of course it should be just pairs, e.g.: >> #( A 1 B 2 C 3) >> Yep this is a good idea for most cases so I'll integrate it. But there are >> those cases where your enum has many items (more than the number of literals >> we can have in a method), and I think in those cases having the user give us >> a prebuilt dictionary is better.
and where you see many literals? #( ..... no matter how many stuff here ... ) is 1 (single) literal! .. (i wonder, why people keep confusing literals in method body versus stuff in a single literal array :) And you don't have to trust my word, you can check it by yourself, just evaluate: | x | x := #(A B C). ^ thisContext method literals size versus: | x | x := #(A B C D E F G H I J K L M N). ^ thisContext method literals size >> >> > then you can have >> > >> > NBTestEnumeration class>>initializeEnum >> > >> > dict := Dictionary newFromPairs: self enumDecl >> > ..... >> > >> > then #initialize should just do 'self initializeEnum' >> > >> > >> > >> >> DO NOT FORGET to call the #initialize method on your class. The rest is >> >> automatically done ;) >> >> >> >> You can use your new enum in two ways: >> >> >> >> add it to a client class poolDictionaries list (see >> >> #NBExternalEnumTests >> >> for an example), and then just write CCC in your code -- CCC here is an >> >> item >> >> of your enum >> >> or you can send the name of an item to your class --- NBTestEnumeration >> >> DDD >> >> >> >> The NBExternalEnumeration implements (instance and class) some more >> >> API >> >> methods like: >> >> >> >> #itemAt: retrieves the item having a specific value --- >> >> NBTestEnumeration >> >> itemAt: 2 >> >> #includes: checks the existence of a specific item in the enum --- >> >> NBTestEnumeration includes: #AAA >> >> >> >> Having this already gives us a nice interface to working with enums. >> >> Now I >> >> plan to improve a little bit on performance and usage scenarios: >> >> >> >> the possibility to accept smalltalk integers as valid input/output for >> >> functions(or callbacks) that use enums as arguments/return. >> >> support the different representation types for the enum values >> >> (int/uint) >> >> >> > >> > to my thinking, it not worth implementing separate type converter for >> > enums.. >> > just put a note that if people would like to deal nicely with enums >> > returned by function(s), >> > they should use a converter , something like that: >> > >> > enumValue := MyEnumeration fromInteger: (self >> > callSomeFunctionReturningInt) > > This is a good idea too. >> >> > >> > then this method can implement converting from int->enum object, >> > as well as do a range checking etc. >> > in same way, if people want to use 'enumValue' for passing it as >> > parameter to external function, >> > they should not pass it directly , but use 'enumValue value' >> > >> > In general, it would be cool to have good 'enum type' converter.. >> > (despite that i will never use it, >> > because to my taste its not really worth it, and i can live with >> > integers and in most cases you hide such low-level details from >> > end-user anyways ;)) >> > but for those, who want more clarity and better structure in their >> > code, of course, they can use it . >> > > > I do not completely agree with you on this one (but you already now it). The > thing is that if we use integers then the user will have to constantly ask > which enum value should I pass here... The idea is to not expose enum values to user at all. Sometimes it easily doable, sometimes not.. it depends , of course.. But ideally, there should be only messages. > If you want that you can always have > it by declaring your function signature as #(void fct(int anEnumValue)) and > then call it with MyEnum DDD value (that's fine). Having an enum type > converter is very good for documenting the argument types (and automatically > checking them). True. But everything has its cost: in this case - performance. > So I think this should be the user choice. Moreover, I'm for > incremental development (and learning) so the way I see it is: When you > first implement the ffi wrapper just try to be as precise as you can be, > then after your library binding is done you can change some declarations to > use more 'low level types' (the underlying representation) for speed reasons > mainly (if it ever comes to that). > Yes. > But at the end I think we should give our users options, which will help > them make decisions based on their particular needs, not based on our "gut" > feeling ;) > I agree that this will be nice addition: for better coverage alien (C) data structures. I am totally with you on that. I just wanted to say that i never thought about it as a necessary part (simply because i can live without it). -- Best regards, Igor Stasenko.
