<div dir="ltr">On Fri, Jan 11, 2013 at 12:12 PM, Jed Brown <span dir="ltr"><<a href="mailto:jedbrown@mcs.anl.gov" target="_blank">jedbrown@mcs.anl.gov</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>Ah, Dependency versus Duplication. I blame the lack of transparency on the editors, which could display the definition of the typedef instead of having to jump to it. I like that the typedefs allow us to document the function in one place and that changing arguments (hopefully only while working out the initial implementation, but whenever it's deemed necessary) is more reliable. Since dynamic functions are cast to void(*)(void), the compiler may not be able to check that types match. Also, ability to grep for any place that a given callback is manipulated.</div>
<div><br></div><div>Pros of typedef:</div><div>* typedef is, in principle, "safer" for developers</div><div><div>* typedef helps avoid duplication in documentation; maintains symmetry between Get() and Set()</div>
<div>* typedef uses simpler type notation (nice for less experienced C programmers)</div></div><div><br></div><div>Cons of typedef:</div><div>* typedef is less transparent when reading code</div><div>* information is more scattered (harder for people that don't have the source code indexed and don't know where to find definitions)</div>
<div>* because every usage does not need to be updated, it's hard to determine consequences of a change when reading diff</div><div><br></div><div>I'll stop using function pointer typedefs if you don't like them.</div>
</div></blockquote><div><br></div><div style>I don't like them either, but I agree with you that this is a technical problem that could be solved, just not by us.</div><div style><br></div><div style> Matt</div><div>
</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">On Fri, Jan 11, 2013 at 10:26 AM, Barry Smith <span dir="ltr"><<a href="mailto:bsmith@mcs.anl.gov" target="_blank">bsmith@mcs.anl.gov</a>></span> wrote:<br>
<div class="gmail_extra"><div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><br>
The thing I don't like about typedef's for function pointers is that they do not display the calling sequencing in the code<br>
<br>
For example from<br>
<div><br>
> typedef struct _n_TSDM *TSDM;<br>
> struct _n_TSDM {<br>
> TSRHSFunction rhsfunction;<br>
<br>
</div> or<br>
<br>
PetscErrorCode TSSetRHSFunction(TS ts, TSRHSFunction rhsfunction)<br>
<br>
I have no freaking idea what the calling sequence of rhsfunction is. but with<br>
<div><br>
> typedef struct _n_TSDM *TSDM;<br>
> struct _n_TSDM {<br>
</div>> PetscErrorCode (*TSRHSFunction)(TS,PetscReal,Vec,Vec,void*);<br>
<br>
or<br>
<br>
PetscErrorCode TSSetRHSFunction(TS ts, PetscErrorCode (*TSRHSFunction)(TS,PetscReal,Vec,Vec,void*);<br>
<br>
boom I know exactly the calling sequence.<br>
<br>
Maybe there is some way we can do manual pages for these beasties and consistency of names in different locations so we get the best of both worlds?<br>
<span><font color="#888888"><br>
Barry<br>
</font></span><div><div><br>
<br>
<br>
On Nov 25, 2012, at 3:58 AM, Jed Brown <<a href="mailto:jedbrown@mcs.anl.gov" target="_blank">jedbrown@mcs.anl.gov</a>> wrote:<br>
<br>
> On Sun, Nov 25, 2012 at 4:42 AM, Barry Smith <<a href="mailto:bsmith@mcs.anl.gov" target="_blank">bsmith@mcs.anl.gov</a>> wrote:<br>
><br>
> typedef struct _n_KSPDM *KSPDM;<br>
> struct _n_KSPDM {<br>
> PetscErrorCode (*computeoperators)(KSP,Mat,Mat,MatStructure*,void*);<br>
> PetscErrorCode (*computerhs)(KSP,Vec,void*);<br>
> PetscErrorCode (*computeinitialguess)(KSP,Vec,void*);<br>
><br>
> typedef struct _n_SNESDM *SNESDM;<br>
> struct _n_SNESDM {<br>
> PetscErrorCode (*computefunction)(SNES,Vec,Vec,void*);<br>
> PetscErrorCode (*computegs)(SNES,Vec,Vec,void*);<br>
> PetscErrorCode (*computejacobian)(SNES,Vec,Mat*,Mat*,MatStructure*,void*);<br>
><br>
> /* objective */<br>
> PetscErrorCode (*computeobjective)(SNES,Vec,PetscReal*,void*);<br>
><br>
><br>
> typedef struct _n_TSDM *TSDM;<br>
> struct _n_TSDM {<br>
> TSRHSFunction rhsfunction;<br>
> TSRHSJacobian rhsjacobian;<br>
><br>
> TSIFunction ifunction;<br>
> TSIJacobian ijacobian;<br>
><br>
> The PETSc style guide says to avoid typedef of function pointers unless there is a damn good reason to use them (or it should);<br>
><br>
> Can we revisit this choice in the interest of writing one man page that documents the assumptions that one can make about a callback routine? I hate duplicating the same information in TS{Set,Get}IFunction() and DMTS{Set,Get}IFunction(). Also, if a typedef is used everywhere, we can more reliably find all places that depend on it. (using grep or M-x gtags-find-symbol).<br>
><br>
> but why use them for TS but not for SNES or KSP functions?<br>
><br>
> Because they were already defined for use with TSSetIFunction()/TSGetIFunction().<br>
<br>
</div></div></blockquote></div><br></div></div>
</blockquote></div><br><br clear="all"><div><br></div>-- <br>What most experimenters take for granted before they begin their experiments is infinitely more interesting than any results to which their experiments lead.<br>
-- Norbert Wiener
</div></div>