Example:
<?php $formElement->display()?>
Is this fine, or should I provide a ; ? Well I guess that the PHP interpreter is clever enough to see that the line is finished and the expression done because of the ?> at the end. Right?
Example:
<?php $formElement->display()?>
Is this fine, or should I provide a ; ? Well I guess that the PHP interpreter is clever enough to see that the line is finished and the expression done because of the ?> at the end. Right?
Here's what worked best for me when trying to script this (in case anyone else comes across this like I did):
$ pecl -d php_suffix=5.6 install <package>
$ pecl uninstall -r <package>
$ pecl -d php_suffix=7.0 install <package>
$ pecl uninstall -r <package>
$ pecl -d php_suffix=7.1 install <package>
$ pecl uninstall -r <package>
The -d php_suffix=<version>
piece allows you to set config values at run time vs pre-setting them with pecl config-set
. The uninstall -r
bit does not actually uninstall it (from the docs):
vagrant@homestead:~$ pecl help uninstall
pecl uninstall [options] [channel/]<package> ...
Uninstalls one or more PEAR packages. More than one package may be
specified at once. Prefix with channel name to uninstall from a
channel not in your default channel (pecl.php.net)
Options:
...
-r, --register-only
do not remove files, only register the packages as not installed
...
The uninstall line is necessary otherwise installing it will remove any previously installed version, even if it was for a different PHP version (ex: Installing an extension for PHP 7.0 would remove the 5.6 version if the package was still registered as installed).
The problem here is a limitation in TypeScript: control flow analysis (as implemented and described in microsoft/TypeScript#8010) does not propagate into or out of function scope boundaries. See microsoft/TypeScript#9998 for details and discussion. There is also a more specific issue, microsoft/TypeScript#11498 which suggests being able to "inline" control flow analysis for certain types of callback.
The compiler analyzes the code block if (!map) { map = new Map(); }
and successfully understands that after this block, map
is definitely not undefined
, as you can demonstrate by trying to use methods of map
before and after that code block:
map.has(""); // error
if (!map) {
map = new Map();
}
map.has(""); // okay
All is going well until you get down inside the body of a callback function, crossing the boundary of a function scope:
[1, 2, 3].forEach(() => map.has("")); // error, map might be undefined
The compiler really does not know when or if that callback will be called. You know that the array forEach()
runs its callback synchronously once for each element in the array. But the compiler does not know this, or even know how to represent this in the type system (without implementing some way of tracking what functions do with their callbacks as suggested in microsoft/TypeScript#11498.)
Imagine you saw a function foobar(() => map.has(""))
. Would you know when or if that callback gets invoked without finding the implementation of foobar()
and examining it? That's what the compiler thinks about forEach()
.
The compiler thinks it might be possible that the callback will get invoked at some point where its previous control flow analysis no longer applies. "Maybe map
gets set to undefined
in some other later part of the outer function" And so, it gives up and treats map
as possibly undefined
. Again, you know this is not the case, since map
goes out of scope without ever being delete
d or getting a map = undefined
done to it. But the compiler does not spend the cycles necessary to figure this out. Giving up is a trade-off where performance is valued over completeness.
It gets even worse when you realize that the compiler just assumes that a closed-over value will not be modified inside a callback function. Just as no control flow analysis from the outer scope propagates inward, no control flow analysis from the inner scope propagates outward:
[4, 5, 6].forEach(() => map = undefined);
return map; // no error?!
In the above code, the map
is definitely going to be undefined
when you get to return map
, but the compiler allows it with no warning. Why? Again, the compiler has no idea that the callback will ever be called or when. It would be safer to just throw away all control flow analysis results after a closure is defined or called, but this would make control flow analysis nearly useless. Trying to inline the callback would require understanding how forEach()
is different from foobar()
and involve a lot of work and probably result in a much slower compiler. Pretending that callbacks don't affect control flow analysis is a trade-off where performance and convenience are valued over soundness.
So what can be done? One easy thing is to assign your value to a const
variable in a scope where control flow analysis has happened. The compiler knows that a const
variable can never be reassigned, and it knows (well, pretends) that this means the type of the variable will also never change:
function parseUrlArgs(inputString: string, map?: Map<string, string>): Map<string, string> {
if (!map) {
map = new Map();
}
const resultMap = map; // <-- const assignment here
const re = /(^[^=]+)=(.*$)/;
inputString.trim().split("&").forEach((kvp) => {
const result = re.exec(kvp);
if (result) {
const key = decodeURIComponent(result[1]);
const value = decodeURIComponent(result[2]);
resultMap.set(key, value); // <-- use const variable here
}
});
return resultMap; // <-- use const variable here
}
By copying map
into resultMap
at a point where map
is known to be defined, the compiler knows that resultMap
is of type Map<string, string>
and not undefined
. This type persists for the rest of the function, even inside callbacks. This might be a bit redundant, but the compiler can track it and is relatively type safe.
Or you could keep using the non-null operator !
. It's up to you.
Playground link to code
I’d write it like this instead:
def checkRadioButton(xml: DslBuilder): String => XmlTree = {
val inputs = top(xml).\*(hasLocalNameX("input"));
(buttonValue: String) => { // <-- changed position of {
// code omitted
}
}
Never used any of those, but they look interesting..
Take a look at Gearman as well.. more overhead in systems like these but you get other cool stuff :) Guess it depends on your needs ..
It is not required, but you should put it, as a good practice.
That way, the day you need to add another instruction after this one, it'll work fine.
And here is the manual's page that answers your question : Instruction separation (quoting, emphasis mine) :
As in C or Perl, PHP requires instructions to be terminated with a semicolon at the end of each statement.
The closing tag of a block of PHP code automatically implies a semicolon; you do not need to have a semicolon terminating the last line of a PHP block.
The closing tag for the block will include the immediately trailing newline if one is present.