Search code examples
inno-setuppreprocessor

Why would we need to use the #expr directive in Inno Setup?


Here's the documentation for Inno Setup Preprocessor: #expr and this one is for Inno Setup Preprocessor: Preprocessor output.

Why would we want to use the #expr directive?


Solution

  • I believe the #expr documentation explicitly mentions, why would you use the directive:

    This directive is intended to be used with functions that produce side effects and do not return any significant value.

    The documentation also shows a practical example of that:

    #expr SaveToFile(...)
    

    It seems that you do not know, what a side effect it. Check the Wikipedia article on Side effect (emphasis mine):

    Function ... is said to have a side effect if it modifies some state variable value(s) outside its local environment, that is to say has an observable effect besides returning a value (the main effect) to the invoker of the operation.

    In the case of the SaveToFile function, the side effect is the saving of the function parameter to a file. This particular function does not even return anything. So it would be safe to use it with the #emit directive:

    #emit SaveToFile(...)
    

    It would still save the file. And as the function "returns" void, it won't emit anything (though it actually emits an empty line, but that's in most cases ignored by Inno Setup). But it's confusing to use #emit, as a reader of the code might expect the function actually does return (and consequently emit) something. Use of the #expr explicitly shows that the expression (and whole directive) has no effect on the script contents.


    And with expressions/functions that do return something, like with ForceDirectories or Exec, you have to use #expr. Of course, it makes sense only in case you do not bother checking the results.

    #expr ForceDirectories(Path)
    

    With #emit, the function would emit its result, what would result in an invalid script.

    Another way to do, what #expr does, is using the #emit with a comma operator with void second parameter:

    #emit ForceDirectories(Path), void
    

    Though again, this emits an empty line. And it's less obvious, what you want to do, than with the #expr.