Why are struct literals "literal" - struct

In golang what are struct literals?
Why is the following a literal even though there is a variable? And aren't structs literally variable, even when not const? So how does it make sense.
MyType{Field: var)
It has a variable and yet it's a "literal"?
Also why is it only called a "struct literal" when you first initialize it?

Programming languages use the word "Literal" when referring to syntactic ways to construct some data structure. It means it's not constructed by creating an empty one and adding or subtracting as you go.
Compare:
MyType{Field: myVariable}
to
var x = new(MyType)
x.Field = myVariable
The benefit is that your code's appearance reflects the data structure in some way. The downside is that you have to know the layout in advance and have the content initialized already, not possible, if for instance, you're constructing a map with unknown keys.
Here are links to the literals in the Go language specification. Notice that they all are syntactic ways to define a data structure:
Lexical elements
Integer literals
Floating-point literals
Imaginary literals
Rune literals
String literals
Expressions
Composite literals
Function literals

literal just means the grammar or the way to compose source code, i.e., construct a value of a certain type following the literal meaning of its source code.
int/string literal happens to construct a constant value that is the same as the literal meaning of the source code.
from go spec
Composite literals construct new composite values each time they are evaluated.
from their definition, it's syntactic sugar to construct value for the composite type. It's not the fixed value referred by literal wiki page.
cited from gopl 4.4.1 for struct literal:
A value of a struct type can be written using a struct literal that specifies values for its fields.
type Point struct{ X, Y int }
p := Point{1, 2}
Both string literals and struct literals are source codes to guide the compiler to construct value in memory. struct literals can be non-constant at compile time, i.e., only known at runtime.
there's also another type of literal: type literal:
A type may also be specified using a type literal, which composes a type from existing types.
which just means a fixed value in the source code for the type system.
struct{}
struct{ foo int32 }

Related

What is the relationship between slices and references in Rust?

I am completely new to Rust (as in I just started looking at it yesterday), and am working my way through "The Rust Programming Language". I'm a little stuck on Chapters 4.2 (References and Borrowing) / 4.3 (The Slice Type) and am trying to solidify my initial understanding of references before I move on. I'm an experienced programmer whose background is mainly in C++ (I am intimately familiar with several languages, but C++ is what I'm most comfortable with).
Consider the following Rust code:
let string_obj: String = String::from("My String");
let string_ref: &String = &string_obj;
let string_slice: &str = &string_obj[1..=5];
Based on my understanding, from the first line, string_obj is an object of type String that is stored on the stack, which contains three fields: (1) a pointer to the text "My String", allocated on the heap, encoded in UTF-8; (2) A length field with value 9; (3) A capacity field with a value >= 9. That's straightforward enough.
From the second line, string_ref is an immutable reference to a String object, also stored on the stack, which contains a single field - a pointer to string_obj. This leads me to believe that (leaving aside ownership rules, semantics, and other things I am yet to learn about references), a reference is essentially a pointer to some other object. Again, pretty straightforward.
It's the third line which causing me some headaches. From the documentation, it would appear that string_slice is an object of type &str that is stored on the stack, and contains two fields: 1) a pointer to the text "y Str", within the text "My String" associated with string_obj. 2) A length field with value 5.
But, by appearances at least, the &str type is by definition an immutable reference to an object of type str. So my questions are as follows:
What exactly is an str, and how is it represented in memory?
How does &str - a reference type, which I thought was simply a pointer - contain TWO fields (a pointer AND a length)?
How does Rust know in general what / how many fields to create when constructing a reference? (and consequently how does the programmer know?)
Slices are primitive types in Rust, which means that they don't necessarily have to follow the syntax rules of other types. In this case, str and &str are special and are treated with a bit of magic.
The type str doesn't really exist, since you can't have a slice that owns its contents. The reason for requiring us to spell this type "&str" is syntactic: the & reminds us that we're working with data borrowed from somewhere else, and it's required to be able to specify lifetimes, such as:
fn example<'a>(x: &String, y: &'a String) -> &'a str {
&y[..]
}
It's also necessary so that we can differentiate between an immutably-borrowed string slice (&str) and a mutably-borrowed string slice (&mut str). (Though the latter are somewhat limited in their usefulness and so you don't see them that often.)
Note that the same thing applies to array slices. We have arrays like [u8; 16] and we have slices like &[u8] but we don't really directly interact with [u8]. Here the mutable variant (&mut [u8]) is more useful than with string slices.
What exactly is an str, and how is it represented in memory?
As per above, str kind-of doesn't really exist by itself. The layout of &str though is as you suspect -- a pointer and a length.
(str is the actual characters referred to by the slice, and is a so-called dynamically-sized type. In the general case, a &T can't exist without a T to refer to. In this case it's a bit backwards in that the str doesn't exist without the &str slice.)
How does &str - a reference type, which I thought was simply a pointer - contain TWO fields (a pointer AND a length)?
As a primitive, it's a special case handled by the compiler.
How does Rust know in general what / how many fields to create when constructing a reference? (and consequently how does the programmer know?)
If it's a non-slice reference, then it's either a pointer or it's nothing (if the reference itself can be optimized away).

Why a function can be a literal and a expression can't?

I understand that the concept literal is applied to whenever you represent a fixed value in source code, exactly as it is meant to be interpreted, vs. a variable or a constant, which are names for several of a class or one of them respectively.
But they are also opposed to expressions. I thought it was because they could incorporate variables. But even expressions like 1+2 are not (see first answer in What does the word "literal" mean?).
So, when I define a variable this way:
var=1+2
1+2 is not a literal even though it is not a name and evaluates to a single value. I could then guess that it is because it doesn't represent the target value directly; in other words, a literal represents a value "exactly as it is".
But then how is it possible that a function like this one is a literal (as pointed it the same linked answer)?
(x) => x*x
Only anonymous functions can be literal because they are not bound to an identifier
so (x)=>x*x is a literal because it is a anonymous function,or function literal
but a
void my_func()
{#something}
is not a literal cause it is bound to an identifier;
read these,
https://en.wikipedia.org/wiki/Literal_(computer_programming)
https://en.wikipedia.org/wiki/Anonymous_function
Expressions can be divided into two general types: atomic expressions and composite expressions.
Composite expressions can be divided by operator, and so on; atomic expressions can be divided into variables, constants, and literals. I guess different authors might use other categories or boundaries here, so it might not be universal. But I will argue why this categorization might make sense.
It's fairly obvious why strings or numbers are literals, or why a sum isn't. A function call can be considered composite, as it operates on subexpressions - its parameters. A function definition does not operate on subexpressions. Only when the so defined function is called, that call passes parameters into the function. In a compiled language, the anonymous function will likely be replaced by a target address where the corresponding code is located - that memory location is obviously not dependent on any subexpression.
#rdRahul's answer references this Wikipedia article, which says that object literals, such as {"cat", "dog"} can be considered literals. This can be easily argued by pointing out that the object which is the value of the expression is just one opaque thing, such as a pointer to the memory location of the object.

Why is the keyword `string` used to verify a variable type

For example, suppose we have a variable named i and set to 10. To check if it is an integer, in tcl one types : string is integer $i.
Why is there the keyword string ? Does it mean the same as in python and C++ ? How to check if a tcl string (in the meaning of a sequence of characters) is a string ? string is string $myString does not work because string is not a class in tcl.
Tcl doesn't have types. Or rather it does, but they're all serializable to strings and that happens magically behind the scenes; it looks like it doesn't have types, and you're not supposed to talk about them. Tcl does have classes, but they're not used for types of atomic values; something like 1.3 is not an instance of an object, it's just a value (often of floating point type, but it could also be a string or a singleton list or version identifier, or even a command name or variable name if you really want). Tcl's classes define objects that are commands, and those are (deliberately!) heavyweight entities.
The string is family of tests check whether a value meets the requirements for being interpreted as a particular kind of value. There's quite a few kinds of value, some of which make no sense as types at all (e.g., an all-uppercase string). There's nothing for string is string because everything you can ask that about would automatically pass; all values are already strings, or may be transparently converted to them.
There's exactly one way to probe what the type of a value currently is, and that is the command ::tcl::unsupported::representation (8.6 only). That reports the current type of a value as part of its output, and you're not supposed to rely on it (there's quite a few types under the hood, many of which are pretty obscure unless you know a lot about Tcl's implementation).
% set s 1.3
1.3
% ::tcl::unsupported::representation $s
value is a pure string with a refcount of 4, object pointer at 0x100836ca0, string representation "1.3"
% expr {$s + 3}
4.3
% ::tcl::unsupported::representation $s
value is a double with a refcount of 4, object pointer at 0x100836ca0, internal representation 0x3ff4cccccccccccd:0x0, string representation "1.3"
As you can see, types are pretty flexible. You're supposed to ignore them. We mean it. Make your code demand the types it needs, and throw an error if it can't get them. That's what Tcl's C API does for you.

Why does the compiler not accept this generic function?

public static T clipGN<T>(this T v, T lo, T hi) where T : decimal,double
{ return Math.Max(lo, Math.Min(hi, v)); }
gives for the second line:
Argument 1: cannot convert from 'T' to 'decimal'
Why? I thought both types meeting that T constraint can be converted to decimal.
BTW, an acceptable alternative coding can be found in the answer here:
How should one best recode this example extension method to be generic for all numeric types?
I tried compiling that code myself and I receive the following error myself:
'double' is not a valid constraint. A type used as a constraint must
be an interface, a non-sealed class or a type parameter. (CS0701)
Same for decimal. This suggests that neither decimal nor double are allowed to constrain the type parameter T since the only types that could meet that constraint are themselves (it would be no different from making a non-generic overload, replacing T with either decimal or double). Even if, individually, they were allowed to constrain T (which they are not), the combination constraint should still not be allowed since no type can simultaneously be a decimal and a double.
This is unlike if the constraint had read where T : IComparable<T>, where both types, as well as other types, can meet that constraint.
You don't need generics for this. While the concept of "DRY" makes the idea of coding a single function that can work for all types, this is a case where you're better off having discreet functions for each numeric type. All of the numeric types are known, and the list is not overly large; there are likely numeric types that you aren't actually going to use, anyway. If you really (for whatever reason) want a single function, then your only real option is the IComparable option that you linked to, which has the unfortunate (and unnecessary) consequence of causing boxing on the numeric parameters.
That being said, your problem is that you cannot have T : decimal, double, as that means that T must be both decimal and double (which is impossible), not that it can be either one.
In addition, since this is all that this function does, I'd probably not call the Math.Max and Math.Min functions anyway. It's probably just as simple, if not slightly clearer, to write the functions this way:
public static decimal ClipGN(this decimal v, decimal lo, decimal hi)
{
return v <= lo ? lo : v >= hi ? hi : v;
}
And you should be able to duplicate this code verbatim (apart from the return and parameter types, of course) for each of the numeric types.

What is a strictly typed language? [duplicate]

This question already has answers here:
What are the key aspects of a strongly typed language?
(8 answers)
Closed 1 year ago.
What is a strictly typed language?
Strictly typed languages enforce typing on all data being interacted with.
For example
int i = 3
string s = "4"
From here on out, whenever you use i, you can only interact with it as an integer type. That means you are restricted to using with methods that work with integers.
As for string s you can only interact with it as a string type. You can concatenate it with other string, print it out, etc. However, even though it contains that character "4", you cannot add to an integer without using some function to convert the string to an integer type.
In a dynamically typed language, you have a lot more flexibility:
i = 3
s = "4"
Types are inferred; meaning they are determined based on the data they are set to. i is obstensively a number type, and s is a string type, based on how they were set. However when you have i + s; type inference is used and depending on your environment, you may get the result i + s = 7; since s was implicitly converted to an int by the programming environment. However, this operation could also result in the string "34", if the environment infers an int + string should equal a concatenation operation vs an addition operation.
This flexibility has made loosely typed languages very popular. However, because these type inference can sometimes produce unexpected results; they can also result in more bugs in your code if you're not careful. In a typed language, if I perform i + s, I am forced by the compiler to change s into an int first, so I know by adding i to s, I will get 7 because I was forced to convert s to an explicit int first. In a dynamic language, it attempts to do this for you implicitly, but the results may not be what you were expecting, since anything can be in i or s; a string, a number, or even an object. You don't know until you run your code and see what happens.
I tried to look up "strict typing" and wasn't able to find a definitive definition for the term. Perhaps it refers to a strongly typed language?
Strong typing refers to a type system in which there are restrictions to the operation on which two variables of different types can be performed. For example, in a very strongly typed language, trying to add a string and number may lead to an error.
string s;
number n;
s + n; <-- Type error.
The error may occur at compile time for statically typed languages or at runtime for dynamically typed languages. It should be noted that static/dynamic and strong/weak may sound like similar concepts, they are quite different.
A less strongly typed language may allow casting of variables to allow operations between variables originating from different types:
s + (string)n; <-- Allowed, as (number) has been explicitly
casted to (string), so variable types match.
In a weakly typed language, variables of differing types may become automatically casted to compatible types.
s + n; <-- Allowed, where the language will cast
the (number) to (string)
Perhaps, the "strictly typed language" refers to a very strongly typed language in which there are more strict restrictions as to how operations can be performed on variables of different types.
There's dissenting opinions about how strong or weak various type systems are, but I've generally heard "strictly typed programming language" to mean a very strongly typed programming language. This often describes the static type systems found in several functional languages.
Languages where variables must be declared to contain a specific type of data.
If your variable declarations look like:
String myString = "Fred";
then your language is strictly typed, variable "myString" is explicitly declared to contain only string data.
If the following works:
x = 10;
x = "Fred";
then it's loosely typed (two different types of data in the same variable and scope).
languages where '1' + 3 would be illegal, because it's adding a string to an integer.

Resources