Page 1 of 2 12 LastLast
Results 1 to 15 of 20

Thread: caveats

  1. #1
    Platinum Lounger
    Join Date
    Feb 2001
    Location
    Yilgarn region of Toronto, Ontario
    Posts
    5,453
    Thanks
    0
    Thanked 0 Times in 0 Posts

    caveats

    <pre>Option Explicit

    Public Function ReturnThis(s1 As String)
    s1 = s1 & "something"
    End Function
    Sub TESTReturnThis()
    Dim s1 As String
    s1 = "a"
    Call ReturnThis(s1)
    MsgBox s1
    s1 = "b"
    Call ReturnThis(s1 & Application.PathSeparator)
    MsgBox s1
    End Sub
    </pre>


  2. #2
    Platinum Lounger
    Join Date
    Dec 2000
    Location
    Queanbeyan, New South Wales, Australia
    Posts
    3,730
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: caveats

    Very quiet on the forum today. It figures, it's only the Canadians & Aussies online (Americans and Brits on hols).

    Most strange behavious. Even in VB6 (with a few variations):

    <pre>Public Sub ReturnThis(ByRef s1 As String)
    s1 = s1 & "something"
    End Sub
    Sub form_load()
    Dim s1 As String
    s1 = "a"
    Call ReturnThis(s1)
    Debug.Print s1
    s1 = "b"
    Call ReturnThis(s1 & "")
    Debug.Print s1
    End Sub
    </pre>


    returns "asomething" from the first call, and "b" from the second, where I would have expected "bsomething".

    It seems to be something with arithmetic operators. 'Call ReturnThis(s1 & "+")' gives the same result; however, the following gives a correct result:
    <pre>Public Function ReturnThis(ByRef s1 As String) As String
    ReturnThis = s1 & "something"
    End Function
    Sub form_load()
    Dim s1 As String
    s1 = "a"
    Debug.Print ReturnThis(s1)
    s1 = "b"
    Debug.Print ReturnThis(s1 & "/")
    End Sub
    </pre>

    Subway Belconnen- home of the Signboard to make you smile. Get (almost) daily updates- follow SubwayBelconnen on Twitter.

  3. #3
    Platinum Lounger
    Join Date
    Dec 2000
    Location
    Queanbeyan, New South Wales, Australia
    Posts
    3,730
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: caveats

    Whoops, a gotcha.

    The parameter is being passed by reference. That means an address is being returned from the sub. But when you're concatenating a string to a string as a parameter, the only address which can be returned is the address of the first part of the string.

    If the parameter is "byRef" (which was implied in your original example) I cannot pass anything but a variable name, and expect to get a correct answer returned. The correct value is passed to the routine, but only the address of a variable is passed back- into an expression rather than a simple variable.

    So, from your example:
    <pre> s1 = "b"
    Call ReturnThis(s1 & Application.PathSeparator)</pre>

    would not work, but
    <pre> s1 = "b" & Application.PathSeparator
    Call ReturnThis(s1)
    </pre>


    should work OK.

    I hope that makes sense- it's a bit difficult to explain though.
    Subway Belconnen- home of the Signboard to make you smile. Get (almost) daily updates- follow SubwayBelconnen on Twitter.

  4. #4
    Platinum Lounger
    Join Date
    Dec 2000
    Location
    Queanbeyan, New South Wales, Australia
    Posts
    3,730
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: caveats

    Yep, byRef is passing an address.

    But that does not cause a problem UNLESS you're trying to reference the "changed" value further along in the code.

    It adds weight to something you were saying earlier about the value of only returning values by using functions.

    In your example, with a single value being returned, a Function call would have done the job without giving a wrong answer.

    If you are relying on the user not to do the wrong thing, and you wanted multiple values returned from your routine, then you might have to look at another way of doing it.

    Perhaps for multiple values you need to define an "imParm" and an "outParm". Not that this would provide complete protection, it would just cut down on the possibility of a problem. If the user defined an "outParm" with an expression isntead of a variable, they would still have a problem.

    If you are providing a routine to another programmer, then the warning has been given in this thread.

    If you were providing something for external use, you might also want to look at class modules. You have more control over what is accepted and returned, using the "Let, Set and Get".
    Subway Belconnen- home of the Signboard to make you smile. Get (almost) daily updates- follow SubwayBelconnen on Twitter.

  5. #5
    Uranium Lounger
    Join Date
    Jan 2001
    Location
    South Carolina, USA
    Posts
    7,295
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: caveats

    This is correct and expected behavior. The default is to pass a parameter ByRef. Therefore, if you modify the parameter in the subroutine, then the value in the parameter is modified. This is what is happening when you pass S1 as a parameter.

    However, if you pass S1 & "", then VBA does the calculation (concatenation in this case), and stores the result in a temporary variable. The temporary variable is then passed ByRef to the Subroutine, and the temporary variable is modified by the subroutine, not S1.

    If you do the Debug.Print (S1 & ""), then Debug.Print is printing the temporary variable which was modified by the Subroutine, not S1.
    Legare Coleman

  6. #6
    Platinum Lounger
    Join Date
    Feb 2001
    Location
    Yilgarn region of Toronto, Ontario
    Posts
    5,453
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: caveats

    ...and also in reference to 42067 ...

    Quite so. When it first occurred my reaction was "bug", but before my original posting, I *knew* where the bug was - in my head.

    The technical explanation is correct. The human side is "Be very careful when returning results by argument".

    I'll even qualify that: There's little harm in returning results by argument IN AN ARRAY, but that is only because I don't know how to call a function with an array expression.

    So my current rule pretty well boils down to "Never pass an expression as an argument".

    There are benefits to observing this rule. The construct
    <pre>(snip)
    Dim strArg as string
    strArg = s1 & application.pathSeparator
    call MyProcedure(strArg)
    (snip)</pre>

    allows me to inspect the value of each argument AS IT WILL BE SEEN BY THE PROCEDURE before calling the procedure while stepping through the procedure in Debug mode.


    I know Geoff wants (grin) me to find a use for Class modules so that I'll know all about them. I suspect that they're not much different from what we USED to call macros a long time ago.

  7. #7
    Platinum Lounger
    Join Date
    Dec 2000
    Location
    Queanbeyan, New South Wales, Australia
    Posts
    3,730
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: caveats

    <hr>I know Geoff wants (grin) me to find a use for Class modules <hr>

    Not quite true. I don't know nearly enough about class modules myself- so I was hoping you would find a way for ME to use class modules.

    I've used them in pure VB days, but I haven't used them for a while. I was throwing a morsel- one which I don't have a chance to follow myself just yet. I just thought that, from my memories of class modules, they presented a nice way of providing a little more protection against incorrect passing of variables than that allowed by subroutines. You can specifiy which variables you expose to the calling routine, which ones are passed in by the calling routine, etc.

    Having said that, my memory banks are getting exercised. We used them in a situation where a programmable component on a form could be used in more than one place. Just like a control- but we could embed the control (eg, a list box showing all records meeting a certain criteria) in a number of places. using the "Get, Let and Set" enabled us to use the class module as a control, and have its own properties and methods which the programmer could control.

    Sorry, a rather simplistic, and probably inaccurate explantion. It's probably better to leave experts to expand (or more probably, to correct).
    Subway Belconnen- home of the Signboard to make you smile. Get (almost) daily updates- follow SubwayBelconnen on Twitter.

  8. #8
    Plutonium Lounger
    Join Date
    Dec 2000
    Location
    Sacramento, California, USA
    Posts
    16,775
    Thanks
    0
    Thanked 1 Time in 1 Post

    Re: caveats

    When you go that far, you're reaching into building COM objects rather than abstract classes. They operate on the same principles, but COM objects have a visible interface rather than an interface that is only accessible from code.

    Of course, if you use the WithEvents keyword to instantiate the class, you can handle built in objects as well and use their provided interface, so the line isn't entirely clear. But any abstract class will be usable in pretty much any of the VBA applications as well as VB, although you'll have to suppress the property lines in the module if you try to use it in Access.
    Charlotte

  9. #9
    Platinum Lounger
    Join Date
    Feb 2001
    Location
    Yilgarn region of Toronto, Ontario
    Posts
    5,453
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: caveats

    > It adds weight to something you were saying earlier about the value of only returning values by using functions.

    That was here: A Function should only take in two values, and then return one value

    >>> It adds weight to something you were saying earlier about the value of only returning values by using functions.

    That is based on the "straight and narrow" philosophy. I figure that the further I stray away from the machine architecture, the more likely I am to get into trouble.

    I think of computer hardware as the old machine-language instructions, where you can add memory contents to an accumulator, etc. The most you could ever do is take two arguments and produce one result. Of course, you do that often enough, you get pretty amazing things, like <A target="_blank" HREF=http://www.woodyswatch.com/office/services.asp>Office XP</A>.


    NOT sticking to the path doesn't mean I'm going to get into trouble, but it does increase my chance of trouble; by how much is debatable.


    I can count on the fingers of two hands the number of times I've gotten into trouble by not initializing a variable (There was that job in France, the position in the UK, the time in Singapore, ....). hence my VBA code, like all other code, DIMensions a variable and immediately initializes it. I know I don't need to do it in VBA, but I need to keep doing it in my head. Again, this is a throwback to the machine, where you can't assume that a memory location assigned to you is necessarily "empty".



    So, my original problem of a few days ago really boil down to being cheap in programming. Nowadays it costs even less than before to build an interim result and pass that as an argument. It's what Ihad to do years ago. By dropping that standard i ran into trouble.



    I'm going to pre-concede to whoever is listening that maybe this:
    <pre> dim strInterim as string
    strInterim = strField & Application.pathseparator
    call MyFunc(strInterim)
    </pre>

    isn't as readable as this:
    <pre> call MyFunc(strField & Application.pathseparator)
    </pre>

    but the first one is pretty well guranteed to work in any language, while the second one isn't.

  10. #10
    Platinum Lounger
    Join Date
    Feb 2001
    Location
    Yilgarn region of Toronto, Ontario
    Posts
    5,453
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: caveats

    Not difficult; I agree with your explanation. I posted no comment with the original post because I wasn't sure what to say. My code in the host module was in error - I shouldn't have been passing Application.PathSeparator as an additive. Since mine was a coding bug, I couldn't find it in my heart to criticize.

    So based on my understanding of compilers/interpreters you'd be spot on. ByRef is passing an ADDRESS whereas ByExpression will fail. (I just invented ByExpression, but it's a sort of anti-matter equivalent of ByVal).

    Yet, how to alert the next user? I have added two search strings, but they won't be an awful lot of help.

  11. #11
    Platinum Lounger
    Join Date
    Feb 2001
    Location
    Yilgarn region of Toronto, Ontario
    Posts
    5,453
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: caveats

    Monday, June 04, 2001 I decided that a STACK would make a good model for a class object.
    A stack has methods and properties.
    Methods include Clear and Put.
    Properties include blnEmpty.
    The Class module StringStack holds sample code.
    Your (as in "You, the general public", not GeoffW) mission is to develop a LongStack class module and demonstrate use of it.
    Attached Files Attached Files

  12. #12
    Plutonium Lounger
    Join Date
    Dec 2000
    Location
    Sacramento, California, USA
    Posts
    16,775
    Thanks
    0
    Thanked 1 Time in 1 Post

    Re: caveats

    Chris,

    A stack is an excellent model for a class. In fact, if I remember correctly, Ken Getz (of Access Developer's Handbook fame, among other things) created a class demo using a stack model.
    Charlotte

  13. #13
    Platinum Lounger
    Join Date
    Dec 2000
    Location
    Queanbeyan, New South Wales, Australia
    Posts
    3,730
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: caveats

    Chris,

    I think you have explained far more clearly than any technical explanation about what a class module is, what it can do, and how it can be used.

    Thanks for suggesting it's not my job to code!
    Subway Belconnen- home of the Signboard to make you smile. Get (almost) daily updates- follow SubwayBelconnen on Twitter.

  14. #14
    Platinum Lounger
    Join Date
    Feb 2001
    Location
    Yilgarn region of Toronto, Ontario
    Posts
    5,453
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: caveats

    > Ken Getz

    Correct. I based my code on his after deciding that it could be stripped WAY down for a first attempt. I had problems using the Err.Raise and getting an On Error to recognise it, so that got tossed out, too.

    I posted something a couple of weeks ago that suggested a regular stack mechanism wasn't always called for - I think I found myself stacking single characters and realised that the old left$(string,len(string)-1) trick would work just as well.

    Not many application programmers use stacks. I'd like to find a few more data objects and make models for those. My INI file routines float in the background. I've thought of a SET of INI files, each with its own sections. I already switch between INI files on the fly, so maybe a class and methods/properties would be a good idea. Still thinking .....

  15. #15
    Platinum Lounger
    Join Date
    Feb 2001
    Location
    Yilgarn region of Toronto, Ontario
    Posts
    5,453
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: caveats

    > Thanks for suggesting it's not my job to code!

    You're welcome, but .....

    .... I need a few more PRACTICAL examples, so suggestions are being sought.

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •