So Im learning Dart right now, and I have a problem when it comes to declare lists.
In a tutorial I saw that the teacher declared a list by using this syntax:
void main() {
final names = ['Foo', 'Bar', 'Baz'];
}
And in another turorial I saw this:
void main() {
List<String> names = ['Foo', 'Bar', 'Baz'];
}
I want to know if there is a differance between the two.
And thank you guys for reading my question
final just means that once assigned it can't be reassigned. So you can't do
final names = ['Foo', 'Bar', 'Baz'];
names = ['Foo2', 'Bar2', 'Baz2'];
You could add it also to the other one as well like
final List<String> names = ['Foo', 'Bar', 'Baz'];
Without final it's fine to do
List<String> names = ['Foo', 'Bar', 'Baz'];
names = ['Foo2', 'Bar2', 'Baz2'];
Furthermore it's usually okay to leave out the type, because the compiler is smart enough to see that it is in fact a List<String> in this case. If you want to make a non-final variable without indicating the type you can use the keyword var, like
var names = ['Foo', 'Bar', 'Baz'];
So in these examples
var names = ['Foo', 'Bar', 'Baz'];
List<String> names = ['Foo', 'Bar', 'Baz'];
are identical, and
final names = ['Foo', 'Bar', 'Baz'];
final List<String> names = ['Foo', 'Bar', 'Baz'];
are identical.
First one is the List which can be use as dynamic list or you can use as
List<dynamic> name= ['one,'two','three'];
Where as second one is used for specific String List OR
List<int> numbers= [1,2,3];
Related
In the bucklescript doc example for bs.deriving abstract, you can get the property on you created object with nameGet()
This works:
#bs.deriving abstract]
type person = {
name: string,
age: int,
job: string,
};
let joe = person(~name="Joe", ~age=20, ~job="teacher");
let name = nameGet(joe);
If you change it to capitalize the name key like below, your generated getter becomes _NameGet():
type person = {
_Name: string,
age: int,
job: string,
};
let joe = person(~_Name="Joe", ~age=20, ~job="teacher");
let name = _NameGet(joe);
In the second example, the name value comes back undefined. How can that be fixed?
example in repl:tryreason
Use [bs.as] to alias the name of the key. This will apparently not change the name of the getter which will remain _NameGet in this case but the value no longer returns undefined.
[#bs.deriving abstract]
type person2 = {
[#bs.as "Name"]
_Name: string,
age: int,
job: string,
};
let john = person2(~_Name="John", ~age=20, ~job="teacher")
let namejohn = _NameGet(john);
Js.log(namejohn);
output: John
docs: renaming fields
I am sorting an array of objects queried from Ember-Data by 'type'-key before returning them in the model()-method of an Ember.Route to be rendered.
app/routes/test.js
export default Ember.Route.extend({
model() {
let obj = Ember.Object.create({a: [], b: [], c: []});
this.get('store').findAll('obj').then(function(unsorted){
unsorted.forEach(function(item) {// sort per type
obj.get(item.get('type')).addObject(item);
});
return obj;
});
}
});
The array returned by (the promise of) the Ember-Data query looks like this (all objects have Ember internal properties)
[
{
_id: '1',
type: 'a',
properties: {...}
},
{
...
},
{
_id: '15',
type: 'b',
properties: {...}
}
]
And the new object with objects sorted by "type"-key looks like this
{
a: [{
_id: '1',
type: 'a',
properties: {...}
},
...
],
b: [
... ,
{
_id: '15',
type: 'b',
properties: {...}
},
c: [...]
};
app/routes/test.hbs
<h2>Test</h2>
<h3>Type a</h3>
{{#each model.a as |source|}}
<div>
{{source.properties.prop1}}
</div>
{{/each}}
The template doesn't render the part that loops over the array, nor does the Ember-inspector plugin list the Model property under "Own properties" of the route (right panel in "View tree"-mode).
However, when returning a POJO (literally pasting object with array's by key in code) everything behaves as expected.
I suspect this has something to do with the internal (Ember-)properties of the objects returned by Ember-data (I have read about the owner of an object etc.) but I can't seem to figure this out ...
The answer of #Pavol gets to the basic problem, however return this.store...then(...) will work because this is how promises work. Read the documentation.
So this will work:
model() {
let obj = Ember.Object.create({a: [], b: [], c: []});
return this.get('store').findAll('obj').then(function(unsorted){
unsorted.forEach(function(item) {// sort per type
obj.get(item.get('type')).addObject(item);
});
return obj;
});
}
.then(onFulfilled) returns a new promise, that will resolve with the return value of the onFulfilled-callback. Creating a new promise with new Promise(...) is always totally useless if you already have promises and only for interoperability with callback-style code.
You are missing return statement in your model() hook:
export default Ember.Route.extend({
model() {
let obj = Ember.Object.create({a: [], b: [], c: []});
this.get('store').findAll('obj').then(function(unsorted){
unsorted.forEach(function(item) {// sort per type
obj.get(item.get('type')).addObject(item);
});
return obj;
});
// no return value before, findAll() returns promise, thus model() returns undefined
}
});
However, adding return this.store... won't solve your situation since you are updating different object after your promise is solved (the then() function).
I would recommend wrapping it in a promise and resolve it passing a modified object based on your sorting logic.
Note: I did not consider whether sorting at this stage makes sense and is of 'Ember-way'. Sorting usually happens via computed properties on controller/component level.
export default Ember.Route.extend({
model() {
return new Ember.RSVP.Promise((resolve)=>{
let obj = Ember.Object.create({a: [], b: [], c: []});
this.get('store').findAll('obj').then(function(unsorted){
unsorted.forEach(function(item) {// sort per type
obj.get(item.get('type')).addObject(item);
});
resolve(obj);
});
});
}
});
Update: Of course this.store() returns a valid promise (which I pointed out in the snippet but explained incorrectly later) and so you do not have to wrap it, sorry for the confusement! I havenĀ“t realized that return value of the callback passed to then() is automatically internally passed in a promise, although I use promise chaining and this on a daily basis, too. Shame on me! Thx #Lux for putting this on a right way.
I have a function:
func parseJSON3(inputData: NSData) -> NSArray {
var tempDict: (id:Int, ccomments:Int, post_date:String, post_title:String, url:String) = (id: 0, ccomments: 0, post_date: "null", post_title: "null", url: "null")
var resultArray: (id:Int, ccomments:Int, post_date:String, post_title:String, url:String)[] = []
var error: NSError?
var jsonDictionary: NSDictionary = NSJSONSerialization.JSONObjectWithData(inputData, options: NSJSONReadingOptions.MutableContainers, error: &error) as NSDictionary
var firstArray = jsonDictionary.objectForKey("locations") as NSArray
for dict in firstArray {
tempDict.id = dict.valueForKey("ID") as Int
tempDict.ccomments = dict.valueForKey("ccomments") as Int
tempDict.post_date = dict.valueForKey("post_date") as String
tempDict.post_title = dict.valueForKey("post_title") as String
tempDict.url = dict.valueForKey("url") as String
resultArray.append(tempDict)
}
return resultArray
}
In line
resultArray.append(tempDict)
I have an error:
Missing argument for parameter 'ccomments' in call
Why? Help please....
It looks to me like resultArray.append() is treating the tuple a little bit like a variadic parameter, and trying to expand the tuple to match its own arguments. It's complaining about your second parameter because it's only expecting one. I haven't seen this behavior for Array.append() documented anywhere, so I would say it's a bug in Swift.
Using the appending operator += doesn't seem to have that issue:
resultArray += tempDict
So this is pretty wild - not sure if I would qualify it as a bug or as undocumented behavior, but it's definitely something that should be on the radar for a fix / clarification!
The situation is that append is treating your argument tempDict (which we would expect to be the only argument to an Array method that takes a single member and adds it to the collection) as the first argument in a signature where it is looking for 5 arguments (!), one for each member of the Tuple type that the Array holds.
See the following for some interesting behavior (including assigning a label to the single member of a 1-member 'Tuple' ??) ->
var arrayOne: Array<String> = []
arrayOne.append("hi")
println(arrayOne[0]) // hi
var arrayTwo: Array<(String)> = [] // where (String) is a single-member Tuple
arrayTwo.append("hi")
println(arrayTwo[0]) // hi
println(arrayTwo[0].0) // hi -> using .0 subscript to access the first member of the Tuple
// wanna see something crazy? remember arrayOne, that holds members of type String?
println(arrayOne[0].0) // hi -> this Array does not hold Tuples, but it looks like we can still treat its members like "single-member Tuples"?
var arrayThree: Array<(str: String)> = [] // members of the Array are single-member Tuples with the label 'str' for their member
arrayThree.append(str: "hi") // now we can't use append without providing the label 'str', acting as what looks like an argument label?
var byeString = "bye"
var byeTuple = ("bye")
arrayThree += byeString // += doesn't care about the label, and will take either a String or a single-member Tuple holding a String
arrayThree += byeTuple
println(arrayThree[0]) // hi
println(arrayThree[0].0) // hi
println(arrayThree[0].str) // hi -> accessing the single member of the Tuple by its label
...so in your case, where you are seeing the error with append what it wants you to do is (using the labels you used to declare the Tuple as something that looks like argument labels):
var resultArray: (id:Int, ccomments:Int, post_date:String, post_title:String, url:String)[] = []
...
resultArray.append(id: someIntValue, ccomments: someOtherIntValue, post_date: someStringValue, post_title: someOtherStringValue, url: someAnotherStringValue)
...and of course, as discussed, you can avoid doing that by just using += instead
Crazy stuff! could be by design to serve some purpose, could be a consequence of protocol inheritance that wasn't meant to have this effect... would be interesting to know the answer!
resultArray.append() seems to be taking tempDict as the first tuple element (id).
Changing it to :
resultArray += tempDict
seems to compile and work.
I'm not sure why append() doesn't behave the same way, maybe you can file a bug!
We can create Em.Object like this:
var foo = Em.Object.create({
somevar : '123'
});
and then use it:
foo.get('somevar');
but how to create a private property or method in Em.Object which would be accessable from the object but wouldnt be ourside?
There is indeed a way to have private variables in Ember objects, as follows:
MyObject = Ember.Object.extend({
init: function() {
// private variable
var a = 1;
// methods to get, set, or otherwise accesss the private variables
this.getA = function() {return a;};
this.setA = function(val) {a = val;}
// don't forget this!
this._super(...arguments);
}
});
now try
o1 = MyObject.create()
o2 = MyObject.create()
o1.setA(42);
o2.getA(); //1
In other words, you have to declare the private variables, AND any getters, setters, or other routines that want to use them, in the init hook. Of course, this means that those getters/setters will be present on each instance of the class, rather than in its prototype. That's slightly inefficient, but the same holds for any approach to private variables for classes in JavaScript.
It is conceivable that Ember could introduce a new private: {} hash on objects, but then Ember would need a lot of machinery to handle finding and controlling access to private variables across class hierarchies. It would be equivalent to redesigning or extending the language itself, which is not part of the Ember mission.
Meanwhile, the above approach works fine if the number of private instance variables is limited and the number of routines that need to access them is small. So the accepted answer that says this is impossible is, well, wrong.
It's not possible, since Ember.js does not provide any encapsulation mechanisms.
However, you can simply use some convention for private members. For example, prefix them with _ sign.
You could use a closure:
(function() {
var somePrivateProperty = 'xyz';
MyObject = Em.Object.extend({
someComputedProperty: function() {
return 'somePrivateProperty = ' + somePrivateProperty;
}).property()
})
})();
Is possible with a little trick:
var obj = Em.Em.Object.create(
new function(){
var privateVar = "this is private";
this.getPrivateVar = function(){
return privateVar ;
}
},
{
emberVar: "Ember var",
emberMethod : function(){
return this.getPrivateVar();
},
emberMethod1 : function(){
return privateVar ;
},
emberBinding : 'emberVar'
}
)
now if U try to get private var
obj.privateVar
> unknown
obj.getPrivateVar()
> "this is private"
obj.emberMethod()
> "this is private"
The only problem is that:
obj.emberMethod1()
> unknown
I have a list and I want to copy three other lists into it.
// The main list
List<List<string>> list= new List<List<string>>();
// The lists which I want to combine
ArrayList sublist1= new ArrayList();;
ArrayList sublist2= new ArrayList();;
ArrayList sublist3= new ArrayList();;
What I tried is:
list[0].AddRange(sublist1);
list[0].AddRange(sublist2);
list[0].AddRange(sublist3);
It doesn't work because It is multidimensional list. I need this type of list for the future plans.
How can I accomplist it?
As already mentioned in comments just use List<string> instead of ArrayList.
It has nothing to do about multidimensional arrays, just types mismatch.
Then you say List<List<string>> it basically means create list type, which will contain List<string> as items (the part in angle brackets), so you need to add them, not ArrayLists. Similarly List<string> means type of list which will contain string as items.
As in the comments, you need to pass a type that follows IEnumerable. For example, you can change your ArrayLists to List
// The main list
List<List<string>> list = new List<List<string>>();
// The lists which I want to combine
var sublist1 = new List<string>();
var sublist2 = new List<string>();
var sublist3 = new List<string>();
list[0].AddRange(sublist1);
list[0].AddRange(sublist2);
list[0].AddRange(sublist3);
change type of sublists to some IEnumerable<string> (string[] or List<string> or something else)
var sublist1 = new string[] {};
var sublist2 = new string[] {};
var sublist3 = new string[] {};
OR do cast
list[0].AddRange((IEnumerable<string>) sublist1);
list[0].AddRange((IEnumerable<string>) sublist2);
list[0].AddRange((IEnumerable<string>) sublist3);
Because you are trying to use AddRange method of System.Collections.Generic.List<T>
and the signature of this method is
public void AddRange(System.Collections.Generic.IEnumerable<T> collection)
so it requires IEnumerable as a parameter.