Gotchas

From Rosetta Code
Revision as of 14:31, 12 July 2022 by PureFox (talk | contribs) (Created new draft task and added a Wren example.)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Gotchas is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
Definition

In programming, a gotcha is a valid construct in a system, program or programming language that works as documented but is counter-intuitive and almost invites mistakes because it is both easy to invoke and unexpected or unreasonable in its outcome.

Task

Give an example or examples of common gotchas in your programming language and what, if anything, can be done to defend against it or them without using special tools.


Wren

There are 3 gotchas in Wren which immediately spring to mind because they've bitten me more than once in the past.

1. The classic 'if (a = b) code' problem which everyone who's familiar with C/C++ will know about and which is already adequately described in the linked Wikipedia article together with the standard remedy.

2. In Wren, class fields (unlike variables) are never declared but instead their existence is deduced from usage which can be in any method of the class. This is possible because fields (which are always private to the class) are prefixed with a single underscore if instance or a double underscore if static, and no other identifiers are allowed to begin with an underscore. Fields are always assigned the value 'null' unless they are assigned to immediately.

Normally, this works fine but the problem is that if you mis-spell the field name, then it won't be picked up by the compiler which will simply allocate a slot for the mis-spelled field within the class's fields symbol table. You may therefore end up assigning to or referencing a field which has been created by mistake!

The only defence against this gotcha is to try and keep field names short which reduces the chance of mis-spelling them.

3. Wren's compiler is single pass and if it comes across a method call within a class which has not been previously defined it assumes that it will be defined latter. Consequently, if you forget to define this method later or have already defined it but then mis-spelled or misused it, the compiler won't alert you to this and at some point a runtime error will arise.

The same defence as in 2. above can be used to defend against this gotcha though, if the methods are public (and hence need self-explanatory names), it may not be practical to keep them short.

I've tried to construct an example below which illustrates these pitfalls. <lang ecmascript>class Rectangle {

   construct new(width, height) {
       // Create two fields.
       _width = width
       _height = height
   }
   area {
      // Here we mis-spell _width.
      return _widht * _height
   }
   isSquare {
       // We inadvertently use '=' rather than '=='.
       // This sets _width to _height and will always return true.
       if (_width = _height) return true
       return false
   }
   diagonal {
       // We use 'sqrt' instead of the Math.sqrt method.
       // The compiler thinks this is an instance method of Rectangle
       // which will be defined later.
       return sqrt(_width * _width + _height * _height)
   }

}

var rect = Rectangle.new(80, 100) System.print(rect.isSquare) // returns true which it isn't! System.print(rect.area) // runtime error: Null does not implement *(_) System.print(rect.diagonal) // runtime error (if previous line commented out)

                           // Rectangle does not implement 'sqrt(_)'</lang>