I was looking at the source code of the crystal compiler, and I came across this:
def self.from(obj : Array)
case obj.size
when 0
Nop.new
when 1
obj.first
else
new obj
end
end
In particular, new obj. I know that T.new is used to create a new instance of type T, but I have never seen new x before. Is it some sort of method? I didn't see it defined in that file. What is this new, and what does it do?
Probably it's just Something.new(x). new it's self.new, because you can drop self inside scope.
Related
I want the following code to set the 'name' field of the myClass instance to be equal to 'super_awesome_name':
super_awesome_name = myClass();
where the myClass constructor is as follows:
function obj = myClass()
obj.name = ???;
end
Is there some way to do this in Matlab? Right now I can accomplish something very similar with assignin, but it makes the syntax very unnatural:
myClass(super_awesome_name);
where the myClass constructor is as follows:
function obj = myClass(var_name)
obj.name = assignin('caller',var_name, obj);
end
As far as I know, there is no convenient way of doing so. You can see this yourself since MATLAB will have to perform some when constructing an object like that.
First construct the object
Store that object in super_awesome_name
But step 1 needs information from step 2 (i.e. the name of the variable). So you will have to work around that.
You solution may work, but it leaves a lot of room for error. Just consider the case when super_awesome_name is undefined before the construction: this will throw an exception due to an unitialized variable.
IMHO it is easier to make a constructor that accepts a string containing the name (or possibly a variable, as you can get the variable name of an argument by using inputname). Using inputname, however is just a bit clearer than using assignin.
Why do you need such functionality? I'm thinking of a situation where you might do something like:
x = myObjectThatHasAName(); % x.name contains 'x'
y = myObjectThatHasAName(); % y.name contains 'y'
x = y; % x.name contains 'y' !
So that might be the behavior you are looking for, but it may become very confusing if you pass the variables along a lot. It looks to me like you are mixing debugging information into your actual computations.
If you need the functionality to determine the actual variable name in another method or function, just use inputname. Then you won't need to keep track of the variable name yourself with all confusing consequences. That would be what I'd propose to do in most cases. You can see an example in the MATLAB documentation.
On the other hand, I think the clearest way to store the variable name inside the object, could be something like:
classdef myObjectThatHasAName
properties
name = '';
end
methods
function obj = myObjectThatHasAName()
end
function obj = storeName(obj,name)
if nargin < 2
name = inputname(1);
end
if ~isempty(name) % && isempty(obj.name)
obj.name = inputname(1);
end
end
end
end
I haven't tested this (lack of MATLAB on my current computer), but the following code should do it:
x = myObjectThatHasAName();
x = x.storeName();
% or x = storeName(x);
% or x = storeName(x,'x');
If you don't mind the overhead, you could always incorporate the storeName into each other method (and forget about calling storeMethod outside of the methods). This keeps track of the variable name where the object resided before the last assignment. A possible method might look like this:
function obj = otherMethod(obj,arguments)
obj = obj.storeName(inputname(1));
% actual code for the method
end
That way the name is set when you first call any method on the object (this almost does what you want, but I guess it will do what you need in most cases). You can of course adjust the code to just remember the first assignment (just comment out the code in storeName).
Which one is best approach out of the following? Or Both has same effect ?
Dim carrierName As String
Dim someotherName As String
Dim anotherOne As String
Using oDa As New MyCompany.DataAccess.MyModule
carrierName = oDa.GetCarrierName(itemNumber)
End Using
Using oDa As New MyCompany.DataAccess.MyModule
someotherName = oDa.GetSomeOtherName(itemNumber,1)
End Using
Using oDa As New MyCompany.DataAccess.MyModule
anotherOne = oDa.GetAnotherName("somevalue")
End Using
OR
Using oDa As New MyCompany.DataAccess.MyModule
carrierName = oDa.GetCarrierName(itemNumber)
someotherName = oDa.GetSomeOtherName(itemNumber,1)
anotherOne = oDa.GetAnotherName("somevalue")
End Using
Well, one version will create three MyModule instances, the other will only create one. We can't tell what the difference is without knowing more about MyModule.
The second approach looks cleaner to me, but without knowing the semantic differences, it's hard to say that it's definitely better.
In the first, you are creating and disposing of 3 instances of MyModule while in the second you are only creating and disposing 1 instance. So the second approach is better. It's cleaner and more straightforward too.
The two approachs are fondamentally different, but the end result depend on your MyModule implementation.
The second one seems better, as it creates and manages only one MyModule object, especially if MyModule is costly to create and to dispose.
The first one can be necessary if your MyModule doesn't allow multiple requests with the same instance. But if it's the cas. hem... it would look like a bug to me.
The latter is better in most cases. Using is just shortcut for
var oDa = new MyCompany.DataAccess.MyModule();
try {
carrierName = oDa.GetCarrierName(itemNumber)
someotherName = oDa.GetSomeOtherName(itemNumber,1)
anotherOne = oDa.GetAnotherName("somevalue")
}
finally {
oDa.Dispose();
}
First method could be used when every method allocates huge amount of memory that will need to be cleaned right away, but I don't think it is your case.
btw: you seem to have mistaken c# with visual basic
I have an array of objects in MATLAB and I've called their constructors in a loop:
antsNumber = 5;
for counter = 1: antsNumber
ant(counter) = TAnt(source, target);
end
MATLAB warns me to use preallocation to speed up the process. I do know the benefits of preallocation but I don't know how to do that for objects.
Here are a few options, which require that you design the class constructor for TAnt so that it is able to handle a no input argument case:
You can create a default TAnt object (by calling the constructor with no input arguments) and replicate it with REPMAT to initialize your array before entering your for loop:
ant = repmat(TAnt(),1,5); %# Replicate the default object
Then, you can loop over the array, overwriting each default object with a new one.
If your TAnt objects are all being initialized with the same data, and they are not derived from the handle class, you can create 1 object and use REPMAT to copy it:
ant = repmat(TAnt(source,target),1,5); %# Replicate the object
This will allow you to avoid looping altogether.
If TAnt is derived from the handle class, the first option above should work fine but the second option wouldn't because it would give you 5 copies of the handle for the same object as opposed to 5 handles for distinct objects.
The following link might be of help:
http://www.mathworks.com/help/techdoc/matlab_oop/brd4btr.html#brd4nrh
Web archive of dead link
New link:
http://de.mathworks.com/help/matlab/matlab_oop/creating-object-arrays.html
The warning it gives is superfluous, unless you are doing computational heavy stuff, I would ignore it.
The reason why it's giving you the error, is because it has to find new space. Say, I give you a list of seven objects, and I tell you that you need to place them all in a row, I then go off, and give you a few more things you need to put somewhere. I then give you an eighth object and tell you to put it right after the seventh. Because you have stuff where the eighth object is, you either have to move it out of the way, or you have to move all seven objects. Matlab, is telling you it would be faster if you were to tell it beforehand that you want to put 5 things in there, rather than just giving it things one by one, having to look for a new spot each time. You can do that by adding this line to the top of your code:
ant = [1:5];
There are also other ways to do this too.
Not sure if I got your problem right, but if you want to initialize an array of your self-defined class "TAnt", here is how I would do it
For TAnt's constructor method, put something like:
function obj = TAnt(source, target)
if nargin > 0
obj.mySource = source;
obj.myTarget = target;
else
obj.mySource = defaultValue;
obj.myTarget = defaultValue;
end
end
Then to initialize/pre allocate an array of default TAnt objects,
ants(1,n) = TAnt(); % n is the length of your ants array
Some code to illustrate my question:
With Test.AnObject
.Something = 1337
.AnotherThing = "Hello"
''// why can't I do this to pass the object itself:
Test2.Subroutine(.)
''// ... and is there an equivalent, other than repeating the object in With?
End With
There is no way to refer to the object referenced in the With statement, other than repeating the name of the object itself.
EDIT
If you really want to, you could modify your an object to return a reference to itself
Public Function Self() as TypeOfAnObject
Return Me
End Get
Then you could use the following code
With Test.AnObject
Test2.Subroutine(.Self())
End With
Finally, if you cannot modify the code for an object, you could (but not necessarily should) accomplish the same thing via an extension method. One generic solution is:
' Define in a Module
<Extension()>
Public Function Self(Of T)(target As T) As T
Return target
End Function
called like so:
Test2.Subroutine(.Self())
or
With 1
a = .Self() + 2 ' a now equals 3
End With
I suspect you'll have to repeat yourself. If the expression (to get the object) is expensive, then perhaps drop it into a variable first, and either use that variable in the With, or drop the With completely:
tmp = Test.AnObject;
tmp.Something = 1337;
...
Test2.Subroutine(tmp);
As others have said, you're going to have to write
Test2.Subroutine(Test.AnObject)
This is a good example of why it's worth being a little careful with the With construct in VB.Net. My view is that to make it worth using at all, you really need to be setting more than one or two properties, and/or calling more than one or two methods on the object in the With statement.
When there are lots, and you're not interspersing the .SomeProperty = , or .DoSomething, with other things, it's a terrific aid to readability.
Conversely, a few dots sprinkled amongst a load of other stuff is actually a lot harder to read than not using With at all.
In this case, . characters on their own could easily get lost visually, although of course, it would be syntactically consistent.
I guess they just chose not to implement it. VB isn't really the sort of language where they want to encourage single character language elements, and as a heavy user of VB.Net, I broadly agree with that.
Bottom line: if you're using a With clause with many contained elements, having to refer to the object itself isn't that big a deal. If you're using it with just one or two, maybe better not to use a With clause in the first place.
I'm not sure this is an "answer", per se, but it does illustrate another reason to want a short-hand reference to the parent in a With.
Here's a code sample using a "bare With" (that's what I call it, anyway):
With New frmMySubForm
.lblLinkLabel.Links.Add(New LinkLabel.Link With {.Name = "link", .LinkData = "someUrl", .Start = .lblLinkLabel.Text.IndexOf("link"), .Length = "link".Length})
...
End With
But you actually can't code that because in the term .Start = .lblLinkLabel.Text.IndexOf("link") the compiler expects anything starting with . to be a member of LinkLabel.Link, which .lblLinkLabel isn't.
What would be good, I think, is to be able to write something like:
With New frmMySubForm
.lblLinkLabel.Links.Add(New LinkLabel.Link With {.Name = "link", .LinkData = "someUrl", .Start = Me.lblLinkLabel.Text.IndexOf("link"), .Length = "link".Length})
...
End With
where Me in this scope is taken to be New frmMySubForm.
Yes, I realize that I'm being picky and I could easily assign a variable, etc. But the example form is something I use a lot simply out of preference.
All
I am currently trying implement something along the lines of
dim l_stuff as List(of Stuff)
dim m_stuff as new Stuff
m_stuff.property1 = 1
m_stuff.property2 = "This"
if not l_stuff.exists(m_stuff) then
l_stuff.add(m_stuff)
end if
This fails obviously as the Exist method is looking for a predicate of Stuff.
Can anyone fully explain the predicate and how i can achieve what I am trying to do here.
I have tried to use
if not l_stuff.contains(m_stuff) then
l_stuff.add(m_stuff)
end if
however this doesn't detect the idenitcal entry and enters a duplicate into the list
Thank
List(Of T).Contains is the method you should be using. Exists, as you say, expects a predicate. Of course, for .Contains to work as expected, you need to override the Equals() method, as well as GetHashCode().
List(Of T).Exists expects a function that will return a Boolean value when passed an item of type T, where T, in your case, is of type Stuff. So, you could write a method that looks like:
If Not l_stuff.Exists(Function(x) x.property1 = m_stuff.property1 And _
x.property2 = m_stuff.property2) Then
and so on.