© The Author(s), under exclusive license to APress Media, LLC, part of Springer Nature 2022
A. DanialPython for MATLAB Developmenthttps://doi.org/10.1007/978-1-4842-7223-7_15

15. Language Pitfalls

Albert Danial1  
(1)
Redondo Beach, CA, USA
 

15.1 Troublesome Language Features

Neither MATLAB nor Python are ideal languages. Both have annoying and downright dangerous aspects—at least for novice programmers unfamiliar with more subtle aspects of the languages’ designs. Detractors of one or the other language are keen to point out the other’s flaws while brushing off criticism of their preferred language.

15.2 MATLAB

  • Dangerous: Mixed-type mathematical expressions are typecast downward instead of upward.

>> a = uint8(1) - 0.6
a =
    uint8
    0
The result of 0 instead of 0.4 is astonishing (or, more plainly put, flat-out wrong). MATLAB stands alone in this design choice. C, C++, Fortran, Go, Java, JavaScript, Julia, Mathematica, OCaml, Python+NumPy, R, Rust, and Scala all typecast upward and yield the expected result of a floating-point value of 0.4 for the preceding calculation. It goes without saying that MATLAB’s downcasting can lead unsuspecting developers to incorrect results.
  • Dangerous: MATLAB’s “every conceivable function exists in the namespace” can cause unexpected behavior when running the same m-file on computers with the same version of MATLAB but different toolboxes.

  • Annoying: While an .m file may contain multiple functions, none of these may be called from other .m files unless the file with these functions is converted into a class. Code in large projects that don’t embrace object-oriented programming ends up spread over hundreds of .m files. This adds logistical hassle to code editing, debugging, and project file management.

  • Annoying: Matrix slices inherit the dimensions of the original matrix rather than the dimension of the slice itself. For example, if we create a 4D matrix and then extract a 1D slice along each dimension, the result has either two, three, or four dimensions:

>> a = rand(3,4,5,6);
>> size(a)
     3     4     5      6
>> size(a(:,1,1,1))
     3     1
>> size(a(1,:,1,1))
     1     4
>> size(a(1,1,:,1))
     1     1     5
>> size(a(1,1,1,:))
     1     1     1       6
This causes problems for functions such as plot() that cannot handle more than two dimensions:
>> plot(a(:,1,1,1))   % plot appears
>> plot(a(1,:,1,1))   % plot appears
>> plot(a(1,1,:,1))
Error using plot
Data cannot have more than 2 dimensions.
To get the desired behavior—a slice with just one dimension in this example—one must explicitly call squeeze() on the slice.
  • Annoying: The default emacs keybindings (control-w and control-y to cut and paste; control-x control-s to save, and so on) irritate new MATLAB users. The rest of the world has adopted Windows keybindings (control-c and control-v to cut and paste; control-s to save, etc.) for GUI applications. Although the MATLAB IDE allows one to change the keybinding to Windows style (Home/Environment/Preferences/Keyboard/Shortcuts/Active Settings/Windows Default Set), a few users seem to be aware of this and continue with the default.

  • Annoying: One cannot cut and paste function definitions to the MATLAB prompt—“Error: Function definition not supported in this context. Create functions in code file.” This impedes rapid sandbox testing of simple functions.

  • Annoying: One cannot control whether arguments passed to MATLAB functions are pass-by-value or pass-by-reference.1 Technically, all arguments are pass-by-reference, but MATLAB’s just-in-time (JIT) compiler employs copy-on-write logic that may or may not honor the code’s repeated use of input and output arguments. The performance penalty can be severe if the JIT compiler decides to copy rather than use a variable in-place.

  • Annoying: It is not possible to determine which toolboxes a MATLAB program needs unless the toolboxes are already installed. In other words, if one receives a MATLAB program from an external source, the matlab.codetools.requiredFilesAndProducts() function only reports toolbox dependencies in the program for toolboxes found on the computer running the function.

  • Annoying: The keyword end closes index ranges, classes, functions, if blocks, for loops, while loops, switch/case statements, try/catch blocks, and possibly other language constructs. While the MATLAB IDE makes it easy to see what construct an end closes, viewing an m-file with a less sophisticated editor or on paper, a web page, a PDF or Word document can make this pairing quite challenging.

  • Annoying: Is it a function or a data structure? MATLAB’s use of parentheses to pass arguments to a function and to index matrices and cell arrays makes it impossible to look at code, for example, grF(x), and tell whether the symbol grF is a function or a data container. In Python, one can immediately identify grF(x) as a function call and grF[x] as an indexed data container.

  • Annoying: The MATLAB File Exchange hosted by The MathWorks is a helpful repository of m-files contributed by users. Unlike other code sharing sites such as GitHub or SourceForge, downloads from the File Exchange require an authenticated login. This nuisance inhibits MATLAB code sharing.

15.3 Python

  • Dangerous: Lists and NumPy arrays are bounds-checked when indexed by scalar indices, but not index ranges. This can allow errors to propagate silently through a program (Section 4.​3.​6).

  • Dangerous: When the right-hand side of an equals sign is a data structure, the variable on the left-hand side becomes a reference to the right-hand side, not a copy of it (Section 4.​8). Thus, if A is a list, dictionary, NumPy array, and so on, the assignment B = A leaves one with two variables that point to the data. Changes to A become changes to B and vice versa. To have B contain a copy of A’s data, one must import the copy module and use its copy() or deepcopy() functions . Developers unaware of Python’s reference copy behavior are likely to see corrupted data and incorrect results from their code.

  • Annoying: Index slices M:N and calls to range(N) and np.arange(N) are maddening to MATLAB programmers who expect N to appear. The “don’t use the end value” behavior of these constructions takes a long time to get used to.

  • Annoying: NumPy and SciPy both have linear algebra submodules called linalg with common functions but different capabilities. For example, scipy.linalg.eig() can solve both standard (Ax = λx) and general (Ax = λBx) eigenvalue problems, while numpy.linalg.eig() only solves the standard problem. At a minimum, the built-in documentation for both functions should have a “See also” entry that refers to its companion in the other module.

  • Annoying: Compared to MATLAB’s comprehensive implementation of sparse matrices, Python’s sparse matrices feel like second-class citizens.

  • Annoying: Typecasting NumPy arrays requires a different notation than typecasting scalars. These examples demonstrate the syntax for converting scalars and arrays from integers to doubles:

In : I_scalar = 4  # 64 bit integer
In : I_array  = np.array(([5, 6]), dtype=np.int64)
In : D_scalar = np.double(I_scalar)        # <- type cast scalar
In : D_array = I_array.astype(np.double)   # <- type cast array
The I.astype(np.double) notation is not intuitive. It would be clearer if one could just write np.float(I) to typecast a NumPy array as well as a scalar to a float.
  • Annoying: Virtual environments are a drag. They add unwelcome complexity by forcing one to fragment collections of modules among multiple environments and then having to remember which environment is capable doing.

  • Annoying: Compared to the uniformly high quality of built-in MATLAB documentation, documentation for the many Python modules one needs for science and engineering work varies widely in quality, style, and location. While a good Internet connection and web browser often yield answers to complex Python questions quickly, developers on isolated networks struggle in this regard.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.47.59