>>3
Ignoring the "static" solution (not a real one), you could write this in 2 main ways:
1) Unportable: malloc a buffer, and write the function code to it, insert n's value in the function code. Not hard to do, but not portable.
2) Portable: make a FUNCALL-like macro, which calls a function with a context struct or value cell array, and have the function use the values in the struct (in this case, the value of n).
In the case 2, a function is either a piece of code or a structure which contains the address of a real function and an array or structure of values closed over (or pointers to them). A funcall function or macro can call the real function or the encapsulated structure (containing the real function and closed over values). This is how most Lisps do it, but it's done behind the scenes, so you don't really need to know how closures are implemented.
>>3 int (*foo(int n))(int)
{ int f(int i)
{ return n + i; }
return f; }
Name:
Anonymous2010-07-16 19:28
And here's the old C++ way to do it using templates and compile-time functors, although it's not exactly the same thing as actual lambdas and closures that are in C++0x.
template< int N >
struct foo
{
int operator()(int i) {
return i + N;
}
};
>>11
It looks like it just creates a closure on the stack to capture the value of 'n' that gets passed in when calling the the returned pointer to 'f' (the compiler already knows it's on the stack after the call to foo, so it optimizes it out).
So it looks to be pretty efficient. Not sure yet what would happen across optimization boundaries.
Name:
Anonymous2010-07-16 20:11
DISCLAIMER: THIS IS A TOY! I DO NOT ACTUALLY CODE LIKE THIS
Should run under ikarus with the iksqlite lib
(import (rnrs) (zeptodyne iksqlite))
(define make-counter
(letrec* ((db (sqlite-open "/tmp/test.db"))
(n 0)
(make-name
(lambda ()
(set! n (+ n 1))
(string-append "counter"
(number->string n)))))
(sqlite-exec db "create table retarded_counter (k string, v integer)")
(lambda (x)
(let ((name (make-name)))
(sqlite-exec db (format "insert into retarded_counter values (~s,~s)" name x))
(lambda ()
(let ((ans (string->number
(vector-ref
(car (sqlite-exec db (format "select v from retarded_counter where k = ~s" name))) 0))))
(sqlite-exec db (format "update retarded_counter set v = ~s where k = ~s"
(+ ans 1) name))
ans))))))
Name:
Anonymous2010-07-16 20:15
>>17
If this were real code, it would be a candidate submission for thedailywtf.com.
(defun foo (n) (curry #'+ n))
Should also work, where you should write or import your currying function (a simple 3-4 line version is easy to write, if you don't have it in a library).
>>35 >>36
>clang does not support nested functions; this is a complex feature which is infrequently used, so it is unlikely to be implemented anytime soon.