Dart final keyword performance impact - dart

I am aware that once assigned a value, a final variable's value cannot be changed. Does the keyword final have a positive performance impact compared to a not-final variable?

For local variables, there is no advantage. Any competent compiler can detect whether a local variable is assigned to, whether it's declared final or not.
For instance variables, it's harder to detect whether there is a subclass overriding the variable, or some other implementation of the interface. That means that even if the variable is final, the compiler can rarely trust that for anything. A compiler with access to the whole program might detect that there is no assignment anywhere.
It makes a difference for your API though.
For static and top-level variables there might be a slight advantage in making the variable final. It means that local analysis can know that the value won't change, even without seeing the entire program.
All in all, anything but local variables, you should make unchanging variables final because it's good modelling, not because you worry about performance. For local variables, it doesn't matter.

Related

Why does Lua have both `__gc` and `__close`?

The Lua manual states that the __close metamethod is used when to-be-closed variables go out of scope, and should release the variable's resources. But it also says that when a value is garbage-collected, the __gc metamethod is used to release resources.
In this question one of the comments says that if you have __close (or both __close and __gc) you have to be careful to avoid freeing the memory twice.
I'm still a little confused, though. So long as you're careful about how you write it, why can't there just be a single __gc function that gets used in both cases?

What are dangers or drawbacks of re-def'ing variables?

I always load a namespace not-really-constants. It contains, among other definitions:
(def foo 0.05)
Another namespace contains
(ns other-ns
(require [not-really-constants :as cn]))
(defn bar [x] (* x cn/foo))
However, sometimes I want foo to have a different value. So I load a namespace containing
(in-ns 'not-really-constants)
(def foo 0.025)
And then I call other-ns/bar in the place where it would normally be called. bar then uses the new value of foo, 0.025, rather than the original 0.05.
I'm not sure whether to be suprised about this behavior. I think of redefining using def as a handy convenience in the repl, but as something that's one is not supposed to do in normal code. However, I'm not sure why. Redefining foo in this way seems to work without trouble running everything from the commandline using lein run, loading files via require.
So, my question is: What are the dangers or other drawbacks of this practice--i.e. of redefining a variable using def?
(BTW I don't add ^:dynamic to the definition of foo because I don't need thread-local bindings; the new value of foo should be used everywhere. If I add ^:const to the definition of foo, bar uses the original 0.05 value despite the fact that I redefined foo, as bar should in that case.)
Redefining a var is not thread safe and should not be done in production environments. There is a good response available to a similar question that goes into more depth on the underlying reasons.
The main drawback to redefining vars in Clojure has less to do with thread safety, and more to do with the inherent dangers of mutable state. Idiomatic Clojure strives to be purely functional and free of side-effects. This makes it much easier to reason about the logic of your program - given the same inputs, a function will always produce the same output.
When you redefine a var, you're basically treating it as a mutable global variable. The behavior of code that uses that variable now depends not only on its inputs, but the order in which it is executed relative to other code that might have altered that variable. This extra dimension of time makes it much harder to reason about your program.
I'd treat redefining a var as a code smell: it might be OK in this particular situation, but should be an indication that you should re-evaluate your approach and see if there's a better way.

Can I somehow preserve values of local macros in Stata after the completion of the do-file?

Whenever I add new lies to the code (e.g. when computing a different estimate) I do not want to rerun the whole do-file again. However, I often need the values of certain local macros that were generated during the previous run of the do-file.
Is there a way to keep those values? Or I should switch to using more globals instead?
Yes, use global.
But note that you need to be careful with global for the exact reason you are using it: the macro remains in memory until you exit that instance of Stata, or until you reset it within the code.
Some people have very strong feelings about not using global ever (see pp5 and continuing here: http://faculty.chicagobooth.edu/matthew.gentzkow/research/ra_manual_coding.pdf). Once you learn their properties, and to not incur the small number of problems they can potentially cause, you should be fine.
Globals are by no means the only alternative.
First, consider using scalars. A scalar with a permanent name will survive beyond the end of a do-file.
Second, consider converting your do-file to a program and learning about saved results.
Third, you can always consider putting results in a new variable; it's just that it is usually bad style and wasteful on storage.
At a guess, the first is likely to be the most useful for you. Many Stata users are happy to use do-files with many dataset-specific statements. Jumping to writing fully-fledged and more general programs is a big jump and not (at first) trivial.

When do FORTRAN subprograms save data, and when not?

Have a pretty simple function for taking the name of a month, "Jan", "Feb", etc. and converting to the number of the month:
function month_num(month_str)
character*(*) :: month_str
character*3 :: month_names(12)
integer :: ipos(1),location(12)
data month_names/'Jan','Feb','Mar','Apr','May','Jun','Jul','Aug', &
'Sep','Oct','Nov','Dec'/
where (month_names==month_str) location=1
ipos = maxloc(location)
month_num = ipos(1)
end function
And OK, yes, I know it's dangerous to not define "location" before using it.
Problem: During execution of the function, if input is OK, some value of "location" will be set to 1. And, to my surprise, when the function is called again, that value will still be equal to 1. And this, of course, really messes things up. So I figured I would fix it with a new line
data location/12*0/
And I got the same problem.
Finally, I put in
location = 0
just before the "where" statement, and that fixed everything.
So, I thought FORTRAN subprograms would not save data unless the variables were declared with the "SAVE" attribute. Also, with many compilers, you can invoke some sort of "static" option that will keep everything saved. I did neither of these here, but the "location" array was saved just the same. Can someone enlighten me on the rules of when FORTRAN saves data and when not? Thanks.
The value of a variable local to a procedure is preserved across (ie it is SAVEd) in one of two ways:
The programmer specifies the SAVE attribute when declaring the variable, for example:
REAL, SAVE :: var1
The programmer initialises the variable upon declaration, for example
REAL :: var1 = 3.1415
This second, implicit, behaviour is one features of Fortran which seem designed to catch out the programmer, and not just beginners. Note that the value the variable has upon re-invocation is not, in the 2nd example 3.1415, but whatever value it had when the last invocation exited.
It is common for compilers to behave as if a variable is SAVEd when the programmer has not exercised either of these options, perhaps the memory locations used by one invocation of a procedure are not overwritten before the next invocation. But this behaviour is not to be relied on.
The situation is slightly different for variables declared in modules. Again any variable with the SAVE attribute is saved but any other variable only retains its value while the module is use-associated with a program unit which has started executing but not finished. Again some compilers, and some executions of some programs, may behave as if the value of a module variable is preserved despite the module going out of scope but this is non-standard behaviour and not to be relied on.
This behaviour is scheduled to change in Fortran 2008 when variables defined in modules will acquire the SAVE attribute implicitly.
Personally I like to explicitly SAVE variables even when I am sure that they would get the attribute implicitly, it makes the code just a bit easier to understand next time round.

With Delphi are you more likely to re-use temporary variables than with other languages?

Since Delphi makes you go all the way up to the var section of a method to declare a local variable, do you find yourself breaking "Curly's Law" (re-using variables) more often than you did in college?(unless of course, you programmed Pascal in college).
If so, what do you do to break yourself of that habit, especially in functions where you need to get and/or set large numbers of properties. Is there a threshold where it is acceptable to declare TempInt : Integer and TempStr : String. (Do you use an 'e' in Temp sometimes and not other times?)
I hardly ever reuse variables. I hate to say never, but it is close to never.
Here is why:
Small methods (It's good practice to keep methods and property-getters/setters as concise as possible).
When only one thing is done, no need to reuse variables
The var section is always on the screen.
The compiler reuses the storage as necessary, so reuse is only a lazy coder crutch with no performance improvements.
Newer versions of Delphi have CTRL+SHIFT+V to declare a variable if I am feeling lazy.
Reusing variables makes debugging more difficult - more time and effort is spent on maintenance then development (for any serious application) so always do things to make maintenance easier, even if it makes development a little harder.
Prefer user defined types, so a Account Balance is a specific type, not just a Currency. This means variables are less reusable anyway.
For loop variables (a common reused variable) are used less now that we can use for in and skip the iterator all together.
My variables have descriptive names, so it would not make sense to use them out of context.
Generally speaking, I like having all the variables at the top for the same reason I like having an interface section on my units. It is kind of like having an abstract on a paper - give me a general idea of what is going on without having to read the whole paper. Delphi could benefit from having the ability to declare variables at "inner scope" like within a for loop or other begin / end blocks, but I don't know how much that would distract from the cleanliness and readability of Delphi code.
This is just a matter of discipline. Yes, Delphi would probably be better served by inline variable declaration, but that's not really a big deal. Just be sure to name your variables in a descriptive way, and then it will just feel awkward to use them incorrectly. And, as Stephan Eggermont said, if your methods are really getting that long, then that's a whole different code smell.
Not really. As I make my methods really small the var section is not far away. As my method size has reduced a lot since university, I'd say I break it less often.
I definitely do tend to re-use local variables like 'Findex' (or just plain 'i') if the routine has several distinct iterative sections to it. Not really the best practice I guess, but I'd like to think it's only really obvious where I do it, and obviously the usage doesn't overlap.
It's not usually a big deal to go back to the top of the routine and key-in the new variables, though I didn't know about Ctrl-Shift-V (will be trying that later!).
It'll be interesting to see what everyone else says. :-)
I don't tend to reuse local vars as a general safety rule. I do love the new "var" live template stuff in d2007+. Just type var[tab] and the helper pops up. Also check out Ctrl-Shift-D (others mentioned Ctrl-Shift-V for local vars) to declare a field.
Declaring variables is very simple - some times they would get automatically created ('for' loop template), other times you can just use 'Declare Variable' refactoring (or 'Add Local Var' if you are using MMX - as you should).
You can develop your own style of coding that uses variables as required. I generally use unique vars (90%) with a few temp vars (10%) when required.
It depends on the nature of the var. If it is a var to help support other code (counter for loops, building SQL strings, etc.) then a temp var you can re-use is helpful. In this case your temp vars are useful as "disposable" vars in sections of code. Just add a comment to your var declarations indicating the temp vars.
i.e. //temp vars are re-used as required in this procedure --> clear/re-initialise them after/before use.
Other than that I avoid temp vars & never use them to hold critical data. A unique var should be used then to avoid confusion & make readability/maintenance of code clearer.
I think delphi makes the exception with the overuse of temp variables. Most of the time when i'm creating a function/procedure where i know i will need loops or temp strings, first thing i do is to create a var i,j:integer; tmp:string; and add more as needed :)
As a long time Delphi user (since 1.0) this is the major thing I hate about Pascal. all other modern languages support definition at the point of use, yet Delphi persists with the var section, and Delphi programmers persist in ridiculous hand-waving antics to justify it.
Well Curly did have a good point. I'm a sinner in that respect occasionally. Usually just a temp string variable for convenience more than anything.
To be honest I've never really thought about it... until now. I have no issue with the VAR section being where it is as that's been a habit formed since Delphi 1.0.
To answer the question, I only re-use a temp variable, usually a string, and usually only to gain some slight performance improvements. Don't have an issue with that.
I probably would have found this to be a bigger problem if hadn't had CTRL-SHIFT-V as a shortcut to the VAR section. I'm not writing GIGANTIC methods here, but sometimes they get a little out of hand (and I can justify this of course) and it helps a lot. I'm not sure if that shortcut comes from cnTools or GExperts, but they're both pretty useful and I'd recommend them both.

Resources