Loading ...
Sorry, an error occurred while loading the content.

Understanding Writing Subroutines

Expand Messages
  • Bob Gorman
    Bob McAllister, ... Music to my ears! I had hoped so, since I do a lot of my idea development in Logo, which greatly supports Lists, Words (Strings), Arrays,
    Message 1 of 11 , Apr 13, 2006
    • 0 Attachment
      Bob McAllister,
      At Thursday 12:30 AM 4/13/2006, you wrote:

      >What you are hoping to do is certainly possible using a custom
      >function so long as you switch from Replace to StrReplace.

      Music to my ears!

      I had hoped so, since I do a lot of my idea development in Logo, which
      greatly supports Lists, Words (Strings), Arrays, and a few specials, I then
      want to move my final code to NoteTab Clip Language. Most of it has been
      going OK, but this subroutine call or function nesting had me frustrated.


      >Here are your clips reworked.
      >
      >H="m2y"
      >^!Set %trans%=^$StrReplace("me";"you";"^&";0;1)$
      >^!Set %trans%=^$StrReplace("I was";"you were";"^%trans%";0;1)$
      >^!Set %trans%=^$StrReplace("I'm";"you're";"^%trans%";0;1)$
      >^!Set %trans%=^$StrReplace("I";"you";"^%trans%";0;1)$
      >^!Set %trans%=^$StrReplace("myself";"yourself";"^%trans%";0;1)$
      >^!Set %trans%=^$StrReplace("my";"your";"^%trans%";0;1)$
      >^!Set %Result%=^$StrReplace("mine";"yours";"^%trans%";0;1)$
      >
      >H="Call m2y"
      >^!Set %Ans%=^?{Text to be manipulated}
      >Original:
      >^%Ans%
      >Reversed:
      >^$m2y(^%Ans%)$

      I learn best by studying an example first and only then exploring the
      general case. So this example really helped.
      Thanks!

      >Note that when a custom function (in this case m2y) is called by
      >another clip, any parameters passed come in identified as ^&. So that
      >is the string on which the first StrReplace acts.

      That makes it clear to me.

      >The variable %trans%
      >is one i created to make the cascade through seven string replacements
      >manageable. If you are better at counting brackets than I am, you
      >could put them all in a single line nested seven deep (and avoid the
      >use of %trans% entirely).

      I greatly prefer using %trans% over nesting, because this and my other text
      analysis software is constantly evolving as I test it out. Making changes
      to the %trans% version is easy; to the nested version, which you put in
      your 2nd post, it would be virtually impossible. On this particular
      function, one of the improvements I made over time was actually switching
      the order of the replacements, so ease of modification is paramount for me.

      > The 0;1 parameters at the end of the line
      >are to make the replacement case insensitive but whole words only.

      I hadn't run into a case so far, but I believe setting the Whole Word Only
      flag is the right way to go.

      >The key to using a custom function is to assign the output to the
      >special variable %Result%.

      That helps immensely.

      >When calling the custom function (or sub-routine) you do not need to
      >use the ^!Clip command (even though you are calling a clip). When
      >NoteTab does not recognise the function name ^$m2y()$ it looks for a
      >clip m2y in your current library and starts it.

      >So the line ^$m2y(^%Ans%)$ is doing all the work. It takes the current
      >value of %Ans% and passes it to the m2y clip (as ^&). Then when the
      >subroutine ends, that line has the value held in %Result% which is
      >printed into the current document.

      This is VERY useful information. It may actually be, technically, somewhere
      in the help file but your explanation of the flow of events helped me.

      >I hope this helps. Custom Functions really do give you enormous power
      >to create sub-routine-like structures in clips. It is certainly worth
      >persevering.
      >
      >Bob McAllister

      Again, Thanks!

      Bob Gorman


      If at first, you don't succeed;
      Parachuting is probably not for you!


      [Non-text portions of this message have been removed]
    • Don - htmlfixit.com
      ... I think that to be bad form even if functional as using the command makes it clearer what you are doing. It also has a much greater probability of working
      Message 2 of 11 , Apr 13, 2006
      • 0 Attachment
        >>When calling the custom function (or sub-routine) you do not need to
        >>use the ^!Clip command (even though you are calling a clip). When
        >>NoteTab does not recognise the function name ^$m2y()$ it looks for a
        >>clip m2y in your current library and starts it.

        I think that to be bad form even if functional as using the command
        makes it clearer what you are doing. It also has a much greater
        probability of working over time should they later make an update to the
        software as they almost always have reverse engineered commands and
        functions.
      • Alan_C
        ... FWIW though, a (called, child) clip written by Fookes software calls (the child clip in turn then calls/uses) a custom function does so not via clip but
        Message 3 of 11 , Apr 13, 2006
        • 0 Attachment
          On Thursday 13 April 2006 12:10, Don - htmlfixit.com wrote:
          > >>When calling the custom function (or sub-routine) you do not need to
          > >>use the ^!Clip command (even though you are calling a clip). When
          > >>NoteTab does not recognise the function name ^$m2y()$ it looks for a
          > >>clip m2y in your current library and starts it.
          >
          > I think that to be bad form even if functional as using the command
          > makes it clearer what you are doing. It also has a much greater
          > probability of working over time should they later make an update to the
          > software as they almost always have reverse engineered commands and
          > functions.

          FWIW though, a (called, child) clip written by Fookes software calls (the
          child clip in turn then calls/uses) a custom function does so not via clip
          but via function name:

          H="_BuildScript"
          ^!Set %Index%=0
          ^!Set %Count%=^%FieldNames0%

          :StartLoop
          ^!Inc %Index%
          ^!If ^%Index% > ^%Count% EndLoop
          ^!Set %FieldName%=^%FieldNames^%Index%%
          ^!IfTrue ^$IsEmpty(^%FieldName%)$ StartLoop
          ^!Set ^%FieldName%=^$GetXmlField(^%FieldName%)$

          ^^^^^^

          ^$GetXmlField()$

          http://www.google.com/search?q=site%3Anotetab.com+xml&start=0&ie=utf-8&oe=utf-8&client=firefox-a&rls=org.mozilla:en-US:official

          http://www.notetab.com/pad/index.htm

          That particular (sub routine) clip is near the bottom of PAD.clb
          -------------------

          Earlier, I'd overlooked the possibility of custom function.

          I never got much into custom function. I long since learned enough of Perl
          which happens to integrate well/nicely with Notetab.

          Learning curve for Perl (EZ stuff is EZ, happens quick in Perl) but to get to
          intermediate to advanced I found learn curve higher and longer than NTB clip.

          But I find that Perl uses way less code than clip. And (after some Perl
          experience) I find Perl significantly easier to track/follow/decipher than
          clip (for example, the PAD.clb to track/follow *understand* what makes it
          tick, how it does what it does) (decipher, key, *access* myself *into* it).

          Idiomatic Perl. get to know it and then now I got it. A *very* expressive
          language -- so much so that some do not like it because of the height of its
          expressivenes. I experience Perl as fun!

          But this is me. I've no idea if it's consensus of others or not. (obviously
          one needs to Perl in order to comment).

          So I (for myself) just write a Perl script/clip rather than a NTB custom
          function.

          And I didn't see a prob with:

          ; 4 speed and not see it happen
          ^!SetScreenUpdate OFF
          ^!Toolbar "new document"
          ; dump var's content to doc here
          ^!Find
          ^!Replace
          ; etc.
          ^!select ALL
          ; back into var
          ^!Set %my_var%(get_selection)
          ; close discard doc here
          ; got what I wanted done onto my var's content

          Notetab lets us choose. We each get to do it how chosen. No prob with that!
          Must be good news!

          And a custom function only needs Notetab, not needs perl installed in the case
          of sharing clip library with other Notetab users.

          --
          Alan.
        • Bob McAllister
          ... Don I guess that you could argue it to be bad form in some abstract computer science sense, but it does happen to be how Eric wrote NoteTab. Have a look
          Message 4 of 11 , Apr 13, 2006
          • 0 Attachment
            On 4/14/06, Don - htmlfixit.com <don@...> wrote:

            > I think that to be bad form even if functional as using the command
            > makes it clearer what you are doing. It also has a much greater
            > probability of working over time should they later make an update to the
            > software as they almost always have reverse engineered commands and
            > functions.
            >

            Don

            I guess that you could argue it to be "bad form" in some abstract
            computer science sense, but it does happen to be how Eric wrote
            NoteTab. Have a look at the Custom Functions page in Clip Help where
            it is described as "an approach similar to the ^!Clip command".

            As (the other) Bob found, trying to stick a ^!Clip command in front of
            a custom function, such as ^$m2y()$, is redundant and the resulting
            code just does not work.

            You can call the clip m2y with ^!Clip m2y (which I infer to be your
            preference) but lose the ability to pass a parameter, which was the
            point of the whole exercise.

            Bob McAllister
          • rpdooling
            Don, Bob, et al. I haven t read the entire thread closely, just parts of it. But don t you guys think you re testing the limits of clip code? We had this
            Message 5 of 11 , Apr 13, 2006
            • 0 Attachment
              Don, Bob, et al.

              I haven't read the entire thread closely, just parts of it. But don't
              you guys think you're testing the limits of clip code? We had this
              discussion once before, I think.

              Personally I believe that's why Eric made it so easy to call a Perl or
              Gawk script, because when you start wanting to do things like pass
              variables or do sophisticated regex you're probably better off just
              biting the bullet and learning a little Perl or Python or any of the
              other scripting languages you can call from within NoteTab.

              Just one man's opinion.

              rpd

              --- In ntb-clips@yahoogroups.com, "Bob McAllister" <fortiter@...> wrote:
              >
              > On 4/14/06, Don - htmlfixit.com <don@...> wrote:
              >
              > > I think that to be bad form even if functional as using the command
              > > makes it clearer what you are doing. It also has a much greater
              > > probability of working over time should they later make an update
              to the
              > > software as they almost always have reverse engineered commands and
              > > functions.
              > >
              >
              > Don
              >
              > I guess that you could argue it to be "bad form" in some abstract
              > computer science sense, but it does happen to be how Eric wrote
              > NoteTab. Have a look at the Custom Functions page in Clip Help where
              > it is described as "an approach similar to the ^!Clip command".
              >
              > As (the other) Bob found, trying to stick a ^!Clip command in front of
              > a custom function, such as ^$m2y()$, is redundant and the resulting
              > code just does not work.
              >
              > You can call the clip m2y with ^!Clip m2y (which I infer to be your
              > preference) but lose the ability to pass a parameter, which was the
              > point of the whole exercise.
              >
              > Bob McAllister
              >
            • Don - htmlfixit.com
              sombody wrote; ... And here I thought you were a smart person??? The Answer: Of course not, clip code has no limits ... only limits on how you can get it to do
              Message 6 of 11 , Apr 14, 2006
              • 0 Attachment
                sombody wrote;
                > But don't
                > you guys think you're testing the limits of clip code?

                And here I thought you were a smart person???
                The Answer: Of course not, clip code has no limits ... only limits on
                how you can get it to do it ... not whether it can do it.

                But more seriously, I would say no for the following reasons:
                1. I often and regularly write clips for other people for fun and/or
                very modest profit ... and they often don't have perl/gawk/etc. so I
                would have to get them to where I am with a language installed locally
                instead of just writing the clip.

                2. I often write a clip and email it to someone when I will be helping
                that someone else. I then only need to install notetab light on their
                computer and run the clip ... same point, I haven't cluttered up their
                computer with a program they won't later use (cause they will use
                notetab but not perl later).

                3. Why do it the easy way when the very reason I compute is for the
                challenge of it? To me this is like doing jigsaw puzzles. It keeps me
                sharper than I might otherwise be (don't even ponder how dense that
                might be).

                4. There often is a better tool to do job a OR b OR c, but seldom one
                that can do a AND b AND c ... but notetab can.

                I have taken to writing subroutines (if that is what we will call them)
                after our prior discussions unlocked the concept a little further. I
                have come to find them very handy. I will pass parameters by using a
                two line call:
                line one sets the variables that will be used in the subroutine
                and line two calls the subroutine that then has those variables
                available to it when it runs ...
                and when I get back, the variables are essentially the returned values
                because they are again available in the clip.

                Because in this example the "function" to be performed in the subroutine
                is a one liner, there is no advantage to the subroutine, but if the
                subroutine is a 30 line thing ... well then yes it would be worth it if
                reused.

                I also find it a great way to write portable bits of code. For example
                I wrote one to adjust back and forth between light and pro for the
                replace line feed situation (that I call a bug). I have used the same
                subroutine to correct that in several clips now by calling it as a
                subroutine clip.

                Thems my thoughts on it.

                D
              • Don - htmlfixit.com
                ... I didn t realize that this was a custom function. I guess you are correct and that won t go away. I also see what you say about passing a parameter. It
                Message 7 of 11 , Apr 15, 2006
                • 0 Attachment
                  Bob McAllister wrote:
                  > I guess that you could argue it to be "bad form" in some abstract
                  > computer science sense, but it does happen to be how Eric wrote
                  > NoteTab. Have a look at the Custom Functions page in Clip Help where
                  > it is described as "an approach similar to the ^!Clip command".
                  >
                  I didn't realize that this was a custom function. I guess you are
                  correct and that won't go away. I also see what you say about passing a
                  parameter.

                  It appears that the only way to pass a parameter is the highlight the
                  "parameter" so the parameter must be in your text document? I remember
                  trying to understand these a while back and thinking that it wasn't
                  worth the effort. Here is how I have taken to using "subroutines" and
                  as you see I am using an array to pass the parameters.

                  H="first letter"
                  ;set variables to be passed as parameters
                  ^!SetArray %items%=red;orange;yellow;green;blue;indigo;violet
                  ;call "subroutine"
                  ^!Clip "grabfirstletters"
                  ^!SetArray %items%=Mediocrity;Ego;Limits;Vanity;Incompetence;Name-calling
                  ;call "subroutine"
                  ^!Clip "grabfirstletters"


                  H="_grabfirstletters"
                  ^!Set %count%=1;%string%=""
                  :Loop
                  ^!Set %string%=^%string%^$StrCopyLeft("^%items^%count%%";1)$
                  ^!Inc %count%
                  ^!If ^%count% <= ^%items0% Loop
                  ^!InsertText ^%string% = ^%items%^P
                • rpdooling
                  All I m saying is, why not have NoteTab run a single Python script that fits on two lines: t = [ red , orange , yellow , green , blue , indigo , violet ]
                  Message 8 of 11 , Apr 15, 2006
                  • 0 Attachment
                    All I'm saying is, why not have NoteTab run a single Python script
                    that fits on two lines:

                    t = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet']
                    for color in t: print color[0],

                    >>r o y g b i v

                    Instead of having NoteTab run two clips worth of code:

                    H="first letter"
                    ;set variables to be passed as parameters
                    ^!SetArray %items%=red;orange;yellow;green;blue;indigo;violet
                    ;call "subroutine"
                    ^!Clip "grabfirstletters"
                    ^!SetArray %items%=Mediocrity;Ego;Limits;Vanity;Incompetence;Name-calling
                    ;call "subroutine"
                    ^!Clip "grabfirstletters"

                    H="_grabfirstletters"
                    ^!Set %count%=1;%string%=""
                    :Loop
                    ^!Set %string%=^%string%^$StrCopyLeft("^%items^%count%%";1)$
                    ^!Inc %count%
                    ^!If ^%count% <= ^%items0% Loop
                    ^!InsertText ^%string% = ^%items%^P

                    And the remark in your last post about portability was off the mark.
                    If you write a script in Perl or Python you can run it in NoteTab on
                    Windows, in Emacs on Linux, in BBedit on Mac, and so on. That's what's
                    commonly called "portability." A clip can only be run in NoteTab.

                    Hey, I love NoteTab, too, but it's main attraction is that it's
                    extensible far beyond clip code.

                    rd


                    --- In ntb-clips@yahoogroups.com, "Don - htmlfixit.com" <don@...> wrote:
                    >
                    > Bob McAllister wrote:
                    > > I guess that you could argue it to be "bad form" in some abstract
                    > > computer science sense, but it does happen to be how Eric wrote
                    > > NoteTab. Have a look at the Custom Functions page in Clip Help where
                    > > it is described as "an approach similar to the ^!Clip command".
                    > >
                    > I didn't realize that this was a custom function. I guess you are
                    > correct and that won't go away. I also see what you say about
                    passing a
                    > parameter.
                    >
                    > It appears that the only way to pass a parameter is the highlight the
                    > "parameter" so the parameter must be in your text document? I remember
                    > trying to understand these a while back and thinking that it wasn't
                    > worth the effort. Here is how I have taken to using "subroutines" and
                    > as you see I am using an array to pass the parameters.
                    >
                    > H="first letter"
                    > ;set variables to be passed as parameters
                    > ^!SetArray %items%=red;orange;yellow;green;blue;indigo;violet
                    > ;call "subroutine"
                    > ^!Clip "grabfirstletters"
                    > ^!SetArray
                    %items%=Mediocrity;Ego;Limits;Vanity;Incompetence;Name-calling
                    > ;call "subroutine"
                    > ^!Clip "grabfirstletters"
                    >
                    >
                    > H="_grabfirstletters"
                    > ^!Set %count%=1;%string%=""
                    > :Loop
                    > ^!Set %string%=^%string%^$StrCopyLeft("^%items^%count%%";1)$
                    > ^!Inc %count%
                    > ^!If ^%count% <= ^%items0% Loop
                    > ^!InsertText ^%string% = ^%items%^P
                    >
                  • rpdooling
                    On second thought, it all fits on ONE LINE, even though it probably wraps when posted: for color in [ red , orange , yellow , green , blue , indigo ,
                    Message 9 of 11 , Apr 15, 2006
                    • 0 Attachment
                      On second thought, it all fits on ONE LINE, even though it probably
                      wraps when posted:

                      for color in ['red', 'orange', 'yellow', 'green', 'blue', 'indigo',
                      'violet']: print color[0],

                      rpd

                      --- In ntb-clips@yahoogroups.com, "rpdooling" <rpdooling@...> wrote:
                      >
                      > All I'm saying is, why not have NoteTab run a single Python script
                      > that fits on two lines:
                      >
                      > t = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet']
                      > for color in t: print color[0],
                      >
                      > >>r o y g b i v
                      >
                      > Instead of having NoteTab run two clips worth of code:
                      >
                      > H="first letter"
                      > ;set variables to be passed as parameters
                      > ^!SetArray %items%=red;orange;yellow;green;blue;indigo;violet
                      > ;call "subroutine"
                      > ^!Clip "grabfirstletters"
                      > ^!SetArray
                      %items%=Mediocrity;Ego;Limits;Vanity;Incompetence;Name-calling
                      > ;call "subroutine"
                      > ^!Clip "grabfirstletters"
                      >
                      > H="_grabfirstletters"
                      > ^!Set %count%=1;%string%=""
                      > :Loop
                      > ^!Set %string%=^%string%^$StrCopyLeft("^%items^%count%%";1)$
                      > ^!Inc %count%
                      > ^!If ^%count% <= ^%items0% Loop
                      > ^!InsertText ^%string% = ^%items%^P
                      >
                      > And the remark in your last post about portability was off the mark.
                      > If you write a script in Perl or Python you can run it in NoteTab on
                      > Windows, in Emacs on Linux, in BBedit on Mac, and so on. That's what's
                      > commonly called "portability." A clip can only be run in NoteTab.
                      >
                      > Hey, I love NoteTab, too, but it's main attraction is that it's
                      > extensible far beyond clip code.
                      >
                      > rd
                      >
                      >
                      > --- In ntb-clips@yahoogroups.com, "Don - htmlfixit.com" <don@> wrote:
                      > >
                      > > Bob McAllister wrote:
                      > > > I guess that you could argue it to be "bad form" in some abstract
                      > > > computer science sense, but it does happen to be how Eric wrote
                      > > > NoteTab. Have a look at the Custom Functions page in Clip Help where
                      > > > it is described as "an approach similar to the ^!Clip command".
                      > > >
                      > > I didn't realize that this was a custom function. I guess you are
                      > > correct and that won't go away. I also see what you say about
                      > passing a
                      > > parameter.
                      > >
                      > > It appears that the only way to pass a parameter is the highlight the
                      > > "parameter" so the parameter must be in your text document? I
                      remember
                      > > trying to understand these a while back and thinking that it wasn't
                      > > worth the effort. Here is how I have taken to using "subroutines"
                      and
                      > > as you see I am using an array to pass the parameters.
                      > >
                      > > H="first letter"
                      > > ;set variables to be passed as parameters
                      > > ^!SetArray %items%=red;orange;yellow;green;blue;indigo;violet
                      > > ;call "subroutine"
                      > > ^!Clip "grabfirstletters"
                      > > ^!SetArray
                      > %items%=Mediocrity;Ego;Limits;Vanity;Incompetence;Name-calling
                      > > ;call "subroutine"
                      > > ^!Clip "grabfirstletters"
                      > >
                      > >
                      > > H="_grabfirstletters"
                      > > ^!Set %count%=1;%string%=""
                      > > :Loop
                      > > ^!Set %string%=^%string%^$StrCopyLeft("^%items^%count%%";1)$
                      > > ^!Inc %count%
                      > > ^!If ^%count% <= ^%items0% Loop
                      > > ^!InsertText ^%string% = ^%items%^P
                      > >
                      >
                    • Bob McAllister
                      ... Don I have modified your two clips to use custom functions as below. H=first letter ^!SetArray %items%=red;orange;yellow;green;blue;indigo;violet
                      Message 10 of 11 , Apr 16, 2006
                      • 0 Attachment
                        On 4/16/06, Don - htmlfixit.com <don@...> wrote:
                        > Here is how I have taken to using "subroutines" and
                        > as you see I am using an array to pass the parameters.
                        >
                        > H="first letter"
                        > ;set variables to be passed as parameters
                        > ^!SetArray %items%=red;orange;yellow;green;blue;indigo;violet
                        > ;call "subroutine"
                        > ^!Clip "grabfirstletters"
                        > ^!SetArray %items%=Mediocrity;Ego;Limits;Vanity;Incompetence;Name-calling
                        > ;call "subroutine"
                        > ^!Clip "grabfirstletters"

                        Don

                        I have modified your two clips to use custom functions as below.

                        H=first letter
                        ^!SetArray %items%=red;orange;yellow;green;blue;indigo;violet
                        ^$grabfirstletter(^%items%)$ = ^%items%^%NL%
                        ^!SetArray %items%=Mediocrity;Ego;Limits;Vanity;Incompetence;Name-calling
                        ^$grabfirstletter(^%items%)$ = ^%items%^%NL%

                        H=_grabfirstletter
                        ^!SetArray %wordlist%=^&
                        ^!Set %count%=1;%Result%=""
                        :Loop
                        ^!Set %Result%=^%Result%^$StrCopyLeft("^%wordlist^%count%%";1)$
                        ^!Inc %count%
                        ^!If ^%count% <= ^%items0% Loop

                        The key is the use of the "special variable" %Result% in the
                        definition of the custom function. That will be what is returned at
                        the end of the sub-routine and its value printed by the top-level clip
                        at the point where the custom function was called.

                        This is a general case where the "content" of your array variable
                        %items% is passed to the custom function (as ^&) and placed into a new
                        variable. It works regardless of the source of the passed parameter.

                        In your situation where tou already know the name of the variable
                        holding the data on which the function is to operate, I can
                        short-circuit by using that same variable in the custom function (and
                        so effectively pass an empty parameter).

                        The following clips implement that special case relying on knowing the
                        variable name in calling routine.
                        H=flspecialcase
                        ^!SetArray %items%=red;orange;yellow;green;blue;indigo;violet
                        ^$grabfirstletterx()$ = ^%items%^%NL%
                        ^!SetArray %items%=Mediocrity;Ego;Limits;Vanity;Incompetence;Name-calling
                        ^$grabfirstletterx()$ = ^%items%^%NL%

                        H=_grabfirstletterx
                        ^!Set %count%=1;%Result%=""
                        :Loop
                        ^!Set %Result%=^%Result%^$StrCopyLeft("^%items^%count%%";1)$
                        ^!Inc %count%
                        ^!If ^%count% <= ^%items0% Loop

                        There may be circumstances where you prefer this method.

                        Bob
                      • rpdooling
                        Bob, ... I have never seen that. That IS a nifty trick. Rick H=first letter ^!SetArray %items%=red;orange;yellow;green;blue;indigo;violet
                        Message 11 of 11 , Apr 17, 2006
                        • 0 Attachment
                          Bob,

                          >> ^$grabfirstletter(^%items%)$ = ^%items%^%NL%

                          I have never seen that. That IS a nifty trick.

                          Rick


                          H=first letter
                          ^!SetArray %items%=red;orange;yellow;green;blue;indigo;violet
                          ^$grabfirstletter(^%items%)$ = ^%items%^%NL%
                          ^!SetArray %items%=Mediocrity;Ego;Limits;Vanity;Incompetence;Name-calling
                          ^$grabfirstletter(^%items%)$ = ^%items%^%NL%

                          H=_grabfirstletter
                          ^!SetArray %wordlist%=^&
                          ^!Set %count%=1;%Result%=""
                          :Loop
                          ^!Set %Result%=^%Result%^$StrCopyLeft("^%wordlist^%count%%";1)$
                          ^!Inc %count%
                          ^!If ^%count% <= ^%items0% Loop

                          --- In ntb-clips@yahoogroups.com, "Bob McAllister" <fortiter@...> wrote:
                          >
                          > On 4/16/06, Don - htmlfixit.com <don@...> wrote:
                          > > Here is how I have taken to using "subroutines" and
                          > > as you see I am using an array to pass the parameters.
                          > >
                          > > H="first letter"
                          > > ;set variables to be passed as parameters
                          > > ^!SetArray %items%=red;orange;yellow;green;blue;indigo;violet
                          > > ;call "subroutine"
                          > > ^!Clip "grabfirstletters"
                          > > ^!SetArray
                          %items%=Mediocrity;Ego;Limits;Vanity;Incompetence;Name-calling
                          > > ;call "subroutine"
                          > > ^!Clip "grabfirstletters"
                          >
                          > Don
                          >
                          > I have modified your two clips to use custom functions as below.
                          >
                          > H=first letter
                          > ^!SetArray %items%=red;orange;yellow;green;blue;indigo;violet
                          > ^$grabfirstletter(^%items%)$ = ^%items%^%NL%
                          > ^!SetArray
                          %items%=Mediocrity;Ego;Limits;Vanity;Incompetence;Name-calling
                          > ^$grabfirstletter(^%items%)$ = ^%items%^%NL%
                          >
                          > H=_grabfirstletter
                          > ^!SetArray %wordlist%=^&
                          > ^!Set %count%=1;%Result%=""
                          > :Loop
                          > ^!Set %Result%=^%Result%^$StrCopyLeft("^%wordlist^%count%%";1)$
                          > ^!Inc %count%
                          > ^!If ^%count% <= ^%items0% Loop
                          >
                          > The key is the use of the "special variable" %Result% in the
                          > definition of the custom function. That will be what is returned at
                          > the end of the sub-routine and its value printed by the top-level clip
                          > at the point where the custom function was called.
                          >
                          > This is a general case where the "content" of your array variable
                          > %items% is passed to the custom function (as ^&) and placed into a new
                          > variable. It works regardless of the source of the passed parameter.
                          >
                          > In your situation where tou already know the name of the variable
                          > holding the data on which the function is to operate, I can
                          > short-circuit by using that same variable in the custom function (and
                          > so effectively pass an empty parameter).
                          >
                          > The following clips implement that special case relying on knowing the
                          > variable name in calling routine.
                          > H=flspecialcase
                          > ^!SetArray %items%=red;orange;yellow;green;blue;indigo;violet
                          > ^$grabfirstletterx()$ = ^%items%^%NL%
                          > ^!SetArray
                          %items%=Mediocrity;Ego;Limits;Vanity;Incompetence;Name-calling
                          > ^$grabfirstletterx()$ = ^%items%^%NL%
                          >
                          > H=_grabfirstletterx
                          > ^!Set %count%=1;%Result%=""
                          > :Loop
                          > ^!Set %Result%=^%Result%^$StrCopyLeft("^%items^%count%%";1)$
                          > ^!Inc %count%
                          > ^!If ^%count% <= ^%items0% Loop
                          >
                          > There may be circumstances where you prefer this method.
                          >
                          > Bob
                          >
                        Your message has been successfully submitted and would be delivered to recipients shortly.