Terraform module as "custom function" - module

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.

Related

Kotlin construction: function call with additional body - what such construction means or how it is called (if I want to look it up in the docs)?

I am seeing the Kotlin code:
navController.navigate("sales_order/" + it.toString()) {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
which I can describe as "function call" (navController.navigate) "with additional body" ({...}). How such construction is called (if I want to look it up in the docs) and what does it mean?
When I checked the type of navController.navigate(...) args, then there are 2 arguments. The first argument - string - is provided in () and I am trying to guess, that everything inside {...} is the content for the second argument which has type NavOptionsBuilder in this case. So, I can guess that NavOptionsBuilder has 3 arguments: 1 function call popUpTo that returns some object and 2 named arguments (launchSingleTop, restoreState) which are Boolean type.
Am I deciphering this construction right - just another way of passing arguments - or is there something deeper?
Am I deciphering this construction right
Almost. You got the beginning right, but the end is not exactly correct.
Let's start with what you got right, and throw in some vocabulary here for posterity. Indeed, you seem to be using the overload of navigate that takes 2 arguments: a string route and a builder function.
Functions in kotlin can be passed in multiple ways, but the most common (and the one used here) is passing a lambda expression. Because the syntax for lambda expressions is based on braces ({ ... }), it makes it look like blocks of code, so the Kotlin language went one step further and allowed to pass lambda expressions outside of the parentheses of the function call when the lambda is the last argument. The reason for this is exactly to allow this kind of constructions which look like their own configuration language. This is what is usually referred to as DSLs (Domain Specific Languages).
Now about what you got wrong:
So, I can guess that NavOptionsBuilder has 3 arguments
Not really. NavOptionsBuilder is the receiver of the function that is passed as the second argument of navigate. This means that, within the lambda that you pass, a NavOptionsBuilder instance is implicitly available as this.
This, in turn, means that you can access methods and properties of NavOptionsBuilder within that lambda block. This is what popUpTo, launchSingleTop, and restoreState are: methods and properties of NavOptionsBuilder - not "arguments".
You can find more general info about this here.

"python function decorator" for objective-c to change a method's behavior

I want to modify the behavior of some function without being the author of that function. What I control is that I can ask the author to follow some pattern, e.g. use a base class, use a certain decorator, property etc.
If in python, I would use a decorator to change the behavior of a method.
As an example, My goal: Improve code coverage by automatically testing over multiple input data.
Pseudo code:
#implementation SomeTestSuiteClass
// If in python, I would add a decorator here to change the behavior of the following method
-(void)testSample1 {
input = SpecialProvider();
output = FeatureToTest(input);
SpecialAssert(output);
}
#end
What I want: During test, the testSample1 method will be called multiple times. Each time, the SpecialProvider will emit a different input data. Same for the SpecialAssert, which can verify the output corresponding to the given input.
SpecialProvider and SpecialAssert will be API under my control/ownership (i.e. I write them).
The SomeTestSuiteClass together with the testSample1 will be written by the user (i.e. test writer).
Is there a way for Objective-C to achieve "what I want" above?
You could mock objects and/or its methods using objective-c runtime or some third party frameworks. I discourage it though. That is a sign of poor architecture choices in the 1st place. The main problem in your approach are hidden dependencies in your code directly referencing
SpecialProvider & SpecialAssert symbols directly.
A much better way to this would be like this:
-(void)testSample1:(SpecialProvider*)provider assert:(BOOL (^)(parameterTypes))assertBlock {
input = provider;
output = FeatureToTest(input);
if (assertBlock != nil) {
assertBlock(output);
}
}
Since Objective-c does not support default argument values like Swift does you could emulate it with:
-(void)testSample1 {
[self testSample1:DefaultSpecialProvider() assert:DefaultAssert()];
}
not to call the explicit -(void)testSample1:(SpecialProvider*)provider assert:(BOOL (^)(parameterTypes))assertBlock all the time, however in tests you would always use the explicit 2 argument variant to allow substituting the implementation(s) not being under test.
Further improvement idea:
Put the SpecialProvider and SpecialAssert behind protocols(i.e. equivalent of interfaces in other programming languages) so you can easily exchange the implementation.

How resolving Kotlin functions/properties with the same name work?

The following statement compiles and prints "fun: called":
fun main(vararg args: String) {
fun toCall(arg: String) = println("fun: $arg")
val toCall = fun(arg: String) = println("val: $arg")
toCall("called")
}
Note: the same problem would arise if they were top level declarations or inside a class, this is just the simplest repro with local function/variable.
Looking for clarification on why this compiles in the first place?
What rule comes into play that picks the function over the property?
Note: it's possible to call the val one through:
(toCall)("called")
toCall.invoke("called")
This document regarding name resolution contains details about it.
I will just quote some passages out of it specifically dealing with your problem. It contains several other interesting things as well, but I think I would end up copying everything here then ;-) If you are interested, I can only recommend you to read it completely.
Summarizing, the compiler divides the functions (member/extension/member extension)/properties into groups and decides which one to call first... The properties are put in the group of the invoke-functions and in the following passage you already see why the function was taken before your val:
The property is considered together with the invoke function. Groups of properties with invoke functions are mixed with groups of regular functions, in a sense that a group of properties can have higher priority than a group of functions and vice versa. However, functions and properties can’t go in one group: the function always surpasses the property of the same category. Both the property and the invoke function determine the priority of the group: we compare the priority of the property and of the invoke function and the "lowest" one becomes the group priority.
That's why the function was considered first here and the property later. As soon as you specified invoke it was clear that it can only be the property as the function itself has no visible invoke (lets not go down the byte code now ;-)). Now (toCall) behaves similarly. Here it is clear, that toCall can only be the property. It isn't possible to call (toCall) with the function (compile errors: function invocation expected / the function invoke is not found).
The linked document also contains a sample with a member property function followed by this statement, which basically also confirms the previous regarding local functions:
Note that there is no member function named foo, but if it was present, it would be put into a separate group with the highest priority.

How should I implement Obj C-like headers in Lua?

Now I have an import(a) function, that in short words dofile's header in .framework like this:
import("<Kakao/KARect>") => dofile("/System/Library/Frameworks/Kakao.framework/Headers/KARect.lua")
And in KARect.lua for example I have:
KARect = {}
function KARect:new(_x, _y, _width, _height, _colorBack)
local new = setmetatable({}, {__index = self})
new.id = KAEntities:generateID()
...
return new
end
function KARect:draw()
...
end
After some time I thought about reworking this system and making "headers" work like typical Lua modules with advanced require() so function will do e.g.:
import("<Kakao/KARect>") => package.path = "/System/Library/Frameworks/Kakao.framework/Headers/?.lua"; KARect = require("KARect")
and file will contain:
local KARect = {}
...
return KARect
Because headers should not contain anything but only classes with their names? I'm getting confused when thinking about it, as I never used Obj C :s
I never used Obj C
Then why are you trying to implement its headers in a language, that does not use headers at all?
Header! What is a header?
Header files in C-like languages store more than just a name. They store constants and macro commands, function and class method argument and return types, structure and class fields. In essence, the contents of the header file are forward declarations. They came into existence due to the need to perform the same forward-declarations across many files.
I don't know what additional rules and functions were added to header files in Obj-C, but you can get general understanding of what they do in the following links: 1, 2, 3, 4 with the last one being the most spot-on.
Answer to the question present
Lua is dynamically-typed interpreted language. It does not do compile time type checks and, typically, Lua programs can and should be structured in a way that does not need forward declarations across files. So there is no meaningful way for a programmer to create and for lua bytecode generator and interpreter to use header files.
Lua does not have classes at all. The code you've posted is a syntactic sugar for an assignment of a function with a slightly different signature to a table which imitates class:
KARect.new = function( first_arg_is_self, _x, _y, _width, _height, _colorBack)
local new = setmetatable({}, {__index = first_arg_is_self})
return new
end
There is no declarations here, only generation of an anonymous function and its assignment to a field in a table. Other parts of program do not need to know anything about a particular field, variable or function (which is stored in variable) in advance (unlike C).
So, no declaration means nothing to separate from implementation. You of course can first list fields of the class-table and do dummy assignments to them, but, again, Lua will have no use for those. If you want to give hints to humans, it is probably better to write a dedicated manual or put comments in the implementation.
Lua has situations where forward declarations are needed to reference local functions. But this situation does not arise in object oriented code, as all methods are accessed through reference to the object, and by the time first object is created, the class itself is usually fully constructed.

When isn't inlining safe?

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.