Path: csiph.com!usenet.pasdenom.info!weretis.net!feeder4.news.weretis.net!eternal-september.org!feeder.eternal-september.org!mx02.eternal-september.org!.POSTED!not-for-mail From: Steve Thompson Newsgroups: comp.lang.c Subject: Re: New directions in C Date: Fri, 10 Apr 2015 18:54:06 +0000 Organization: Friends of the Galactic Collective Lines: 159 Message-ID: References: <16ea447a-b16a-4171-8d1f-252e3ae3ab39@googlegroups.com> <4c38b587-5a66-47fe-8df0-3cbe2ff1ec42@googlegroups.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Injection-Info: mx02.eternal-september.org; posting-host="dfca600df3027c25a5e3889f25105c66"; logging-data="334"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+fBVjwm6wWpSNYaKYsXRdG" User-Agent: NN 6.4.3 Cancel-Lock: sha1:Pfy5L0AG40X2X/nIljwcGNBb0A4= Xref: csiph.com comp.lang.c:59885 On Fri, Apr 10, 2015 at 12:22:05PM +0100, Bartc wrote: > On 10/04/2015 11:53, Richard Heathfield wrote: > >On 10/04/15 11:26, Bartc wrote: > > >>Actually it can save typing, as you can do this: > >> > >>callfn(file:f); > >> > >>instead of: > >> > >>callfn(0, 0, 0, NULL, 1, 0, 1, 1, f, NULL); > > > >That's crying out to be made a struct pointer argument, which reduces it > >to: > > > >callfn(f, NULL); > > > >without changing the language. > > No, you just have to change the entire library! And there's the little > matter of having to define and initialise the struct somewhere. (And the > reader having to deal with such disjointed bits of code.) > > (MS likes to use such structs extensively in their Windows APIs. But > because I had the temerity to call these APIs from my own language, I > had to painstakingly construct an exactly compatible struct each time I > came across a new one. And it was still a PITA to use. I think that's > why I switched over to using the C runtime library for many things. > > Function calls on the same machine, however, are more standardised and > are easier to call from a different language.) > > >>initwindow(width:640, height:480); > >> > >>instead of: > >> > >>initwindow(640, 480); > > >>initwindow(window_width, window_height); > > >I don't see why these are macros. Surely, if you're going to have a > >fixed size for the window's width and height, initwindow will already > >know these sizes. So you can save even more typing, again without having > >to change the language, because you don't have to pass any arguments at > >all! > > No, initwindow allows different sizes of window. But if you only intend > to use a fixed size in your use of it, then normal C obliges you to pass > the dimensions. > > Then, if there are several calls to initwindow(), it makes sense to use > macros. > > My example wasn't about defaults either, but if defaults were used, and > they happened to be (640,480) or you made it that way because it's in > one of your libraries, then you could actually write: > > initwindow(); > > and get the default size. Christ. That's what descriptors are for. How about initwindow(params), where params is a structure pointer describing the window parameters. One of the things about wimp interfaces is that there are generally a zillion little things to set or tune. I would go mad if I was required to use functions expecting tens of function arguments, which is why in my own code I have settled on a parameters structure containing all of the flags and whatnot required to set up the module instance. My avl tree module has the following parameters structure: struct avl_params { str_ing file; avl_compare compare; void * ctxt; avl_ptr start_size; avl_ptr max_nr_nodes; u32 xpn_factor; + u32 nr_bulk; u32 sleep_interval; + u32 spin_max; + u32 nr_pauses; + u8 prefer_readers; + u8 prefer_writers; + u8 allow_dups; u8 mt_safe; u8 mt_update; u8 load_file; u8 save_file; u8 map_file; u8 tlm_record; tlm_rowctr tlm_nr_drows; rwlock_params lock; /* See rwlock.h. */ mem_pool_params pool; /* See mem_pool.h */ obj_id_ptr id; /* See obj_id.h */ }; Granted that a handful of the top-level parameters are duplicates (marked with a +) of items found in rwlock and mem_pool parameters structures, but that is only a convenience for people who might be confused by nested structures. I have a trivial 'avl_params_init' macro that sets sane defaults, and that's that. The prototype for avl_open() is nothing more than "avl * avl_open(avl_params *)". The principle of module design implicit here is extended to the full API, so I have an avl_op structure which is passed to the avl_operation() function: struct avl_op { u8 code; u8 status; u16 reserved; AVL_KEY key; AVL_KEY item; u64 latency; avl_ptr tree_size; avl_tlm * tlm; }; This structure also has its own avl_op_init macro. And so forth. One of the side-effects of this arrangement is that there is next to no copying occuring. Code making use of avl tree primitives (probe, update, insert, delete) declare the avl_op structure on their stack, its elements are filled out and then it's pointer is passed to the function(s) doing the work. This arrangement has the properties of intrinsic efficiency and simplicity. Now consider the notion of functions with default arguments in this scenario. First you must define the function such that it will accept all of the above structure elements individually AND you require that the language is modified to fill in elements that you do not explicitly include in the function call. PLUS you must identify the function arguments that you do use by prefixing them with their identifier. I suppose the compiler can define a structure for you and hide the details of its allocation and initialization to avoid the cost of pushing each individual function argument on the stack, but so what. It is still ugly. Furthermore, I suspect your default function arguments will be be program wide for any given module, rather than specific to a module instance, which limits their utility considerably. So while I am not exactly pleased to find myself in agreement with Mr. Heathfield, I must say that this suggestion is a Bad Idea. The general technique as illustrated above is more than adequate to obviate the need for functions with more than two or three arguments, and that is a 'win'. Regards, Steve Thompson -- "If I had a nickel for every time some idiot called me about a computer problem that turned out to be user error, I would be able to retire and spend the rest of my days cultivating clues in my backyard hillside garden." -- MysteryDog in 24hoursupport.helpdesk.