Posted: Mar 09, 2012 9:12 pm
by VazScep
mizvekov wrote:Yes, there are a few additions to the standard, that came from boost, that will help here.
You can start by using std::shared_ptr, which is a reference counted pointer container, that will delete automatically when the count reaches 0.
Code: Select all
struct B {
        int val;
        B(int v) : val(v) {}
        ~B() { std::cout << "bye " << val << std::endl; }
};

std::function<int(int)> f(std::shared_ptr<B> b) {
        return [b](int a) -> int { return a + b->val; };
}

std::function<int(int)> g() {
        auto a = std::make_shared<B>(10), b = std::make_shared<B>(20);
        return f(a);
}
int main() {
        {
                auto foo = g();
                auto bar = std::bind(foo, 1);
                std::cout << foo(2) << ' ' << bar() << std::endl;
        }
        std::cout << "the end" << std::endl;
}

This will print
Code: Select all
bye 20
12 11
bye 10
the end

I am also using std::function there too, which is a polymorphic wrapper for any callable type.
:awesome: That's seriously cool.

I guess my sniveling concern is adoption. Having first-class lambdas could open up C++ to a lot of new and enticing solutions to existing problems, before we start getting into the sorts of clever tricks you'll be able to play with classes, subtyping and templates. There could be a lot of libraries that would benefit from having their APIs extended or even rewritten to support the new constructs. I wonder to what extent this will mean that C++ styles and idioms will just become ever more diverse. Isn't this a problem even with vanilla C++, that you still have folk who treat it as C with some extensions?

This is very much a problem which plagues Common Lisp, and I suspect it's one that the Java developers intentionally avoided by keeping their feature set on a tight leash.

Wow, I misjudged the LISP guys, I thought they would find something like that an aberration and kill it with fire.
Nope. Maybe the Schemers would. Those were always the academic sort. But then again, Schemers are obsessed with their call/cc, which is almost as dangerous a construct as GOTO.

Most lisps have always allowed seriously nasty destructive side-effects. I think this is for a number of reasons: firstly, people were building machines that were Lisp all the way down to the hardware, and where the operating system was just a Lisp runtime and the scripting language was the Lisp REPL. The only sort of Lisp that can cope with that is one which can cope extremely well with state and global access to data, and which allows you to happily bring the system crashing down on itself just like you can with a good old UNIX box. This sort of thing also calls for a lot of reflection mechanisms. Just like you can see every program accessible to you at your shell and you can redefine shell commands, you should be able to see every Lisp function in your runtime environment and redefine symbols (and you should be able to look at their source code, and recompile them, and uninline them and relink them --- Common Lisp runtimes still perform many tasks that are normally reserved for the OS, and are typically more sophisticated).

The sort of crazy self-modifying power led to various crazy engineering. Brian Smith had wacky ideas about being able to reflect into what is conceptually your own interpreter, and then reflect again (an arbitrary number of times), redefine your semantics and reflect back down again into a new programming language. This fully working nonsense eventually became the Lisp MetaObject Protocol, a self-bootstrapping OO system that allows you to redefine the behaviour of classes and generic function dispatch in a way which would confuse Lewis Carroll (though the applications of this idea are pretty sweet, such as Allegro Common Lisp's seamless system whereby you can have billions of objects in your runtime which are automatically offloaded into databases when your memory fills up).

Basically, Lisp is a monster, for arguably good reasons. But for some bizarre reason, a lot of universities seem to teach only toy versions of it. I can't remember how many times I've encountered the claim that Lisp is not a compiled language, or the claim that every data structure in Lisp is a cons.

Though I'm a little sceptical about using monads or any combinator language in an untyped language. The first serious combinator languages that I'm aware of came from ML, and one of the main guys in the ML community back then stressed that "tactic" combinators were only possible when you had a type system for higher-order functions. Often, when I'm working with monads and monad transformers, I'm not really thinking about code or thinking about what a function does. It's too abstract for me by that point. I get by just thinking entirely at the level of types. And I really don't want my frequent mistakes to show up as runtime exceptions. Given the heavy dosage of lambdas involved, I expect most of those exceptions to be thrown from closures a good distance away from the original error.

I see, your work is pretty interesting :)
Well, if you're interested at all in formal logic, the original inspiration for ML and its earliest applications (such as Logic of Computable Functions) are still, IMO, some of the smartest and coolest examples of functional programming engineering and awesome uses of type abstraction and higher-order functions. I can throw some simple Haskell code your way if you're interested.