brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (04/01/91)
So far, people have given lots of examples of lists of union types. Message queues, for instance, are usually union types. The arguments to printf are union types (though they're not typechecked---I think most people consider this a flaw in the interface). Symbolic manipulation routines deal with union types. People have also given the example of ``list of object that understands foo,'' where foo is an operation. In object-oriented languages, such objects are basic types anyway, so these *still* aren't heterogeneous lists. Does anyone have an example of a heterogeneous list---something beyond unions and callback functions---used in a real program? I suspect not. After all, if a module is like printf and understands all the possible types of objects in the list, it's dealing with a union type. If a module does not know all the possible types, it's going to see just a set of function pointers, and it won't even *want* to deal with the object except through those function pointers. If there is a middle case, how would you use it? ---Dan
lavinus@csgrad.cs.vt.edu (04/02/91)
Hi out there! I make no claims as to how good this example is, nor whether I might have done this in a better way using something other than heterogeneous collections, but here is a 'real' example: I recently wrote a shift-reduce parser in Lisp, to parse infix mathematical expressions. The stack for the actual parser contains both token (terminal) descriptions, representations of nonterminals, and integers representing the state of the underlying FSM in the parser. Additionally, for the code generation portion, there is a "semantic stack" which stores the types of variables (for variables), values of various types of constants, and mathematical operators (+, -, etc.). The only easy way I can see to do this complete system in C or whatever is to either break it up into about five different stacks, or to keep a stack of pointers of type void. Like I say, this may not be a great example, but it does exist as an example of a heterogeneous collection in action. Flames graciously accepted :-). Joe -- _________________________________ \ ___________________________________ Joseph W. Lavinus, Virginia Tech \ email: lavinus@csgrad.cs.vt.edu 1204-A University Terrace /\ phone: (703) 552-0241 Blacksburg, VA 24060 / \ (703) 231-5853
new@ee.udel.edu (Darren New) (04/03/91)
In article <167:Mar3121:32:0891@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes: >So far, people have given lots of examples of lists of union types. >Does anyone have an example of a heterogeneous list---something beyond >unions and callback functions---used in a real program? I think the type system is the way you look at things, not the way you implement them. Dynamic typing is usually going to be implemented with unions and callback functions. To say that printf does not have a hetrogeneous list of arguments but rather a list of unions kind of begs the question. printf's implementation has all the drawbacks of dynamic typing that people have pointed out: extra runtime overhead, misinterpretation of bits when the expected type doesn't match the stated type, and so on. I see unions as hetrogeneous types themselves. I can see only three uses for unions: 1) saving space (by only using one element at a time), which isn't needed if you have real dynamic typing. 2) type punning, which isn't needed unless you are hacking bits, and isn't excluded by dynamic type systems, 3) making hetrogeneous arrays, like symbol tables or printf arguments. I think part of the problem here is that Dan Bernstein is saying "there is no such thing as a hetrogeneous collection" without giving a clear definition of a hetrogeneous type. If you have a definition in mind, why don't you post it, Dan? If you don't, why don't you accept one of the two or three that have come across the net already. I naturally like mine, but choose any you want and I'll try to find an example. If you are going to say "there is no definition of hetrogeneous collection which I will accept" then I can't see how you can contribute anything meaningful to the discussion; maybe you can clarify it. As always, it's all in your mind, and if you insist on talking about implementation of dynamic types or hetro lists only, while refusing to look at it from the next level of abstraction up, I don't see anywhere that communication between you and others can progress. >I suspect not. After all, if a module is like printf and understands >all the possible types of objects in the list, it's dealing with a union >type. And exactly how is an array of unions different from a hetrogeneous array? >If a module does not know all the possible types, it's going to >see just a set of function pointers, and it won't even *want* to deal >with the object except through those function pointers. Again, how is this different from a hetrogeneous array? Nobody said that hetro arrays could not be implemented with unions and callbacks. I just don't know what that has to do with whether they are hetro arrays or not. >If there is a >middle case, how would you use it? Can you define "middle case"? --Darren -- --- Darren New --- Grad Student --- CIS --- Univ. of Delaware --- ----- Network Protocols, Graphics, Programming Languages, FDTs ----- +=+=+ My time is very valuable, but unfortunately only to me +=+=+ + When you drive screws with a hammer, screwdrivers are unrecognisable +
new@ee.udel.edu (Darren New) (04/03/91)
In article <167:Mar3121:32:0891@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes: >Does anyone have an example of a heterogeneous list---something beyond >unions and callback functions---used in a real program? What about Pascal's WRITELN function? Please separate what the language defines from the compiler's implementation of that functionality. An analogy: "Does anyone have an example of a recursive call -- something beyond pushing arguments and return addresses on stacks -- used in a real program?" Do you see the problem? How can you possibly answer that? How do you answer when I say "Well, with a suitable preprocessor, you can put recursion on top of a non-recursive language, so its all syntactic sugar." The syntactic sugar is what makes it work. *Everything* is syntactic sugar for machine language. We are discussing what syntactic sugar is good and bad and worthwhile and not. To repeatedly say that it *is* just syntactic sugar seems to miss the point and certainly fails to communicate any valuable information. -- Darren -- --- Darren New --- Grad Student --- CIS --- Univ. of Delaware --- ----- Network Protocols, Graphics, Programming Languages, FDTs ----- +=+=+ My time is very valuable, but unfortunately only to me +=+=+ + When you drive screws with a hammer, screwdrivers are unrecognisable +
hoelzle@neon.Stanford.EDU (Urs Hoelzle) (04/03/91)
new@ee.udel.edu (Darren New) writes: >printf's implementation has all the drawbacks of dynamic >typing that people have pointed out: extra runtime overhead, >misinterpretation of bits when the expected type doesn't match the >stated type, and so on. IMHO, "dynamic typing" is not equivalent to "weak typing" (and "static typing" isn't the same as "strong typing"). For example, it is impossible to "misinterpret bits" in Self (a dynamically-typed language). That is, you'll never have bugs/behavior which cannot be explained at the language level. Examples: Self: dynamically-typed, strongly-typed C: statically-typed, weakly-typed Ada: statically-typed, strongly-typed (as far as I know) BTW, some languages are between static and dynamic typing; Simula, for example, has a type-test operator in addition to static typing; if you use the type qualification operator you may have run-time type errors. In any case, printf is an example of weak typing, not dynamic typing. -Urs -- ------------------------------------------------------------------------------ Urs Hoelzle hoelzle@cs.stanford.EDU Center for Integrated Systems, CIS 42, Stanford University, Stanford, CA 94305
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (04/04/91)
In article <49591@nigel.ee.udel.edu> new@ee.udel.edu (Darren New) writes: > To say that printf does not have a > hetrogeneous list of arguments but rather a list of unions kind of begs > the question. No, it doesn't. Because varargs are a poorly defined hack, printf cannot in practice typecheck its arguments, but the arguments are nevertheless constrained to come from one of several types---{int,long,float,double, ptr-to-char}, for example. A function taking a heterogeneous argument can be given types not specifically anticipated by the function writer. This is a necessary, though not sufficient, restriction, which still eliminates printf. > I see unions as hetrogeneous types > themselves. Unions are not heterogeneous types. Period. Except for a restriction that union { struct { int a; ... } x; struct { int b; ... } y; } have a and b overlap, union could be implemented as struct. (I don't recall how ANSI formalizes this restriction.) > I think part of the problem here is that Dan Bernstein is saying "there > is no such thing as a hetrogeneous collection" without giving a clear > definition of a hetrogeneous type. I gave the canonical example of a heterogeneous type when I entered this discussion: viz., the set of all (expressible) values. People can argue at length about whether the set of SOME values is a heterogeneous type, for various meanings of SOME. > >I suspect not. After all, if a module is like printf and understands > >all the possible types of objects in the list, it's dealing with a union > >type. > And exactly how is an array of unions different from a hetrogeneous array? How is any type different from a heterogeneous array? Among other things, a heterogeneous array can contain types allowed by the language, but not anticipated by whoever defines how the array is going to be used. > >If a module does not know all the possible types, it's going to > >see just a set of function pointers, and it won't even *want* to deal > >with the object except through those function pointers. > Again, how is this different from a hetrogeneous array? See above. > >If there is a > >middle case, how would you use it? > Can you define "middle case"? A module that does not know all the types it can deal with, but wants to deal with more than just function pointers to perform operations. ---Dan
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (04/04/91)
In article <49605@nigel.ee.udel.edu> new@ee.udel.edu (Darren New) writes: > In article <167:Mar3121:32:0891@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes: > >Does anyone have an example of a heterogeneous list---something beyond > >unions and callback functions---used in a real program? > What about Pascal's WRITELN function? Please separate what the language > defines from the compiler's implementation of that functionality. I have never read the Pascal language definition. As far as I know, writeln can only take values of certain types, as defined beforehand by the implementation. [ further comments ] So you agree that C++, which provides the union types and callback functions (a.k.a. objects) with a reasonable syntax, suffices for everything you can think of to do with heterogeneous lists? In other words, you agree that people don't use heterogeneous lists except in ways handled by a *statically* typed language? ---Dan
new@ee.udel.edu (Darren New) (04/04/91)
In article <167:Mar3121:32:0891@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes: >Does anyone have an example of a heterogeneous list---something beyond >unions and callback functions---used in a real program? >I suspect not. After all, if a module is like printf and understands >all the possible types of objects in the list, it's dealing with a union >type. Hmmm.... I don't remember ever seeing unions in printf(). Let's see: void printf(char *, ... ); /* no unions here */ printf("hello: %d, %f", 3 * 5, 18.2); /* no unions here */ void printf(char * fmt, int args) /* old style ... */ { /* no flames about off-the-cuff code please */ char * ptr = (char *) &args; char buf[big]; ... switch (*fmt++) { case 'd': itoa(*(int *) ptr, buf); puts(buf); ptr += sizeof(int); break; /* no unions there */ case 'f': ftoa(*(float *) ptr, buf); puts(buf); ptr += sizeof(float); break; /* no unions here */ ... } } I don't see anywhere that this particular kind of printf implementation, declaration, or use ever mentions a union. Since sizeof(any_C_type) is fixed, I don't see how printf() could be using a C union. Unless you meant some other kind of union, in which case you will have to tell me how to distinguish between an array of sorta-unions-of-various-sizes is different from an array of things of different types. -- Darren -- --- Darren New --- Grad Student --- CIS --- Univ. of Delaware --- ----- Network Protocols, Graphics, Programming Languages, FDTs ----- +=+=+ My time is very valuable, but unfortunately only to me +=+=+ + When you drive screws with a hammer, screwdrivers are unrecognisable +
new@ee.udel.edu (Darren New) (04/04/91)
In article <1991Apr3.013413.8428@neon.Stanford.EDU> hoelzle@neon.Stanford.EDU (Urs Hoelzle) writes: >new@ee.udel.edu (Darren New) writes: >>printf's implementation has all the drawbacks of dynamic >>typing [...] misinterpretation of bits [...] >In any case, printf is an example of weak typing, not dynamic typing. Good point. It is, however, an example of hetrogeneous lists. "Misinterpretation of bits" in a static type language is similar to "message not found" in dynamic type languages like Smalltalk. That is, after all, what "message not found" means: that you tried to interpret "true" as an integer and "+" wasn't defined. Of course, since C is staticly typed, the analogy will be flawed. -- Darren -- --- Darren New --- Grad Student --- CIS --- Univ. of Delaware --- ----- Network Protocols, Graphics, Programming Languages, FDTs ----- +=+=+ My time is very valuable, but unfortunately only to me +=+=+ + When you drive screws with a hammer, screwdrivers are unrecognisable +
new@ee.udel.edu (Darren New) (04/04/91)
In article <10977:Apr319:27:2891@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes: >In article <49591@nigel.ee.udel.edu> new@ee.udel.edu (Darren New) writes: Just to recap and attempt to avoid confusion, the discussion (as I understand it) is whether there is such a thing as a "real" hetrogeneous collection, rather than either unions or bunches of callback functions. "unions" can be taken (from a later post of Dan's) to mean "the callee knows all possible types" rather than the C unions I thought he meant. I asked Dan to clarify some of his terms, which he did admirably. I herein attempt to present some hetrogeneous collections/functions using Dan's definitions. >A function taking a heterogeneous argument can be given types not >specifically anticipated by the function writer. This is a necessary, >though not sufficient, restriction, which still eliminates printf. OK. So this is part of your definition for hetrogeneous collections. >> I see unions as hetrogeneous types >> themselves. >Unions are not heterogeneous types. Period. I phrased this wrong. *In C*, unions are used primarily to save space, bang bits, or implement hetrogeneous types. In symbol tables, for example, they are used to implement multiple different interpretations of bits within the same array. That's why I prefaced my comment with "I see": because I understand that any given union is a fixed type, but in cases where they are used, they are usually used to declare a variable able to take on multiple types in reality but restricted to a single type formally. You recognise this by saying that unions could be implemented as structures except for the requirement that their elements overlap. Overlap is primarily of interest to space savers and bit bangers, not to hetrogeneous typists, since hetro-typists would not (on purpose) take advantage of the overlap by reading an element after assigning a different element. Hence, to define a structure as containing an integer, a float, and a char pointer and then to use only one of those entries for the lifetime of that structure would seem more like an implementation of dynamic typing on top of static-typing restrictions than it would the use of a homogenous type. That's not really clear, but it isn't too important because that isn't the point I want to address here. >I gave the canonical example of a heterogeneous type when I entered this >discussion: viz., the set of all (expressible) values. OK. In Smalltalk, I declare a variable alpha just by giving its name. I can assign to that variable any expressible value. That declaration hence (by your definition) names a variable of a hetrogeneous type. A collection of such variables (say, the locals of a method/function) would represent a hetrogeneous collection. Hence, Smalltalk supports hetrogeneous collections, not statically typed. The locals of a Smalltalk method thereby represent hetrogeneous collections (i.e., collections of hetrogeneous values) that are used in real life. >Among other >things, a heterogeneous array can contain types allowed by the language, >but not anticipated by whoever defines how the array is going to be used. This is how arrays are defined in Smalltalk. Every array in Smalltalk, including the global dictionary of declarations, is a real-life hetrogeneous array. It is not in any important sense an array of unions, nor is it always dealt with via function pointers. For example, looking up a name in the global dictionary does not involve any function pointers in any important sense, because all the names are of type Symbol and hence are all compared withe the same routine. However, the entries in the dictionary are all different types, namely 2-tuples of the form <Symbol, ???>, where the ??? can be any expressible value. In C, you would not be able to represent such a declaration, because C does not have a declaration for "any expressible value." Hence, different tuples would have different types for their second entry and hence the tuples would be of different types. [an acceptable example of a module dealing with hetrogeneous lists is] >A module that does not know all the types it can deal with, but wants to >deal with more than just function pointers to perform operations. OK. There is a Smalltalk function that is called "instanceAt:" which takes a value of any type and an integer offset and retrieves the value at that offset within the passed-in value. There is another one called "class" which takes any value and returns the type of that value. A third operation "new" takes a type and creates a new value of that type. None of these deals with function pointers in any way. Each is implemented only as a primitive of the language, and hence is implemented only once, rather than once for each type. For example, I can write a function in Smalltalk that iterates through any array passed to it and creates a new array containing the classes of the elements of the array: DECLARE makeClasses: inArray ! outArray ! <- sorry, pipe key is broken outArray <- Array new: inArray size. 1 to: inArray size do: [ :index ! outArray at: index put: (inArray at: index) class ] ^ outArray In this code, I get an inArray which is a collection of any expressible values. The calls to the functions (to:do:, new:, at:put:, at:, class) could all be statically bound to their appropriate implementations, and there is no important sense in which I am dealing with "pointers to functions." However, there are undoubtably values of multiple types here, and I'm doing things (class) with those values. You say, "So where is the "real world" program? What about the "copy" operation, which takes a value and makes a copy of it? It uses "class" to determine the type for the new value, creates such a value using "new", and finially it iterates through the old value using "instanceAt:" to get the old values and "instanceAt:put:" to store them in the new value. Still looking for a C function that accepts a hetrogeneous type, how about, in C, the sizeof "function"? It can accept types and variables that I have declared in C that the compiler-writers could not have anticipated me declaring in any important sense. It does not deal in any way with function pointers. At any time in my program, I can pass it a variable containing any expressible value, and it will return the number of bytes that that value requires to be stored. That I can not pass is an expression, but only a variable, is a restriction that I don't understand (except on ease-of-compiler-implementation grounds). If you wish to say it doesn't count because it isn't a real function but rather is built into the compiler, I will merely take this as one of the advantages of dynamic typing: one doesn't need to kludge function-like things into the compiler merely because the user cannot do it him/herself. -- Darren -- --- Darren New --- Grad Student --- CIS --- Univ. of Delaware --- ----- Network Protocols, Graphics, Programming Languages, FDTs ----- +=+=+ My time is very valuable, but unfortunately only to me +=+=+ + When you drive screws with a hammer, screwdrivers are unrecognisable +
new@ee.udel.edu (Darren New) (04/04/91)
>I have never read the Pascal language definition. As far as I know, >writeln can only take values of certain types, as defined beforehand by >the implementation. OK. Given the definition of "union" as "a value from a subset of types known at compilation-time of the callee", then writeln uses unions. [I said something like "What is dynamic typing but unions and callbacks?"] >So you agree that C++, which provides the union types and callback >functions (a.k.a. objects) with a reasonable syntax, suffices for ^^^^^^^^^^^^^^^^^ debatable :-) >everything you can think of to do with heterogeneous lists? In other >words, you agree that people don't use heterogeneous lists except in >ways handled by a *statically* typed language? No. If I write a "List" class, I don't want to restrict the types which can be put into a list. By an earlier post, you said that a hetrogeneous type is one which can contain "any expressible value", and the logical conclusion is that a hetro list is one which can contain multiple values, each of which is chosen from the set of any expressible values. Hence, by your definitions, C++ does not support hetro lists at all, since all values in a list must belong to classes which inherit from class ListEntry. And, as far as I can tell, this is due to the fact that C++ is statically typed and not from some other reason. All languages with which I am sufficiently familar to determine that they support hetrogeneous lists as you define them also support dynamic typing; that is, the ability to declare a variable capable of holding any expressible value. I suspect that this is the case for all languages, because it would be necessary in a statically typed language to have a "type" which is the "canonical hetrogeneous type" which could be used to declare variables, function results, and so on. In this case, it would seem to be a dynamically typed language, because you could just declare all your variables to be of that one type and never worry about any of the static typing or type checking. I think C++'s requirement that a value be declared to have a certain type is an impediment to reusability, especially of collection classes. If I don't make a class a subclass of a list-entry class, I can't put it in a list. The act of making it a subclass of ListEntry could break things in several ways, the least of which is not having access to all needed sources to recompile, or needing to write utilities to convert stored binary images of such classes to the new format before reading/writing them. As I previously described, whether or not an integer (say) can be a member of any given list seems totally orthagonal to the operations that should be available for an integer. The concept that I need to implement or even declare "find next element of current list" for integers, automobiles, employees, etc, seems unacceptable to me once I became experienced with languages where this is not needed. It would be like having to declare, at the time one declared a structure, the complete list of all functions which would return this structure. For any given program, you eventually do this; the difference is *where* you declare it, a purely syntactic distinction. I think a huge amount of things for which people use hetro lists today *could* be done with static typing, explicit unions, explicit callback functions, and sophisticated preprocessors. However, I don't see any real benefit to this except marginal efficiency. Allowing the mix of static and dynamic typing is the best, IMHO. However, I feel that in such a mix, static typing should be treated as a special case of dynamic typing rather than vica versa. I.e., there shouldn't be any place where a statically-typed variable is permitted that a dynamically typed variable is not. Making dynamically typed variables the special case, to be used only in special constructs, undermines their utility, since every general utility you write would still have to deal with both static and dynamic types. -- Darren -- --- Darren New --- Grad Student --- CIS --- Univ. of Delaware --- ----- Network Protocols, Graphics, Programming Languages, FDTs ----- +=+=+ My time is very valuable, but unfortunately only to me +=+=+ + When you drive screws with a hammer, screwdrivers are unrecognisable +
new@ee.udel.edu (Darren New) (04/04/91)
In article <10977:Apr319:27:2891@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes: >In article <49591@nigel.ee.udel.edu> new@ee.udel.edu (Darren New) writes: >> To say that printf does not have a >> hetrogeneous list of arguments but rather a list of unions kind of begs >> the question. > >No, it doesn't. Because varargs are a poorly defined hack, printf cannot >in practice typecheck its arguments, but the arguments are nevertheless >constrained to come from one of several types---{int,long,float,double, >ptr-to-char}, for example. I was taking "union" to mean "C union" rather than what you imply here. Also, I submit for consideration that varargs is a poorly defined hack due to the inherent lack of ability to manipulate "true" hetrogeneous lists in C. (Actually, varargs seems like a *well* defined hack compared to some of the other library routines. The implementation usually sucks. :-) If C could implement *real* hetrogeneous lists, the varargs "hack" would be neither poorly defined nor a hack. >A function taking a heterogeneous argument can be given types not >specifically anticipated by the function writer. This is a necessary, >though not sufficient, restriction, which still eliminates printf. OK. I was using a definition for "hetrogeneous" meaning "having different types" rather than "having different types and which the function writer didn't know about". I'll use your definition from now on. -- --- Darren New --- Grad Student --- CIS --- Univ. of Delaware --- ----- Network Protocols, Graphics, Programming Languages, FDTs ----- +=+=+ My time is very valuable, but unfortunately only to me +=+=+ + When you drive screws with a hammer, screwdrivers are unrecognisable +
lbruck@eng.umd.edu (Lewis Bruck) (04/17/91)
In article <49726@nigel.ee.udel.edu> new@ee.udel.edu (Darren New) writes: (...lots of stuff deleted...) > >Still looking for a C function that accepts a hetrogeneous type, how >about, in C, the sizeof "function"? It can accept types and variables >that I have declared in C that the compiler-writers could not have >anticipated me declaring in any important sense. It does not deal in >any way with function pointers. At any time in my program, I can pass >it a variable containing any expressible value, and it will return >the number of bytes that that value requires to be stored. That I can >not pass is an expression, but only a variable, is a restriction >that I don't understand (except on ease-of-compiler-implementation >grounds). > The sizeof "function" is resolved completely at compile time (simple lookup in the type information that the compiler (at whatever pass) has determined to find the physical size). >If you wish to say it doesn't count because it isn't a real function >but rather is built into the compiler, I will merely take this as one >of the advantages of dynamic typing: one doesn't need to kludge >function-like things into the compiler merely because the user cannot >do it him/herself. Would be nice if it occured at run-time, though (makes functions a lot more general :-) > -- Darren > Lewis Bruck lbruck@eng.umd.edu
new@ee.udel.edu (Darren New) (04/18/91)
In article <1991Apr17.040927.21608@eng.umd.edu> lbruck@eng.umd.edu (Lewis Bruck) writes: >The sizeof "function" is resolved completely at compile time (simple >lookup in the type information that the compiler (at whatever pass) >has determined to find the physical size). I know this. What is your point? (If it was just to enlighten me, thanks, but I've been programming in C for 7 years. :-) --------------------- I didn't want to start this thread up again, but since it's started again, I just wanted to mention a couple of things I thought of. The two main uses I see for hetrogeneous lists and dynamic typing that cannot be conveniently done with static typing are these: 1) A hetrogeneous list used for resource management. For example, the environment list, the xrdb program, etc. This is normally solved by storing everything as strings, but that requires parsing that shouldn't be necessary (e.g., storing a path as a colon-spearated string). This can be done correctly (and sufficiently conveniently for me) with a polymorph type. Hermes has such a type: any value can be "wrapped" into a polymorph and later unwrapped back into a namipulable value, at which time it is runtime checked to be the right type. I think most of the other stuff about sorting and such can be done with generics well enough. 2) An object-oriented object. Static languages have these, but if I want an object that can do A,B,C,D,E,F, and G, and another object that can do A, C, D, F, and G, and a third one that can do B, C, E, and F and ....... then defining these as all statically typed can be ugly. For example, a menu that responds to "up", "down", and "picked", a scrolling window that responds to "up", "down", and "contents" and "picked", and a button that responds to "contents" and "picked". In the degenerate case, you need gobs of declarations of different subsets, all of which may change when you need a new subset that picks different functions out of them. I don't know any convenient way of handling this without casts or dynamic binding. --------------------------- Did ya ever notice how the nifty language research (like Hermes or Modula-3) always implements languages under UNIX, and nifty OS research (like NeXT IB or Ameoba) always writes the OS in C? Yuck! Why not put Hermes under Ameoba, or use Modula-3 to write IB or something? :-) -- Darren -- --- Darren New --- Grad Student --- CIS --- Univ. of Delaware --- ----- Network Protocols, Graphics, Programming Languages, FDTs ----- +=+=+ My time is very valuable, but unfortunately only to me +=+=+ +=+ Nails work better than screws, when both are driven with screwdrivers +=+