It's going to get even harder as spammers use ChatGPT like tech to write individual spam messages for each person
It's going to get even harder as spammers use ChatGPT like tech to write individual spam messages for each person
No one at google wants spam.
That brings me to something I really want in JS, actual unmutable values. If you use `const x = new SomeClass()`, you cannot reassign it, but you can change fields. The first time I encountered `const`, I thought it did the opposite. It would be cool if you could declare something (object, array) to be an immutable value.
If you really want to introduce new operators, how about operator overloading? For example vector and matrix calculations become a lot clearer and less error-prone with infix operators. It should be technically easy to add them to typescript - rewrite the expression to a function call depending on the types of the operands - but the TS devs refuse to implement this on philosophical grounds unless it is implemented in JS. I guess in JS it would require runtime dispatch, but maybe that is not such a big penalty given that it usually uses a JIT anyway.
Oh, and while we are at it, fix `with`. The JS with statement is ridiculous and deprecated anyway. It makes all fields of an object available in it's scope. Contrast with VB6's `with`, which requires you to use a leading dot and is much more readable:
with (elem.style) {
.fontFamily = 'Arial';
.color = 'red';
console.log(.borderWidth);
// in actual JS this would just be
// console.log(borderWidth);
}That sounds like a fundamental mis-understanding. Variables do not hold objects, they hold references to objects.
const foo = {};
let bar = foo;
foo and bar hold references to the same object. They do not hold the object themselves. foo's reference can not be changed. It's const. bar's reference can. But the object is independent of both variables.If you want the object itself to be unmodifiable there's Object.freeze.
const foo ...
makes foo const. If you wanted a shortcut for making the object constant (vs Object.freeze) it would be something like let foo = new const SomeObject()
This doesn't exist but it makes more sense than believing that `const foo` some how makes the object constant. It only makes foo constant (the reference).> But there are reasons why we encounter deeply nested expressions in each other’s code all the time in the real world, rather than lines of temporary variables.
And the reason it gives is:
> It is often simply too tedious and wordy to write code with a long sequence of temporary, single-use variables.
Sorry, but...that's the job? If naming things is too hard and tedious, you don't have to do it, I guess, but you've chosen a path of programming where you don't care about readability and maintainability of the codebase into the future. I don't think the pipe operator magically rescues the readability of code of this nature.
The tedium of coming up with a name is a forcing function for the author's brain to think about what this thing really represents. It clarifies for future readers what to expect this data to be. It lets your brain forget about the implementation of the logic that came up with the variable, so as you continue reading through the rest of the code your brain has a placeholder for the idea of "the envVar string" and can reason about how to treat it.
The proposal continues:
> If naming is one of the most difficult tasks in programming, then programmers will inevitably avoid naming variables when they perceive their benefit to be relatively small.
Programmers who perceive the benefit of naming variables to be relatively small need to be taught the value of a good name, and the danger of not having a good name, not given a new bit of syntax to help them avoid the naming process altogether.
The aphorism "There are two hard problems in computer science: cache invalidation, and naming things." is not an argument to never cache and never name things. That's mostly what we software folks spend our time doing, in one way or another.
let field = ve.instanceContext.replace(/(#\/)|(#)/ig, "").replace(/\//g, ".")
Which you apparently claim should be const fieldWithHashMarksUnesacped = ve.instanceContext.replace(/(#\/)|(#)/ig, "");
const field = fieldWithHashMarksUnesacped.replace(/\//g, ".")
https://github.com/mirusresearch/firehoser/blob/46e4b0cab9a2...and this
return moment(input).utc().format('YYYY-MM-DD HH:mm:ss')
Which apparently you believe should be const inputAsMoment = moment(input);
const inputConvertedToUTC = inputAsMoment.utc()
return inputConvertedToUTC.format('YYYY-MM-DD HH:mm:ss')personally i detest pointfree syntax. having intermediate values makes it much easier to step through code with a debugger & see what is happening. and it gives the reader some name for what the thing is, which is incredibly useful context. the enablement of pointsfree styles is one of my main concerns about potential pipe operator syntaxes: the various syntaxes that have been raised often introduce implicit variables which are passed, and i greatly fear the loss of clarity pointsfree style brings.
maybe there's something beyond the pointsfree vs not debate here that i'm missing, that makes you dislike the refactored example. personally i greatly enjoy the flatness, the step by step production of intermediate values, each of which can be clearly seen, and then assembled in a last final clear step. that is much more legible to me than one complex expression.
(1) named intermediate values are sometimes more readable ... though I have examples where it's very hard to come up with names and not sure it helped
(2) debugging is easier.
For (2) though, this IMO is a problem with the debugger. The debugger should allow stepping by statement/expression instead of only by line (or whatever it's currently doing). If the debugger stopped at each pipe and showed in values (2) would mostly be solved. I used a debugger that worked by statements instead of lines once 34 years ago. Sadly I haven't seen once since. It should be optional though as it's a tradeoff. Stepping through some code can get really tedious if there are lots of steps.
As ASCII they can pass through email and UUNET and clipboards without BASE64 or equivalent. With flexible line breaks they can even be laid out so the monochrome ones look like the image they describe in a text editor.
See the examples at https://en.wikipedia.org/wiki/Netpbm#
As sample example, a binary format could be as simple as
struct Header {
uint32 width;
uint32 height;
}
struct Image {
Header header;
uint8* data;
}
Image* readIMG(const char* filename) {
int fd = open(filename, ...)
Image* image = new Image();
read(fd, &image->header, sizeof(image->header));
size_t size = image->header.width * image->header.height * 4;
image->data = malloc(size);
read(fd, image->data, size);
close(fd);
return image;
}
Yea I know, that's not a complete example, endian issues, error checking.Reading a PPM file is only simple if you already have something to read buffered strings and parse numbers etc... And it's slow and large, especially for todays files.
But there are smart people who get all this stuff "easily" (previous practice, exposure). The rest of us walk out of the exam wondering how many trucks hit us.
So
This is what I actually want when I think "const". I don't really care that you can reuse a variable, or re-seat a value. What I care about is that I recieve an object and sometimes want to modify it, and sometimes I want to make sure it stays the same. Maybe somebody else holds a reference and I don't want to surprise them.(The inverse problem is when I have a function that takes something like a string or a number, and I want to change that from within the function. There is no way to pass a value type by reference. You have to encapsulate the value in an object and pass that. It would be cool if you could say something like `function double(ref x) { &x = x*2; }`.)
It could be worse. You could be in python that has no const whatsoever :P
I also agree pass by reference is useful. JavaScript only has pass by value, similar to python.