1. RosettaCode

G'day everyone

I'm slowly getting back into Euphoria. I've started solving tasks at RosettaCode. Anyone want to join in?

Bruce.

new topic     » topic index » view message » categorize

2. Re: RosettaCode

Nice to see some folk have taken up the challenge.

Is it fair enough to assume that Function Composition is impossible in Euphoria?

Kind regards, Bruce.

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

3. Re: RosettaCode

bruce1961 said...

Nice to see some folk have taken up the challenge.

Is it fair enough to assume that Function Composition is impossible in Euphoria?

No, you can do it using routine_ids:

function compose( integer f, integer g, object x ) 
    return call_func( f, {call_func( g, {x} )} ) 
end function 

Matt

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

4. Re: RosettaCode

mattlewis said...

No, you can do it using routine_ids:

function compose( integer f, integer g, object x ) 
    return call_func( f, {call_func( g, {x} )} ) 
end function 

Matt

Wow. Way cool, that.

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

5. Re: RosettaCode

Hmmm ... I must be missing something here. 50 year old brain probably. Anyway, I get the following

Bassano:ex bruceaxtens$ eui compose.ex  
-1 
0 
 
/Users/bruceaxtens/Documents/ex/compose.ex:8 in function compose()  
A machine-level exception occurred during execution of this statement  
 
... called from /Users/bruceaxtens/Documents/ex/compose.ex:15  
 
--> See ex.err  

from this code

--=={{header|Euphoria}}== 
--{{works with|Euphoria 4.0.0}} 
--Thanks to Matt Lewis on the [[http://openeuphoria.org/forum/114789.wc?last_id=114808|OpenEuphoria Forum]] 
--<lang Euphoria> 
include std/math.e 
 
function compose( integer f, integer g, object x )  
    return call_func( f, {call_func( g, {x} )} )  
end function  
 
integer iSin = routine_id("sin") 
integer iArcSin = routine_id("math:arcsin") 
? iSin 
? iArcSin 
object func = compose( iSin, iArcSin, 0.5 ) 
? func 
 
--</lang> 

Weird enough that the routine_id of arcsin is '0' and of sin is '-1'

What have I done wrong here?

Bruce.

P.S. Sorry about all the RosettaCode stuff. Too tired to remove.
P.P.S. Running on MacOSX, Snow Leopard.

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

6. Re: RosettaCode

bruce1961 said...

Weird enough that the routine_id of arcsin is '0' and of sin is '-1'

What have I done wrong here?

sin is a built-in, and you cannot get a routine_id for a built-in. That said, you still shouldn't get a machine exception when using an invalid routine_id. That looks like a bug in the interpreter.

Matt

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

7. Re: RosettaCode

mattlewis said...

That looks like a bug in the interpreter.

Should I consider it 'reported' or is there a formal procedure to follow?

Bruce.

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

8. Re: RosettaCode

include std/math.e 
 
function sine( object x ) 
	return sin(x) 
end function 
 
function compose( integer f, integer g, object x )  
    return call_func( f, {call_func( g, {x} )} )  
end function  
 
integer iSine = routine_id("sine") 
integer iArcSin = routine_id("math:arcsin") 
? iSine 
? iArcSin 
object func = compose( iSine, iArcSin, 0.5 ) 
? func 

That seems to work better, giving '0' and '1' for the routine_ids.

Bruce.

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

9. Re: RosettaCode

bruce1961 said...
mattlewis said...

That looks like a bug in the interpreter.

Should I consider it 'reported' or is there a formal procedure to follow?

I've entered ticket:597. Anyone can add tickets, which is the formal way to report bugs.

Matt

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

10. Re: RosettaCode

Also:

include std/math.e  
  
function sin( object x )  
    return eu:sin(x)  
end function  
 
function compose( integer f, integer g, object x )   
    return call_func( f, {call_func( g, {x} )} )   
end function   
  
integer iSin = routine_id("sin")  
integer iArcSin = routine_id("arcsin")  
? iSin  
? iArcSin  
object func = compose( iSin, iArcSin, 0.5 )  
? func  

carlos@carlos-HP-s3733es:~/Escritorio$ eui compose.ex 
0 
1 
0.5 
 

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

11. Re: RosettaCode

mattlewis said...
bruce1961 said...

Nice to see some folk have taken up the challenge.

Is it fair enough to assume that Function Composition is impossible in Euphoria?

No, you can do it using routine_ids:

function compose( integer f, integer g, object x ) 
    return call_func( f, {call_func( g, {x} )} ) 
end function 

Matt

That isn't really function composition though. The compose function should only take arguments f and g, and return a routine_id, not a value.

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

12. Re: RosettaCode

PeteE said...
mattlewis said...
bruce1961 said...

Nice to see some folk have taken up the challenge.

Is it fair enough to assume that Function Composition is impossible in Euphoria?

No, you can do it using routine_ids:

function compose( integer f, integer g, object x ) 
    return call_func( f, {call_func( g, {x} )} ) 
end function 

Matt

That isn't really function composition though. The compose function should only take arguments f and g, and return a routine_id, not a value.

Yeah, I suppose not. With a little more work:

sequence compositions = {} 
function compose( sequence ids ) 
    compositions = append( compositions, ids ) 
    return length( compositions ) 
end function 
 
function call_composition( integer c, sequence x ) 
    sequence comp = compositions[c] 
    for i = length( comp ) to 1 by -1 do 
        x = call_func( comp[i], x ) 
    end for 
    return x 
end function 
 
... 
 
fg = compose( f, g ) 
call_composition( fg, {1} ) 

Matt

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

13. Re: RosettaCode

mattlewis said...

Yeah, I suppose not. With a little more work:

sequence compositions = {} 
function compose( sequence ids ) 
    compositions = append( compositions, ids ) 
    return length( compositions ) 
end function 
 
function call_composition( integer c, sequence x ) 
    sequence comp = compositions[c] 
    for i = length( comp ) to 1 by -1 do 
        x = call_func( comp[i], x ) 
    end for 
    return x 
end function 
 
... 
 
fg = compose( f, g ) 
call_composition( fg, {1} ) 

Matt

Still, this doesn't seem to be in the spirit of function composition. This compose function returns a "compose-id" which isn't compatible with routine-ids. With this you can't further compose two composed functions, although you've helpfully allowed any number of functions to be composed which should be equivalent. You still can't use a compose-id with anything expecting a routine-id.

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

14. Re: RosettaCode

PeteE said...
mattlewis said...

Yeah, I suppose not. With a little more work:

sequence compositions = {} 
function compose( sequence ids ) 
    compositions = append( compositions, ids ) 
    return length( compositions ) 
end function 
 
function call_composition( integer c, sequence x ) 
    sequence comp = compositions[c] 
    for i = length( comp ) to 1 by -1 do 
        x = call_func( comp[i], x ) 
    end for 
    return x 
end function 
 
... 
 
fg = compose( {f, g} ) -- edited to use {} 
call_composition( fg, {1} ) 

Matt

Still, this doesn't seem to be in the spirit of function composition. This compose function returns a "compose-id" which isn't compatible with routine-ids. With this you can't further compose two composed functions, although you've helpfully allowed any number of functions to be composed which should be equivalent. You still can't use a compose-id with anything expecting a routine-id.

But any singular routine-id can be turned into a compose-id.

We can extend this further so it allows composing with routine-ids, compose-ids, or any combination of compose-ids and routine-ids like so:

-- eat up the first element so compose-id -1 is never valid 
sequence compositions = {-1} 
function compose( sequence ids ) 
    compositions = append( compositions, ids ) 
    return -length( compositions ) 
end function 
 
function call_composition( integer c, sequence x ) 
    sequence comp = compositions[-c] 
    for i = length( comp ) to 1 by -1 do 
	if comp[i] = -1 then 
		-- error ? 
	elsif comp[i] < 0 then 
        	x = call_composition( comp[i], x ) 
	else 
        	x = call_func( comp[i], x ) 
	end if 
    end for 
    return x 
end function 
 
... 
 
fg = compose( {f, g} ) 
hfg = compose( {h, fg} ) 
call_composition( hfg, {1} ) 

It's not possible to turn the resulting compose-id into a routine-id (as far as I know). However, it is possible to create a c-func-id from a compose-id that can be used with c_func().

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

15. Re: RosettaCode

PeteE said...

Still, this doesn't seem to be in the spirit of function composition. This compose function returns a "compose-id" which isn't compatible with routine-ids. With this you can't further compose two composed functions, although you've helpfully allowed any number of functions to be composed which should be equivalent. You still can't use a compose-id with anything expecting a routine-id.

Yes, it's not as pure as what you could get if euphoria implemented more functional capabilities. Given more time, I suppose I could come up with a more general implementation, though that's already more generic than some of the implementations given at Rosetta Code.

I suppose we could put compositions into sequences or something, and then we'd know how to compose arbitrary routine ids and compositions.

sequence compositions = {}  
function compose( sequence ids ) 
	sequence comp = {} 
	for i = 1 to length( ids ) do 
		if sequence( ids[i] ) then 
			comp &= compositions[ids[i][1]] 
		else 
			comp &= ids[i] 
		end if 
	end for 
	compositions = append( compositions, ids )  
	return { length( compositions ) } 
end function  
 
function call_composition( sequence comp, sequence x ) 
	comp = compositions[comp[1]] 
	for i = length( comp ) to 1 by -1 do  
		if sequence( comp[i] ) then 
			x = call_composition( comp[i], x ) 
		else 
			x = call_func( comp[i], x ) 
		end if 
	end for  
	return x 
end function  
 
function F( integer a, integer b ) 
	return { a + b, a - b } 
end function 
 
function G( integer a, integer b ) 
	return {a * 2, b * 3 } 
end function 
 
constant 
	f = routine_id("F"), 
	g = routine_id("G"), 
	fg = compose( { f,  g } ), 
	ffg = compose( {f, fg } ) 
 
sequence s = call_func( f, call_func( f, call_func( g, { 1, 2 } ) ) ) 
? s 
? call_composition( ffg, { 1, 2 } ) 

Matt

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

16. Re: RosettaCode

jimcbrown said...

It's not possible to turn the resulting compose-id into a routine-id (as far as I know).

This is what is preventing me from accepting this composition solution. The compose function must take two routine-ids as input, and produce one routine-id as output.*

jimcbrown said...

However, it is possible to create a c-func-id from a compose-id that can be used with c_func().

This I would very much like to see.


[*] Or instead of a routine-id, something that can be passed to call_func() that works. Here's my solution:

-- wrap the built-in call_func function 
function old_call_func(integer id, sequence args) 
  return call_func(id, args) 
end function 
 
-- override built-in call_func to accept an object as the routine-id 
global function call_func(object id, sequence args={}) 
  if sequence(id) then 
    for i = length(id) to 1 by -1 do 
      args = { call_func(id[i], args) } 
    end for 
    return args[1] 
  end if 
  return old_call_func(id, args) 
end function 
 
-- compose two routine-ids into a sequence that can be used with the above call_func 
global function compose(object f, object g) 
  return {f,g} 
end function 

The overriding call_func function here would need to be defined before including any libraries you would want to call with composed routine-ids.

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

17. Re: RosettaCode

PeteE said...

Or instead of a routine-id, something that can be passed to call_func() that works. Here's my solution:

-- wrap the built-in call_func function 
function old_call_func(integer id, sequence args) 
  return call_func(id, args) 
end function 
 
-- override built-in call_func to accept an object as the routine-id 
global function call_func(object id, sequence args={}) 
  if sequence(id) then 
    for i = length(id) to 1 by -1 do 
      args = { call_func(id[i], args) } 
    end for 
    return args[1] 
  end if 
  return old_call_func(id, args) 
end function 
 
-- compose two routine-ids into a sequence that can be used with the above call_func 
global function compose(object f, object g) 
  return {f,g} 
end function 

The overriding call_func function here would need to be defined before including any libraries you would want to call with composed routine-ids.

This code won't work with 4.0, as you now have to use the override keyword. Even then, it's not possible to replace, override, or shadow eu:call_func().

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

18. Re: RosettaCode

PeteE said...

[*] Or instead of a routine-id, something that can be passed to call_func() that works. Here's my solution:

In 4.0, you can do the override, etc, like this:

 
-- override built-in call_func to accept an object as the routine-id 
override function call_func(object id, sequence args={}) 
  if sequence(id) then 
    for i = length(id) to 1 by -1 do 
      args = { call_func(id[i], args) } 
    end for 
    return args[1] 
  end if 
  return eu:call_func(id, args) -- specify the real built-in 
end function 
 

There's no need for the old_* routine, as you can use the built-in "eu" namespace.

Matt

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

19. Re: RosettaCode

mattlewis said...
PeteE said...

[*] Or instead of a routine-id, something that can be passed to call_func() that works. Here's my solution:

In 4.0, you can do the override, etc, like this: <snip>

There's no need for the old_* routine, as you can use the built-in "eu" namespace.

Matt

Oh, ok. I guess I missed that 4.0 change. But you got the idea.

Now the only problem is that all the library functions that accept a routine-id expect it to be an integer, and will exhibit type-check failures when you pass a sequence of composed routine-ids. It should be fixable using Jim's negative routine-id method to map to composed routine-ids in the overriding call_func function.

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

20. Re: RosettaCode

PeteE said...
jimcbrown said...

It's not possible to turn the resulting compose-id into a routine-id (as far as I know).

This is what is preventing me from accepting this composition solution. The compose function must take two routine-ids as input, and produce one routine-id as output.*

Why does it have to be routine-ids, and not some other token like a c-func-id ?

PeteE said...
jimcbrown said...

However, it is possible to create a c-func-id from a compose-id that can be used with c_func().

This I would very much like to see.

Ok, ok, it can't be done in Euphoria. At least not Euphoria alone. A bottle of machine code glue is required...

Change the call_func()s in composed_call_back() to call_composition() and pass in compose-ids from the other compose into this compose() and it all works.

To turn only a single routine-id (or compose-id) into a c-func-id, pass NOT_USED as the second id.

include std/dll.e 
include std/machine.e 
 
constant mach = 
{ 
-- 0 
#55, 
-- 1 
#89, #e5, 
-- 3 
#83, #ec, #18, 
-- 6 
#c7, #45, #f4, 
-- 9 
#78, #56, #34, #12, 
-- 13 
#c7, #45, #f8, 
-- 16 
#21, #43, #65, #87, 
-- 20 
#c7, #45, #fc, 
-- 23 
#01, #f0, #01, #f0, 
-- 27 
#83, #ec, #04, 
-- 30 
#ff, #75, #08, 
-- 33 
#ff, #75, #f8, 
-- 36 
#ff, #75, #f4, 
-- 39 
#8b, #45, #fc, 
-- 42 
#ff, #d0, 
-- 44 
#83, #c4, #10, 
-- 47 
#c9, 
-- 48 
#c3 
-- 49 
} 
 
function composed_call_back(integer a, integer b, integer c) 
	return call_func(a, {call_func(b, {c})}) 
end function 
constant composed_call_back_mach = call_back(routine_id("composed_call_back")) 
 
public function compose(integer rid_a, integer rid_b) 
	atom a 
	a = allocate(length(mach)) 
	poke(a, mach) 
	poke4(a + 9, rid_a) 
	poke4(a + 16, rid_b) 
	poke4(a + 23, composed_call_back_mach) 
	return define_c_func("", a, {C_ULONG}, C_ULONG) 
end function 
 
public function identity(object x) 
	return x 
end function 
public constant NOT_USED = routine_id("identity") 
 
-- example code 
function ax(integer i) 
return i + 2 
end function 
 
function bx(integer i) 
return i * 2 
end function 
 
atom zx = compose(routine_id("ax"), routine_id("bx")) 
atom xz = compose(routine_id("bx"), routine_id("ax")) 
 
-- should print 4 
? c_func(zx, {1}) 
 
-- should print 6 
? c_func(xz, {1}) 
new topic     » goto parent     » topic index » view message » categorize

21. Re: RosettaCode

jimcbrown said...
PeteE said...
jimcbrown said...

However, it is possible to create a c-func-id from a compose-id that can be used with c_func().

This I would very much like to see.

Ok, ok, it can't be done in Euphoria. At least not Euphoria alone. A bottle of machine code glue is required...

Another version, that allows composition of c-func-ids (and only c-func-ids) into c-func-ids.

include std/dll.e 
include std/machine.e 
 
constant mach = 
{ 
-- 0 
#55, 
-- 1 
#89, #e5, 
-- 3 
#83, #ec, #18, 
-- 6 
#c7, #45, #f4, 
-- 9 
#78, #56, #34, #12, 
-- 13 
#c7, #45, #f8, 
-- 16 
#21, #43, #65, #87, 
-- 20 
#c7, #45, #fc, 
-- 23 
#01, #f0, #01, #f0, 
-- 27 
#83, #ec, #04, 
-- 30 
#ff, #75, #08, 
-- 33 
#ff, #75, #f8, 
-- 36 
#ff, #75, #f4, 
-- 39 
#8b, #45, #fc, 
-- 42 
#ff, #d0, 
-- 44 
#83, #c4, #10, 
-- 47 
#c9, 
-- 48 
#c3 
-- 49 
} 
 
function composed_call_back(integer a, integer b, integer c) 
	return c_func(a, {c_func(b, {c})}) 
end function 
constant composed_call_back_mach = call_back(routine_id("composed_call_back")) 
 
public function compose(integer rid_a, integer rid_b) 
	atom a 
	a = allocate(length(mach)) 
	poke(a, mach) 
	poke4(a + 9, rid_a) 
	poke4(a + 16, rid_b) 
	poke4(a + 23, composed_call_back_mach) 
	return define_c_func("", a, {C_ULONG}, C_ULONG) 
end function 
 
public function identity(object x) 
	return x 
end function 
public constant NOT_USED = define_c_func("", call_back(routine_id("identity")), 
{C_ULONG}, C_ULONG) 
 

Neither this or the previous example have been tested on a system that supports DEP.

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

22. Re: RosettaCode

jimcbrown said...
PeteE said...
jimcbrown said...

It's not possible to turn the resulting compose-id into a routine-id (as far as I know).

This is what is preventing me from accepting this composition solution. The compose function must take two routine-ids as input, and produce one routine-id as output.*

Why does it have to be routine-ids, and not some other token like a c-func-id ?

Because you should be able to use a composed function with library routines such as filter, transform, and apply, or any place that accepts routine-ids. Function composition loses its power if you have to rewrite any called library functions to use call_composition or c_func.

jimcbrown said...
PeteE said...
jimcbrown said...

However, it is possible to create a c-func-id from a compose-id that can be used with c_func().

This I would very much like to see.

Ok, ok, it can't be done in Euphoria. At least not Euphoria alone. A bottle of machine code glue is required...

Change the call_func()s in composed_call_back() to call_composition() and pass in compose-ids from the other compose into this compose() and it all works.

To turn only a single routine-id (or compose-id) into a c-func-id, pass NOT_USED as the second id.

Cool. Thanks.

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

23. Re: RosettaCode

mattlewis said...
bruce1961 said...

Nice to see some folk have taken up the challenge.

Is it fair enough to assume that Function Composition is impossible in Euphoria?

No, you can do it using routine_ids:

function compose( integer f, integer g, object x ) 
    return call_func( f, {call_func( g, {x} )} ) 
end function 

As has been said earlier, Euphoria does not support this (yet).

What is needed is ...

  • the ability to get the routine_id of a built-in
  • a built-in routine like routine_id() that operates like this ...
integer new_rid = eu:compose(f, g) 

Where 'f', and 'g' can be either routine_ids or names of routines.

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

24. Re: RosettaCode

Could someone update the information about Euphoria on this page please?

http://rosettacode.org/wiki/Category:Euphoria

I would do it myself if I knew English better:)

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

25. Re: RosettaCode

Fractal tree was made for DOS long time ago...

http://www.rapideuphoria.com/fractal.ex

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

Search



Quick Links

User menu

Not signed in.

Misc Menu