Is there a way for variables to have a few types in GDScript - variables

I know GDScript has dynamic typing, but I was wondering if there was a way to give a variable only a few types it can have. Something like this:
var myVar : int : string = 12;
myVar = "Hello";
Does it have a feature like this?

No. This is not supported in GDScript.
There is a relevant proposal: https://github.com/godotengine/godot-proposals/issues/737 (The syntax would be var myVar: int|string). However, it is not part of the Godot 4.0 milestone.

Related

F# equivalent to Kotlin's ?. operator

I just started my first F# project and coming from the JVM world, I really like Kotlin's nullability syntax and was wondering how I could achieve similarily compact syntax in F#.
Here's an example:
class MyClass {
fun doSomething() {
// ...
}
}
// At some other place in the code:
val myNullableValue: MyClass? = null
myNullableVallue?.doSomething()
What this does:
If myNullableValue is not null, i.e. there is some data, doSomething() is called on that object.
If myNullableValue is null (like in the code above), nothing happens.
As far as I see, the F# equivalent would be:
type MyClass =
member this.doSomething() = ()
type CallingCode() =
let callingCode() =
let myOptionalValue: MyClass option = None
match myOptionalValue with
|Some(x) -> x.doSomething()
|None -> ()
A stamement that is 1 line long in Kotlin is 3 lines long in F#. My question is therefore whether there's a shorter syntax that acomplishes the same thing.
There is no built-in operator for doing this in F# at the moment. I suspect that the reason is that working with undefined values is just less frequent in F#. For example, you would never define a variable, initialize it to null and then have some code that may or may not set it to a value in F#, so the usual way of writing F# eliminates many of the needs for such operator.
You still need to do this sometimes, for example when using option to represent something that can legitimately be missing, but I think this is less frequent than in other languages. You also may need something like this when interacting with .NET, but then it's probably good practice to handle nulls first, before doing anything else.
Aside from pattern matching, you can use Option.map or an F# computation expression (there is no standard one, but it's easy to use a library or define one - see for example). Then you can write:
let myOptionalValue: MyClass option = None
// Option #1: Using the `opt` computation expression
opt { let! v = myOptionalValue
return v.doSomething() }
// Option #2: Using the `Option.map` function
myOptionalValue |> Option.map (fun v -> v.doSomething() )
For reference, my definition of opt is:
type OptionBuilder() =
member x.Bind(v,f) = Option.bind f v
member x.Return v = Some v
member x.ReturnFrom o = o
member x.Zero () = None
let opt = OptionBuilder()
The ?. operator has been suggested to be added to F#.
https://github.com/fsharp/fslang-suggestions/issues/14
Some day it will be added, I hope soon.

Accessing variable from other script

How do I call a variable from other script components?
mirror.transform.position = cop.GetComponent("AI_Car").mirrorPos;
It seems that the public variable carPos declared in the script AI-Car-script cannot be accessed:
'mirrorPos' is not a member of 'UnityEngine.Component'.
2 things:
1) I work in C#, so I may be wrong about this, but I think you have to get the component and THEN get the variable. For example:
var otherScript: OtherScript = GetComponent("AI_CAR");
var newPosition = otherScript.mirrorPos;
2) I think it's best practice to make a temporary variable and then access it. So in the above example, I would then change mirror.transform.position like this:
mirror.transform.position = newPosition;
Obviously it's not not always great to work in vars (sometimes it is, that's an entirely different conversation) but this is just a simple pseudocode example. Hope this helps!
EDIT: here are the docs
You can cast it to the right type:
mirror.transform.position = ((AI_Car)cop.GetComponent("AI_Car")).mirrorPos;
mirror.transform.position = cop.GetComponent<AI_Car>().mirrorPos;
Anyway, the best is to make an AI_Car property, then get it on start, so you can simply read it anywhere in the class by aiCar.mirrorPos or similar.

Accessing Variables by Reference

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)

How to check an object's type in C++/CLI?

Is there a simple way to check the type of an object? I need something along the following lines:
MyObject^ mo = gcnew MyObject();
Object^ o = mo;
if( o->GetType() == MyObject )
{
// Do somethine with the object
}
else
{
// Try something else
}
At the moment I'm using nested try-catch blocks looking for System::InvalidCastExceptions which feels ugly but works. I was going to try and profile something like the code above to see if it's any faster/slower/readable but can't work out the syntax to even try.
In case anyone's wondering, this comes from having a single queue entering a thread which supplied data to work on. Occasionally I want to change settings and passing them in via the data queue is a simple way of doing so.
You can use MyObject::typeid in C++/CLI the same way as typeof(MyObject) is used in C#. Code below shamelessly copied from your question and modified ...
MyObject^ mo = gcnew MyObject();
Object^ o = mo;
if( o->GetType() == MyObject::typeid )
{
// Do somethine with the object
}
else
{
// Try something else
}
You should check out How to: Implement is and as C# Keywords in C++:
This topic shows how to implement the functionality of the is and as C# keywords in Visual C++.
edit: I will leave this here. But this answer is for C++. Probably not even slightly related to doing this for the CLI.
You need to compile with RTTI(Run Time Type Information) on. Then look at the wikipedia article http://en.wikipedia.org/wiki/Run-time_type_information and search google for RTTI. Should work for you.
On the other hand you might want to have a virtual base class for all your data classes with a member variable that describes what type it is.

How to convert string into integer in the Velocity template?

I have a Velocity template file which has the data from XML. I want to convert the string into integer type.
How can I do that?
Aha! Been there.
#set($intString = "9")
#set($Integer = 0)
$Integer.parseInt($intString)
Doing this uses the java underlying velocity. The $Integer variable is nothing more that a java Integer object which you can then use to access .parseInt
Edit: The above code is for demonstration. Of course there are ways to optimize it.
If you have some control over the velocity context, here's an alternative that alleviates the need to set a variable in the Velocity template.
Context velocityContext = new Context();
velocityContext.put(Integer.class.getSimpleName(), Integer.class);
This allows you to call the static methods of java.lang.Integer in your template using $Integer.parseInt($value) and doesn't rely upon the #set having been called prior to performing the type conversion in the template.
The problem with parseInt is that it throws an exception in case the string is not parseable.
In case you have the NumberTool loaded into your context a better solution than parseInt is the following:
#set($intString = "009")
#set($Integer=$numberTool.toNumber($intString).intValue())
#if($Integer)
## ok
#else
## nok
#end
Sometimes the NumberTool is also loaded as $number.
However, a little drawback is, that the NumberTool simply parses the first number it finds and ignores the rest, so "123a" => 123.
Nice and easy:
#set( $stringToCast = "0" )
$number.toNumber($stringToCast)
$number is the default key name for the NumberTool, but it can be override by specifying a different name in the configuration (for example $numberTool). You have to check what name for NumberTool is used in your Velocity environment.
toNumber method returns:
the object as a Number or null if no conversion is possible
If you want to have explicite an int variable, not a Number object, you can use the intValue method on the result. So the above code will looks like this:
#set( $stringToCast = "0" )
$number.toNumber($stringToCast).intValue()
Of course, you can assign the result to another variable (for example $intVal).
So the full code can look like this:
#set( $stringToCast = "0" )
#set( $intVal = $number.toNumber($stringToCast).intValue() )