External Parameters in Swift - function

I am new on Swift, my question is where do we use and need External Parameter?

From the Apple's Swift Language Guide:
Sometimes it’s useful to name each parameter when you call a function,
to indicate the purpose of each argument you pass to the function.
If you want users of your function to provide parameter names when
they call your function, define an external parameter name for each
parameter, in addition to the local parameter name.
So, you don't "need" an external parameter name but it is a good practice to use them because they serve as documentation about the parameters at the point the method is called.
For example, without using external parameter names, you can define a join method like this:
func join(_ s1: String,_ s2: String,_ joiner: String) -> String {
return s1 + joiner + s2
}
which will then be called like this:
join("foo", "bar", ", ")
As you can see, each parameter's meaning is not very clear.
Using external parameter names, you could define the same method like below:
func join(string s1: String, toString s2: String, withJoiner joiner: String) -> String {
return s1 + joiner + s2
}
which would then force the users to call it like this:
join(string: "foo", toString: "bar", withJoiner: ", ")
You can see that it makes the meaning of the parameters, along with what the method does, much more clear.
It might seem not so important in this simple example but when defining methods that take a lot of parameters with not-so-obvious meanings, using external parameter names will make your code much more easy to understand.
Update for Swift 3:
This has become even more meaningful with the introduction of Swift 3. Consider the append(contentsOf:) method of the Array class in Swift 3:
Not having different internal and external parameter names in this case would force us to change the label contentsOf to something like string in the call site, which wouldn't read as good as the former one. Swift 3 API guidelines rely on having different internal and external parameter names to create clear and concise methods.

Related

Can you set dynamic json struct field tags? [duplicate]

How would I use a variable in a Go struct tag?
This works:
type Shape struct {
Type string `json:"type"`
}
This does not work:
const (
TYPE = "type"
)
type Shape struct {
Type string fmt.Sprintf("json:\"%s\"", TYPE)
}
In the first example, I am using a string literal, which works. In the second example, I am building a string using fmt.Sprintf, and I seem to be getting an error:
syntax error: unexpected name, expecting }
Here it is on the Go playground:
https://play.golang.org/p/lUmylztaFg
How would I use a variable in a Go struct tag? You wouldn't, it's not allowed by the language. You can't use a statement that evaluates at runtime in place of a compile time string literal for as an annotation to a field on a struct. As far as I know nothing of the sort works in any compiled language.
With the introduction of go generate, it is possible to do achieve this.
However, go generate essentially makes the compilation a 2 phase process. Phase 1 generates the new code, phase 2 compiles and links etc.
There are a few limitations with using go generate:
Your library will not be 'go get'-able unless you run go generate every time it is needed and check in the result, since go generate needs to be explicitly run before go build
This is a compile time process, so you will not be able to do it at run time using run time information. If you really must do this at run time, and in your case, you are just adding JSON serialization annotations, you could consider using a map.
String const/variable is not allowed in tag value to keep things simple and I support that. However with this limit, we need to use reflection to retrieve the tag value which is costly OR type string literals everywhere in the project, which may lead to bugs because of typos.
Solution
We can generate the tag values as string constant and then use this constant further in the project. It doesn't use reflection(saves performance cost), is more maintainable and removes the possibility of any bug because of typos.
ast package is an amazing tool to analyse and generate the go code. For example -
type user struct {
Name string `json:"name"`
Age int `json:"age"`
}
We can generated constants for user struct as below -
const (
UserNameJson = "name"
UserAgeJson = "age"
)
You may find tgcon helpful to generate the field tag value as const.

How to simplify HTTP post of JSON to GraphQL mutation resolver

I would like to HTTP POST values directly as JSON to an addBook resolver already declared in my GraphQL Mutation.
However, the examples I've seen (and proven) use serialisation of parameters from JSON to SDL or re-declaration of variables in SDL to bind from a Query Variable.
Neither approach makes sense because the addBook mutation already has all parameters and validation declared. Using these approaches would lead to unnecessary query serialisation logic having to be created, debugged and maintained.
I have well-formed (schema- edited and -validated) JSON being constructed in the browser which conforms to the data of a declared GraphQLObjectType.
Can anyone explain how to avoid this unnecessary reserialisation or duplication when posting against a mutation resolver?
I've been experimenting with multiple ways of mapping a JSON data structure against the addBook mutation but can't find an example of simply sending the JSON so that property names are be bound against addBook parameter names without apparently pointless reserialisation or boilerplate.
The source code at https://github.com/cefn/graphql-gist/tree/master/mutation-map is a minimal reproducible example which demonstrates the problem. It has an addBook resolver which already has parameter names, types and nullability defined. I can't find a way to use JSON to simply POST parameters against addBook.
I'm using GraphiQL as a reference implementation to HTTP POST values.
I could write code to serialise JSON to SDL. It would end up looking like this which works through GraphiQL:
mutation {addBook(id:"4", name:"Education Course Guide", genre: "Education"){
id
}}
Alternatively I can write code to explicitly alias each parameter of addBook to a different query which then allows me to post values as a JSON query variable, also proven through GraphiQL:
mutation doAdd($id: String, $name: String!, $genre: String){
addBook(id:$id, name:$name, genre:$genre){
id
}
}
...with the query variable...
{
name: "Jonathan Livingstone Seagull",
id: "6"
}
However, I am sure there's some way to directly post this JSON against addBook, telling it to take parameters from a Query Variable. I'm imagining something like...
mutation {addBook($*){
id
}}
I would like a mutation call against addBook to succeed, taking named values from a JSON Query Variable, but without reserialisation or redeclaration of the properties to parameter names.
This boils down to schema design. Instead of having three arguments on your field
type Mutation {
addBook(id: ID, name: String!, genre: String!): Book
}
you can have a single argument that takes an input object type
type Mutation {
addBook(input: AddBookInput!): Book
}
input AddBookInput {
id: ID
name: String!
genre: String!
}
Then your query only has to provide a single variable:
mutation AddBook($input: AddBookInput!) {
addBook(input: $input) {
id
}
}
and your variables look something like:
{
"input": {
"name": "Jonathan Livingstone Seagull",
"genre": "Fable"
}
}
Variables have to be explicitly defining as part of the operation definition because GraphQL and JSON are not interchangeable. A JSON string value could be a String, an ID or some custom scalar (like DateTime) in GraphQL. The variable definitions tell GraphQL how to correctly serialize and validate the provided JSON values. Because variables can be used multiple times throughout a document, their types likewise cannot simply be inferred from the types of the arguments they are used with.
EDIT:
Variables are only declared once per document. Once declared, they may be referred to any number of times throughout the document. Imagine a query like
mutation MyMutation ($id: ID!) {
flagSomething(somethingId: $id)
addPropertyToSomething(id: $id, property: "WOW")
}
We declare the variable once and tell GraphQL it's an ID scalar and it's non-nullable (i.e. required). We then use the variable twice -- once as the value of somethingId on flagSomething and again as the value of id on addPropertyToSomething. The same variable could also be used as the value to a directive's argument too -- it's not limited to just field arguments. Notice also that nothing says the variable name has to match the field name -- this is typically only done out of convenience.
The other notable thing here is that there's two validation steps happening here.
First, GraphQL will check if the provided variable (i.e. the JSON value) can be serialized into the type specified. Since we declared the variable as non-null (using !), GraphQL will also verify the variable actually exists and is not equal to null.
GraphQL will also verify that the type you specified for the variable matches the types of the arguments where it's actually used. So an Int variable will throw if it's passed to a String argument and so on. Moreover, nullability is checked here too. So an argument that is an Int! (non-null integer) will only accept variables that are also Int!. However, an argument that is Int (i.e. nullable) will accept either Int or Int! variables.
The syntax that exists is there for a reason. The kind of syntax you're imagining would only make sense in a specific scenario where you're only querying a single root field and using all the variables as arguments to that one field and the variable names match the argument names and you don't need to dynamically set any directive arguments.

Which one to use Value vs std::string in cocos2d-x V3 C++?

According to http://www.cocos2d-x.org/wiki/Value,
Value can handle strings as well as int, float, bool, etc.
I'm confused when I have to make a choice between using
std::string
or
Value
In what circumstances should I use Value over std::string, and vice versa??
I think you have misunderstood the Value object. As written in the documentation you linked to:
cocos2d::Value is a wrapper class for many primitives ([...] and std::string) plus [...]
So really Value is an object that wraps a bunch of other types of variables, which allows cocos2d-x to have loosely-typed structures like the ValueMap (a hash of strings to Values - where each Value can be a different type of object) and ValueVector (a list of Values).
For example, if you wanted to have a configuration hash with keys that are all strings, but with a bunch of different values - in vanilla C++, you would have to create a separate data structure for each type of value you want to save, but with Value you can just do:
unordered_map<std::string, cocos2d::Value> configuration;
configuration["numEnemies"] = Value(10);
configuration["gameTitle"] = Value("Super Mega Raiders");
It's just a mechanism to create some loose typing in C++ which is a strongly-typed language.
You can save a string in a Value with something like this:
std::string name = "Vidur";
Value nameVal = Value(name);
And then later retrieve it with:
std::string retrievedName = nameVal.asString();
If you attempt to parse a Value as the wrong type, it will throw an error in runtime, since this is isn't something that the compiler can figure out.
Do let me know if you have any questions.

Use a period in a field name in a Matlab struct

I'm using webwrite to post to an api. One of the field names in the json object I'm trying to setup for posting is odata.metadata. I'm making a struct that looks like this for the json object:
json = struct('odata.metadata', metadata, 'odata.type', type, 'Name', name,);
But I get an error
Error using struct
Invalid field name "odata.metadata"
Here's the json object I'm trying to use in Matlab. All strings for simplicity:
{
"odata.metadata": "https://website.com#Element",
"odata.type": "Blah.Blah.This.That",
"Name": "My Object"
}
Is there a way to submit this json object or is it a lost cause?
Field names are not allowed to have dots in them. The reason why is because this will be confused with accessing another nested structure within the structure itself.
For example, doing json.odata.metadata would be interpreted as json being a struct with a member whose field name is odata where odata has another member whose field name is metadata. This would not be interpreted as a member with the combined field name as odata.metadata. You're going to have to rename the field to something else or change the convention of your field name slightly.
Usually, the convention is to replace dots with underscores. An automated way to take care of this if you're not willing to manually rename the field names yourself is to use a function called matlab.lang.makeValidName that takes in a string and converts it into a valid field name. This function was introduced in R2014a. For older versions, it's called genvarname.
For example:
>> matlab.lang.makeValidName('odata.metadata')
ans =
odata_metadata
As such, either replace all dots with _ to ensure no ambiguities or use matlab.lang.makeValidName or genvarname to take care of this for you.
I would suggest using a a containers.Map instead of a struct to store your data, and then creating your JSON string by iterating over the Map filednames and appending them along with the data to your JSON.
Here's a quick demonstration of what I mean:
%// Prepare the Map and the Data:
metadata = 'https://website.com#Element';
type = 'Blah.Blah.This.That';
name = 'My Object';
example_map = containers.Map({'odata.metadata','odata.type','Name'},...
{metadata,type,name});
%// Convert to JSON:
JSONstr = '{'; %// Initialization
map_keys = keys(example_map);
map_vals = values(example_map);
for ind1 = 1:example_map.Count
JSONstr = [JSONstr '"' map_keys{ind1} '":"' map_vals{ind1} '",'];
end
JSONstr =[JSONstr(1:end-1) '}']; %// Finalization (get rid of the last ',' and close)
Which results in a valid JSON string.
Obviously if your values aren't strings you'll need to convert them using num2str etc.
Another alternative you might want to consider is the JSONlab FEX submission. I saw that its savejson.m is able to accept cell arrays - which can hold any string you like.
Other alternatives may include any of the numerous Java or python JSON libraries which you can call from MATLAB.
I probably shouldn't add this as an answer - but you can have '.' in a struct fieldname...
Before I go further - I do not advocate this and it will almost certainly cause bugs and a lot of trouble down the road... #rayryeng method is a better approach
If your struct is created by a mex function which creates a field that contains a "." -> then you will get what your after.
To create your own test see the Mathworks example and modify accordingly.
(I wont put the full code here to discourage the practice).
If you update the char example and compile to test_mex you get:
>> obj = test_mex
obj =
Doublestuff: [1x100 double]
odata.metadata: 'This is my char'
Note: You can only access your custom field in Matlab using dynamic fieldnames:
obj.('odata.metadata')
You need to use a mex capability to update it...

Using a variable in the struct tag

How would I use a variable in a Go struct tag?
This works:
type Shape struct {
Type string `json:"type"`
}
This does not work:
const (
TYPE = "type"
)
type Shape struct {
Type string fmt.Sprintf("json:\"%s\"", TYPE)
}
In the first example, I am using a string literal, which works. In the second example, I am building a string using fmt.Sprintf, and I seem to be getting an error:
syntax error: unexpected name, expecting }
Here it is on the Go playground:
https://play.golang.org/p/lUmylztaFg
How would I use a variable in a Go struct tag? You wouldn't, it's not allowed by the language. You can't use a statement that evaluates at runtime in place of a compile time string literal for as an annotation to a field on a struct. As far as I know nothing of the sort works in any compiled language.
With the introduction of go generate, it is possible to do achieve this.
However, go generate essentially makes the compilation a 2 phase process. Phase 1 generates the new code, phase 2 compiles and links etc.
There are a few limitations with using go generate:
Your library will not be 'go get'-able unless you run go generate every time it is needed and check in the result, since go generate needs to be explicitly run before go build
This is a compile time process, so you will not be able to do it at run time using run time information. If you really must do this at run time, and in your case, you are just adding JSON serialization annotations, you could consider using a map.
String const/variable is not allowed in tag value to keep things simple and I support that. However with this limit, we need to use reflection to retrieve the tag value which is costly OR type string literals everywhere in the project, which may lead to bugs because of typos.
Solution
We can generate the tag values as string constant and then use this constant further in the project. It doesn't use reflection(saves performance cost), is more maintainable and removes the possibility of any bug because of typos.
ast package is an amazing tool to analyse and generate the go code. For example -
type user struct {
Name string `json:"name"`
Age int `json:"age"`
}
We can generated constants for user struct as below -
const (
UserNameJson = "name"
UserAgeJson = "age"
)
You may find tgcon helpful to generate the field tag value as const.