Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
GeorgieMordor
Jan 23, 2015

Nolgthorn posted:

https://www.codewars.com/

Is my favourite practice website, it proposes you a (often very) simple challenge. You solve it and then it compares you to everyone else's solution, you can vote up and down other people's solutions it's a little like a social network about code. I've found interviewers are happy when I mention it.

I'm liking this a lot -- thanks for the suggestion. The solution review and comparison is a really great way to learn.

Adbot
ADBOT LOVES YOU

geeves
Sep 16, 2004

GeorgieMordor posted:

I'm liking this a lot -- thanks for the suggestion. The solution review and comparison is a really great way to learn.

I've learned a lot from the comparison section. It was really helpful when learning more about ES6+ and Java 8

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



Hah, they want you to pay them to see your upvotes now.

Sab669
Sep 24, 2009

Friday, fighting off a cold and just staring at this function for like an hour wondering why the gently caress it isn't working when my array has a single empty string in it:

JavaScript code:
function SubstituteTotalValues(controlArray)
{
	//If all elements are empty, do nothing
    if (controlArray.every((val, i, controlArray) => val === "" ))
        return controlArray;

	//Replace empty strings, dashes and values > 7 with a 1
    for (var i = 0; i < controlArray.length; i++)
    {
        if (isNaN(controlArray[i]) || controlArray[i] > 7 || controlArray[i] == "-")
            controlArray[i] = 1;
    }

    return controlArray;
}
The number of times I get burned by isNaN(someEmptyString) returning false is too drat high :sigh:

Edit: Actually I am in fact confused now?

http://jsfiddle.net/2na5wvbh/

Works exactly how I expect it to. But when I debug my application:



Element 3 doesn't have its empty value replaced? Debugging it, it does step into controlArray[i] = 1; but...?


Double Edit: OK it does actual work, but the Watch window is lovely and doesn't reflect this. If I mouse over controlArray in the actual code window I can see these values get updated.

Sab669 fucked around with this message at 21:36 on Jan 18, 2019

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

roomforthetuna posted:

Aha, I found a sort-of answer to my question, which is that evidently webpack is doing something a bit different from the way package.json people think you'll be building stuff. As such, having
code:
"baseUrl": "path/to/your/dependencies"
in your tsconfig.json allows a webpack set up with ts-loader to do its thing without any package.json in the dependencies nor any intermediate js files being generated nor any references to the dependencies in the node_modules of the topmost package.
A followup to this tale of woe, I debugged the tsloader package with some log statements to try to figure out why some packages from my baseUrl would load and others would not.
I didn't ever quite resolve why some packages would would, but I found the reason for the failure is that "baseUrl": "C:/herp/derp" in tsconfig.json gets transformed by the loader module into "C:/herp/derp/C:/herp/derp" by going through code that says if (!path.Absolute(yourPath)) then append it to current working directory.
If you instead (or additionally) put it in webpack.config like
code:
  resolve: {
    plugins: [new TsConfigPathsPlugin({configFile: 'tsconfig.json', baseUrl: 'C:/herp/derp'})],
  },
then it gets passed through through path.resolve instead of path.isAbsolute, which doesn't do the self-appending thing, so everything works (at a slightly annoying cost of having to specify baseUrl in two places instead of one.)

Dominoes
Sep 20, 2007

Hey dudes. What's the best way to refresh data from a server every 30 seconds or so? So points to using setInterval, but the answers are mainly from 2010, so not sure if its' still the best way. Eg call a fetch functino from setInterval. Don't think I need websockets for this.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Dominoes posted:

Hey dudes. What's the best way to refresh data from a server every 30 seconds or so? So points to using setInterval, but the answers are mainly from 2010, so not sure if its' still the best way. Eg call a fetch functino from setInterval. Don't think I need websockets for this.
setInterval is still alright, though there's a small risk of weirdness if a request takes over 30 seconds for some reason. Do you actually want a request every 30 seconds, or do you want, say, 30 seconds after the previous request completing? I generally prefer the latter, so I do it with a setTimeout to send the request again at the end of the response-handler (and error-handler) rather than setInterval, which protects against the small risk of ending up with two or more requests in flight at once.

spiritual bypass
Feb 19, 2008

Grimey Drawer
That ought to cover the purely technical answer for the face-value interpretation, but do you mind describing the use case a little more?

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
I needed to run code on a schedule, for example at the top of every hour and I opted to use setTimeout instead. Calculating the time until the top of the hour and calculating again after I finished doing whatever I was doing. But if I didn't care, I can't imagine what's wrong with setInterval as long as you account for possible timeouts.

spiritual bypass
Feb 19, 2008

Grimey Drawer
Ah, ok. I was thinking that if the true update needs were indeterminate, it might do better with a websocket instead of xhr polling, but it sounds like that's not the case.

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
Don't get me wrong I love websockets. Websockets are the best thing ever and as soon as I have an excuse I'll use them. Like for example if the server ever needs to tell me anything. I'd take websockets over polling for sure.

The thing that's hard about them is maintaining the connection, detecting a lost connection, and managing requests that involve a response.

So a wrapper something like https://www.npmjs.com/package/passage-rpc

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
Disclaimer: I wrote that ages ago. Nobody is downloading it. :( It works perfectly.

Volguus
Mar 3, 2009

Nolgthorn posted:

Disclaimer: I wrote that ages ago. Nobody is downloading it. :( It works perfectly.

Most (all?) websocket libraries that I've worked with in various languages had the concept of a "ping interval". That is, the library itself would keep the socket open by pinging the server at a set interval. Never had to worry about sockets being closed for no reason . Of course, the socket can be closed for a variety of reasons, but the libraries do let you know via their listeners.

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
The main focus of the library is RPC rather than maintaining connection, it's for client side apps especially single page apps that forego http entirely, I guess that isn't really popular yet. Maybe it's time I updated it and better the documentation.

Nolgthorn fucked around with this message at 17:00 on Jan 21, 2019

Rahu
Feb 14, 2009


let me just check my figures real quick here
Grimey Drawer
I have a typescript/express question, hope this is the right thread for it.

I recently wrote a pretty simple site in typescript to learn about express and server-side javascript development in general.

My problem is that I created a middleware function that attaches some basic information about the currently logged in user to res.locals. Because res.locals has type 'any' all of its properties have type 'any' as well. This means that later when a request is being handled, when I reference the login status object, its type is 'any'.

My question is, is there some way I can add an object to res.locals (or the request or response objects in general) and keep the typescript compiler aware of its type? I've defined an interface named LoginStatus that describes the properties of this object.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Rahu posted:

My question is, is there some way I can add an object to res.locals (or the request or response objects in general) and keep the typescript compiler aware of its type? I've defined an interface named LoginStatus that describes the properties of this object.
I think the closest thing to what you're asking for is you could make an interface that 'extends' the request/response interface/class with an override of the locals type.
Just tried this in the typescript playground and it seems to work:
code:
interface LoginStatus {
    whatever: string;
}
interface LoginStatusResponse extends Response {
    locals: { loginStatus: LoginStatus };
}

type LoginResponseHandler = (res: Response) => void;

const x: LoginResponseHandler = (res: LoginStatusResponse) => {
    // Do whatever
}
Edit: (Not sure if the Response type that exists in the playground matches the type you're working with, but I tried extending over an existing member of a different interface or class type and it was accepted just fine.)

Rahu
Feb 14, 2009


let me just check my figures real quick here
Grimey Drawer
That seems to work, thanks :)

Dominoes
Sep 20, 2007

roomforthetuna posted:

setInterval is still alright, though there's a small risk of weirdness if a request takes over 30 seconds for some reason. Do you actually want a request every 30 seconds, or do you want, say, 30 seconds after the previous request completing? I generally prefer the latter, so I do it with a setTimeout to send the request again at the end of the response-handler (and error-handler) rather than setInterval, which protects against the small risk of ending up with two or more requests in flight at once.

rt4 posted:

That ought to cover the purely technical answer for the face-value interpretation, but do you mind describing the use case a little more?
Appreciate it. Got it working using this. I have a digital scheduling board, where one screen will be up displaying it read-only, and want it to auto-refresh when someone edits it on a different computer. If it needs to be faster-updating, will probably attempt WS.

Dominoes
Sep 20, 2007

Another one: Is there an elegant way to dedupe an array of tuples? This approach doesn't seem to work, nor does Lodash's uniq. Array.includes doesn't seem to help either.
JavaScript code:
const a = [[1, 2], [2, 3], [1, 2]]
[...new Set(a)]
This appears to do it, but it's odd Set doesn't work this way:
JavaScript code:
export function dedupeTuple(vals: [any, any][]): [any, any][] {
    let result = [], exists
    for (let v of vals) {
        exists = false
        for (let v2 of result) {
            if (v[0] === v2[0] && v[1] === v2[1]) {
                exists = true
                break
            }
        }
            if (!exists) {
                result.push(v)
            }
    }
    return result
}

Dominoes fucked around with this message at 00:52 on Jan 22, 2019

necrotic
Aug 2, 2005
I owe my brother big time for this!
A Set is going to compare the object identity, not the content of the arrays. If you do:

code:
const z = [1, 2];
const y = [2, 3];
const a = [z, y, z];
[...new Set(a)]; // this works now

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Dominoes posted:

Another one: Is there an elegant way to dedupe an array of tuples?
Not super elegant, but something like
code:
function tupleEquals(a, b) {return a[0]===b[0] && a[1]===b[1];}
a = a.filter((v1, i) => a.findIndex((v2) => tupleEquals(v1, v2)) !== i);
This is O(n^2) - you could bring that down if your data is large by first sorting by tuple-contents and then doing filter comparisons only between adjacent elements, but much like this it'll still be DIY sort functions and comparisons, and will still suck.

And if you want to make it generic you're going to be doing something even worse like transforming your tuples into JSON strings, then you can put *those* into a set to remove duplicates and then de-JSON the elements of the set afterwards.

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
code:
const a = [[1, 2], [2, 3], [1, 2]];
Oooh a coding challenge.

code:
function findUniqueIndexes(arr) {
    const indexes = [];
    for (let i = 0; i < arr.length; i++) {
        if (arr.indexOf(arr[i]) === i) indexes.push(i);
    }
    return indexes;
}

function dedupeTuples(tuples) {
    const arr = tuples.map(tuple => tuple.join(','));
    const indexes = findUniqueIndexes(arr);

    return indexes.map(index => tuples[index]);
}

dedupeTuples(a);

Osmosisch
Sep 9, 2007

I shall make everyone look like me! Then when they trick each other, they will say "oh that Coyote, he is the smartest one, he can even trick the great Coyote."



Grimey Drawer
I think you're looking for uniqWith? The _.isEqual example should work.

e: if I was writing it myself I'd probably base it on an object with hashed indices, like so:

code:
function hash(val) {
  return val.join(','); 
}

function dedupeTuple(arr) {
  var itemsByHash = _.reduce(arr, (accum, item) => {
    accum[hash(item)] = item;
    return accum;
  }, {});
  return _.values(itemsByHash);
}
You can make the accum write conditional but I can't think of a reason reason to.

Osmosisch fucked around with this message at 12:19 on Jan 22, 2019

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
I don't use reduce very often but if you prefer.

code:
const compareTuple = t1 => t2 =>
    t1[0] === t2[0] && t1[1] === t2[1];

function dedupeTuples(tuples) {
    return tuples.reduce((acc, cur, idx) => {
        if (tuples.findIndex(compareTuple(cur)) === idx) acc.push(cur)
        return acc;
    }, []);
}

dedupeTuples(a);
or filter like tuna said.

code:
const compareTuple = t1 => t2 =>
    t1[0] === t2[0] && t1[1] === t2[1];

function dedupeTuples(tuples) {
    return tuples.filter((tuple, i) => tuples.findIndex(compareTuple(tuple)) === i);
}

dedupeTuples(a);
Imo it gets harder to read the smaller you go. I dunno what runs the fastest.

Nolgthorn fucked around with this message at 12:20 on Jan 22, 2019

Blinkz0rz
May 27, 2001

MY CONTEMPT FOR MY OWN EMPLOYEES IS ONLY MATCHED BY MY LOVE FOR TOM BRADY'S SWEATY MAGA BALLS
code:
tuples.reduce((acc, cur) => {
  const key = curr.join(',');
  if (!key in acc) {
    acc[key] = curr;
  }
}, {}).values();
Untested but should work. You can sort the tuple before it's joined if you want reversed tuples to be considered equal.

Not sure what the performance implications of joining every tuple in the array is but doing key lookup should be faster than array indexing.

Blinkz0rz fucked around with this message at 14:34 on Jan 22, 2019

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
That would also work without the if statement.

Blinkz0rz
May 27, 2001

MY CONTEMPT FOR MY OWN EMPLOYEES IS ONLY MATCHED BY MY LOVE FOR TOM BRADY'S SWEATY MAGA BALLS

Nolgthorn posted:

That would also work without the if statement.

:doh:

Osmosisch
Sep 9, 2007

I shall make everyone look like me! Then when they trick each other, they will say "oh that Coyote, he is the smartest one, he can even trick the great Coyote."



Grimey Drawer
Yeah, that's the same solution as I posted a bit upthread, though I lean on lodash (I prefer to let one library handle all the browser compatibility stuff vs. shim/transpile).

e: I did some jsbenching, looks like for 10k elements the hash version is about 100x faster, with the native reduce and Object.values() faster than lodash's version.

https://jsbench.me/7qjr7x9o5c/1

The if statement does not appear to have significant impact.

Osmosisch fucked around with this message at 16:37 on Jan 22, 2019

Dominoes
Sep 20, 2007

Love the variety. Esp like the reduce approach.

Roadie
Jun 30, 2013

Dominoes posted:

Another one: Is there an elegant way to dedupe an array of tuples? This approach doesn't seem to work, nor does Lodash's uniq. Array.includes doesn't seem to help either.
JavaScript code:
const a = [[1, 2], [2, 3], [1, 2]]

Don't forget the true galaxy brain approach:
JavaScript code:
[...new Set(a.map(JSON.stringify))].map(JSON.parse)

Roadie fucked around with this message at 08:00 on Jan 23, 2019

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
Is jsperf broken or something, yesterday it told me using lodash was fastest too.

Osmosisch
Sep 9, 2007

I shall make everyone look like me! Then when they trick each other, they will say "oh that Coyote, he is the smartest one, he can even trick the great Coyote."



Grimey Drawer

Nolgthorn posted:

Is jsperf broken or something, yesterday it told me using lodash was fastest too.



There's a bunch of variance there since all the benchmarks are running in your browser. So for example if you (or some background process) are doing poo poo in another tab during one of the tests it will gently caress with the results. Or a garbage collection is triggered, or any of tons of other possibilities.

e: added the galaxy brain solution, it's on my machine about 25% below hashbased which is not surprising given that JSON.parse isn't exactly a free operation.

Osmosisch fucked around with this message at 11:58 on Jan 23, 2019

Happy Thread
Jul 10, 2005

by Fluffdaddy
Plaster Town Cop

Roadie posted:

Don't forget the true galaxy brain approach:
JavaScript code:
[...new Set(a.map(JSON.stringify))].map(JSON.parse)

:drat: That's the stuff

Roadie
Jun 30, 2013

Dumb Lowtax posted:

:drat: That's the stuff

Fun fact: It's also dependent on the specific interaction of map and JSON.stringify/parse, so if you swap those for other functions weird poo poo might happen.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Roadie posted:

Fun fact: It's also dependent on the specific interaction of map and JSON.stringify/parse, so if you swap those for other functions weird poo poo might happen.
What? In what way? It's the normal expected way map and the JSON functions work, they're not doing anything specific to the pairing are they?

Like yeah this behavior is specific to a reversible mapping to/from a unique identifier, but if you switched the JSON functions for any other reversible to/from unique value serializer/deserializer the outcome would be the same.

I mean yeah, if you switched them out for other functions like ... parseInt and console.log then weird poo poo would happen, but it's always the case that if you swap out a function for a function that does something different then something different will happen. How is this case special such that you're remarking on it?

Roadie
Jun 30, 2013

roomforthetuna posted:

What? In what way? It's the normal expected way map and the JSON functions work, they're not doing anything specific to the pairing are they?

Like yeah this behavior is specific to a reversible mapping to/from a unique identifier, but if you switched the JSON functions for any other reversible to/from unique value serializer/deserializer the outcome would be the same.

I mean yeah, if you switched them out for other functions like ... parseInt and console.log then weird poo poo would happen, but it's always the case that if you swap out a function for a function that does something different then something different will happen. How is this case special such that you're remarking on it?

Array.map supplies three arguments to its callback, not one. If you use a whateverParsing function that isn't as quick to dump non-matching args as the JSON.x ones are, it'll use those to do...... something.

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
Why explicit straight forward code is better 101.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Roadie posted:

Array.map supplies three arguments to its callback, not one. If you use a whateverParsing function that isn't as quick to dump non-matching args as the JSON.x ones are, it'll use those to do...... something.
The first argument is the useful one though. You don't need a function that discards anything, you just need a function that doesn't take additional arguments.

But you're right that it's dependent on the specific implementation, in that it's technically undefined behavior to use JSON.stringify this way, since its second parameter is documented as a function or an array of filters or null or unset, and array.map will feed it an index which is a number which is none of those things, and its third parameter is documented as as a string or number or null, and array.map will feed it an array in that position.

Kraus
Jan 17, 2008
A while ago, I designed a few exercises to help a friend learn Javascript. Below is one such exercise:

code:

<!DOCTYPE html>
<html>

<head>
	<style>
		.red {
		
			background-color:red;
		
		}

		
		.yellow {
			
			background-color:yellow;
			
		}
	</style>
</head>

<body>

<p class="red" onclick="yellowize(this)">ONE</p>

<p class="red" onclick="yellowize(this)">TWO</p>

<p class="red" onclick="yellowize(this)">THREE</p>

<p id="success" style="display:none">Success</p>


	<script>

		
		//Your goal is to use no more than five statements to complete the following task:
		//When a paragraph is clicked on, two things should happen:
		//1. The clicked on paragraph should change classes so that its background is yellow.
		//2. The function should then check to see if all visible the paragraphs are yellow, 
		//or that none of them are red, and if so, make the final paragraph visible too. 
		// The integer 3 may not appear anywhere in your solution. It must be generalizeable to any number of paragraphs.
		
		
		
		function yellowize(para) {
			
			
				
			
		}

	</script>


</body>

</html>


Now, I gave this to some of my other programmer friends, and we golfed a bit, and we eventually came up with this monstrosity as a one-line solution:

code:

(para.className = "yellow") && document.getElementsByClassName("red").length ? 0 : document.getElementById("success").style.display = "block"; 

However, the other day, someone suggested this as a slightly shorter solution:

code:

(para.className = "yellow") && document.getElementsByClassName("red").length || document.getElementById("success").style.display = "block"; 

For some reason, this simply doesn't work. If you replace the "success" part with something like alert("success"), this works just fine. I, for the life of me, have no idea why Javascript doesn't like the version with the getElementById. Anyone know why?

Adbot
ADBOT LOVES YOU

MrMoo
Sep 14, 2000

That last one looks like a TypeScript shortcut not EcmaScript, I’ve made that mistake.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply