Need ByRef Help

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
sirksel
Posts: 222
Joined: 12 Nov 2013, 23:48

Need ByRef Help

20 Mar 2021, 00:01

I thought I understood the byref changes but I guess I don't. I changed this snippet of code which used to work fine ByRef. Without passing too much judgement for the need for such a function, did I update the syntax incorrectly?

Code: Select all

na := '`vna'  ;not available sentry global

vfd(   ;vars from defaults; replaces na vars with corresponding defaults
      &var1:='', dft1:='', &var2:='', dft2:=''
    , &var3:='', dft3:='', &var4:='', dft4:=''
    , &var5:='', dft5:='', &var6:='', dft6:=''
    , &var7:='', dft7:='', &var8:='', dft8:=''
    , &var9:='', dft9:='') {
  cnt := 0
  while ++cnt <= 9 and var%cnt% is varref
    if var%cnt% == na
      var%cnt% := dft%cnt%
  return cnt-1
}

x := na,  y := 55
vfd(&x, 99, &y, 88)
msgbox(x ' ' y)
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: Need ByRef Help

20 Mar 2021, 16:36

function whose parameters are declared ByRef(as in myFunc(&arg1) { ... }) require that a VarRef is passed at their callsite(as in myFunc(&someVar)) and theyll automatically dereference the passed in VarRef in their function bodies for u, so testing for var%cnt% is varref doesnt make sense unless u actually need to know whether the VarRef u passed in itself contains a reference to another VarRef as in:

Code: Select all

_x := na,  _y := 55
x := &_x,  y := &_y
vfd(&x, 99, &y, 88)
but then ull have to further dereference those VarRefs if u want to test them for string equality

just delete and var%cnt% is varref
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: Need ByRef Help

21 Mar 2021, 23:09

One of the benefits of the new approach is that a variadic function can take VarRefs, identify them with "is VarRef" and explicitly deref them with %%. This allows you to do away with the long list of parameters and the dynamic variables.
sirksel
Posts: 222
Joined: 12 Nov 2013, 23:48

Re: Need ByRef Help

22 Mar 2021, 09:31

Thanks guys. This helps a lot. And, yes, @lexikos, I'm definitely seeing the advantages of the new approach. I had several functions like this that now can use variadic params rather than a finite list of byrefs of arbitrary length.

In case it helps anyone, my resulting function is below. I added a little error-checking for the varref calling errors I will inevitably make. I also improved the return value to indicate the actual number of default replacements made.

(N.B. This function checks for a quasi-constant global sentry I've named na, which typically indicates a missing value, an 'unset' parameter that needs to be passed from function to function, or the like. Any varrefs that contain the sentry are replaced with their corresponding defaults.)

Code: Select all

vfd(prms*) {   ;vars from defaults; replaces na vars with dfts (v1,d1,v2,d2,..)
  cnt := rpl := 0,  len := prms.length // 2
  while ++cnt <= len
    if not ((v := prms[cnt*2-1]) is varref)
      throw typeerror('vfd(&v1, d1, &v2, d2, ...) vars must be called varref'
        , -2, 'Param #' cnt*2-1 ' is ' string(v) ' instead of a varref.')
    else if %v% == na   ;if varref contains not available sentry
      %v% := prms[cnt*2],  rpl++   ;then replace it with default value
  return rpl   ;returns number of replacements made
}
sirksel
Posts: 222
Joined: 12 Nov 2013, 23:48

Re: Need ByRef Help

27 Aug 2021, 18:43

Just a quick follow-up... I'm amazed at the power of the combination of all of the recent changes by @lexikos, as I rewrite a few of my libraries. Just these varref changes (discussed above) + enumerator changes + the function call changes... have enabled some pretty cool functional programming code. Below is a grouping or "chunking" enumerator I wrote in just a few lines. It uses the arity of the for..in to determine the chunk size:

Code: Select all

rpt(f, i) {   ;repeat f(a_index) i times
  loop i
    f(a_index)
}

grp(xs)   ;grouped enumerator of xs array; size of group matches for/in arity
  => {__enum : (_,a) => (len := xs.length // a,  i := 0,  (rs*) 
    => (++i > len) ? 0 : (rpt(j => (%rs[j]% := xs[i*a-(a-j)]), a), 1))}

a := [2,4,6,8,10,12,14,16,18,20]
for x,y in grp(a)
  msgbox(x ',' y)         ;2,4 .. 6,8 .. 10,12 ..
for x,y,z in grp(a)
  msgbox(x ',' y ',' z)   ;2,4,6 .. 8,10,12 .. 14,16,18 ..
I'll ultimately use this to rework the "defaults" function described above, since it requires pairwise enumeration of a variadic. Thanks again for all the hard work, Lexikos! Rewriting code for this beta is truly a pleasure because of all the power you've unlocked.
"Languages should be designed not by piling feature on top of feature, but by removing the restrictions that make additional features appear necessary." —Scheme reference standard

Return to “Ask for Help (v2)”

Who is online

Users browsing this forum: miyake, niCode, songdg and 48 guests