Support closures in E2 #2830
Replies: 11 comments
-
|
Would it though? What is the expected output? 2x first message, 1x the second one? |
Beta Was this translation helpful? Give feedback.
-
|
Yes, that's the expected output, we can do the same thing in Lua: function setMessage(message)
function sayMessage()
print(message)
end
end
setMessage("To infinity... and beyond!")
sayMessage()
sayMessage()
setMessage("I'm proud of you, cowboy.")
sayMessage()In some languages, the variable is captured by reference, which means changes to the variable affect what's seen in the scope: function counter(value)
return function()
value = value + 1
print(value)
end
end
local increment = counter(0)
increment() --> 1
increment() --> 2In other languages, the variable is captured by value, so the value of the variable is saved at the time the closure is created. Some languages like C++ even let you choose on a per-variable basis whether to capture by value or by reference. The implementation would be simpler if we choose pass by value, but pass by reference wouldn't be too tricky to implement either. |
Beta Was this translation helpful? Give feedback.
-
|
I really do not see the advantage here, can you explain it to me? Extending your lua-example, this would still be true? function counter(value)
return function()
value = value + 1
print(value)
end
end
local a = counter(0)
a() --> 1
a() --> 2
local b = counter(5)
b() --> 6
b() --> 7
a() --> 3
b() --> 8Wouldn't this sample E2 code achieve the same than what you have done in your E2 sample? @persist GlobalVar
function sayMessage()
{
print(GlobalVar)
}
GlobalVar = "To infinity... and beyond!"
sayMessage()
sayMessage()
GlobalVar = "I'm proud of you, cowboy."
sayMessage()What I expect from closures is being able to print out function counter(value)
return function()
value = value + 1
print(value)
end
end
local a = counter(0)
a() --> 1
a() --> 1
local b = counter(5)
b() --> 6
b() --> 6
a() --> 1
b() --> 6 |
Beta Was this translation helpful? Give feedback.
-
Yes.
Yes.
Yes, if Lua's closures passed by value, that'd be the outcome. Closures become much more useful once functions are first-class values, and can be passed to other functions. For example: def filterInRange(list, min, max):
return filter(list, lambda item: min <= item and item < max)
filterInRange([1, 3, 5, 7, 9], 3, 8) # --> [3, 5, 7]But closures are independent of first-class functions, so there's nothing stopping us implementing them now. |
Beta Was this translation helpful? Give feedback.
-
|
This is obviously a topic you know more about than I do. Your E2 example confuses me because this is what I imagine when I read "closure": function setMessage(Message: string)
{
return function()
{
print(Message)
}
}
A = setMessage("There's a snake in my boot!")
A() # > There's a snake in my boot!
A() # > There's a snake in my boot!
B = setMessage("Reach for the sky!")
B() # > Reach for the sky!
B() # > Reach for the sky!
A() # > There's a snake in my boot!
B() # > Reach for the sky!Although as you said, that is not possible because it requires functions to be first-class entities. Is my E2 example more or less what should be possible in the future? |
Beta Was this translation helpful? Give feedback.
-
|
Do you perhaps have an illustrative example of why closures are independent of first-class functions? Maybe a different one to your E2 example, or at least explain me why and what we see there...? |
Beta Was this translation helpful? Give feedback.
-
Yes - def filterInRange(list, min, max):
def inRange(item):
return min <= item and item < max # the use of local variables from outside the function is what makes this a closure
return filter(list, inRange)
Yes, once first-class functions and closures are implemented.
They're independent because they don't require each other to be used. They are more useful together though, you're right, as without first-class functions only one instance of each function defined in the source code can exist at a time. But they are still useful currently. Given that we have string functions, you could do something like this: function map(Items: array, Callback: string) {
for (Index, Item: number = Items) {
Items[Index] = Callback(Item)[number]
}
}
function scaleAll(Items: array, Multiplier: number, Offset: number) {
function scale(Item: number): number {
return Item * Multiplier + Offset
}
map(Items, "scale")
}
A = array(1, 2, 3)
scaleAll(A, 2, 1)
print(A) # --> [3, 5, 7] |
Beta Was this translation helpful? Give feedback.
-
|
Alright, then I am looking forward to this new feature! :) By the way, when will the Haskell interpreter follow? ^_^ |
Beta Was this translation helpful? Give feedback.
-
|
you mean Lisp, not Haskell. |
Beta Was this translation helpful? Give feedback.
-
|
Probably won't be anywhere near a reality until custom types are at least added |
Beta Was this translation helpful? Give feedback.
-
|
Finally implemented. let SetMessage = function(Message:string) {
SayMessage = function() {
print(Message)
}
}
SetMessage("There's a snake in my boot!")
SayMessage()
SayMessage()
SetMessage("Reach for the sky!")
SayMessage() |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
A closure is a function with upvalues. It'd be nice if we could do:
Beta Was this translation helpful? Give feedback.
All reactions