This is rather a Swift compiler optimization question about the Swift optional stack object (such as struct) and "if let".
In Swift "if let" provides you a syntactic sugar to work with optionals.
What about the structs that live on the stack? As a c++ programmer, I would not introduce an unnecessary copy of a stack object, especially, only in order to check it's presence in the container. Is the struct being copied with all it's members recursively every time you use "if let", or the swift compiler is optimized enough to create a local variable by reference or using other tricks?
For example, we have this struct packaged into an optional:
struct MyData{
var a=1
var b=2
//lots more store....
func description()->String{
return "MyData: a="+String(a)+", b="+String(b)
}
}
var optionalData:MyData?=nil
optionalData=MyData()
since the struct is on the stack, to unpack, is there an unnecessary copy from the container optionalData to local var data, or the fact that the data is a constant, the copy is optimized away?
if let data=optionalData{//is data copy or reference?
println(data.description())
}
since the struct is on the stack, to unpack, is there an unnecessary copy from the container optionalData to local var data, or the fact that the data is a constant, the copy is optimized away?
It is unlikely that the compiler is actually emitting code to make a copy. let essentially gives another name to an expression.
With classes, "let x = y" will allow you to write through your copy of x (because you are just copying a reference), i.e.
let x = y
x.foo = bar
y.foo // => bar
but with structs, this is not the case. You aren't allowed to write to a let struct or call any mutable methods on it. This allows the Swift compiler to treat let x = y, where y is a struct, as a no-op.
However, this code probably does make a copy of y:
y.foo = bar
let x = y
y.foo = baz
x.foo // => bar
It has to, because you wrote to the thing you were copying from. This is known as "copy-on-write", and it's an optimization that's made possible by using let semantics.
To answer your final question:
if let data=optionalData{//is data copy or reference?
println(data.description())
}
data is assuredly a reference in this case. Actually it probably does not exist at all; the compiler is going to emit the same code as if you wrote:
if (optionalData != nil)
{
println(optionalData!.description())
}
Related
I have just downloaded the last version of ILNumerics, to be used in my F# project. Is it possible to leverage on this library in F#? I have tried simple computations and it seems very cumbersome (in F#).
I would like to set up a constrained (or even unconstrained) optimization problem. The usual Rosenbrock function would do and then I will use my own function. I am having hard times in having even an Array being defined. The only kind of array I could define was a RetArray, for example with this code
let vector = ILMath.vector<float>(1.0, 2.0)
The compiler signals that vector is a RetArray; I think this is due to the fact that it is returning from a function (i.e.: ILMath.vector). If I define another similar vector, I can -e.g.- sum vectors, simply writing, for example
let a = ILMath.vector<float>(1.0, 2.0)
let b = ILMath.vector<float>(3.2,2.2)
let c = a + b
and I get
RetArray<float> = seq [4.2; 4.2]
but if I try to retrieve the value of c, again, writing, for example in FSI,
c;;
I get
Error: Object reference not set to an instance of an object.
What is the suggested way of using ILNumerics in F#? Is it possible to use the library natively in F# or I am forced to call my F# code from a C# library to use the whole ILNumerics library? Other than with the problem cited, I have problems in understanding the very basic logic of ILNumerics, when ported in F#.
For example, what would be the F# equivalent of the C# using scope as in the example code, as in:
using (ILScope.Enter(inData)) { ...
}
Just to elaborate a bit on brianberns' answer, there are a couple of things you could do to make it easier for yourself.
I would personally not go the route of defining a custom operator - especially one that overrides an existing one. Instead, perhaps you should consider using a computation expression to work with the ILMath types. This will allow you to hide a lot of the uglyness, that comes when working with libraries making use of non-F# standards (e.g. implicit type conversions).
I don't have access to ILMath, so I have just implemented these dummy alternatives, in order to get my code to compile. I suspect you should be able to just not copy that in, and the rest of the code will work as intended
module ILMath =
type RetArray<'t> = { Values: 't seq }
and Array<'t> = { OtherValues: 't seq } with
static member op_Implicit(x: RetArray<_>) = { OtherValues = x.Values }
static member inline (+) (x1, x2) = { Values = (x1.OtherValues, x2.OtherValues) ||> Seq.map2 (+) }
type ILMath =
static member vector<'t>([<ParamArray>] vs : 't []) = { ILMath.Values = vs }
If you have never seen or implemented a computation expression before, you should check the documentation I referenced. Basically, it adds some nice, syntactic sugar on top of some uglyness, in a way that you decide. My sample implementation adds just the let! (desugars to Bind) and return (desugars to Return, duh) key words.
type ILMathBuilder() =
member __.Bind(x: ILMath.RetArray<'t>, f) =
f(ILMath.Array<'t>.op_Implicit(x))
member __.Return(x: ILMath.RetArray<'t>) =
ILMath.Array<'t>.op_Implicit(x)
let ilmath = ILMathBuilder()
This should be defined and instantiated (the ilmath variable) at the top level. This allows you to write
let c = ilmath {
let! a = vector(1.0, 2.0)
let! b = vector(3.2, 2.2)
return a + b
}
Of course, this implementation adds only support for very few things, and requires, for instance, that a value of type RetArray<'t> is always returned. Extending the ILMathBuilder type according to the documentation is the way to go from here.
The reason that the second access of c fails is that ILNumerics is doing some very unusual memory management, which automatically releases the vector's memory when you might not expect it. In C#, this is managed via implicit conversion from vector to Array:
// C#
var A = vector<int>(1, 2, 3); // bad!
Array<int> A = vector<int>(1, 2, 3); // good
F# doesn't have implicit type conversions, but you can invoke the op_Implicit member manually, like this:
open ILNumerics
open type ILMath // open static class - new feature in F# 5
let inline (!) (x : RetArray<'t>) =
Array<'t>.op_Implicit(x)
[<EntryPoint>]
let main argv =
let a = !vector<float>(1.0, 2.0)
let b = !vector<float>(3.2,2.2)
let c = !(a + b)
printfn "%A" c
printfn "%A" c
0
Note that I've created an inline helper function called ! to make this easier. Every time you create an ILNumerics vector in F#, you must call this function to convert it to an array. (It's ugly, I know, but I don't see an easier alternative.)
To answer your last question, the equivalent F# code is:
use _scope = Scope.Enter(inData)
...
I'm writing a function that should take a couple of vectors and produce their Cartesian product (all of their pair combinations) as a vector in row-major order. In other words, if I have
let x_coords = vec![1, 2, 3];
let y_coords = vec![4, 5, 6];
I want to produce
vec![ [1,4], [1,5], [1,6], [2,4], [2,5], [2,6], [3,4], [3,5], [3,6] ]
This seemed like a perfect job for .flat_map():
fn main() {
let x_coords = vec![1, 2, 3];
let y_coords = vec![4, 5, 6];
let coord_vec: Vec<[isize; 2]> =
x_coords.iter().map(|&x_coord| {
y_coords.iter().map(|&y_coord| {
[x_coord, y_coord]
})
}).flat_map(|s| s).collect();
// Expecting to get: vec![ [1,4], [1,5], [1,6], [2,4], [2,5], [2,6], [3,4], [3,5], [3,6] ]
println!("{:?}", &coord_vec);
}
But this doesn't work, because &x_coord doesn't live long enough. According to the compiler, it ends up inside the y_coords map and then never makes it back out.
I tried using .clone() and move in the closures, but got a strangely long and unclear lecture by the compiler in the form of multiple Note: lines.
Am I just completely off base with flat_map, or can this be saved?
Solution
You were really close! This works:
let coord_vec: Vec<_> = x_coords.iter()
.flat_map(|&x_coord| {
y_coords.iter().map(move |&y_coord| {
// ^^^^
[x_coord, y_coord]
})
})
.collect();
The only thing I added is the move keyword in front of the inner closure. Why? Let's try to understand what the compiler is thinking below!
A few notes, though:
I renamed map to flat_map and removed the second flat_map call... You made your life more complicated than it has to be ;-)
I omitted part of the type annotation of coord_vec, because it's not necessary
Explanation
The type x_coord is i32 (or any other integer). Not a reference or anything but the value directly. This means that x_coord is owned by the enclosing function, which happens to be a closure, specifically the "outer" closure, that you pass to flat_map. Thus x_coord lives just inside the closure, not longer. That's what the compiler is telling you. So far so good.
When you define the second closure (the "inner" one), you access the environment, specifically x_coord. The important question now is: how does a closure access its environment? It can do so with an immutable reference, with a mutable reference and by value. The Rust compiler determines what kind of access to the environment is needed and chooses the "least intrusive" option that works. Let's look at your code: the compiler figures out that the closure only needs to borrow the environment immutably (because i32 is Copy and thus the closure can transform its &i32 into a i32 easily).
But in this case, the compiler's reasoning is wrong! The closure borrowing its environment leads to a limited lifetime. And in this case we need the closure to live for longer than it can, hence the error.
By adding move, we force the compiler to pass the environment to the closure by value (transferring ownership). This way the closure borrows nothing and can live forever (satisfies 'static).
I am learning Go, and I have a question based on the following code:
package main
import (
"fmt"
)
type Vector struct {
x, y, z int
}
func VectorFactory(x,y,z int) *Vector {
return &Vector{x, y, z}
}
func main() {
vect := VectorFactory(1, 2, 3)
fmt.Printf("%d\n", (vect.x * vect.y * vect.z))
}
Here I've defined a type Vector with x, y, and z, and I've defined function VectorFactory which declares a pointer to a Vector and returns that pointer. I use this function to create a new Vector named vect.
Is this bad code? Should I be using the new keyword rather than building a Factory?
Do I need to delete the Vector after using it, like in C++? If so, how?
Thanks. I'm still waiting for my Go book to be delivered.
Prefer NewThing to ThingFactory.
Don't make a NewThing function, unless you have complex initialisation, or you're intentionally not exporting parts of a struct. Selectively setting only parts of a struct is not complex, that can be accomplished by using labels. Complex would be things like "the value of slot Q depends on what the value of slot Zorb is". Unexported struct fields can be useful for information hiding, but should be used with care.
Go is garbage-collected, any piece of data that is not referenced is eligible to be collected. Start out y not worrying about it, then get to a point where you ensure you clean up any reference to data you're no longer interested in so as to avoid accidental liveness ("accidental liveness" is essentially the GC equivalent of "memory leak").
If you expect to print your data structures frequently, consider making a String method for them (this is not exactly corresponding to the print you do, but might be generally more useful for a vector):
func (v Vector) String() string {
return fmt.Sprintf("V<%d, %d, %d>", v.x v.y, v.z);
}
Unless "vect" really means something to you, prefer either "v" or "vector" as a name.
I am trying to figure out the basic way to reference a simple type in Swift.
In C, it's no issue:
int a = 42;
int* refA = &a;
*refA = 43;
// At this point, a is 43
In Swift, it seems that I can't do this.
var a:Int = 42
println ( a )
// var aRef:Int = &a // Nope.
// var aRef:Int& = &a // Nah.
// inout var:Int aRef = &a // Nyet
// var inout:Int aRef = &a // Non
// var aRef:Int* = &a // What are you, stupid, or stubborn?
//
// aRef = 43 // If any of the above worked, I could do this.
println ( a ) // How can I get this to print "43"?
I can't find anything in the docs that say I can do this. I know about inout as a function parameter modifier, but I'd like to be able to do this outside of functions.
There's some basic reasons that I'd like to do this. Declaring classes of everything introduces some overhead (mostly planning and writing, as opposed to execution time).
Values cannot be passed by reference in Swift (except for inout parameters), this is one of the things that makes it "Objective-C without the C". You might have to rethink your approach with the possibilities and restrictions of the language in mind.
In general, trying to use Language A as if it were Language B on a feature-for-feature basis is a good way to get yourself into round-peg-square-hole issues. Instead, step back a bit -- what problems do you solve using Feature X in Language B? Language A might have different (and even perhaps more elegant) ways to address those problems.
Not being able to create a pointer (or C++-style reference) to any arbitrary value is probably part of Swift's type/memory safety. Adding that level of indirection makes it harder for a compiler to make reasoned deductions about code (in particular, the ownership of memory addresses), opening all kinds of possibilities for undefined behavior (read: bugs, security holes).
Swift is designed to eat bugs. By using carefully-designed semantics for values vs. references, augmented with inout for specific uses, Swift can more carefully control memory ownership and help you write more reliable code. Without any loss in expressivity, really -- that expressivity just takes different forms. :)
If you really want to put a round peg into a square hole, you can cut down your "planning and writing" overhead with a single generic implementation that wraps any value in a reference. Something like this, maybe:
class Handle<T> {
var val: T
init(_ val: T) {
self.val = val
}
}
Note that with this, you still need to plan ahead -- since you can't create pointers/references to arbitrary things that already exist, you'll have to create something through a Handle when you want to be able to treat it like a reference type later.
And with some custom operator definitions, you might even be able to make it look a little bit like C/C++. (Maybe post on Terrible Swift Ideas if you do.)
For the record, your desired behavior is not all the difficult to achieve:
1> func inc (inout x: Int) { x = x + 1 }
2> var val:Int = 10
val: Int = 10
3> inc(&val)
4> val
$R0: Int = 11
What you loose is the 'performance' of a builtin binary operation; but what you gain by using functional abstraction well out weighs any non-builtin issue.
func incrementor (by: Int) (inout _ x: Int) { x = x + by } #Bug in Swift prevents this '_'
var incBy10 = incrementor (10)
incBy10(&val)
I grew up in the days when passing around structures was bad mojo because they are often large, so pointers were always the way to go. Now that C++11 has quite good RVO (right value optimization), I'm wondering if code like the following will be efficient.
As you can see, my class has a bunch of vector structures (not pointers to them). The constructor accepts value structures and stores them away.
My -hope- is that the compiler will use move semantics so that there really is no copying of data going on; the constructor will (when possible) just assume ownership of the values passed in.
Does anyone know if this is true, and happens automagically, or do I need a move constructor with the && syntax and so on?
// ParticleVertex
//
// Class that represents the particle vertices
class ParticleVertex : public Vertex
{
public:
D3DXVECTOR4 _vertexPosition;
D3DXVECTOR2 _vertexTextureCoordinate;
D3DXVECTOR3 _vertexDirection;
D3DXVECTOR3 _vertexColorMultipler;
ParticleVertex(D3DXVECTOR4 vertexPosition,
D3DXVECTOR2 vertexTextureCoordinate,
D3DXVECTOR3 vertexDirection,
D3DXVECTOR3 vertexColorMultipler)
{
_vertexPosition = vertexPosition;
_vertexTextureCoordinate = vertexTextureCoordinate;
_vertexDirection = vertexDirection;
_vertexColorMultipler = vertexColorMultipler;
}
virtual const D3DVERTEXELEMENT9 * GetVertexDeclaration() const
{
return particleVertexDeclarations;
}
};
Yes, indeed you should trust the compiler to optimally "move" the structures:
Want Speed? Pass By Value
Guideline: Don’t copy your function arguments. Instead, pass them by value and let the compiler do the copying
In this case, you'd move the arguments into the constructor call:
ParticleVertex myPV(std::move(pos),
std::move(textureCoordinate),
std::move(direction),
std::move(colorMultipler));
In many contexts, the std::move will be implicit, e.g.
D3DXVECTOR4 getFooPosition() {
D3DXVECTOR4 result;
// bla
return result; // NRVO, std::move only required with MSVC
}
ParticleVertex myPV(getFooPosition(), // implicit rvalue-reference moved
RVO means Return Value Optimization not Right value optimization.
RVO is a optimization performed by the compiler when the return of a function is by value, and its clear that the code returns a temporary object created in the body, so the copy can be avoided. The function returns the created object directly.
What C++11 introduces is Move Semantics. Move semantics allows us to "move" the resource from a certain temporary to a target object.
But, move implies that the object wich the resource comes from, is in a unusable state after the move. This is not the case (I think) you want in your class, because the vertex data is used by the class, even if the user calls to this function or not.
So, use the common return by const reference to avoid copies.
On the other hand,, DirectX provides handles to the resources (Pointers), not the real resource. Pointers are basic types,its copying is cheap, so don't worry about performance. In your case, you are using 2d/3d vectors. Its copying is cheap too.
Personally, I think that returning a pointer to an internal resource is a very bad idea, always. I think that in this case the best aproach is to return by const reference.