When isn't inlining safe? - optimization

I keep reading (for example in the Closure Compiler and other compilers) that inlining of functions isn't always safe. Could you please provide an example when inlining of functions shouldn't be done?

In many languages, inlining a function will have no observable semantic effects, although it is likely to affect the compiled size and execution time of the program. However, that is not true in languages in which the call stack and/or local variable bindings are visible.
As a simple example, in Javscript the local variable arguments always refers to an array-like object containing the arguments to the current function call. Clearly, if the function in which it occurred were inlined, its semantics would change. An inliner would have to either refuse to inline a function whose body references arguments or it would have to modify the code in a way which preserved the semantics, possibly by creating another local variable with a different name and substituting the reference.
Another example would be the (non-recommended) use of eval. Name lookup in the string passed to eval is done within the scope of the function which calls eval. For example:
inner = function(s) { var x = 4; return eval(s); }
outer = function(s) { var x = 3; return inner(s); }
outer("x+1")
Here the value returned by outer is 5. If inner were inlined, which would require renaming its local variable x to avoid name conflict, the value returned would be 4. (If both inner and outer were inlined, the value would probably be something else again.)
In general, it's going to be very difficult to inline a function which calls eval because there is no easy way to know the contents of the argument to eval.

Related

Terraform module as "custom function"

It is possible to use some i.e. local module to return let' say same calculated output. But how can you pass some parameters? So each time you will ask for the output value you will get different value according to the parameter(ie different prefix)
Is it possible to pass resource to module and enhance it with tags?
I can imagine that both cases are more likely to be case for providers, but for some simple case it should work maybe. The best would be if they implemented some custom function that you will be able to call at will.
It is possible in principle to write a Terraform module that only contains "named values", which is the broad term for the three module features Input Variables (analogous to function arguments), Local Values (analogous to local declarations inside your function), and Output Values (analogous to return values).
Such a module would not contain any resource or data blocks at all and would therefore be a "computation-only" module, which therefore has all of the same capabilities as a function in a functional programming language.
variable "a" {
type = number
}
variable "b" {
type = number
}
locals {
sum = var.a + var.b
}
output "sum" {
value = local.sum
}
The above example is contrived just to show the principle. A "function" this simple doesn't really need the local value local.sum, because its expression could just be written inline in the value of output "sum", but I wanted to show examples of all three of the relevant constructs here.
You would "call the function" by declaring a module call referring to the directory containing the file with the above source code in it:
module "example" {
source = "./modules/sum"
a = 1
b = 2
}
output "result" {
value = module.example.sum
}
I included the output "result" block here to show how you can refer to the result of the "function" elsewhere in your module, as module.example.sum.
Of course, this syntax is much more "chunky" than a typical function call, so in practice Terraform module authors will use this approach only when the factored out logic is significant enough to justify it. Verbosity aside though, you can include as many module blocks referring to that same module as you like if you need to call the "function" with different sets of arguments. Each call to the module can take a different set of input variable values and therefore produce a different result.

Using inline function kotlin

I know there was documented in main kotlin page, but there is no clear explanation about when to use it, why this function need a receiver as a function. What would be the correct way to create a correct definition of inline function.
This is inline function
inline fun String?.toDateString(rawDateFormat: String = MMMM_DD_YYYY, outputDate: String = MM_DD_YYYY, block: (date: String) -> String): String {
return try {
var sdf = SimpleDateFormat(rawDateFormat, Locale.US)
val date = sdf.parse(this.orEmpty())
sdf = SimpleDateFormat(outputDate, Locale.US)
block(sdf.format(date ?: Date()).orEmpty())
} catch (ex: Exception) {
block("")
}
}
The same way we also can do
inline fun String?.toDateString(rawDateFormat: String = MMMM_DD_YYYY, outputDate: String = MM_DD_YYYY): String {
return try {
var sdf = SimpleDateFormat(rawDateFormat, Locale.US)
val date = sdf.parse(this.orEmpty())
sdf = SimpleDateFormat(outputDate, Locale.US)
sdf.format(date ?: Date()).orEmpty()
} catch (ex: Exception) {
""
}
}
If anyone could have a detail explanation about this?
Edit:
I understand that the inline function will insert the code whenever it called by the compiler. But this come to my attention, when I want to use inline function without functional parameter receiver type the warning show as this in which should have a better explain. I also want to understand why this is such recommendation.
There are few things here.
First, you ask about using a function with a receiver.  In both cases here, the receiver is the String? part of String?.toDateString().  It means that you can call the function as if it were a method of String, e.g. "2021-01-15 12:00:00".toDateString(…).
The original String? is accessible as this within the function; you can see it in the sdf.parse(this.orEmpty()) call.  (It's not always as obvious as this; you could simply call sdf.parse(orEmpty()), where the this. is implied.)
Then you ask about inline functions.  All you have to do is to mark the function as inline, and the compiler will automatically insert its code wherever it's called, instead of defining a function in the usual way.  But you don't need to worry about how it's implemented; there are just a few visible effects in the code.  In particular, if a function is inline and accepts a function parameter, then its lambda can do a few things (such as calling return) that it couldn't otherwise do.
Which leads us to what I think is your real question: about the block function parameter.  Your first example has this parameter, with the type (date: String) -> String — i.e. a function taking a single String parameter and returning another String.  (The technical term for this is that toDateString() is a higher-order function.)
The toDateString() function calls this block function before returning, applying it to the date string it has formatted before returning it to the caller.
As to why it does this, it's hard to tell.  That's why we put documentation comments before functions: to explain anything that's not obvious from the code!  Ideally, there would be a comment explaining why you're required to supply a block lamdba (or function reference), when it's not vital to what the function does.
There are times when blocks passed this way are very useful.  For example, the joinToString() function accepts an optional transform parameter, which it applies to each item before joining it to the list.  If it didn't, the effect would be a lot more awkward to obtain.  (You'd probably have to apply a map() to the collection before calling joinToString(), which would be less efficient.)
But this isn't one of those times.  As your second example shows, toDateString() would work perfectly well without the block parameter — and then if you needed to pass the result through another function, you could just call it on toDateString()'s result.
Perhaps if you included a link to the ‘main kotlin page’ where you saw this, it might give some more context?
The edited question also asks about the IDE warning.  This is shown when it thinks inlining a function won't give a significant improvement.
When no lambdas are involved, the only potential benefit from inlining a function is performance, and that's a trade-off.  It might avoid the overhead of a function call wherever it's called — but the Java runtime will often inline small functions anyway, all on its own.  And having the compiler do the inlining comes at the cost of duplicating the function's code everywhere it's called; the increased code size is less likely to fit into memory caches, and less likely to be optimised by the Java runtime — so that can end up reducing the performance overall.  Because this isn't always obvious, the IDE gives a warning.
It's different when lambdas are involved, though.  In that case, inlining affects functionality: for example, it allows non-local returns and reified type parameters.  So in that case there are good reasons for using inline regardless of any performance implications, and the IDE doesn't give the warning.
(In fact, if a function calls a lambda it's passed, inlining can have a more significant performance benefit: not only does the function itself get inlined, but the lambda itself usually does as well, removing two levels of function call — and the lambda is often called repeatedly, so there can be a real saving.)

Why Are My Tables Returning NIL and Not Populating?

I'm new to Lua and trying to understand the concept of OOP in Lua. To do so, I've tried creating an object and creating methods and "private variables". My issue is when I try to use "setters" or "getters", it's indicating that my tables are returning NIL which means I'm either having a scoping issue or something else I can't figure out.
The kicker is I'm using an example from an online Lua coding tutorial, and when I run the tutorial it works flawlessly. However, when I run mine, I get NIL or nothing outputs whenever I try to "get" or return a value from one of the member functions.
I'm using a couple of different environments:
ZeroBrain
Sublime Text
Lua for Windows
Do you know why my code is not returning populated tables?
newPlayer = function(n, h, a, r)
player = {}
n = n or ""
h = h or 100
a = a or 100
r = r or 0
function player:getPlayerName()
return n
end
function player:getPlayerHealth()
return h
end
function player:getPlayerArmor()
return a
end
function player:getPlayerRank()
return r
end
function player:setPlayerName(arg)
n = arg
end
function player:setPlayerHealth(arg)
h = arg
end
function player:setPlayerArmor(arg)
a = arg
end
function player:setPlayerRank(arg)
r = arg
end
function player:connect(arg)
print(string.format(" %s joined" , arg))
end
return player
end
player1 = newPlayer("John", 100, 100, 1000)
player1.getPlayerName()
Your code does not contain "populated tables" to return.
Your newPlayer function does create a table, and it does return it. It creates a number of functions within that table. But that's all newPlayer does: creates a table and puts some functions in it.
The data accessed by those functions is not part of the table. n, h, a, and r (BTW, please use better variable names) are all local variables. Your inner functions will access the specific stack containing those variables, but the variables themselves will not be magically associated with the table.
Your principle problem is almost certainly with the setters. And it comes from a combination of this:
function player:setPlayerName(arg)
with this:
player1.getPlayerName()
When you create a function using a : character between a table name and the function's name, you are using syntactic sugar for a function which implicitly takes as its first argument a value called self. As the name suggests, this is supposed to represent the object which this function is being called upon. So your function creation code is equivalent to:
function player.setPlayerName(self, arg)
Since you create all of your functions with :, all of your functions take at least one parameter.
The : syntax can also be used when calling such functions. If you did player1:getPlayerName(), this would cause the table you accessed to find the getPlayerName function to be used as the first argument in the function call. So that line would be equivalent to player1.getPlayerName(player1).
Obviously, these two syntaxes are mirrors of one another: functions created with : take a parameter that is expected to refer to the table it is being called on, and functions called with : will be given the table which was accessed to get that function.
But... your code didn't stick to the symmetry. You created the functions with :, but you call them with .
Now, you get functions are able to get away with this because... well, none of your values are actually part of the table. So your get functions just return the local value that they adopted from their creating context.
The set functions pose a problem. See, they take a parameter. But because the function was declared with :, they really take two parameters, the first being the implicit self.
Now, : syntax is just syntactic sugar; it's just a convenient way to do what you could have done yourself. So it is in theory OK to call a function with . even if you created it with :. But if you do so, you must pass the table as the first parameter. Though your code doesn't show it, I strongly suspect you didn't do that.
If you called player1.setPlayerName("foo"), what will happen is that the implicit self parameter will get the value "foo", and the arg parameter will be nil. And you will assign that nil value to the n local variable. So subsequent calls to player1.getPlayerName() will return nil.
Basically, what's going on here is that you're combining two different ways of creating objects in Lua. You stored your private data in a way that external code cannot access (ie: local upvalues), but that data is now no longer part of the table itself. Which means that, although you dutifully create those functions with : syntax to indicate that they take a self table, they never actually use that table. And because they never use the table, it's a lot harder to figure out what's going wrong.
Basically, the key here is to be symmetrical. If you create a function with :, then you should either call it with : or make sure to pass it the object table as the first parameter.
Broadly speaking, the standard way to create private members is by convention, not by forbidding it. That is, you agree not to mess with any members of a table other than those with certain names. Python convention is to pretend that names starting with _ don't exist, and Lua programs sometimes use that.
Upvalues are an interesting solution for private variables, but they do come with problems. If you want to invent a member variable, you have to do it in a centralized place rather than wherever you might need one. Even if the variable is optional, you have to create a named local at the top of the function.
TLDR of Nicol's answer, see my answer to another question:
function player:setPlayerArmor(arg)
a = arg
end
The : syntax is syntactic sugar. It creates an implicit 'self' argument when declared, and when used. If you declare it one way and use it another, the arguments won't be what you're expecting. Say your player has 100 health. Look at this result:
player1.setPlayerHealth(55, 66)
print(player1.getPlayerHealth())
-- will display '66', not '55' because `:` declares implicit 'self' argument
This displays 66 because the setPlayerHealth function has an implicit 'self' parameter because it was declared with :. If you instead called it
with the ::
player1:setPlayerHealth(55, 66)
print(player1:getPlayerHealth())
-- will display '55' because `:` passes player1 as self
function player:setHealth1(arg)
-- implicit 'self' argument refers to player1 when called on player1
end
-- is the same as
function player.setHealth2(self, arg)
-- with `.` notation, you need to add the 'self' argument explicitly
end
player1.setHealth1(31) -- self argument will be 31 and arg will be nil
player1.setHealth2(32) -- self argument will be 32 and arg will be nil
player1:setHealth1(33) -- self argument will be player1 and arg will be 33
player1:setHealth2(34) -- self argument will be player1 and arg will be 34

Is the term immutable variable just a convention?

In Rust variables are immutable by default, i.e., they don't vary but are not constants (as noted here).
Do they retain the name "variable" just by convention, or is there another reason why the term "variable" is maintained?
It should be noted that the term mut in Rust was hotly debated before stabilization with some arguing that it should be called excl or uniq. The matter is that the mut in in let mut x and &mut x are two completely different things.
let mut x declares that x is mutable, in the sense that it can be re-assigned, but also that one can take a &mut reference of it; which is best called an exclusive or unique reference. It is quite possible in Rust in some cases to mutate through a shared reference in the case of std::cell::Cell, for instance, and not all operations that require an exclusive reference involve mutation. An operation that requires an exclusive reference is simply one that would be unsafe with a shared one; Cell is designed in such a way that it is not, by strictly controlling under what conditions mutation can occur.
In theory, the two functions of let mut x could have different keywords, but they are compressed into one for simplicity. Rust could in theory be designed with mut and excl being different keywords, and allowing for let excl x, which would be a variable wherefrom one could take an exclusive reference, but not mutate.
One can also have variables that are not declared with mut, in particular in function calls. In a signature like fn func ( x : u32 ), x is not mutable, but it is variable, because it a different x can be passed every single time.
The let mut x type of "mutable" is purely a lint and, in theory, unnecessary for Rust to work — any currently working Rust program will continue to work if all non-mutable variables be made mutable. It's simply considered bad practice to do so and the compiler will warn the programmer whenever he make a variable mutable that isn't necessary to be mutable; this helps catching unintended bugs. This is absolutely not the case with exclusive and shared references, which are necessary to be distinguished and more than just a lint.
Here "variable" means "factor involved in computation" not "varying". This is from the mathematical principle where expressions like f(x) include x, a variable, as a part of the equation.
In Rust, like with other languages, you'll need variables (e.g. input) that affects how the program runs, otherwise your program would only ever behave in a singular, specific way, producing the same output each time.
You'll need to think of what variables change during processing and which do not. Those that do not need to change do not need to be declared mutable.
Regardless of if or when they change, they're still considered variables.
In C++ you'll have things like const int x which is a constant (read-only) variable, so the term can take on all sorts of specific meanings.
Is the term immutable variable just a convention?
By definition every... definition of a word is a convention, language, meaning of the word, change by time, is unique for every people that live, you can take 100 peoples and end with 100 difference definition of 1 word. That why we often start scientific paper by defining word that could be miss understand in the paper. Trying to clarify as much as possible. Rust does not differs that why we have The Reference
We have a specific section for variable
A variable is a component of a stack frame, either a named function
parameter, an anonymous temporary, or a named local variable.
A local variable (or stack-local allocation) holds a value directly,
allocated within the stack's memory. The value is a part of the stack
frame.
Local variables are immutable unless declared otherwise. For example:
let mut x = ....
Function parameters are immutable unless declared with mut. The mut
keyword applies only to the following parameter. For example: |mut x,
y| and fn f(mut x: Box, y: Box) declare one mutable variable
x and one immutable variable y.
Local variables are not initialized when allocated. Instead, the
entire frame worth of local variables are allocated, on frame-entry,
in an uninitialized state. Subsequent statements within a function may
or may not initialize the local variables. Local variables can be used
only after they have been initialized through all reachable control
flow paths.
So there is not much to add, variable in rust is clearly defined, it doesn't matter if your definition doesn't match or you find a definition of variable that doesn't match Rust one. In the context of Rust, variable is that. If you want to ask about opinion about this choice then it's off topic as opinion oriented. But, wiki definition make Rust definition quite standard both from mathematics view than computer science:
Variable (computer science), a symbolic name associated with a value and whose associated value may be changed
Variable (mathematics), a symbol that represents a quantity in a mathematical expression, as used in many sciences

Function/variable scope (pass by value or reference?)

I'm completely confused by Lua's variable scoping and function argument passing (value or reference).
See the code below:
local a = 9 -- since it's define local, should not have func scope
local t = {4,6} -- since it's define local, should not have func scope
function moda(a)
a = 10 -- creates a global var?
end
function modt(t)
t[1] = 7 -- create a global var?
t[2] = 8
end
moda(a)
modt(t)
print(a) -- print 9 (function does not modify the parent variable)
print(t[1]..t[2]) -- print 78 (some how modt is modifying the parent t var)
As such, this behavior completely confuses me.
Does this mean that table variables
are passed to the function by
reference and not value?
How is the global variable creation
conflicting with the already define
local variable?
Why is modt able to
modify the table yet moda is not able
to modify the a variable?
You guessed right, table variables are passed by reference. Citing Lua 5.1 Reference Manual:
There are eight basic types in Lua: nil, boolean, number, string, function, userdata, thread, and table.
....
Tables, functions, threads, and (full) userdata values are objects: variables do not actually contain these values, only references to them. Assignment, parameter passing, and function returns always manipulate references to such values; these operations do not imply any kind of copy.
So nil, booleans, numbers and strings are passed by value. This exactly explains the behavior you observe.
Lua's function, table, userdata and thread (coroutine) types are passed by reference. The other types are passed by value. Or as some people like to put it; all types are passed by value, but function, table, userdata and thread are reference types.
string is also a kind of reference type, but is immutable, interned and copy-on-write - it behaves like a value type, but with better performance.
Here's what's happening:
local a = 9
local t = {4,6}
function moda(a)
a = 10 -- sets 'a', which is a local introduced in the parameter list
end
function modt(t)
t[1] = 7 -- modifies the table referred to by the local 't' introduced in the parameter list
t[2] = 8
end
Perhaps this will put things into perspective as to why things are the way they are:
local a = 9
local t = {4,6}
function moda()
a = 10 -- modifies the upvalue 'a'
end
function modt()
t[1] = 7 -- modifies the table referred to by the upvalue 't'
t[2] = 8
end
-- 'moda' and 'modt' are closures already containing 'a' and 't',
-- so we don't have to pass any parameters to modify those variables
moda()
modt()
print(a) -- now print 10
print(t[1]..t[2]) -- still print 78
jA_cOp is correct when he says "all types are passed by value, but function, table, userdata and thread are reference types."
The difference between this and "tables are passed by reference" is important.
In this case it makes no difference,
function modt_1(x)
x.foo = "bar"
end
Result: both "pass table by reference" and "pass table by value, but table is a reference type" will do the same: x now has its foo field set to "bar".
But for this function it makes a world of difference
function modt_2(x)
x = {}
end
In this case pass by reference will result in the argument getting changed to the empty table. However in the "pass by value, but its a reference type", a new table will locally be bound to x, and the argument will remain unchanged. If you try this in lua you will find that it is the second (values are references) that occurs.
I won't repeat what has already been said on Bas Bossink and jA_cOp's answers about reference types, but:
-- since it's define local, should not have func scope
This is incorrect. Variables in Lua are lexically scoped, meaning they are defined in a block of code and all its nested blocks.
What local does is create a new variable that is limited to the block where the statement is, a block being either the body of a function, a "level of indentation" or a file.
This means whenever you make a reference to a variable, Lua will "scan upwards" until it finds a block of code in which that variable is declared local, defaulting to global scope if there is no such declaration.
In this case, a and t are being declared local but the declaration is in global scope, so a and t are global; or at most, they are local to the current file.
They are then not being redeclared local inside the functions, but they are declared as parameters, which has the same effect. Had they not been function parameters, any reference inside the function bodies would still refer to the variables outside.
There's a Scope Tutorial on lua-users.org with some examples that may help you more than my attempt at an explanation. Programming in Lua's section on the subject is also a good read.
Does this mean that table variables are passed to the function by reference and not value?
Yes.
How is the global variable creation conflicting with the already define local variable?
It isn't. It might appear that way because you have a global variable called t and pass it to a function with an argument called t, but the two ts are different. If you rename the argument to something else, e,g, q the output will be exactly the same. modt(t) is able to modify the global variable t only because you are passing it by reference. If you call modt({}), for example, the global t will be unaffected.
Why is modt able to modify the table yet moda is not able to modify the a variable?
Because arguments are local. Naming your argument a is similar to declaring a local variable with local a except obviously the argument receives the passed-in value and a regular local variable does not. If your argument was called z (or was not present at all) then moda would indeed modify the global a.