4 ms·
But when you define a function (or a class), you are also inventing your own little dialect/dsl. Operating overloading is another. They can all be used well or
by hyperpallium 9y ago
But when you define a function (or a class), you are also inventing your own little dialect/dsl. Operating overloading is another. They can all be used well or confusingly.
Where do you draw the line? At least with functions, there's only one syntactic structure that is user-definable, making it easy to distinguish foreground from background.
- simias 9y ago> But when you define a function (or a class), you are also inventing your own little dialect/dsl. I don't understand what you mean by that. When I call a function in Common Lisp I have some garantees, I know it won't change the value of the parameters that I pass by value, I know it won't add or remove variables from the current scope, I know that the parameters to the function will be evaluated before the invocation. For macros anything goes, for all you know it could expand to a RETURN-FROM and exit your function prematuraly, it could implicitly modify a local variable etc... > Operating overloading is another. They can all be used well or confusingly. I completely agree and I consider that operator overloading for anything that's not "semantically" equivalent to the builtin operator behaviour is inherently evil. It makes sense to overload "*" and "+" on a matrix or vector type, it doesn't make a lot of sense to overload "<<" or ">>" to deal with input/output. But obviously nobody would be insane enough to do that. When I read "a = b + c" in some C++ code I fully expect that "a" will be set to the value of a sum of "b" and "c", whatever makes sense for the types of "b" and "c". If adding "b" and "c" doesn't make any obvious sense semantically (adding database handles with strings) then it shouldn't be done. I think that it's easier to draw the line and design sane guidelines for when you're allowed to implement overloaded operators. Macros have much broader use cases.
- hyperpallium 9y ago> inventing your own little dialect of the language which is opaque to any 3rd party reading your code unless they take the time to unravel your macros. I meant that a whole bunch of specialzed functions can also be a dialect, which are opaque unless one takes the trouble to look into them. You can write very confusing code, unless it matches up closely to a domain (and even then, you need to be on top of the domain). Of course, the "unraveling" is easier, (and less literal) than for macros. I was just trying to say it's a difference in degree not in kind - if you measure in terms of power and usability. I take your point that it's not just syntax, but differences in (basic) guarantees, so there's less ability to treat it as a black box (information hiding within a module). But any module (e.g. a fn) can behave differently from how you expect. tl;dr macros vs fn is a difference in degree, in terms of outcome (i.e. confusion).
- kazinator 9y agoThe reason you know that a function won't modify locals is not because of limitations on what a function can do, but because of what has not been done locally: your lexical scope has not been captured in a lexical closure; or else, that closure has not escaped; or else, if it has escaped, its body doesn't contain any code which mutates variables. The space of things that a function won't do is tiny compared to the space of what it may. You've taken a vast universe of possible behavior and eliminated from it a few possibilities like mutation of a local variable in the caller; that still leaves a vast space. Generally, to maintain code, at some point you have to grapple with understanding what it does more than with what it doesn't do.
- ngrilly 9y ago> But when you define a function (or a class), you are also inventing your own little dialect/dsl. No. When you define a function or a class, you define a new vocabulary (a new verb, a new name), but you don't change the grammar. Macros are a different beast because they can change the grammar.