Simulating Keyword Arguments

From LineComments:

  super(new GridLayout(2,1)); // 2 rows, 1 column

For some reason, if this comment isn't there, I have to think and then go look at the javadoc. Because there's a hole in my brain and "number of rows comes first" keeps falling out of it.

The lack of keyword arguments in Java was mentioned as the reason this kind of "comment smell" was necessary. Discussion of how to simulate keyword arguments in languages that don't have them was refactored from that page:

What about

  int rows, columns;
  super(new GridLayout(rows = 2, columns = 1));
Maybe not too useful in this situation, but I have found it nice when writing tests, and I want to invoke a function with a series of different arguments. Is this usage of assignment just plain ugly?

Or:

 super( new GridLayout( (int rows = 2), (int cols = 1) ) ) ;
Which is similar, but has less NamespacePollution?.


The extra storage is not really necessary.

 super( new GridLayout(
     2,                      // rows
     1                       // columns
 ));

What's the advantage of this over the original form, or the slightly less redundant

 super(new GridLayout(2,1)); // rows, columns

?

This style works well with Win32. This example is not characteristic of when parameter lists are sufficiently long to cause problems. If you are really stuck, you usually can just wave the mouse cursor over the token and read a tooltip with the signature. Assuming you are using a decent environment.

If the parameter list is not sufficiently long to cause problems, why treat it as if it is? Incidentally, I think you meant "my favourite environment", unless you're really saying that no other features could possibly compensate for not having signature tooltips activated by waving the mouse cursor over the token.


From time to time I've done this:

  super(new GridLayout( /* rows = */ 2, /* columns = */ 1 ));
(...and even confessed my crimes! ;-)

Outside of the SmalltalkLanguage, the lack of named parameters can really be a drag, at times. -- JeffGrigg

I think that's one of the reasons why XML DOMs are so nice. Well, well written DOMs, not the usual OO monkey gyms people write. My example below about initializing members directly really comes from an XML DOM in C++. There's vastly more going on that what I allude to, but fundamentally if you want to parameterize the XML element you just do something akin to rect->m_Attributes[Rect::X] = 42;. Nothing like rect->set(1,2,3,4); which could mean (x,y,width,height) or (x1,y1,x2,y2) or (top,left, bottom,right) or--increduously--(top,left,right,bottom). Note the array indexed by an enumeration? I'll leave implementing reflection as an exercise for the reader. -- SunirShah


Consider (in C++):

    class Rows {
        int n;
    public:
        Rows( int nn ) : n(nn) {};
        int get() const { return n; }
    };
    class Cols {
        int n;
    public:
        Cols( int nn ) : n(nn) {};
        int get() const { return n; }
    };

class Layout { public: Layout( Rows r, Cols c ) rows(r.get()), cols(c.get()){ //... }; //... };

super(new GridLayout(Rows(2),Cols(1))); super(new GridLayout(Cols(2),Rows(1))); // Compile error.

This gives you keyword arguments in C++, albeit for a lot of work. Something similar will be possible in Java, although probably not as efficiently. -- DaveHarris


Not to sound stuffy, but I think you're all forgetting to relate the code to what's happening in the real world. It seems like the code ought to be something like

  #define GLOTTLE_STOP_ROWS 2
  #define GLOTTLE_STOP_COLS 1
  super(new GridLayout(GLOTTLE_STOP_ROWS,GLOTTLE_STOP_COLS));

This avoids the unnecessary storage, but of course its really ugly. I tend to avoid line comments so that they don't have to be lined up, thus:

  // specify a layout for a glottle-stop.  Note: rows,cols
  super(new GridLayout(2,1));

What you might want to really solve is the problem where the "other programmer" writes a prototype with several true/false parameters:

   errcode = glottle_stopper(housekeeping, glottle, TRUE, TRUE, FALSE);
I've had success switching these to enumerations with mnemonic mnemonics. -- JohnStoshMuczynski


At the risk of being pedantic, there is a way in C++ to give mnemonic labels to the parameters of GridLayout() without using any storage, without using comments, and without using the hated #define:

 const int rows = 2;
 const int columns = 1;
 super(new GridLayout(rows,columns));

Actually, there is no guarantee that no storage will be used for this, but a decent C++ implementation should use literals in place of rows and columns. -- MikeSmith

So then you'd have

  // specify a layout for a glottle-stop.
  // User story 123 specifies why the 2,1 sizing works
  // so much better than the 2,2 sizing.
  const int glottle_stop_rows = 2;
  const int glottle_stop_columns = 1;
  super(new GridLayout(glottle_stop_rows, glottle_stop_columns)); 
-- JohnStoshMuczynski

Use:

enum {rows = 1; columns = 2};

(with your preference of returns and tabs). This documents the call and is sufficient for a single call of this type. It is also clear that this is a defined constant value and you do not have to rely on the compiler to eliminate storage. -- WayneMack


As GridLayout comes from Java, try the following, for the same effect:

  final int rows = 2;
  final int cols = 1;
  super(new GridLayout(rows, cols));

Again, a decent Java compiler should inline the references.


Ol' Venerable C

 typedef struct {
     int rows;
     int columns;
 } GridLayout;

GridLayout gridLayout; gridLayout.rows = 2; gridLayout.columns = 1;

I have realized there are SelfDocumentingCode advantages to assigning directly to members. Some people have complained that this is more complex than writing a constructor. I strongly suspect this is because they value encapsulation more than is pragmatically necessary, perhaps because Booch was ingrained into us so dogmatically not so long ago? -- SunirShah

Um... What happens when you need to add another variable, say, cellspacing (which may defaults to 1) to the struct GridLayout?

 typedef struct {
     int cellspacing;
     int rows;
     int columns;
 } GridLayout;
 GridLayout defaultGridLayout = { 1, 0, 0 };

GridLayout gridLayout = defaultGridLayout; gridLayout.rows = 2; gridLayout.columns = 1;


EditText of this page (last edited February 14, 2002) or FindPage with title or text search