Author Topic: Applying function pointers  (Read 2665 times)

0 Members and 1 Guest are viewing this topic.

Arnold

  • Guest
Applying function pointers
« on: August 22, 2017, 10:42:36 AM »
Hi Charles,

at Rosettacode.org there is a task: "Apply a callback to an array". I tried to apply some of the examples with Oxygenbasic. This one is adapted from Euphoria:

Code: OxygenBasic
  1. 'Oxygenbasic A43 2017-08-07
  2.  
  3. include "$/inc/console.inc"
  4.  
  5. function apply_to_all(int s[], int c, sys @f)
  6.     ' apply a function to all elements of a sequence
  7.  
  8. '    dim result[] as int at @s
  9.    int *result[] = @s[]
  10.  
  11.     for i = 1 to c
  12.         ' we can call add1() here although it comes later in the program
  13.         result[i] = call f(s[i])
  14.     next i
  15.     return result[]
  16. end function
  17.  
  18. function add1(int x) as int
  19.     return x+1
  20. end function
  21.  
  22. int array[] = {10, 20, 30, 40, 50}
  23.  
  24. ' add1() is visible here, so we can call the function
  25. array[] = apply_to_all(array[], countof array, @add1)
  26.  
  27. printl
  28. for x=1 to countof array
  29.   print array[x] " "
  30. next
  31. printl
  32.  
  33. printl "Enter ..." : waitkey
  34.  

Output:

11 21 31 41 51

Enter ...

This example is adapted from Freebasic. When I coded it I noticed that in fact I would not need any pointer to a function at all, but anyway:

Code: OxygenBasic
  1. 'Oxygenbasic A43 2017-08-07
  2.  
  3. include "$/inc/console.inc"
  4.  
  5. sub PrintEx(int n)
  6.   printl n + tab + n * n + tab + n * n * n
  7. end sub
  8.  
  9. sub Proc(int array[], c, sys @call_back)
  10.   for i = 1 to c
  11.     call call_back(array[i])
  12.   next
  13. end sub
  14.  
  15.  
  16. int a[10] = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100}
  17.  
  18. printl "n" + tab + "n^2" + tab + "n^3"
  19. printl "-" + tab + "---" + tab + "---"
  20. Proc(a[], countof a, @PrintEx)
  21. printl
  22.  
  23. printl "Enter ..." : waitkey
  24.  

Output:

n       n^2     n^3
-       ---     ---
10      100     1000
20      400     8000
30      900     27000
40      1600    64000
50      2500    125000
60      3600    216000
70      4900    343000
80      6400    512000
90      8100    729000
100     10000   1000000

Enter ...

Is this approach ok? Are there altenatives in Oxygenbasic when using function pointers?

There is also another interesing example done in FBSL with languages[]. But I am not sure about the purpose of the MAP() function. Is this something which you achieve in tests\Constructs\ArrayOfCalls.o2bas or in examples\Linkage\FuncLinkTbls.o2bas?

Roland
« Last Edit: August 22, 2017, 10:58:24 AM by Arnold »

Kuron

  • Guest
Re: Applying function pointers
« Reply #1 on: August 22, 2017, 01:49:09 PM »
Euphoria

OT.  Bought that when it came out in '93.  Great language and racked up some $$ in long distance charges using their BBS.  Still have the old printed manual boxed up somewhere.

Arnold

  • Guest
Re: Applying function pointers
« Reply #2 on: August 23, 2017, 12:49:54 AM »
Quote
Euphoria
Yes, Euphoria is a nice programming language for Windows and Linux with some own concepts. There are only few data types:

integer : from -1073741824 to +1073741823
atom : 32-bit integer or double value
object : atoms or sequence
sequence (array) : can be multidimensional, can be a mix of atoms, objects and sequences e.g (very basic):
  {{"john", "doe"}, 75328, 33.67}

For me most impressive is the archive which contains a lot of user contributed code, libraries and applications. I still use Euphoria from time to time.
« Last Edit: August 24, 2017, 06:03:16 AM by Arnold »

Arnold

  • Guest
Re: Applying function pointers
« Reply #3 on: August 24, 2017, 06:02:23 AM »
I managed to get the results of the first example of FBSL. It works similar like the first example above:

Code: OxygenBasic
  1. 'Oxygenbasic A43 2017-08-07
  2.  
  3. include "$/inc/console.inc"
  4.  
  5. #lookahead
  6.  
  7. int e[] = {1, 2, 3}
  8.  
  9. MyMap(@Add42, int e[], countof e)
  10.  
  11. printl
  12. for x = 1 to countof e
  13.     print e[x] " "
  14. next
  15.  
  16. printl "Enter ..." : pause
  17.  
  18. function MyMap(sys @f, int a[], int c)
  19.     int *retval[] = @a[]
  20.     int e  'different from e[]
  21.  
  22.     for e = 1 to c
  23.         retval[e] = call f(a[e])
  24.     next
  25.  
  26.     return retval[]
  27. end function
  28.  
  29. function Add42(int n) as int : return n + 42 : end function
  30.  

Output:

43 44 45
Enter ...

I will also get the results of FBSL's second example. But I assume this is no mapping at all?

Code: OxygenBasic
  1. 'Oxygenbasic A43 2017-08-07
  2.  
  3. include "$/inc/console.inc"
  4.  
  5. type language
  6.    string lang
  7.    string numbers[10]
  8. end type
  9.  
  10. language languages[2]
  11. languages[1].lang = "English"
  12. languages[1].numbers[] = {"one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"}
  13. languages[2].lang = "French"
  14. languages[2].numbers[] = {"un", "deux", "trois", "quatre", "cinq", "six", "sept", "huit", "neuf", "dix"}
  15.  
  16.  
  17. sub NameANumber(string lang, int nb, string number)
  18.     printl "The number "  nb " is called " number " in " lang
  19. end sub
  20.  
  21. sub SpeakALanguage(language lang[], int c)
  22.     for x=1 to c
  23.     for y=1 to 10
  24.        NameANumber(lang[x].lang, y, lang[x].numbers[y])
  25.     next
  26.         printl string(40, "-")
  27.     next
  28. end sub
  29.  
  30. SpeakALanguage(languages[], countof languages)
  31.  
  32. printl "Enter ..." : waitkey
  33.  

Output:

The number 1 is called one in English
The number 2 is called two in English
The number 3 is called three in English
The number 4 is called four in English
The number 5 is called five in English
The number 6 is called six in English
The number 7 is called seven in English
The number 8 is called eight in English
The number 9 is called nine in English
The number 10 is called ten in English
----------------------------------------
The number 1 is called un in French
The number 2 is called deux in French
The number 3 is called trois in French
The number 4 is called quatre in French
The number 5 is called cinq in French
The number 6 is called six in French
The number 7 is called sept in French
The number 8 is called huit in French
The number 9 is called neuf in French
The number 10 is called dix in French
----------------------------------------
Enter ...

Charles Pegge

  • Guest
Re: Applying function pointers
« Reply #4 on: August 24, 2017, 07:24:04 AM »
You can often replace functions with macros for this type of task. The primary advantages are high performance and polymorphism.

As you will see, there are no function pointers, and the array V could be any numeric type.

To achieve full encapsulation within a macro, locally used terms are appended to the macro prototype.

Iteration is done with striding pointers. So there are no arrays to index.

Code: [Select]
function add1(int *v)
v+=1
end function

macro madd1(v)
v+=1
end macro

macro Apply(v,f,  w,n)
int n = countof v
typeof v *w = @v
while n--
  f w
  @w+=sizeof v 'stride
wend
end macro

macro smallList(v,f,   c,n,w,s)
int c
int n=countof v
typeof v *w = @v
string s
while n--
  c++
  s += c  chr(9)  w  chr(13,10)
  @w+=sizeof v 'stride
wend
f s
s=""
end macro

float v={10.5,20,30,40,50}
apply     v, madd1
smallList v, print

Arnold

  • Guest
Re: Applying function pointers
« Reply #5 on: August 28, 2017, 05:54:13 AM »
Hi Charles,

I was out of town last weekend at a great wedding celebration. No computer, no internet. But nevertheless a lot of young people using their smartphone for selfies.

Your example using macros looks tempting. Unfortunately I got an error:
;ASM ERR:   v3 mov eax,=!! Unidentified instruction: v3
;AFTER: ._cnd
;LINE:  33   (which points to: apply     v, madd1)

I changed:
function add1(float *v)
and used this:
apply     v, add1.

This will give the correct results but I assume the purpose of the macro madd1 is to work independently of the used type. I tried several possible modifications yet nothing worked as expected. But I think something is missing in macro madd1?

Is there a way to check what is happening within a macro?

Roland



Arnold

  • Guest
Re: Applying function pointers
« Reply #6 on: August 29, 2017, 02:05:03 AM »
Hi Charles,

if I add overloading to function add1 with int,float,double then this will do the job.

I noticed a difference between macro apply and macro smallList: if I add print typeof f in macro smallList I get the message: metatype -16 core function. In macro apply I get the message: metatype -5 proc sub or function (using add1). If I comment out f w in macro apply and try typeof f then I will get the error: Linker found unidentified names: ::= level 0 (using madd1).

Would it be better in this case to use functions instead of macro for the calling process?

Roland
« Last Edit: August 30, 2017, 07:06:10 AM by Arnold »

Charles Pegge

  • Guest
Re: Applying function pointers
« Reply #7 on: September 03, 2017, 01:27:18 AM »
Hi Roland,

I would go with function overloading for now.

 I have been fine-tuning the macro system and started a generics file, which I hope will prove to be very useful for high-level programming. But I don't want to rush it. There are so many permutations to test.

OxygenBasic is also on a strict diet. - lost about 300 lines of code so far :)

Arnold

  • Guest
Re: Applying function pointers
« Reply #8 on: September 03, 2017, 01:46:06 AM »
Hi Charles,

using this example you pointed me to "typeof" and this is really an interesting feature. At the moment I am experimenting a little bit with this capability.

Roland