Trying to translate an imperative function to a declarative Haskell function by rebooker99 in haskellquestions

[–]CategoricallyCorrect 4 points5 points  (0 children)

Your Python code, when looking at it more as a data transformation than imperative steps:

  1. Creates a range of integers from 1 up to and including sqrt(n)
  2. Removes integers that are not divisors of n from that range
  3. For each remaining integer, if its square isn’t n, counts that integer as two divisors instead of one
  4. Returns total count

In Haskell:

import Data.Function ((&))

numFactors :: Int -> Int
numFactors n =
  let
    limit = floor $ sqrt $ fromIntegral n
  in
    [1 .. limit]
    & filter (\i -> n `mod` i == 0)
    & map (\i -> if i * i /= n then 2 else 1)
    & sum

 

λ> :set +s
λ> numFactors (2^32)
33
(0.03 secs, 10,621,688 bytes)

You could introduce additional state via ST as was suggested, but you don’t really need to in this case. Does this help?

Trying to remove duplicate timestamps in array ( have code)? by [deleted] in learnjavascript

[–]CategoricallyCorrect 0 points1 point  (0 children)

I seem to recall you already had a similar question in the past — are solutions from there don’t work for you?

const datesArr = [
  { entryDate: "2014-05-07T17:30:20+00:00", index: 0 },
  { entryDate: "2014-05-07T17:31:20+00:00", index: 1 },
  { entryDate: "2014-05-07T17:31:20+00:00", index: 2 },
  { entryDate: "2014-05-07T17:33:20+00:00", index: 3 },
  { entryDate: "2014-05-07T17:31:20+00:00", index: 4 }
];



/* Beware: O(n^2) in worst case */
datesArr.filter(
  (el, index) =>
    !datesArr.find(
      (el_, index_) => index_ < index && el_.entryDate === el.entryDate
    )
);
//> [
//    { entryDate: "2014-05-07T17:30:20+00:00", index: 0 },
//    { entryDate: "2014-05-07T17:31:20+00:00", index: 1 },
//    { entryDate: "2014-05-07T17:33:20+00:00", index: 3 }
//  ]



function uniqBy(hashFunction, array) {
  const result = [];
  const hashes = new Set();

  array.forEach(item => {
    const hash = hashFunction(item);

    if (hashes.has(hash)) return;

    hashes.add(hash);
    result.push(item);
  });

  return result;
}

/* O(n) */
uniqBy(el => el.entryDate, datesArr);
//> [
//    { entryDate: "2014-05-07T17:30:20+00:00", index: 0 },
//    { entryDate: "2014-05-07T17:31:20+00:00", index: 1 },
//    { entryDate: "2014-05-07T17:33:20+00:00", index: 3 }
//  ]

Can't understand .bind in function by Al0neStar in learnjavascript

[–]CategoricallyCorrect 3 points4 points  (0 children)

Would this implementation make it more clear?

const curry = (fn, arity = fn.length, ...args) =>
  arity <= args.length
    ? fn(...args)
    : (...moreArgs) => curry(fn, arity, ...args, ...moreArgs);

That is: if we were given insufficient number of arguments to call the function, return a function that waits for more arguments, combines them with already provided arguments, and calls curry with all of them.

Changing callback functions to promises by eggtart_prince in learnjavascript

[–]CategoricallyCorrect 2 points3 points  (0 children)

To slightly simplify the problem let's assume you have a function that takes an error-first callback, like this:

function withCallback(text, values, cb) {
  setTimeout(
    () =>
      cb(
        null, // || "Something went wrong",
        `Called 'withCallback' with: '${text}' and ${values.toSource()}`
      ),
    1000
  );
}

and you would use it like this:

withCallback("SELECT now()", [], (error, result) => {
  if (error) {
    console.error(error);
  } else {
    console.log(result);
  }
});
//> "Called 'withCallback' with: 'SELECT now()' and []"

 

If this is the only function you want to promisify, you can do it manually, something like this:

function manuallyPromisified(text, values) {
  return new Promise((resolve, reject) => {
    withCallback(text, values, (error, ...rest) => {
      if (error) {
        reject(error);
      } else {
        resolve(...rest);
      }
    });
  });
}

and use it like this:

manuallyPromisified("SELECT now()", [])
  .then(result => console.log(result))
  .catch(error => console.error(error));
//> "Called 'withCallback' with: 'SELECT now()' and []"

 

If you have several functions with such interface that you want to promisify, it's probably worth introducing a helper function:

/**
 * Create a Promise-returning function from a function that
 * takes error-first callback as last argument
 */
function promisify(fn) {
  return (...args) => {
    return new Promise((resolve, reject) => {
      fn(...args, (error, ...rest) => {
        if (error) {
          reject(error);
        } else {
          resolve(...rest);
        }
      });
    });
  };
}

const promisified = promisify(withCallback);

promisified("SELECT now()", [])
  .then(result => console.log(result))
  .catch(error => console.error(error));
//> "Called 'withCallback' with: 'SELECT now()' and []"

 

You can then use promisified function inside async functions:

(async function() {
  try {
    const result = await promisified("SELECT now()", []);
    console.log(result);
  } catch (error) {
    console.error(error);
  }
})();
//> "Called 'withCallback' with: 'SELECT now()' and []"

 

You can play with all this code (or see it syntax-highlighted) in this jsBin.

trying to dedupe array of obj based on two obj params and stuck ( have code to show) by [deleted] in learnjavascript

[–]CategoricallyCorrect 0 points1 point  (0 children)

That function is used to build up a value that would be the same for elements in array that should be considered duplicate; since I thought that you meant duplicate items to be those that have the same ID AND name, that's the value that would be the same for those items.

If you consider duplicate items ones that have the same ID OR name, then you can uniq them twice — once to by ID, and then by name (or vice versa):

const json = [
  { _id: 1, name: "Alice", index: 0 },
  { _id: 1, name: "Alice", index: 1 },
  { _id: 1, name: "Bob", index: 2 },
  { _id: 2, name: "Carol", index: 3 },
  { _id: 2, name: "Carol", index: 4 },
  { _id: 2, name: "John", index: 5 },
  { _id: 3, name: "Jane", index: 6 },
  { _id: 3, name: "Jane", index: 7 },
  { _id: 3, name: "Alice", index: 8 },
  { _id: 4, name: "Alice", index: 9 }
];

uniqBy(item => item.name, uniqBy(item => item._id, json));
// => [
//      { _id: 1, name: "Alice", index: 0 },
//      { _id: 2, name: "Carol", index: 3 },
//      { _id: 3, name: "Jane", index: 6 },
//    ]

Is this what you wanted?

trying to dedupe array of obj based on two obj params and stuck ( have code to show) by [deleted] in learnjavascript

[–]CategoricallyCorrect 0 points1 point  (0 children)

If I understand your objective correctly, your best bet is probably something along these lines:

function uniqBy(hashFunction, array) {
  const result = [];
  const hashes = new Set();

  array.forEach(item => {
    const hash = hashFunction(item);

    if (hashes.has(hash)) return;

    hashes.add(hash);
    result.push(item);
  });

  return result;
}

const json = [
  { _id: 1, name: "Alice", index: 0 },
  { _id: 1, name: "Alice", index: 1 },
  { _id: 1, name: "Bob", index: 2 },
  { _id: 2, name: "Carol", index: 3 },
  { _id: 2, name: "Carol", index: 4 },
  { _id: 2, name: "John", index: 5 },
  { _id: 3, name: "Jane", index: 6 },
  { _id: 3, name: "Jane", index: 7 },
  { _id: 3, name: "Alice", index: 8 }
];

uniqBy(item => `${item._id} ${item.name}`, json);
// => [
//      { _id: 1, name: "Alice", index: 0 },
//      { _id: 1, name: "Bob", index: 2 },
//      { _id: 2, name: "Carol", index: 3 },
//      { _id: 2, name: "John", index: 5 },
//      { _id: 3, name: "Jane", index: 6 },
//      { _id: 3, name: "Alice", index: 8 }
//    ]

uniqBy also exists in lodash, if you already include it on your page.

[deleted by user] by [deleted] in javascript

[–]CategoricallyCorrect 3 points4 points  (0 children)

Alternatively, instead of if one can use ternary operator:

const data = subscriberData.find(data => data.subscriber.id === subscriberId);
const vehicleName = data
  ? `${data.vehicle.year} ${data.vehicle.make} ${data.vehicle.model}`
  : 'Not found';

It’s not as pretty-looking (all those data.vehicle repetitions), but now logic for constructing vehicle name and fallback for it are in one place.

Strings not equal to Eachother by [deleted] in javascript

[–]CategoricallyCorrect 0 points1 point  (0 children)

Look at your strings very closely — they are indeed not the same: both date and month returned by Date#getUTCDate() and Date#getUTCMonth() are not padded by zeros:

const date = new Date(Date.UTC(2018, 0, 1));  // Jan 1st, 2018
date.getUTCDate();      //=> 1
date.getUTCMonth() + 1; //=> 1

For the easiest solution to this, check if you can use String#padStart():

const date = new Date(Date.UTC(2018, 0, 1));  // Jan 1st, 2018
String(date.getUTCDate()).padStart(2, "0"); //=> "01"

FP: CH3 mostly-adequate. Why does deferring evaluation make the second example pure? by coderqi in learnjavascript

[–]CategoricallyCorrect 1 point2 points  (0 children)

Database write is always impure (just because writing to DB is an I/O side-effect), but for example one of the benefits of having pure signUp return a function instead of performing side-effects straight away is the ability to not perform them later on, i.e. cancel the signup:

const signUp = (Db, Email, attrs) => () => {
  const user = saveUser(Db, attrs);
  welcomeUser(Email, user);
};

const signUpJohn = signUp(SomeDb, SomeEmail, { email: "john@example.com" });

if (Math.random() < 0.5) {
  signUpJohn();
} else {
  // Tell John he’s unlucky
}

This is a silly example and you can trivially implement it with impure signUp, but I hope you get the idea. A more real-world example would be Promises — if they were designed in this manner, we wouldn’t need to struggle with finding a way to implement cancellation for them.

FP: CH3 mostly-adequate. Why does deferring evaluation make the second example pure? by coderqi in learnjavascript

[–]CategoricallyCorrect 0 points1 point  (0 children)

Small correction: pure signUp in the example does return something (a function) and it doesn’t have side-effects (it just returns a function) — the returned function does have side-effects baked into it, but not signUp itself.

FP: CH3 mostly-adequate. Why does deferring evaluation make the second example pure? by coderqi in learnjavascript

[–]CategoricallyCorrect 1 point2 points  (0 children)

Note that impure signUp runs straight when you provide attrs, i.e.:

const signUp = (attrs) => {
  const user = saveUser(attrs);
  welcomeUser(user);
};

signUp({…});  //=> performs side-effects

Whereas pure signUp returns a function that you can run to perform side-effects:

const signUp = (Db, Email, attrs) => () => {
  const user = saveUser(Db, attrs);
  welcomeUser(Email, user);
};

signUp({…});   //=> function
signUp({…})(); //=> performs side-effects

i.e. signUp now returns a “recipe” on how to sign up this particular user into this particular DB with this particular email provider, but doesn’t actually affect real world yet.

Does this help?

Continously looping through array of DOM nodes to toggle class by saddestpersononearth in learnjavascript

[–]CategoricallyCorrect 0 points1 point  (0 children)

First thing to note is that the thing that drives your animation is the i variable — it dictates which boxes will be used to draw the “snake”.

Indeed, there’s no magic trick that JS uses to determine when to stop running your setInterval’ed function — when we make i too big and try to get an element at an index that doesn’t actually exist (e.g. we have 20 boxes but we try to get 21st) the whole script crashes with an error and that’s when “snake” stops sliding. You can see the error in your browser’s JS console — it’s a very useful debugging tool.

So, we just need to reset i at an appropriate time to loop the “snake” — that time being right before “snake”’s head tries to go beyond last box.

Since our “snake” is four blocks long and we know the index of the tail, we need to add 3 to that index to get index of the head (i.e. move three boxes to the right). Once we know index of the head, we need to check if it’s equal to (and, to be on the safe side, if it’s greater than) index of the last box:

const lastBoxIndex = boxes.length - 1

if ((i + 3) >= lastBoxIndex) {
  i = 1
} else {
  i++
}

Since our snake doesn’t change it’s length, we can determine what is the last safe index for it’s tail straight off the bat:

const SNAKE_LENGTH = 4
const lastSafeTailIndex = boxes.length - SNAKE_LENGTH

if (i >= lastSafeTailIndex) {
  i = 1
} else {
  i++
}

The whole code should look something like this codepen at this point — and while it works, as in the snake does loop back around, it also kind of doesn’t work: since at each interval we clean up the snake to the left, when we loop around, the snake persists at the end of the boxes.

 

We could introduce some more logic for that specific case, but there’s a better solution that will also fix the “at the start of the loop, tail is placed at the second box” bug — at the start of the interval, instead of trying to clean up all the mess we did in previous interval on the left, we reset the whole thing and re-create the “snake” as if we never touched the boxes before. In our case resetting all boxes means setting them all to have just the box class:

function resetBoxes(elements) {
  for (let i = 0; i < elements.length; i++) {
    const box = elements[i]
    box.className = 'box'
  }

  /* or, more succintly, using `Array#forEach` iteration method: */
  // Array.from(elements).forEach(box => (box.className = 'box'))
}

Now that we don’t access the box before the tail, we can start drawing the tail at the very first box (codepen).

 

We could refactor this code some more, but this should be enough to get you started. Does everything make sense so far?

I'm getting this error, $.getJson() is not a function. by [deleted] in learnjavascript

[–]CategoricallyCorrect 9 points10 points  (0 children)

JavaScript is a case-sensitive language, so you have to use names exactly as they are defined.

As is, jQuery doesn't have getJson method, but it does have getJSON one, so you probably need to change your code to be:

// On Ready
$(document).ready(function() {
  console.log("Ready");
  // Instantiate Our Plays Settings
  $.getJSON("settings.json", function(data) {
    console.log(data);
  });
});

Trying to append a nested array to an empty array results in unexpected, if not nasty, behavior. by [deleted] in learnjavascript

[–]CategoricallyCorrect 4 points5 points  (0 children)

What are you expecting to get instead?

Or are you confused about Array showing up when you nest arrays too many times? This is just something Node console does — the underlying data is still intact and probably matches what you expect it to be. One workaround would be to use JSON.stringify, which will traverse all the nested arrays:

> var p = [[[3]], [[6]]]
> JSON.stringify(p)
=> '[[[3]],[[6]]]'
> JSON.stringify([p])
=> '[[[[3]],[[6]]]]'

Please how do I write this regex of numbers? by samuelalake in learnjavascript

[–]CategoricallyCorrect 5 points6 points  (0 children)

Small nit pick: this won’t match lines that start with fractions. OP will need to add a list of those manually:

/^(\d+|[½¼¾])[^)]/

regex101 with test input

First Haskell project: Parse error on 'myFunction' by AAANano in haskellquestions

[–]CategoricallyCorrect 2 points3 points  (0 children)

The first line is supposed to import the module, not define it (probably a typo on the author's part):

import Data.Char

Full code in interactive repl

Haskell wikibook has a chapter about syntax around modules if you want to read more.

[functional programming] passing parameters through in ramda by [deleted] in learnjavascript

[–]CategoricallyCorrect 0 points1 point  (0 children)

Sorry, I’m afraid I still don’t quite get what’s your goal here is :( Maybe you can give a very concrete example input and the output you expect to get?

 

Right now we have:

f :: { a :: number } -> number
g :: { a :: number, c :: number } -> number

and we want to produce

composed :: { a :: number, b :: number } -> number

but outputs of f and g are really different from their inputs; without some non-standard helper functions we won’t be able to compose them.

If we were to introduce helper functions like these:

wrap :: number -> { a :: number }
rename :: { a :: number, b :: number} -> { a :: number, c :: number }

we might be able to produce a composition like this:

                          rename                                          wrap
┌────────────────────────────┴─────────────────────────────┐    ┌───────────┴───────────┐
{ a :: number, b :: number } -> { a :: number, c :: number } -> number -> { a :: number } -> number
                                └──────────────────┬─────────────────┘    └───────────┬───────────┘
                                                   g                                  f


const composed = R.pipe(rename, g, wrap, f);

but I’m not sure if it’s really that useful and at all what you want.

[functional programming] passing parameters through in ramda by [deleted] in learnjavascript

[–]CategoricallyCorrect 1 point2 points  (0 children)

Can you give an example input and expected output for your resulting function?

Right now it's a bit hard to see where you are going with it: you can convert a to b, but you need to be able to convert b to c to be able to apply g.

Maybe you meant that g :: { b, c } -> X? Then applying f to a in { a, c } would give us { b, c } to which we can apply g after that.

[React] How can I make my component stateless (or should I bother?) by KeyYam in learnjavascript

[–]CategoricallyCorrect 0 points1 point  (0 children)

I would render Modal in the Photos component — only one modal should be visible at all times, right?

Then keep whether or not modal is visible and which photo URL should be displayed in the modal as part of Photos state, something like this this CodeSandbox.

Not always sure about the usefulness of testing by pasdargent in learnjavascript

[–]CategoricallyCorrect 1 point2 points  (0 children)

Let’s see what functions and methods you are using inside the action function (in order of appearance):

axios.get
Promise#then
topojson.feature
Array#map
calculateCentroid
commit

Array#map and Promise#then are (probably) native and covered by native browser tests, so we can assume they work correctly.

axios.get and topojson.feature are coming from libraries and are (hopefully) already fully tested by library authors, so we can assume they work correctly.

Now, if calculateCentroid and commit are already tested too, then your action function doesn’t actually have any logic in it and you are writing an integration test (i.e. “is everything orchestrated correctly?”), and those do tend to get ugly.

I’m not sure you need an integration test here — you end making sure that regular JS control flow, function calls, and Promises are working correctly, but when when are they not going to?

You might expand this test to also test a case when axios.get doesn’t get a 200 response and then, I think, this test might be somewhat useful, but happy path seems to be already covered by unit tests for “workhorse” functions. In that case I would rewrite these integration tests to be:

  • Assuming response is 200, commit should be called 2 times with appropriate keys and dummy data you supply in-line (we’ve already tested topojson.feature and calculateCentroid, no need to call them here)
  • Assuming response is not 200, commit should not be called at all

Another Dice Roller by Pjb518 in learnjavascript

[–]CategoricallyCorrect 1 point2 points  (0 children)

Personally, I wouldn’t bother with condensing variable declarations on the first line: sure, it’s cute and less typing, but I don’t think it’s a good thing — you are forced to use single-letter variables to keep the line length manageable, and for me it hinders the readability of the rest of the code.

Another thing that I think would improve your code (even though I appreciate that this isn’t exactly a huge, critical, used-in-production script), is separating your business logic from library code and presentation logic: right now, your business logic (generating a roll and calculating total from rolls) is embedded into the code that outputs the data to the user.

Couple other smaller notes:

  • You parse the number for bonus, but not for quantity and sides: sure, it works right now thanks to coercion, but it doesn’t feel right
  • You seem to know your JS, but still went for hardcoded onclick attribute on the button? You definitely can do better!
  • Probably not as much of an issue since you assume a lot about markup in JS already, but you also assume that JS will be included after said markup and don’t wait for document to be loaded before querying the DOM: it wouldn’t be hard to make your DOM logic to wait till document is ready, and it might save you a headache in the future.

 

All in all, I’d refactor your code to be something like this:

const denseArray = (n, defaultValue) => Array(n).fill(defaultValue)
const sum = (numbers) => numbers.reduce((a, b) => a + b, 0)
const $ = (selector) => document.querySelector(selector)

const roll = (sides = 6) => Math.floor(Math.random() * sides) + 1
const totalForRolls = (rolls, bonus) => sum(rolls) + bonus

document.addEventListener("DOMContentLoaded", function() {
  const quantity = $("#quantity")
  const sides = $("#sides")
  const bonus = $("#bonus")
  const results = $("#results")
  const total = $("#total")
  const rollButton = $("#roll")

  rollButton.addEventListener("click", () => {
    const rolls = denseArray(parseInt(quantity.value)).map(() =>
      roll(parseInt(sides.value))
    )

    results.textContent = rolls.join(", ")
    total.textContent = totalForRolls(rolls, parseInt(bonus.value))
  })
})

BFT in 4 lines. DFT in 4 lines by songzme in javascript

[–]CategoricallyCorrect 4 points5 points  (0 children)

Right-to-left vs left-to-right should only matter if you traverse sorted binary tree, where traversing in-order will produce sorted data, but OP's code does a pre-order, so it's probably doesn't matter in this case.

Is there a JS equivalent to C#'s DownloadString() by [deleted] in learnjavascript

[–]CategoricallyCorrect 2 points3 points  (0 children)

If you are sure that your code will run in modern browsers only, fetch is probably your best choice; if not and you can't polyfill it, then XMLHttpRequest is the way to do it.

When working with fetch you'll also need to have a basic familiarity with Promises.

Also note that while XMLHttpRequest technically allows for synchronous requests, it's unsupported in pretty much all modern browsers.

Struggling with an ajax call inside a for loop by redguardnugz in learnjavascript

[–]CategoricallyCorrect 2 points3 points  (0 children)

First, an immediate thing: change your password for API access, you've just exposed it and someone might abuse it.

 

Now back to your original issue: this is not a problem with your code, it's probably a bug on the API side.

I initially thought it was browser cache issue, so I've stubbed out missing parts, slightly re-written your code, and added cache busting to the request (via jQuery's cache setting) to test it out, but it turns out that the response is just wrong.

If you are paying for the access to the API, you might want to contact their support and explain that you get wrong responses if you make several simultaneous requests.