From: <jk...@ik...> - 2004-11-17 13:10:44
|
[Apologies if this message is a duplicate; it seems that Gmane ate my previous attempt at replying, since I sent another message to the list before acking Gmane's autoreply.] Andrew Straw writes: > To me, nargout, like so much of Matlab, is a brutish hack introduced > because that language is not as capable or elegant as Python. Arguably Matlab has the elegant Lisp-like feature lacking in Python of multiple return values. In Lisp you can write (setq x (floor 3.14)) to set the value of x to 3, or (multiple-value-setq (x y) (floor 3.14)) to set the value of x to 3 and the value of y to 0.14. Note how it is left up to the caller of the FLOOR function whether to capture just the first returned value or both of them. This is paralleled by Matlab's x = some_function(a,b,c) [x,y] = some_function(a,b,c) where the caller decides how many values will be returned. I imagine nargout could have arisen as an optimization aid: if a value is not needed, the function can decide to not compute it. A reasonably good Lisp compiler would probably do this optimization automatically, but Matlab is (or was, until some recent version?) an interpreted language with fewer opportunities for optimization. Where Matlab goes terribly wrong (IMHO) is in that it encourages abuse of the nargout mechanism: built-in functions like find change their behavior depending on how many return values are expected. In effect, the name "find" denotes two different functions, dispatched by the value of nargouts. > Regardless of whether your sense of aesthetics is different than mine, > the kind of low-level shenanigans suggested as a work-around seems, at > the very least, brittle and prone to maintenance and portability > issues. (Would that even work on IronPython or PyPy?) I imagine that the Psyco JIT compiler might have some problems with the hack. I would like to amend my suggestion upthread: instead of changing mlab.find, add another function, say find2 unless someone thinks of a better name, that always returns a tuple. The current version of find could be left as it is, or, even better (this might be important for automatic Matlab-to-Python translation), changed to return a single index for any kind of array. This would require a mechanism for addressing array elements by a single index, which probably doesn't exist. For Matlab compatibility, the addressing should use the column-major, i.e., Fortran, order. In fact, I don't see why this wouldn't solve the problem of automatic translation of functions that use nargout. The value of nargout is a static feature of the function call, so the translator should easily be able to dispatch according to the value, or add it as a keyword argument. That is, if the user has a function like function [a,b]=foo(bar) switch nargout, case 1, a=bar; case 2, a=1; b=bar; end the translator could produce the Python function def foo(bar, nargout=0): if nargout==1: return bar; elif nargout==2: return (1,bar); and translate foo(1); a=foo(2); [b,c]=foo(3); to foo(1); a=foo(2,nargout=1); (b,c)=foo(3,nargout=2); I wouldn't do this for find, since (in my experience) the two-return-value form of find is the more common case, and it would not be very nice to always type in the nargout parameter when using matplotlib interactively. > it seems to me that early design mistakes resulted in terrible > backwards compatibility issues, as well. For example, I remember > being driven mad trying to figure out whether parentheses were > needed when calling certain functions. I guess for some they are > required and for others they aren't. I wonder if this is the same problem that I had for a long time: I finally realized that Matlab either does both auto-parenthesizing and auto-quoting, or neither of them, so print -depsc2 fname is equivalent to print('-depsc2', 'fname') so if you want to create one of the parameters dynamically, you cannot use the first form but will have to write something like print('-depsc2', sprintf('picture-%d', num)) (Then there is the confusion of {} vs () indexing, and cell strings that are almost like real strings but sometimes need a {:} after them, except that if you get them from a function, since the parser gets confused if you type fun(param){:} so you need a temp variable, and cell arrays of structs that sometimes act like structs of cell arrays... Automatic translation of Matlab code will certainly have some interesting challenges.) -- Jouni K Seppänen |