1. [DOS] Can we emulate "pass by reference" in Eu?

Dear List

For my general knowledge, rather than with a specific program in mind, I'd like
to ask how to pass a non-global variable (two scenario's: an atom; a sequence) as
an argument to:
1 a procedure that changes the variable (eg increments it)
2 a function that changes the variable (eg increments it) but returns some
other, different, variable

A "minimal" example to achieve the above, would be enough.

Thank you

Alex Caracatsanis

new topic     » topic index » view message » categorize

2. Re: [DOS] Can we emulate "pass by reference" in Eu?

On 18 Oct 2004, at 20:58, Alex Caracatsanis wrote:

> 
> 
> posted by: Alex Caracatsanis <CaracatsanisA at ramsayhealth.com.au>
> 
> Dear List
> 
> For my general knowledge, rather than with a specific program in mind, I'd
> like
> to ask how to pass a non-global variable (two scenario's: an atom; a sequence)
> as an argument to: 1 a procedure that changes the variable (eg increments it)
> 2
> a function that changes the variable (eg increments it) but returns some
> other,
> different, variable
> 
> A "minimal" example to achieve the above, would be enough.

Not sure if this is what you meant ........ 

atom  var1
sequence  seq1

procedure add1(atom var2)
  var1 = var2
end procedure

function add2(atom var2)
  var1 += var2
  return var1
end function

procedure app1(sequence seq2)
  seq1 = seq2 & seq2
end procedure

function app2(sequence seq2)
sequence nothing
  nothing = ""
  seq1 = seq2 & seq2
  return nothing
end function

procedure test()
atom var0
sequence seq0


  var0 = 12
  seq0 = "something"

  add1(var0)
  var0 = add2(var0)

  app1(seq0)
  seq0 = app2(seq0)
end procedure

test()


> Thank you

<curtsey>

Kat

new topic     » goto parent     » topic index » view message » categorize

3. Re: [DOS] Can we emulate "pass by reference" in Eu?

Alex Caracatsanis wrote:
> 
> Dear List
> 
> For my general knowledge, rather than with a specific program in mind, I'd
> like to
> ask how to pass a non-global variable (two scenario's: an atom; a sequence) as
> an argument
> to:
> 1 a procedure that changes the variable (eg increments it)
> 2 a function that changes the variable (eg increments it) but returns some
> other, different,
> variable
> 
> A "minimal" example to achieve the above, would be enough.
> 

File name "mem.e" ...
----------------------
sequence Mem, MemUse
Mem = {}
MemUse = {}

global function NewRef()
    integer lPos
    
    lPos = find(0, MemUse)
    if lPos = 0 then
        Mem    &= 0
        MemUse &= 0
        lPos= length(Mem)
    end if
    
    MemUse[lPos] = 1
    Mem[lPos]    = 0
    return lPos
    
end function

global procedure FreeRef(integer pPos)
    MemUse[pPos] = 0
    Mem[pPos] = 0
end procedure


global function GetRefData(integer pPos)
    return Mem[pPos]
end function

global procedure SetRefData(integer pPos, object pData)
    Mem[pPos] = pData
end procedure

--------------------

File name: "test.ex" which uses "mem.e" ...
--------------------
include mem.e

--------------------------
function addCustomer( sequence pNewCust)
--------------------------

    integer lNewRef
    
    lNewRef = NewRef() 
    SetRefData( lNewRef, pNewCust )
    
    return lNewRef
end function

--------------------------
function calcInterest( integer pCustRef )
--------------------------
    sequence lCust
    atom lInterest
    atom lRate
    
    lCust = GetRefData( pCustRef )
    
    if lCust[4] = 'A' then
        lRate = 0.1025
    elsif lCust[4] = 'G' then
        lRate = 0.1550
    else
        lRate = 0.0
    end if
    
    lInterest = floor((lCust[3] * lRate) * 100) / 100
    
    lCust[3] += lInterest
    
    SetRefData(pCustRef, lCust)
    
    return lInterest
end function

--------------------------
procedure displayCust( integer pCustRef )
--------------------------
    sequence lCust
    
    lCust = GetRefData( pCustRef )

printf(1, "%-25s Balance=%9.2f Rate=%s\n", {lCust[1] & ' ' & lCust[2],
    lCust[3], lCust[4]})
end procedure

sequence vCustList

vCustList = {}


vCustList &= addCustomer( {"Derek", "Parnell",      1000, 'A'} )
vCustList &= addCustomer( {"George", "Potter",        200, 'B'} )
vCustList &= addCustomer( {"Joyce", "Grimwade",      300, 'G'} )
vCustList &= addCustomer( {"Jim", "Ng",            321, 'G'} )
vCustList &= addCustomer( {"Diane", "Smith-Jones",   827, 'B'} )
vCustList &= addCustomer( {"Horace", "Thomas",      1211, 'A'} )
vCustList &= addCustomer( {"Betty", "Boo",          9820, 'A'} )
    
atom vTot

for j = 1 to 3 do
    printf(1, "\n\nCycle %d\n", j)
    vTot = 0
    for i = 1 to length(vCustList) do
        vTot += calcInterest( vCustList[i] )
    end for 
    printf(1, "Total interest: %9.2f\n\n", vTot)
    
    for i = 1 to length(vCustList) do
        displayCust( vCustList[i] )
    end for 
   
    -- Delete third customer
    FreeRef( vCustList[3] )
    vCustList = vCustList[1..2] & vCustList[4..length(vCustList)]
end for

------------------------

-- 
Derek Parnell
Melbourne, Australia

new topic     » goto parent     » topic index » view message » categorize

4. Re: [DOS] Can we emulate "pass by reference" in Eu?

Alex Caracatsanis wrote:
> 
> Dear List
> 
> For my general knowledge, rather than with a specific program in mind, I'd
> like to
> ask how to pass a non-global variable (two scenario's: an atom; a sequence) as
> an argument
> to:
> 1 a procedure that changes the variable (eg increments it)
> 2 a function that changes the variable (eg increments it) but returns some
> other, different,
> variable
> 
> A "minimal" example to achieve the above, would be enough.
> 
> Thank you
> 
> Alex Caracatsanis
> 

Maybe I should add: what I'm thinking about is something like this...

procedure incrementProcedure( object obj )
  -- code that will increment the actual parameter (num),
  -- not a copy of it, such that num is now 11 or {11, 21}
end procedure

function incrementFunction( object obj )
  object retVar

  -- code that will increment the actual parameter (num),
  -- not a copy of it, such that num is now 12 or {12, 22}
  -- code to do other things as well

  return retVar
end function  

procedure main()
  atom num  num = 10
  sequence seq  seq = {10, 20}
  object retVal

  incrementProcedure( num )
  ? num  -- now num = 11
  
  retVal = incrementFunction( num )
  ? num  -- now num = 12
  -- retVal is anything; not interested in it for now

  incrementProcedure( seq )
  ? seq  -- now seq = {11, 21}

  retVal = incrementFunction( seq )
  ? seq  -- now seq = {12, 22}
  -- retVal is anything; not interested in it for now
end procedure

main()


Hope that's clear.

Thanks

Alex Caracatsanis

new topic     » goto parent     » topic index » view message » categorize

5. Re: [DOS] Can we emulate "pass by reference" in Eu?

Alex Caracatsanis wrote:
> 
> Alex Caracatsanis wrote:
> > 
> > Dear List
> > 
> > For my general knowledge, rather than with a specific program in mind, I'd
> > like to
> > ask how to pass a non-global variable (two scenario's: an atom; a sequence)
> > as an argument
> > to:
> > 1 a procedure that changes the variable (eg increments it)
> > 2 a function that changes the variable (eg increments it) but returns some
> > other, different,
> > variable
> > 
> > A "minimal" example to achieve the above, would be enough.
> > 
> > Thank you
> > 
> > Alex Caracatsanis
> > 
> 
> Maybe I should add: what I'm thinking about is something like this...
> 
> }}}
<eucode>
include mem.e

procedure incrementProcedure( object obj )
  -- code that will increment the actual parameter (num),
  -- not a copy of it, such that num is now 11 or {11, 21}
  object lData
  
  lData = GetRefData( obj )
  lData += 1
  SetRefData(obj, lData)
end procedure

function incrementFunction( object obj )
  object retVar

  -- code that will increment the actual parameter (num),
  -- not a copy of it, such that num is now 12 or {12, 22}
  -- code to do other things as well
  object lData
  
  lData = GetRefData( obj )
  lData += 1
  SetRefData(obj, lData)

  retVar = 0 
  if sequence(lData) then
      for i = 1 to length(lData) do
        retVar += lData[i]
      end for
  else
    retVar = lData
  end if
  return retVar
end function  

procedure main()
  integer num
  integer seq 
  object retVal

  num = NewRef()
  SetRefData(num, 10)
  incrementProcedure( num )
  ? GetRefData(num)
  
  retVal = incrementFunction( num )
  ? GetRefData(num)
  ? retVal -- retVal is anything; not interested in it for now

  seq = NewRef()
  SetRefData(seq, {10,20})
  incrementProcedure( seq )
  ? GetRefData(seq)  -- now seq = {11, 21}

  retVal = incrementFunction( seq )
  ? GetRefData(seq)  -- now seq = {12, 22}
  ? retVal --  retVal is anything; not interested in it for now
end procedure

main()
</eucode>
{{{


Here you go. It this the sort of thing?

-- 
Derek Parnell
Melbourne, Australia

new topic     » goto parent     » topic index » view message » categorize

6. Re: [DOS] Can we emulate "pass by reference" in Eu?

Kat, Derek,

Thanks for your helpful examples. Now to study them...

Alex Caracatsanis

new topic     » goto parent     » topic index » view message » categorize

7. Re: [DOS] Can we emulate "pass by reference" in Eu?

> 
> posted by: Alex Caracatsanis <CaracatsanisA at ramsayhealth.com.au>
> 
> Dear List
> 
> For my general knowledge, rather than with a specific program in mind, I'd
> like to ask how to pass a non-global variable (two scenario's: an atom; a
> sequence) as an argument to:
> 1 a procedure that changes the variable (eg increments it)
> 2 a function that changes the variable (eg increments it) but returns some
> other, different, variable
> 
> A "minimal" example to achieve the above, would be enough.
> 
> Thank you
> 
> Alex Caracatsanis


Yes:
sequence sharedvars
sharedvars=repeat(0,27) --whatever max limit to the number of shared variables
--extending it dynamically is trickier, see below

procedure proc1(integer passedbyref,object othervars)
object whatever
--some code
sharedvars[passedbyref]=whatever
--...
end procedure

--...
sharedvars[slot]=myarg
proc1(slot,optionallySomethingElse)
--sharedvars[slot] holds the modified value


Replace "procedure" by "function" as needed. After all, that's how the network 
interrupt #5C works.
You have to keep track of slot alloction and return types yourself.

Now some code in order to forget about any max size of sharedvars:

sequence sharedvars sharedvars={0,0,0}
integer usedslots usedslots=0

function allotslot(object x)
if usedslots=length(sharedvars) then sharedvars&=0 end if
usedslots+=1
sharedvars[usedslots]=x
return usedslots
end function
procedure endgame() usedslots=0 end procedure
--...

procedure proc1(integer passedbyref,object othervars)
object whatever
--some code
sharedvars[passedbyref]=whatever
--...
end procedure

integer slot
slot=allotslot(myarg)
proc1(slot,optionallySomethingElse)
--sharedvars[slot] holds the modified value
--...
endgame()  --current tempvars no longer valid, clean up


That's clumsier, but you no longer take care of slots; just remember which 
holds what.
And you can typecheck sharedvars[slot] at any time and take any appropriate 
action.

CChris

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu