Is the final comma in Rust struct definitions necessary? - rust

Consider the following code:
struct User {
user: String,
email: String,
}
The compiler doesn't complain about it. The trailing comma after the email field struck me as odd, so I tried this:
struct User {
user: String,
email: String // no comma
}
The compiler still doesn't complain. Is there a difference or are the two scenarios completely equivalent?

The last comma is purely optional in struct definitions. This is pure convenience; it allows you to leave that trailing comma in, so you do not have to go back and modify a line if you add an additional field, delete a field or change their order.
It also, coincidentally, makes code generation from macros easier, as your codegen macro no longer has to care about keeping track of whether you are on the last generated field.
The one time when you'll see a trailing comma being mandatory is in macros like the diesel table! macro, and the reason is down to the macro invocation structure chosen by the diesel developers.

Have to say that you are an acute observer. They are equivalent according to rust reference:
StructFields :
StructField (, StructField)* ,?
It is that way for convenience reason: be able to add or remove lines without touching previous ones.
Here's a counter-example. In languages that don't have such convenience, people may choose to format the code in unusual ways to achieve virtually the same, such as:
data Person = Person
{ firstName :: String
, lastName :: String
, age :: Int
}
I like an optional trailing comma more.

Related

Terraform string manipulation to remove X elements

I have several strings that I just want to get a subset of like so:
my-bucket-customer-staging-ie-app-data
my-bucket-customer2-longname-prod-uk-app-data
and I just need to get the customers name from the string, so with the above examples I'd be left with
customer
customer2-longname
There's probably a simple way of doing this with regex although I've failed miserably in my attempts.
I'm able to strip the first part of the string using
trimprefix("my-bucket-customer-staging-ie-app-data", "my-bucket-")
trimprefix("my-bucket-customer-longname-prod-uk-app-data", "my-bucket-")
resulting in
customer-staging-ie-app-data
customer-longname-prod-uk-app-data
However Terraform's trimsuffix won't work as there can be several different regions/environments used.
What I'd like to do is slice the string and ignore the last 4 elements, which should then return the customer name regardless of whether it contains an additional delimiter in it.
Something like this captures the customer, however fails for long customer names:
element(split("-",trimprefix("my-bucket-customer-staging-uk-app-data", "my-bucket-")), length(split("-",trimprefix("my-bucket-customer-staging-uk-app-data", "my-bucket-")))-5)
customer
and is also quite messy.
Is there a more obvious solution I'm missing
I believe it's what regex is for.
> try(one(regex("\\w*-\\w*-(\\w*(?:-\\w*)*)-\\w*-\\w*-\\w*-\\w*","my-bucket-customer-staging-ie-app-data")),"")
"customer"
> try(one(regex("\\w*-\\w*-(\\w*(?:-\\w*)*)-\\w*-\\w*-\\w*-\\w*","my-bucket-customer2-longname-prod-uk-app-data")),"")
"customer2-longname"
> try(one(regex("\\w*-\\w*-(\\w*(?:-\\w*)*)-\\w*-\\w*-\\w*-\\w*","my-bucket-customer2-longname-even-longer-prod-uk-app-data")),"")
"customer2-longname-even-longer"
Reference: https://www.terraform.io/language/functions/regex

Can you set multiple (different) tags with the same value?

For some of my projects, I have had to use the viper package to use configuration.
The package requires you to add the mapstructure:"fieldname" to identify and set your configuration object's fields correctly, but I have also had to add other tags for other purposes, leading to something looking like the following :
type MyStruct struct {
MyField string `mapstructure:"myField" json:"myField" yaml:"myField"`
}
As you can see, it is quite redundant for me to write tag:"myField" for each of my tag, so I was wondering if there was any way to "bundle" them up and reduce the verbosity, with something like this mapstructure,json,yaml:"myField"
Or is it simply not possible and you must specify every tag separately ?
Struct tags are arbitrary string literals. Data stored in struct tags may look like whatever you want them to be, but if you don't follow the conventions, you'll have to write your own parser / processing logic. If you follow the conventions, you may use StructTag.Get() and StructTag.Lookup() to easily get tag values.
The conventions do not support "merging" multiple tags, so just write them all out.
The conventions, quoted from reflect.StructTag:
By convention, tag strings are a concatenation of optionally space-separated key:"value" pairs. Each key is a non-empty string consisting of non-control characters other than space (U+0020 ' '), quote (U+0022 '"'), and colon (U+003A ':'). Each value is quoted using U+0022 '"' characters and Go string literal syntax.
See related question: What are the use(s) for tags in Go?

Different separators for the same variable in Rust Macros

I want to match a pattern like:
foo!(1,2,3;4,5,6;7,8,9);
The same code would be generated for all numbers, but I'd want additional code to run when there's a semi-colon. Is this sort of pattern possible?
I've tried:
macro_rule! {
foo ($($x:expr),*);*) => ...
But I can't seem to make that work on the right-hand side.
You never explained what the problem was with your existing code, so I don't know what to highlight in this example:
macro_rules! foo {
($($($x:expr),*);*) => {
$(
$(
print!("{},", $x);
)*
println!("semi");
)*
}
}
fn main() {
foo!(1,2,3;4,5,6;7,8,9);
}
I can point out things from your original code:
It's called macro_rules!, not macro_rule!
The name of the macro being defined goes before the original {, not after.
Like most programming, paired delimiters need to be evenly matched to be syntactically valid.
The Rust Programming Language, first edition has several pieces of valuable information.
Basic syntax for defining a macro is covered in the macros chapter; I strongly suggest you read the entire thing. It also links to the reference, which contains some more lower-level detail.
The section most related to your question is:
Repetition
The repetition operator follows two principal rules:
$(...)* walks through one "layer" of repetitions, for all of the $names it contains, in lockstep, and
each $name must be under at least as many $(...)*s as it was matched against. If it is under more, it’ll be duplicated, as appropriate.

Get argument names in String Interpolation in Scala 2.10

As of scala 2.10, the following interpolation is possible.
val name = "someName"
val interpolated = s"Hello world, my name is $name"
Now it is also possible defining custom string interpolations, as you can see in the scala documentation in the "Advanced usage" section here http://docs.scala-lang.org/overviews/core/string-interpolation.html#advanced_usage
Now then, my question is... is there a way to obtain the original string, before interpolation, including any interpolated variable names, from inside the implicit class that is defining the new interpolation for strings?
In other words, i want to be able to define an interpolation x, in such a way that when i call
x"My interpolated string has a $name"
i can obtain the string exactly as seen above, without replacing the $name part, inside the interpolation.
Edit: on a quick note, the reason i want to do this is because i want to obtain the original string and replace it with another string, an internationalized string, and then replace the variable values. This is the main reason i want to get the original string with no interpolation performed on it.
Thanks in advance.
Since Scala's string interpolation can handle arbitrary expressions within ${} it has to evaluate the arguments before passing them to the formatting function. Thus, direct access to the variable names is not possible by design. As pointed out by Eugene, it is possible to get the name of a plain variable by using macros. I don't think this is a very scalable solution, though. After all, you'll lose the possibility to evaluate arbitrary expressions. What, for instance, will happen in this case:
x"My interpolated string has a ${"Mr. " + name}"
You might be able to extract the variable name by using macros but it might get complicated for arbitrary expressions. My suggestions would be: If the name of your variable should be meaningful within the string interpolation, make it a part of the data structure. For example, you can do the following:
case class NamedValue(variableName: String, value: Any)
val name = NamedValue("name", "Some Name")
x"My interpolated string has a $name"
The objects are passed as Any* to the x. Thus, you now can match for NamedValue within x and you can do specific things depending on the "variable name", which now is part of your data structure. Instead of storing the variable name explicitly you could also exploit a type hierarchy, for instance:
sealed trait InterpolationType
case class InterpolationTypeName(name: String) extends InterpolationType
case class InterpolationTypeDate(date: String) extends InterpolationType
val name = InterpolationTypeName("Someone")
val date = InterpolationTypeDate("2013-02-13")
x"$name is born on $date"
Again, within x you can match for the InterpolationType subtype and handle things according to the type.
It seems that's not possible. String interpolation seems like a compile feature that compiles the example to:
StringContext("My interpolated string has a ").x(name)
As you can see the $name part is already gone. It became really clear for me when I looked at the source code of StringContext: https://github.com/scala/scala/blob/v2.10.0/src/library/scala/StringContext.scala#L1
If you define x as a macro, then you will be able to see the tree of the desugaring produced by the compiler (as shown by #EECOLOR). In that tree, the "name" argument will be seen as Ident(newTermName("name")), so you'll be able to extract a name from there. Be sure to take a look at macro and reflection guides at docs.scala-lang.org to learn how to write macros and work with trees.

Is there software to contract word combinations?

I think it's a common situation when one needs to contract certain phrases to make identifiers, preserving the original sense. Is there a software/algorithms to facilitate it?
I have a hundred word combinations each around 20 characters long which I want to turn into no-more-than-12-character-long identifiers.
An example:
CUSTOMER_ACCOUNT -> CUSTOMER_ACC
or even
CUSTOMER_ACCOUNT -> CUST_ACC
Solution A
Do it manually, load your words into any text processing editor, run Find-And-Replace with your words, for example:
Find: CUSTOMER
Replace with: CUST
It is human readable but requires manual work.
Solution B
Use hashtable:
HASH | PHRASE
------------------------------
hash1| CUSTOMER_ACCOUNT
hash2| CUSTOMER_ACCOUNT_CREDIT
Hash function will be unique and you can tailor its length, the problem is, it is not human-readable.
Solution C
If you store this somewhere (db, xml, etc.) you can have a structure like
metacode
struct
{
GUID id;
string Name;
}
Each phrase has its own unique id and the text. Internally you use GUID, but for display purposes you use text representation.

Resources