1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Function containing iff doesn't work in build 48

Discussion in 'Support' started by David Marcus, Apr 27, 2010.

  1. David Marcus

    Joined:
    Jun 4, 2008
    Messages:
    646
    Likes Received:
    1
    Why doesn't MakeDir1 in the Test.btm file below work? It works in build 41.

    C:\Junk>ver /r

    TCC 11.00.48 Windows Vista [Version 6.0.6002]
    TCC Build 48 Windows Vista Build 6002 Service Pack 2
    Registered to davidmarcus - 1 System License

    C:\Junk>type Test.btm
    *setlocal
    function MakeDir1=`iff not isdir "%1" then %+ mkdir /n /s "%1" %+ endiff %+ echo done1`
    function MakeDir2=`echo start2 %+ iff not isdir "%1" then %+ mkdir /n /s "%1" %+ endiff %+ echo done2`
    echo MakeDir1
    %@MakeDir1[C:\Doc]
    echo MakeDir2
    %@MakeDir2[C:\Doc]

    C:\Junk>Test.btm
    MakeDir1
    MakeDir2
    start2
    done2

    C:\Junk>

    Here it is with "echo on" in the btm:

    C:\Junk>Test.btm
    function MakeDir1=`iff not isdir "%1" then %+ mkdir /n /s "%1" %+ endiff %+ echo done1`
    function MakeDir2=`echo start2 %+ iff not isdir "%1" then %+ mkdir /n /s "%1" %+ endiff %+ echo done2`
    echo MakeDir1
    MakeDir1
    echo MakeDir2
    MakeDir2
    echo start2
    start2
    iff not isdir "C:\Doc" then
    echo done2
    done2

    C:\Junk>
     
  2. Steve Fabian

    Joined:
    May 20, 2008
    Messages:
    3,523
    Likes Received:
    4
    | Why doesn't MakeDir1 in the Test.btm file below work? It works in
    | build 41.
    ...
    | function MakeDir1=`iff not isdir "%1" then %+ mkdir /n /s "%1" %+ endiff
    %+ echo done1`
    ...

    Your MakeDir1 and MakeDir2 seem to define aliases, not variable
    functions. Using the value of a variable function as a command, as
    your TEST.BTM does, seems to stretch even the DWIM parser! What
    surprises me is your claim it worked in an earlier build. If it did,
    my guess is that it did by chance, not design. Variable functions are
    intended to return a string or numeric value, to be used in the same
    way as the value of an internal or environment variable, i.e., as a
    command parameter. Your function MakeDir1 returns the string done1 to
    be used as a command. MakeDir2 returns two lines as a single command.

    Your function definitions should not surround %1 by quotation
    marks (though irrelevant in your example of C:\DOC) because they must
    be included in the CALL to the function when the desired path
    contains whitespace, else the part following the whitespace would not
    be part of %1. If the path is already quoted, the quotation marks in
    the function definition would make it look like:

    iff not isdir ""C:\Progarm Files\ABC"" then ...

    which would yield syntax error.

    BTW, remember that SETLOCAL does NOT work on functions. If you use a
    global list for functions, all changes to the function table are
    global, regardless of the use of SETLOCAL.
    --
    Steve
     
  3. David Marcus

    Joined:
    Jun 4, 2008
    Messages:
    646
    Likes Received:
    1
    OK, but the Help says, "User-defined functions are powerful alternatives to subroutines." So, that's where I got the idea that they worked like subroutines. In quite a few languages, functions and subroutines are both procedures that can be called.

    I know. I had %$, but changed it when simplifying the example.
     
  4. Steve Fabian

    Joined:
    May 20, 2008
    Messages:
    3,523
    Likes Received:
    4
    | ---Quote (Originally by Steve Fbin)---
    | Your MakeDir1 and MakeDir2 seem to define aliases, not variable
    | functions. Using the value of a variable function as a command, as
    | your TEST.BTM does, seems to stretch even the DWIM parser! ---End
    | Quote---
    | OK, but the Help says, "User-defined functions are powerful
    | alternatives to subroutines." So, that's where I got the idea that
    | they worked like subroutines. In quite a few languages, functions
    | and subroutines are both procedures that can be called.

    That statement was dropped from V11 HELP. It was present in the HELP of
    earlier versions, but was using incorrect terminology, because in languages
    such as Fortran which use the term SUBROUTINE the term usually refers to a
    procedure that performs some action without returning any value to its
    caller. These languages use the term FUNCTION when the procedure returns a
    value, using the same terminology as mathematics. AFAIK only the C and C++
    languages include procedures not returning a value (more technically
    "function returning void") in their use of the term FUNCTION.

    Regardless, your goal can be achieved more clearly by defining the very same
    actions as aliases. I did not test, by have no doubt that making them
    aliases will result in exactly what you want, with more readable code.
    Furthermore, you can actually just use the alias

    MakeDir=*mkdir/s/ne

    which will silently ignore a request to create an existing directory, but
    will report an error if the specified directory does not exist when the
    command is completed.


    | ---Quote---
    | Your function definitions should not surround %1 by quotation
    | marks (though irrelevant in your example of C:\DOC) because they must
    | be included in the CALL to the function when the desired path
    | contains whitespace, else the part following the whitespace would not
    | be part of %1.
    | ---End Quote---
    | I know. I had %$, but changed it when simplifying the example.

    I recommend frequent use of the @QUOTE[] function, esp. when names are
    generated automatically.
    --
    Steve
     
  5. David Marcus

    Joined:
    Jun 4, 2008
    Messages:
    646
    Likes Received:
    1
    It is still in my copy of the V11 Help on the "FUNCTION" page.

    PHP is another.

    I assume I can use the /nt and /ne options together. A /e option would be more logical than overloading the /n option. One has to read the Help carefully to find all the options. Any idea in what version the /ne option appeared?
     
  6. Steve Fabian

    Joined:
    May 20, 2008
    Messages:
    3,523
    Likes Received:
    4
    | ---Quote (Originally by Steve Fbin)---
    || That statement was dropped from V11 HELP.
    | ---End Quote---
    | It is still in my copy of the V11 Help on the "FUNCTION" page.

    You are right, it is still there. What confused me was that in the older
    HELP versions using the "search" tab with the string "subroutine" the topic
    FUNCTION is listed, but not in the V11 HELP.

    || Furthermore, you can actually just use the alias
    ||
    || MakeDir=*mkdir/s/ne
    ||
    || which will silently ignore a request to create an existing
    || directory, but
    || will report an error if the specified directory does not exist when
    || the
    || command is completed.

    | I assume I can use the /nt and /ne options together. A /e option
    | would be more logical than overloading the /n option. One has to
    | read the Help carefully to find all the options. Any idea in what
    | version the /ne option appeared?

    Proper combined use of the suboptions is /net, and is valid. The e and t
    suboptions of /N appeared in V7 for the MD/MKDIR command. Yes, a plain /e
    might be simpler, but the option letter E is not available in every command
    where it makes sense. This is the reason why the /N command with suboptions
    was introduced in V7, to permit as closely identical syntax as possible of
    different commands, one of the great benefits of using TCC instead of the
    POSIX style of "a separate little program for each minor task (with its own
    unique syntax)".

    Documenting the suboptions in the quick help is difficult.
    --
    Steve

    I agree that in some commands
     
  7. David Marcus

    Joined:
    Jun 4, 2008
    Messages:
    646
    Likes Received:
    1
    Seems to me that TCC should generate an error rather than accepting incorrect syntax.
     
  8. Steve Fabian

    Joined:
    May 20, 2008
    Messages:
    3,523
    Likes Received:
    4
    | ---Quote (Originally by Steve Fbin)---
    || Using the value of a variable function as a command, as your
    || TEST.BTM does, seems to stretch even the DWIM parser!
    | ---End Quote---
    | Seems to me that TCC should generate an error rather than accepting
    | incorrect syntax.

    I think your syntax was correct, but totally unexpected. While I have used
    the value of a variable as a command, I never stretched that idea to using
    the value of a variable function as a command, and the individual commands
    executed during calculation of the function value as "subroutine steps".
    Undoubtedly Rex will provide a better explanation.

    Note that the value returned by either of your functions is an empty string,
    which is a legal command. The embedded "echo" commands are executed without
    a return value.
    --
    HTH, Steve
     
  9. rconn

    rconn Administrator
    Staff Member

    Joined:
    May 14, 2008
    Messages:
    9,726
    Likes Received:
    80
    Despite your puzzling usage of UDFs instead of aliases, using the obsolete
    %+ construct, and using IFF when a plain IF would do, your batch file is
    working fine here in build 48:


    MakeDir1
    done1
    MakeDir2
    start2
    done2

    Rex Conn
    JP Software
     
  10. Charles Dye

    Charles Dye Super Moderator
    Staff Member

    Joined:
    May 20, 2008
    Messages:
    3,277
    Likes Received:
    38
    There seems to be a lot of that going around.
     
  11. David Marcus

    Joined:
    Jun 4, 2008
    Messages:
    646
    Likes Received:
    1
    The reason was to avoid (accidentally) interfering with commands. Using UDFs keeps the subroutines used by the batch file separate from the commands that are used from the command line. Essentially, a separate namespace.

    I used to have different command separators on different computers. If I recall, the default command separator changed at some point in the past. Plus, the command separator is configurable. %+ always has the same meaning.

    IFF is more readable since the command is separated from the condition.

    Still not working here on two different computers. Computer 1:

    Microsoft Windows [Version 6.0.6002]
    Copyright (c) 2006 Microsoft Corporation. All rights reserved.

    c:\>"\Program Files\JPSoft\TCMD11\tcc.exe" /i

    TCC 11.00.48 Windows Vista [Version 6.0.6002]
    Copyright 2010 Rex Conn & JP Software Inc. All Rights Reserved
    Registered to davidmarcus - 1 System License

    c:\>Junk\Test.btm
    setlocal
    echo off
    MakeDir1
    MakeDir2
    start2
    done2

    c:\>type Junk\Test.btm
    *setlocal
    echo off
    function MakeDir1=`iff not isdir "%1" then %+ mkdir /n /s "%1" %+ endiff %+ echo done1`
    function MakeDir2=`echo start2 %+ iff not isdir "%1" then %+ mkdir /n /s "%1" %+ endiff %+ echo done2`
    echo MakeDir1
    %@MakeDir1[C:\Doc]
    echo MakeDir2
    %@MakeDir2[C:\Doc]

    c:\>

    Computer 2:

    Microsoft Windows [Version 6.1.7600]
    Copyright (c) 2009 Microsoft Corporation. All rights reserved.

    C:\>"\Program Files\JPSoft\TCMD11x64\tcc.exe" /i

    TCC 11.00.48 x64 Windows 7 [Version 6.1.7600]
    Copyright 2010 Rex Conn & JP Software Inc. All Rights Reserved
    Registered to davidmarcus - 1 System License

    C:\>Junk\Test.btm
    setlocal
    echo off
    MakeDir1
    MakeDir2
    start2
    done2

    C:\>type Junk\Test.btm
    *setlocal
    echo off
    function MakeDir1=`iff not isdir "%1" then %+ mkdir /n /s "%1" %+ endiff %+ echo done1`
    function MakeDir2=`echo start2 %+ iff not isdir "%1" then %+ mkdir /n /s "%1" %+ endiff %+ echo done2`
    echo MakeDir1
    %@MakeDir1[C:\Doc]
    echo MakeDir2
    %@MakeDir2[C:\Doc]

    C:\>
     
  12. David Marcus

    Joined:
    Jun 4, 2008
    Messages:
    646
    Likes Received:
    1
    It would be nice if the Help page for "+ (pseudovariable)" said it was obsolete and said what to use instead.
     

Share This Page