Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411275 Posts in 69323 Topics- by 58380 Members - Latest Member: bob1029

March 28, 2024, 04:57:34 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Does AngelScript have lambdas?
Pages: [1]
Print
Author Topic: Does AngelScript have lambdas?  (Read 2694 times)
oahda
Level 10
*****



View Profile
« on: May 20, 2015, 07:18:54 AM »

I'm starting to suspect that the answer is no, but googling doesn't really confirm neither yes nor no. All I can find is one AS forum result from ages ago. Can't register there either, because it's paid, so I'll ask here. In the past I've gotten good replies when mailing the creator directly but I asked like two weeks ago and no reply this time, so yeah.

DOES ANGELSCRIPT HAVE LAMBDAS OR SOMETHING SIMILAR (C-style functions pointers/refs don't count) OR NOT? Huh?

Is there anybody on the whole world wide web who knows? ._.
Logged

Lavesson
Level 0
***


View Profile WWW
« Reply #1 on: May 20, 2015, 07:24:15 AM »

I tried to determine this too when I considered AngelScript. The only thing I could really find was a work-in-progress list. Not sure how up-to-date the author keeps it (also, if you've googled around, you might have already seen it):
http://www.angelcode.com/angelscript/wip-language.html

If it *is* up-to-date, then I'm guessing no. I can imagine lambdas/closures/anon funcs being quite a major implementation task if it wasn't designed to have it from the very start :/
Logged

oahda
Level 10
*****



View Profile
« Reply #2 on: May 20, 2015, 07:32:15 AM »

Yeah, I've looked there and it does seems like it's not in there.

Pity, seeing as the author of AS seemed to claim in the forum thread I found that it shouldn't be much work at all to add, but still the thread is like two years old and nothing has happened… :/
Logged

Ky.
Level 0
***


Programmer & Web Slinger


View Profile WWW
« Reply #3 on: May 22, 2015, 12:03:59 PM »

as one who has never used one before, what is a lambda and what exactly are you trying to accomplish with it?
Logged

oahda
Level 10
*****



View Profile
« Reply #4 on: May 22, 2015, 12:15:42 PM »

An anonymous function, more or less.

In JavaScript you can do it anywhere with the function keyword:

Code:
var handleToFunction = function() {
    console.log("hello");
};

handleToFunction();

In old C++ you could do function pointers, variables referencing functions, but only to normal, non-anonymous functions (lambdas did not exist in old C++) somewhere else in the program:

Code:
void thisIsAGlobalFunction()
 {
    printf("hello\n");
 }

void (*handleToFunction)() = &thisIsAGlobalFunction;

handleToFunction();

Modern C++ introduced lambdas:

Code:
void (*handleToFunction)() = []()
 {
    printf("hello\n");
 };

handleToFunction();

That way functions can be assigned to handles on the fly without putting them into an actual namespace or class, only existing in that handle. Can be used for adding custom callbacks to individual objects and so on.

Since my game engine uses modern C++ and lambda callbacks it would be neat to have something corresponding for the AngelScript module of the engine, which is mapped largely 1:1 to the C++.
Logged

Lavesson
Level 0
***


View Profile WWW
« Reply #5 on: May 22, 2015, 02:04:32 PM »

I agree with everything, but I think there's one other thing that's worth pointing out about lambdas, especially how they differ from function pointers: They're *usually* implemented as closures, meaning that they close over the scope where they're defined, allowing you to capture variables from an outer scope

Some languages (such as C#) does this automatically, for instance:

Code:
var n = 2;

// Print all even numbers
Enumerable
    .Range(0, 100)
    .Where(i => i % n == 0)
    .ToList()
    .ForEach(Console.WriteLine);

In this case, the following:
i => i % n == 0
... is an anonymous function, but it also allows you to capture and use the variable 'n', even though it's defined outside of the function's scope. This works well in a lot of languages (Python, Lua, JavaScript, Lisp etc...)

Some languages, such as C++11, allows you to do this, but you need to explicitly declare what to capture. Here's a few various C++ lambdas:

Code:
[](){}    // Simplest possible lambda:
          // Description: [] = capture list, () = parameter list, {} = function body

[&x](){}              // A lambda capturing the variable x by reference,
                      // allowing you to use it in the function
[x](){}               // A lambda capturing the variable x by copy
[=](){}               // A lambda capturing everything from the outer scope by copy
[&](){}               // A lambda capturing everything from the outer scope by reference
[this](){}            // A lambda capturing the this pointer

The neat thing about this is that lambdas are literals in the same sense as other values that you can store in variables, allowing you to write functions that either take other functions as arguments (and still having access to the captured variables), or even functions having functions as return values.

As an example, I make use of a bunch of timers in my current engine, where I provide a callback once the timer has finished. The code usually looks like this:

Code:
interval.onDone([this](){
    evt->dispatch(Event::QuakeOccured(0.5, false, Event::QuakeOccured::WAVELET, 0.3f));
    audio->playSoundFx(AudioType::THUNDER);
    // ... More code here
});

In this case, the function is actually called inside the timer (the interval instance), but once run, it will still be able to access the evt and audio variables, even though they're actually fields in the class where the lambda is defined, basically giving you deferred execution.

Just a few quick and dirty examples. Could probably scrounge up a few more ones that's a bit more well thought out Wink

tl;dr: Lambdas and closures allow you to factor out flow control.
« Last Edit: May 22, 2015, 04:33:59 PM by Lavesson » Logged

Lavesson
Level 0
***


View Profile WWW
« Reply #6 on: May 22, 2015, 02:14:59 PM »

And, just for completeness, this is what the onDone and related functions for the 'interval' timer in my previous post looks like:

Code:
#include <functional>

// A function taking zero args, returning void:
typedef std::function<void()> Action;

// This one is called in advance to register a callback when the timer is done
void CountdownTimer::onDone(Action action) {
    _action = action;
}

// Update function where the passed function gets called. Basically, this is the part
// allowing you to invoke "_action", as any other function without any args, but it
// still executes with access to the captured variables where it was defined:
void CountdownTimer::update(Time dt) {
    // ... Uninteresting crap omitted
    if (_done) _action();
}

« Last Edit: May 22, 2015, 02:25:22 PM by Lavesson » Logged

oahda
Level 10
*****



View Profile
« Reply #7 on: May 22, 2015, 10:44:39 PM »

Yeah, sure. There's a boatload of options for and usages of lambdas. I didn't want to overcomplicate it. :p Thanks for expanding on it in in case Kyle wants more details tho!
« Last Edit: May 23, 2015, 12:39:30 AM by Prinsessa » Logged

oahda
Level 10
*****



View Profile
« Reply #8 on: June 11, 2015, 12:52:16 AM »

Well, I've probably solved my personal problem, which shouldn't have been a problem had I implemented my AS support properly from the start — and it's weird that I didn't, because I only had to change a few lines in my code to get it working properly.

I figured it out when someone reminded me that AS is module-based.

Previously, my script files attached to components would have functions as event callbacks (they still do), so that a function of the shape void begin(Component @) would be bound to the "begin" event and so on, which can also be bound to in C++ using lambdas or w/e. However, these were the only thing registered from the files; anything else was ignored and would not be visible from inside these functions; the functions would not even see each other. Everything was also added to the main module.

A few changes, and now everything from a script file is read, and all event callbacks can see each other, other functions, global variables, classes… Anything declared within the script file. I can finally actually use all of the power of AS for my scripts and not just isolated functions. Tongue

And by global I mean to that script file only. Each file becomes its own module and everything within that file can see and use everything else in it, but it does not see what's in other scripts/modules of other components or even other scripts of the same component, which is exactly how I wanted it. Also, of course, globals are persistent and not reset every time the script is run or something (which would be weird anyway since of course I'm not rerunning the entire script but only calling the event callback function handles), so control variables can be added this way instead of my clunkier system of allowing booleans and stuff to be added to components (which will still be used for things like custom settings and talking between scripts and components, tho, so I will be keeping that as well). Kind of like the classes wrapped around script stuff in Unity, only without the class.

Point being: I can now probably at least pass functions global to a script/module as callbacks.

Happy programmer!
« Last Edit: June 11, 2015, 01:01:12 AM by Prinsessa » Logged

Cheezmeister
Level 3
***



View Profile
« Reply #9 on: June 13, 2015, 07:26:16 PM »

Yeah, there's a thread for that Smiley

Don't forget that AS is open-source (in fact, it looks like it *only* comes in source form) so where documentation is lacking and google fails, you can always go code diving to definitively answer such questions.

May the Source be with you.
Logged

෴Me෴ @chzmstr | www.luchenlabs.com ቒMadeቓ RA | Nextris | Chromathud   ᙍMakingᙌCheezus II (Devlog)
oahda
Level 10
*****



View Profile
« Reply #10 on: June 14, 2015, 12:26:21 AM »

Yeah, I had to do that to figure out what AngelScript's error codes mean. Tongue I could find absolutely no list online, but the actual enumeration containing the codes in the AS source has very clear names (and I suppose that enum is in the AS documentation of you click on some function or method returning one of them, I guess, but yeah).

Had to do similar stuff when SDL 2 was brand new to find what I needed to get it working with input and stuff.
Logged

Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic