I have discovered that Zig function parameters are constant. That means my naive function for freeing a HashMap doesn't work. You can see an example of the code here. I am wondering if the most correct Zig way is to pass dict as a function or if there is some other way in which I can make a parameter mutable.
const Dict = std.StringHashMap;
fn releaseDict(allocator: Allocator, dict: Dict(i16)) void {
var iter = dict.iterator();
while (iter.next()) |entry|
allocator.free(entry.key_ptr.*);
dict.deinit();
}
You don't. Function parameters are immutable by design:
Structs, unions, and arrays can sometimes be more efficiently passed as a reference, since a copy could be arbitrarily expensive depending on the size. When these types are passed as parameters, Zig may choose to copy and pass by value, or pass by reference, whichever way Zig decides will be faster. This is made possible, in part, by the fact that parameters are immutable.
Modifying function parameters can easily lead to unexpected results. If the parameter is passed by value (a copy of it is made), modifying it would not modify the original value.
What you want to do here is: pass a pointer to your hash map. E.g.
fn releaseDict(allocator: Allocator, dict: *std.StringHashMap(i16)) void {
// ...
}
Related
I noticed that I get the same effect if I define this trivial function:
fun double ( i: Int ) = i*2
and if I define a variable and assign a lambda (with an identical body) to it:
var double = { i : Int -> i*2 }
I get the same result if I call double(a) with either declaration.
This leaves me confused. When is it needed, recommended, advantageous to define a variable as a lambda rather than define a function to it?
When is it needed, recommended, advantageous to define a variable as a lambda rather than define a function to it?
Whenever you have the choice of either, you should use a fun declaration. Even with a fun you can still get a first-class callable object from it by using a function reference.
On the JVM, a fun is significantly more lightweight, both in terms of RAM and invocation overhead. It compiles into a Java method, whereas a val compiles into an instance field + getter + a synthetic class that implements a functional interface + a singleton instance of that class that you must fetch, dereference, and invoke a method on it.
You should consider a function-typed val or var only when something is forcing you to do it. One example is that you can dynamically replace a var and effectively change the definition of the function. You may also receive function objects from the outside, or you may need to comply with an API that needs them.
In any case, if you ever use a function-typed property of a class, you'll know why you're doing it.
First, if I understand you right, your question is "Why are functions first-class citizens in Kotlin -- And when to use them as such?", right?
Kotlin functions are first-class, which means that they can be stored in variables and data structures, passed as arguments to and returned from other higher-order functions. You can operate with functions in any way that is possible for other non-function values. (see here)
As stated in the docs, one use case are higher-order functions. As a first step, I will leave the wikipedia link here: https://en.wikipedia.org/wiki/Higher-order_function
Basically, a higher-order function is a function that takes functions as parameters, or returns a function.
This means that a higher-order function has at least one parameter of a function type or returns a value of a function type.
Following a short example of a higher-order function that receives a parameter of function type (Int) -> Boolean:
fun foo(pred: (Int) -> Boolean) : String = if(pred(x)) "SUCCESS" else "FAIL"
This higher-order function can now be called with any (Int) -> Boolean function.
The docs also state ... [can be used] in any way that is possible for other non-function values.
This means that you can, for example, assign different functions to a variable, depending on your current context.
For example:
// This example is verbose on purpose ;)
var checker: (Int) -> Boolean
if (POSITIVE_CHECK) {
checker = { x -> x > 0 } // Either store this function ...
} else {
checker = { x -> x < 0 } // ... or this one ...
}
if (checker(someNumber)) { // ... and use whatever function is now stored in variable "checker" here
print("Check was fine")
}
(Code untested)
You can define variable and assign it lambda when you want change behaviour for some reason. For example, you have different formula for several cases.
val formula: (Int) -> Int = when(value) {
CONDITION1 -> { it*2 }
CONDITION2 -> { it*3 }
else -> { it }
}
val x: Int = TODO()
val result = formula(x)
If you simply need helper function, you should define it as fun.
If you pass a lambda as a parameter of a function it will be stored in a variable. The calling application might need to save that (e.g. event listener for later use). Therefore you need to be able to store it as a variable as well. As said in the answer however, you should do this only when needed!
For me, I would write the Lambda variable as followed:
var double: (Int) -> Int = { i -> //no need to specify parameter name in () but in {}
i*2
}
So that you can easily know that its type is (i: Int) -> Int, read as takes an integer and returns an integer.
Then you can pass it to somewhere say a function like:
fun doSomething(double: (Int) -> Int) {
double(i)
}
When to use functioneExpression rather than function declaration in Go?
I searched Function Expression vs Function Declaration (in JS), it's about hoisting. How about Golang?
There is one unique property to each:
A function declaration binds an identifier, the function name, to a function; so the function name will be an identifier which you can refer to.
A function literals represents an anonymous function. Function literals are closures, they capture the surrounding environment: they may refer to variables defined in a surrounding function. Those variables are then shared between the surrounding function and the function literal, and they survive as long as they are accessible.
Don't be deluded: syntactically whenever a function literal is used, a declared function could also be used. For example the following code is a valid and working Go code:
func do() {}
func main() {
go do()
defer do()
}
The answer to when to use one over the other lies in the unique properties listed above.
Use function declaration when you want to refer to the function, when you want to reuse it. This is also a good way to separate code, function declaration must be at the file level: you can't declare a function in another function. See Golang nested class inside function for details.
Use function literals when you want the function to have access to the local variables and other identifiers surrounding it. Since you can't declare a function in another function, to capture the local variables and identifiers, the only option here is a function literal (unless you want to pass everything as arguments to a declared function, which could quickly get dirty if the function needs to modify the values in which case they need to be "transformed" into pointers and addresses need to be passed). For an interesting related question, check out Define a recursive function within a function in Go.
When the function does not need to have a name, and the function does not need access to the local variables, you may choose which one to use, relying on your judgement, examples seen in other (quality) projects and prior experiences. If the function body is "small", easier / simpler to use a function literal. If the function body is "big", code will be easier to read and understand if you declare it as a separate function and provide sufficient documentation to it.
An interesting / related topic is a variable of function type, which you may initialize using either a function literal or with a declared function. It has the benefits that it is an identifier so you can refer to it, and that its value can be changed and a new function can be assigned to it.
For example:
func do() { fmt.Println("Doing...") }
var f = do
func main() {
f()
f = func() { fmt.Println("Not doing!") }
f()
}
Output of the above (try it on the Go Playground):
Doing...
Not doing!
Very useful for mocking functions in tests. For an example, see Testing os.Exit scenarios in Go with coverage information (coveralls.io/Goveralls).
Anonymous functions in Go are used in various situations:
- to start a goroutine
go func() {
// body
}()
- with a defer statement
defer func() {
// body
}()
- as an argument to another function
err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
// todo
})
- as a closure (examples)
Function declarations are used when you want to refer to the function by name. Maybe to call it from multiple places in your own code, or to expose it to other packages.
I've got a generic function that needs to create a Tuple to call a function whose arguments I don't know the types of.
Something like this (except array in this example is created by some external code, so I can't just apply the function directly):
Result apply<Result, Where>(
Anything[] array,
Callable<Result, Where> fun)
given Where satisfies Anything[] => nothing;
Is there a type-safe way to implement this method and get the function to be called with the given arguments?
This cannot be done completely type-safely... but assuming that the array indeed contains elements of the correct types as they should appear in a Tuple of type Where, the following function will do the trick:
Tuple<Anything, Anything, Anything> typedTuple({Anything+} array) {
if (exists second = array.rest.first) {
return Tuple(array.first, typedTuple({ second }.chain(array.rest.rest)));
}
else {
return Tuple(array.first, []);
}
}
And apply gets implemented as:
Result apply<Result, Where>(
[Anything+] array,
Callable<Result, Where> fun)
given Where satisfies Anything[] {
value tuple = typedTuple(array);
assert(is Where tuple);
return fun(*tuple);
}
There's nothing relating the type of array to the parameters of fun, so that signature can't possibly be implemented in a type-safe way. You're not constraining the type of array at all; it could contain anything. How in principle would a type-safe implementation handle the case where fun expects [String, Integer] but array is [Boolean+]?
I am reading about boost::function and I am a bit confused about its use and its relation to other C++ constructs or terms I have found in the documentation, e.g. here.
In the context of C++ (C++11), what is the difference between an instance of boost::function, a function object, a functor, and a lambda expression? When should one use which construct? For example, when should I wrap a function object in a boost::function instead of using the object directly?
Are all the above C++ constructs different ways to implement what in functional languages is called a closure (a function, possibly containing captured variables, that can be passed around as a value and invoked by other functions)?
A function object and a functor are the same thing; an object that implements the function call operator operator(). A lambda expression produces a function object. Objects with the type of some specialization of boost::function/std::function are also function objects.
Lambda are special in that lambda expressions have an anonymous and unique type, and are a convenient way to create a functor inline.
boost::function/std::function is special in that it turns any callable entity into a functor with a type that depends only on the signature of the callable entity. For example, lambda expressions each have a unique type, so it's difficult to pass them around non-generic code. If you create an std::function from a lambda then you can easily pass around the wrapped lambda.
Both boost::function and the standard version std::function are wrappers provided by the library. They're potentially expensive and pretty heavy, and you should only use them if you actually need a collection of heterogeneous, callable entities. As long as you only need one callable entity at a time, you are much better off using auto or templates.
Here's an example:
std::vector<std::function<int(int, int)>> v;
v.push_back(some_free_function); // free function
v.push_back(&Foo::mem_fun, &x, _1, _2); // member function bound to an object
v.push_back([&](int a, int b) -> int { return a + m[b]; }); // closure
int res = 0;
for (auto & f : v) { res += f(1, 2); }
Here's a counter-example:
template <typename F>
int apply(F && f)
{
return std::forward<F>(f)(1, 2);
}
In this case, it would have been entirely gratuitous to declare apply like this:
int apply(std::function<int(int,int)>) // wasteful
The conversion is unnecessary, and the templated version can match the actual (often unknowable) type, for example of the bind expression or the lambda expression.
Function Objects and Functors are often described in terms of a
concept. That means they describe a set of requirements of a type. A
lot of things in respect to Functors changed in C++11 and the new
concept is called Callable. An object o of callable type is an
object where (essentially) the expression o(ARGS) is true. Examples
for Callable are
int f() {return 23;}
struct FO {
int operator()() const {return 23;}
};
Often some requirements on the return type of the Callable are added
too. You use a Callable like this:
template<typename Callable>
int call(Callable c) {
return c();
}
call(&f);
call(FO());
Constructs like above require you to know the exact type at
compile-time. This is not always possible and this is where
std::function comes in.
std::function is such a Callable, but it allows you to erase the
actual type you are calling (e.g. your function accepting a callable
is not a template anymore). Still calling a function requires you to
know its arguments and return type, thus those have to be specified as
template arguments to std::function.
You would use it like this:
int call(std::function<int()> c) {
return c();
}
call(&f);
call(FO());
You need to remember that using std::function can have an impact on
performance and you should only use it, when you are sure you need
it. In almost all other cases a template solves your problem.
I am trying to understand how you return non-primitives (i.e. types that do not implement Copy). If you return something like a i32, then the function creates a new value in memory with a copy of the return value, so it can be used outside the scope of the function. But if you return a type that doesn't implement Copy, it does not do this, and you get ownership errors.
I have tried using Box to create values on the heap so that the caller can take ownership of the return value, but this doesn't seem to work either.
Perhaps I am approaching this in the wrong manner by using the same coding style that I use in C# or other languages, where functions return values, rather than passing in an object reference as a parameter and mutating it, so that you can easily indicate ownership in Rust.
The following code examples fails compilation. I believe the issue is only within the iterator closure, but I have included the entire function just in case I am not seeing something.
pub fn get_files(path: &Path) -> Vec<&Path> {
let contents = fs::walk_dir(path);
match contents {
Ok(c) => c.filter_map(|i| { match i {
Ok(d) => {
let val = d.path();
let p = val.as_path();
Some(p)
},
Err(_) => None } })
.collect(),
Err(e) => panic!("An error occurred getting files from {:?}: {}", pa
th, e)
}
}
The compiler gives the following error (I have removed all the line numbers and extraneous text):
error: `val` does not live long enough
let p = val.as_path();
^~~
in expansion of closure expansion
expansion site
reference must be valid for the anonymous lifetime #1 defined on the block...
...but borrowed value is only valid for the block suffix following statement
let val = d.path();
let p = val.as_path();
Some(p)
},
You return a value by... well returning it. However, your signature shows that you are trying to return a reference to a value. You can't do that when the object will be dropped at the end of the block because the reference would become invalid.
In your case, I'd probably write something like
#![feature(fs_walk)]
use std::fs;
use std::path::{Path, PathBuf};
fn get_files(path: &Path) -> Vec<PathBuf> {
let contents = fs::walk_dir(path).unwrap();
contents.filter_map(|i| {
i.ok().map(|p| p.path())
}).collect()
}
fn main() {
for f in get_files(Path::new("/etc")) {
println!("{:?}", f);
}
}
The main thing is that the function returns a Vec<PathBuf> — a collection of a type that owns the path, and are more than just references into someone else's memory.
In your code, you do let p = val.as_path(). Here, val is a PathBuf. Then you call as_path, which is defined as: fn as_path(&self) -> &Path. This means that given a reference to a PathBuf, you can get a reference to a Path that will live as long as the PathBuf will. However, you are trying to keep that reference around longer than vec will exist, as it will be dropped at the end of the iteration.
How do you return non-copyable types?
By value.
fn make() -> String { "Hello, World!".into() }
There is a disconnect between:
the language semantics
the implementation details
Semantically, returning by value is moving the object, not copying it. In Rust, any object is movable and, optionally, may also be Clonable (implement Clone) and Copyable (implement Clone and Copy).
That the implementation of copying or moving uses a memcpy under the hood is a detail that does not affect the semantics, only performance. Furthermore, this being an implementation detail means that it can be optimized away without affecting the semantics, which the optimizer will try very hard to do.
As for your particular code, you have a lifetime issue. You cannot return a reference to a value if said reference may outlive the value (for then, what would it reference?).
The simple fix is to return the value itself: Vec<PathBuf>. As mentioned, it will move the paths, not copy them.