On Mon, 2006-08-21 at 01:35 +1000, skaller wrote:
> Felix currently doesn't allow side effects in functions,
[]
> I now have some hacks implemented which would allow
> the constraints to be fixed. This works with my hack:
>
> -------------------------------------
> #import <flx.flxh>
>
> proc f(ref x:int,b:int) {
> x = 22;
> }
>
> fun g(x:int)=>x + x;
> var z = 1;
> print z; endl;
> z = g(f 33);
> print z; endl;
> ----------------------------
The right way to do this still isn't clear.
A general lifting operation:
g [! f 33 !]
where [! .. !] means 'lift this side-effect out' may be useful,
but isn't a complete solution (because you could just forget,
or apply it inappropriately).
A more specific method like:
g ( f $$ 33 )
makes more sense but is less general. This forces a lift:
without the $$ notation, f has the wrong type to apply to 33.
Another issue: the type is better as given by
proc f(x:int) (px:&int) {..}
which is
f: int -> &int -> void
A function
f: int -> int
can be converted to a procedure by adding a pointer
argument and replacing
return x
with an assignment to the pointer followed by a return:
*px = x; return;
and indeed this is precisely what the inliner does.
Functions in Felix are *annoying* because they use the machine
stack for return addresses, defeating fibration (fthreads)
and more generally making service calls impossible.
We have them mainly so we can embed calls to Felix functions
in C:
fun add: int * int -> int = "$1+$2";
add (f x, f y);
where f x has to generate a C expression, which a procedure
call is not. We could, of course, always lift Felix applications
out of the C expression, but that would enforce eager evaluation:
fun cond: bool * int * int = "$1?$2:$3";
no longer has lazy (short cut) semantics
applied to a lifted expression. So transforming ALL functions
into procedures isn't viable.
One thought is simply to allow procedures to return a value:
proc f(x:int): int = {
return x + x;
}
This is a function 'declared' to have side effects by naming
it a proc .. it is implemented by
proc f(x:int) (&px:int) {
*px = x + x;
}
which has the same overload signature, however the return
type is different. The compiler can reliably detect this
and lift an application out, even if the closure is a variable.
Its a bit hacky still, because if you wrote:
proc f(x:int) (&px:int) {
*px = x + x;
}
directly, you shouldn't be able to use it as a function
in an expression because it isn't *declared* to return a value.
The only proper solution here is to modify the type system :)
--
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Felix-language mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/felix-language