|
I think of it more at a concept level rather than saving typing. Avoid reduncancy. Avoid tokens that serve no purpose. Remove clutter.
As I argued earlier in the thread: A language such as CHILL allows any block to have an exception handler attached. Putting "try{...}" around the block before the handler is redundant: If the handler is present, then the block has a handler - no need to pre-announce it! Removing the need for that pre-announcement simplifies the code.
(The real reason for the C/C++ try{} is purely historic: C didn't have any such thing, while several other languages did. So to "compete", a macro-based solution was devised, that required no extension to the underlaying compiler. When adopted into the C/C++ language, it could have been given a cleaner syntax, but to be backwards compatible with all the code that had been written for the macro-based implementation, the syntax was kept unchanged.)
In Pascal (or CHILL), you write a condtion without enclosing parethes like in prose text: If it is raining, then you better wear a raincoat. You need not clutter up that sentence with parentheses markup. You remove the conceptually informationless tokens.
var matching = new List<FileInfo>(); rather than
List<FileInfo> matching = new List<FileInfo>(); removes redundancy, risk of inconsistency, and the reader has fewer tokens to interpret. I do not see what we gain by repeating the type information when it can be infered. (var has other uses as well unrelated to this.)
A language recognizing a statement as a block avoids redundant bracketing: At the spur of the moment, I cannot think of a single case where single-statement block and a single statement are both valid but with different semantics. So I see no reason why some languages insist on adding these extra tokens that carry no semantic information.
The idea is that non-information-carrying elements (that you nevertheless have to relate to) are bad. The fewer elements you need to process mentally, the better.
This is, of course, assuming that the programmer/reader easily relates to the concepts repersented by the tokens. E.g. to a matehmatician, matrix inversion is such a basic and common concept that giving it a separate symbol (analogous to multiply and divide) as it done in APL (created as a mathematical notation, not as a programming languge) is perfectly fine even though non-mathmaticians says "Huh?". For those who are "only engineers", powers are essential, so languages with that user group in mind have a token for that operation (like 2**11 or 2^11); that simplifies and improves readability of engineering calculations, rather than "power(1, 11)". A low-level language for handling bit patterns does the same with left and right shift operators: There is no need for a symbolic function name, and parentheses around an argument, when you can simply write it as a double larger- or smaller-than sign. That removes clutter.
This kind of simplification, avoiding information-less elements, results in a consisness that eases reading and comprehension of the program.
And also: What is essential information should be clearly visible. Whitespace[^] was certainly created as a joke, but we may wonder if that was as a reply to languages that demark e.g. what is to be repeated, a loop body, by ... whitespace. OK, the number of (visible) tokens is reduced, but when the consiseness is based on invisible whitespace tokens that has essential semantic importance, then the language designers have gone too far in "consiseness"!
|
|
|
|
|
|
Kirk 10389821 wrote: If I gave you your "perfectly" concise language, without a bunch of caveats, like no libraries, no classes, no protocol support. Would you want to use it? If you had to implement AES, SMTP, HTTP, etc
i never said anything about eliminating libraries, classes, or protocol support.
|
|
|
|
|
johnywhy wrote: Here's some COBOL. Very human understandable. But not concise:
ADD YEARS TO AGE.
MULTIPLY PRICE BY QUANTITY GIVING COST.
SUBTRACT DISCOUNT FROM COST GIVING FINAL-COST.
The boilerplate required in COBOL in order to encapsulate those three lines is going to be around another 300 lines of code, code which is not particularly human-readable
“That which can be asserted without evidence, can be dismissed without evidence.”
― Christopher Hitchens
|
|
|
|
|
I would say you rewrite fails the "Human understandable" test, as because my understanding of your code is quite different than what the original javascript does. I'd assume it was closer to:
var home =
{
get City ()
{
return "Boston"
}
};
Truth,
James
|
|
|
|
|
James Curran wrote: I would say you rewrite fails the "Human understandable" test, as because my understanding of your code is quite different than what the original javascript does.
You're interpreting "human readable" to mean "js-programmer readable". That's not what i mean. My rewrite throws out much js syntax, and can't be interpreted through a js lens. It's a different language.
|
|
|
|
|
|
File this one under Weird...or annoying.
Background
Created a little web app (including dotnet core Web Api) that allows me to read comics more easily. Because, I mean, why not.
I wanted to be able to save the date of the last comic I read to a remote location so I can then load it from any browser (any of my multiple devices) and keep reading the comics consecutively by date. I got it all working and it's a fun little hobby app.
The Problem
I pulled the app up on my TV via Amazon FireStick (runs Amazon Silk browser).
It all loaded up great. Then I attempted to press the button and nothing happened.
<button id="loadComicDatesButton" onclick="getComicDatesFromApi()" >Load Dates</button> onclick Not Supported On Mobile
This is considered a mobile browser and onclick is not supported. You need the touchstart event.
First Attempt to Fix
I looked it up and found documentation. I figured you could just add the ontouchstart="functionName()" to the button.
Nope!
You have to attach the event to the element using javascript.
document.querySelector("#loadComicDatesButton").addEventListener("touchstart",getComicDatesFromApi); I guess that is because the <button> element doesn't know about ontouchstart or something??
Other devs have probably figured this out and said this 1 million times before. But, it is still weird.
modified 11-May-20 15:30pm.
|
|
|
|
|
I thought browsers were supposed to fire the mouse events as well as the touch events for single-finger activation gestures?
Touch Events - Level 2[^]
Even Amazon's own documentation say they do:
Touch - Amazon Silk[^]
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Interesting. That's what I had expected too.
But, until I added the explicit touchstart event I was getting nothing. I even tested it with a simple alert(). And, once I added it, it started working. So documentation may say something, but we all know the _real documentation_ is the code.
Thanks for finding those though because i couldn't find those docs. I will read them more closely.
|
|
|
|
|
Closing the loop on this...
That second link explains that the onclick event should fire and it is correct.
I created another barebones HTML page and added a button with an onclick event and tried it from my Amazon Kindle fire pad (running Silk browser) and it worked with no problem.
Hmmm...maybe I had a syntax error on my original HTML and it pre-cluded the touch event from firing properly while a normal desktop browser handled it??
Well, thanks again for your help.
|
|
|
|
|
The "inconsistency" of what events are supported in the HTML vs. events that can only be wired up with addEventListener is basically why I always use addEventListener. Besides the fact that I rather despise the whole "on[event]="someFunctionCall()" in the HTML. Makes it a PITA to figure out where to change the handler, and I also use a "UI event router" for these things so they can be handled by actual object instances, logged, etc.
Yes yes, I know, you're doing a fun web app.
|
|
|
|
|
Marc Clifton wrote: basically why I always use addEventListener. Besides the fact that I rather despise the whole "on[event]="someFunctionCall()" in the HTML.
I like that you made those points. I will keep that in mind.
Yours is a much better Separation of Concerns anyways. I believe the lesson I've just learned (new convention for me) is that it is better to wire up events in the JS itself due to your point and the point that mine didn't work very well.
Thanks again.
|
|
|
|
|
EDIT - NOTE: someone pointed out that I said 5.51 billion but I actually generated 551 Billion random numbers.
Yesterday, I was thinking about the JavaScript Math.random() function.
The Math.random() function returns a floating-point, pseudo-random number in the range 0 to less than 1 (inclusive of 0, but not 1) with approximately uniform distribution over that range
I had a script that I uses Math.random() to generate values in range of 1 - 10 (inclusive).
I basically ignored the fact that you could ever get zero. Then something happened and I started wondering why I never seemed to hit the 0 value.
Generate As Many Random Values As Possible
So I decided to write a script and let it just generate random values and run a long while to see if I'd ever actually get 0.
I let the following script run (via NodeJS) for something like 5 or 6 hours and it never generated a value of 0. I finally just killed the script.
var counter = 1;
var MaxLoops = Number.MAX_VALUE;
function runForZero(){
console.log("running...");
for (var x=1;x<=MaxLoops;x++)
{
var rnd = Math.random();
if (rnd === 0)
{
console.log("rnd is " + rnd + " It took " + counter + " tries.");
return;
}
if (counter % 5000000 == 0){
console.log(new Date().toTimeString() + " - Still running : " + counter);
}
counter++;
}
console.log("Complete.");
}
After Reading a Few Thoughts, I Understand, but....
I read this javascript - Can Math.random() exactly equal .5 - Stack Overflow[^] which really exposes the idea that probabilistically (is that a real word? ) you will never hit a specific value.
That SO will also lead you to other readings like : How does JavaScript’s Math.random() generate random numbers? | Hacker Noon[^]
Since 0 is a specific value, it is unlikely that you will ever see that value.
Here's The Thought I Had To Get To For Understanding
Basically think about if you stuck your hand into a bin of numbers which contained from 0 to 1.7976931348623157e+308 (largest Number in JavaScript)*. How likely would it be that you get 0? Or, how many times would you have to stick your hand into the bin to randomly grab the 0? Lots.
But, at some point you must see that value, but you may wait a long time (hundreds of years or something?)
Or it could happen with the first Math.random() call you make.
I think this is an interesting thought experiment, because it will make you think.
*It is some number similar to this for the number of decimal values 0 <= N < 1 (dependent upon Number data type size and precision).
modified 19-Apr-20 21:51pm.
|
|
|
|
|
Quick thumbnail calculation:
Most optimistic (for this purpose) and very likely case, the PRNG returns one of 2^52 values. It might be more, but that's how many bits are in the mantissa of a JS Number.
2^52 is about 4.5e15. You tried 5.5e9 5.5e11 samples, so your chance of hitting any specific value is on the order of 1e-6 1e-4.
Your observation still is entirely plausible.
If you ran it for, say, 3 years you'd be getting on for likely to hit zero.(P ~ 0.5)
Cheers,
Peter
Software rusts. Simon Stephenson, ca 1994. So does this signature. me, 2012
modified 19-Apr-20 22:41pm.
|
|
|
|
|
You have a slight disagreement with yourself. 551,855,000,000 is not 5.5 billion.
"They have a consciousness, they have a life, they have a soul! Damn you! Let the rabbits wear glasses! Save our brothers! Can I get an amen?"
|
|
|
|
|
Haha, you are right. And it was actually the bigger of the two numbers...
It was 551 billion. I was attempting not to exaggerate in my headline (seriously) and then I put the wrong number down.
|
|
|
|
|
If you toss a coin, how many attempts will it take until it comes up heads?
I'd plump for somewhere between one and infinity (inclusive).
The concept is the same, no matter the size of the pool of possible values.
Regards
Nelviticus
|
|
|
|
|
That's not random enough! You'll need a bigger bit size to get close to say simulating a shuffled deck of cards (52!). I.e. chance that a shuffled deck comes out 'sorted'.
The (linear) size of the universe, in Planck lengths, still isn't enough to even simulate the random shuffles of a card deck (leads to arguments about it being a predictable universe - don't go there .
(Size of a random card deck: Every second re-arrange the deck to a new sequence, every billion years, step 1cm along the equator, every time you pass the Pacific, empty out a 5mL teaspoon, each time the Pacific empties, place an A4 sheet of 80gsm paper on a pile, until it reaches the moon. Visit moon a million times. Almost done. Phew, ... need more Jokers)
|
|
|
|
|
Run the test again, except instead of
if (rnd === 0)
use
if (rnd < 0.000001)
Or some small number. That will give you an idea of how close to zero you're getting.
|
|
|
|
|
BryanFazekas wrote: use
if (rnd < 0.000001)
That could be very interesting. I'll try this later and we'll see what we get.
|
|
|
|
|
I thought about this a bit too.
And, remember, it is randomly grabbing a number out of a "bucket" which is a huge set of numbers.
It is no more likely to choose one that is < 0.000001 than any other range : considering this to be the range of 0 - 0.000001.
The point here is that yes, I will get more hits for this because it is a range and not just a single random value (0) that I'm attempting to get, but it doesn't really indicate much more than that.
Just some thoughts.
|
|
|
|
|
FYI - I tried it your suggestion and ran it 10 million times (only takes about 1 or 2 seconds to run).
We got 7 values < 0.000001 out of 10 million generated random numbers.
running...
rnd is 8.534479201127709e-7 in 2432341 tries - lessThanCounter: 1
rnd is 2.3682786065570838e-7 in 3184756 tries - lessThanCounter: 2
rnd is 9.513474119593468e-7 in 4548719 tries - lessThanCounter: 3
11:54:49 GMT-0400 (EDT) - Still running : 5000000
rnd is 3.635436747195797e-7 in 7235129 tries - lessThanCounter: 4
rnd is 9.258161568492795e-7 in 7321777 tries - lessThanCounter: 5
rnd is 3.1373473086127035e-7 in 7743862 tries - lessThanCounter: 6
rnd is 3.704604489840335e-7 in 8554983 tries - lessThanCounter: 7
Again, it makes sense that because we now used a range of values that the probability of hitting a value is higher and we do get the values. However, again, if we chose any specific value then we'd possibly wait forever for that value to be hit. Or, it could occur the first time.
It definitely gets you thinking.
|
|
|
|
|
Yes, I expect that we can choose any number and get the same result (no hits) as you got for zero.
I had my testing hat on -- I was wondering if the RND function is truly random, or if boundaries get missed? Your results indicate we are getting really low numbers.
Curiosity satisfied!
|
|
|
|
|
I do not know javascript but, if it works similarly to c/c++, there is a potential problem with your program that you need to be aware and I do not think anyone pointed it out yet.
The same documentation you link points out that
"The implementation selects the initial seed to the random number generation algorithm; it cannot be chosen or reset by the user".
and the documentation at <a href="https://tc39.es/ecma262/#sec-math.random">https://tc39.es/ecma262/#sec-math.random</a> states that "Each Math.random function created for distinct realms must produce a distinct sequence of values from successive calls."
Depending on how the sequence of numbers is generated by the underlying (maybe system) function, you might get a fixed (although large) number of different numbers and, when you reach the end of the sequence, it just restarts the same sequence.
If the seed can not be reset or changed like it is mentioned in the documentation, you will never get a specific number if that number is not part of the sequence.
That is the main reason why cautioned c/c++ programmers reseed their random number generation functions every once in a while inside their main program loop.
You can easily test if the sequence is repeating by storing the first, say one thousand, numbers and test each time you get a new number if it matches the first number drawn. After the first number being the same, the next drawn number must equal the second and so on.
If you get the same initial sequence, it is clearly repeating since it is statistically improbable that the same (large) sequence of numbers repeats itself in a true random sequence of numbers.
I already had this problem in the past in c++ and, in one of the tests I made, I got a sequence of just five different numbers on a 32bit platform .
This is probably the reason why in the documentation is suggested to use another random number function for cryptography.
Just one note about your program. Do not use floating point numbers as increment counters in loops. They might not work as expected due to the bit limit of your platform (probably 64 bit).
Imagine your counter is already at 1.2345678911234455445656765345542e+300 and you increment one. If your counter has already reached its maximum resolution, incrementing by one does nothing and you get 1.2345678911234455445656765345542e+300 instead of the expected 1.2345678911234455445656765345543e+300 (which would also be wrong since you do not have 300 digits).
This means that the terminating condition of your loop is never reached and you get an infinite loop.
If you have no choice of data type, check the documentation and use a number close to the resolution limit of that data type. As an example, if the data type has 20 bit resolution for the significant digits then the maximum integer value it can hold is (2e+20)-1 .
Or take the "hands on" approach and make a loop in which you increment a counter and check when the number is the same as the last.
Just my random opinion
|
|
|
|
|