1. RosettaCode
- Posted by bruce1961 Jan 24, 2011
- 2278 views
G'day everyone
I'm slowly getting back into Euphoria. I've started solving tasks at RosettaCode. Anyone want to join in?
Bruce.
2. Re: RosettaCode
- Posted by bruce1961 Jan 26, 2011
- 2115 views
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.
3. Re: RosettaCode
- Posted by mattlewis (admin) Jan 26, 2011
- 2086 views
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
4. Re: RosettaCode
- Posted by bruce1961 Jan 26, 2011
- 2011 views
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.
5. Re: RosettaCode
- Posted by bruce1961 Jan 26, 2011
- 2021 views
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.
6. Re: RosettaCode
- Posted by mattlewis (admin) Jan 26, 2011
- 1991 views
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
7. Re: RosettaCode
- Posted by bruce1961 Jan 26, 2011
- 2013 views
That looks like a bug in the interpreter.
Should I consider it 'reported' or is there a formal procedure to follow?
Bruce.
8. Re: RosettaCode
- Posted by bruce1961 Jan 26, 2011
- 1981 views
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.
9. Re: RosettaCode
- Posted by mattlewis (admin) Jan 26, 2011
- 1992 views
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
10. Re: RosettaCode
- Posted by cargoan Jan 26, 2011
- 1960 views
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
11. Re: RosettaCode
- Posted by PeteE Jan 26, 2011
- 2004 views
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.
12. Re: RosettaCode
- Posted by mattlewis (admin) Jan 26, 2011
- 2001 views
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
13. Re: RosettaCode
- Posted by PeteE Jan 26, 2011
- 1940 views
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.
14. Re: RosettaCode
- Posted by jimcbrown (admin) Jan 26, 2011
- 1951 views
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().
15. Re: RosettaCode
- Posted by mattlewis (admin) Jan 26, 2011
- 1964 views
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
16. Re: RosettaCode
- Posted by PeteE Jan 26, 2011
- 1930 views
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.*
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.
17. Re: RosettaCode
- Posted by jimcbrown (admin) Jan 26, 2011
- 1907 views
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().
18. Re: RosettaCode
- Posted by mattlewis (admin) Jan 26, 2011
- 1928 views
[*] 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
19. Re: RosettaCode
- Posted by PeteE Jan 26, 2011
- 1923 views
[*] 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.
20. Re: RosettaCode
- Posted by jimcbrown (admin) Jan 26, 2011
- 1889 views
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 ?
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})
21. Re: RosettaCode
- Posted by jimcbrown (admin) Jan 26, 2011
- 1903 views
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.
22. Re: RosettaCode
- Posted by PeteE Jan 26, 2011
- 1915 views
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.
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.
23. Re: RosettaCode
- Posted by DerekParnell (admin) Jan 26, 2011
- 1984 views
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.
24. Re: RosettaCode
- Posted by Insolor Aug 23, 2011
- 1662 views
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:)
25. Re: RosettaCode
- Posted by achury Aug 23, 2011
- 1616 views
Fractal tree was made for DOS long time ago...