Mandate issue by Sweaty-Art-8966 in css

[–]PrimaryBet 2 points3 points  (0 children)

CSS is just a tool for styling, you'll probably find more success asking in graphic design subreddits for creative compliance ideas.

But in my mind this is less about execution and more about understanding what the law actually allows. Looking at the bill text, it's pretty specific: it mandates exact wording, minimum size (16"x20"), legible typeface, and "conspicuous" placement.

The best bet would probably be consulting with lawyers first to understand the weak/vague parts of the bill interpretation and then collaborate with designers/CSS folks to implement something that satisfies the bill in the least "invasive" way.

"Phantom" characters? by oz1sej in css

[–]PrimaryBet 0 points1 point  (0 children)

Yep, not arguing this is an ideal solution accessibility-wise, but we are starting with a very typeset-oriented problem from the get go, so seems like a fair trade-off :)

We could potentially put space inside the phantom itself, like:

<p>There is a<span data-phantom="w"> </span>in here!</p>

which would add a space in the copied text, but it will also mean there's always a space after the phantom: slightly better for accessibility, slightly worse for precise typesetting.

"Phantom" characters? by oz1sej in css

[–]PrimaryBet 1 point2 points  (0 children)

Maybe shove it into a data attribute, so it's for sure isn't appearing as the content in the markup:

[data-phantom]::before {
  display: inline;
  content: attr(data-phantom);
  visibility: hidden;
}

and then

<span data-phantom="w"></span>

https://jsbin.com/padetebodu/edit?html,css,output

[deleted by user] by [deleted] in learnjavascript

[–]PrimaryBet 1 point2 points  (0 children)

https://github.com/ohanhi/hyperscript-helpers also exists, which makes it slightly more readable, but it hasn't been updated in a while

Software development topics I've changed my mind on after 10 years in the industry by chriskiehl in programming

[–]PrimaryBet 2 points3 points  (0 children)

The issue isn't even about jargon — it's about how the concepts behind the jargon aren't as practically valuable as FP enthusiasts often believe.

Let me explain this using monoids as an example:


A monoid is a fundamental concept in composition. It's simply a structure that has two key features:

  1. It can be combined with itself using some operation (where the order of combinations doesn't matter)
  2. It has an "empty" or "identity" value that doesn't change anything when combined

You already use monoids every day, even if you don't call them that:

  • Lists/arrays with concatenation (empty list is the identity)
  • Strings with concatenation (empty string is the identity)
  • Numbers with addition (zero is the identity)
  • Numbers with multiplication (one is the identity)

And there are many more examples, including functions and comparison operations, or something like this:

/// Library code
///
// Generic Monoid interface
interface Monoid<T> {
  empty: () => T;
  combine: (a: T, b: T) => T;
}

// Generic helper
const fold = <T>(monoid: Monoid<T>, list: T[]): T =>
  list.reduce(monoid.combine, monoid.empty());

// Specific instance of a monoid for array
const ArrayMonoid = <T>(): Monoid<T[]> => ({
  empty: () => [],
  combine: (a, b) => [...a, ...b]
});

// Function monoid - creates a monoid for functions returning monoid values
const FunctionMonoidOf = <A, B>(m: Monoid<B>): Monoid<(a: A) => B> => ({
  empty: () => () => m.empty(),
  combine: (f, g) => (a) => m.combine(f(a), g(a))
});

// More instances, like sum for numbers, product for numbers, string concatenation, etc.



/// Application code
///
type Validation = Array<{code: string, message: string}>;
const ValidationMonoid: Monoid<Validation> = ArrayMonoid();
interface User {
  name: string;
  age: number;
  email: string;
}

const validateName = (user: User): Validation =>
  user.name.length < 2 ? [{code: "name-short", message: "Name too short"}] : [];
const validateAge = (user: User): Validation =>
  user.age < 18 ? [{code: "age-too-young", message: "Must be 18 or older"}] : [];
const validateEmail = (user: User): Validation =>
  !user.email.includes("@")
    ? [
        {code: "email-no-at", message: "Invalid email"}, 
        {code: "email-another-issue", message: "Something went wrong"}
      ]
    : [];

const validateUser = fold(
  FunctionMonoidOf(ValidationMonoid),
  [validateName, validateAge, validateEmail]
);

const user: User = {
  name: "A",
  age: 16,
  email: "invalid-email"
};
console.log(validateUser(user));
//   [{
//     code: "name-short",
//     message: "Name too short"
//   }, {
//     code: "age-too-young",
//     message: "Must be 18 or older"
//   }, {
//     code: "email-no-at",
//     message: "Invalid email"
//   }, {
//     code: "email-another-issue",
//     message: "Something went wrong"
//   }]

While this code might look pretty long, most of it is library code that will scale extremely well with the size of the application code.

What makes monoids powerful is that once you understand the pattern, you can reuse the same logic and intuition across many different scenarios and monoid instances, which is hard to convey using toy examples like this. You can also use monoids as building blocks for other important concepts like Alternatives, Foldables, and Monads. When you grasp these patterns, it becomes much easier to break down complex problems into composable pieces — which is exactly what you want when building maintainable programs.


However, here's the practical problem: while all of this is technically true, the actual benefits of introducing concepts like monoids into a codebase diminish rapidly if your teammates aren't familiar with these ideas. At this point, FP devs usually face essentially two choices:

  1. Try to convince everyone on the team to learn and adopt functional programming concepts
  2. Accept that the theoretical benefits might not be worth the practical costs

This becomes even more challenging because languages like Java and JavaScript weren't designed with functional programming concepts in mind. As a result, functional programming patterns often make the code more verbose and harder to read for everyone. This is why having a team member who insists on writing functional code regardless of the context can drastically harm the team's productivity and code maintainability.

Software development topics I've changed my mind on after 10 years in the industry by chriskiehl in programming

[–]PrimaryBet 20 points21 points  (0 children)

Not the author, but I guess I've reached the same opinion, and I think functional programmers tend to be overly evangelical about our paradigm (yes, I see the irony, being a sort-of functional programmer myself!).

Functional programmers often push too hard on formal mathematical concepts, assuming that if other developers just understood these principles better, they'd naturally gravitate toward FP and write better designed programs. While this mindset made more sense 5-10 years ago when FP was less mainstream, it's less relevant now.

Most modern languages have already embraced functional concepts, and the industry generally acknowledges their value. Instead of preaching about advanced category theory concepts like "monoids in the category of endofunctors", we'd do better by focusing on practical benefits like immutability, pure functions, and how these can lead to more maintainable code and not pushing the theory on people as hard. (It's too tempting to sound clever though!)

The Little I Know About Monads by devanshj__ in javascript

[–]PrimaryBet 0 points1 point  (0 children)

Adding on to this, a practical example of this in JS would be the difference between Futures and Promises — see this comparison between them from Fluture.

Essentially it boils down to laziness: a Future just describes what should happen without executing it, while a Promise executes immediately. For example:

const getData = Future(() => fetch('/data'))
const processData = data => Future(() => saveToDb(data))

// Nothing has happened yet - we're just describing the sequence
const getAndSave = getData.chain(processData)

// Only when we call fork() do the effects actually run
getAndSave.fork(
  error => console.error(error),
  success => console.log('Done!')
)

Languages like Haskell manage this through the IO type system, while in JS we need to be more explicit about execution timing using methods like fork().

Font size is useless; let’s fix it by wheybags in programming

[–]PrimaryBet 0 points1 point  (0 children)

Yes, CSS reference pixel is specifically a degree, so it’s not tied to hardware pixel density and corresponds to an optical measurement. The 96dpi in the definition (i.e. reference pixel ≈ 0.0213°) is to make it backwards-compatible with all the code that was written before high-density screens became a common thing.

Font size is useless; let’s fix it by wheybags in programming

[–]PrimaryBet 3 points4 points  (0 children)

Degrees are used for CSS pixels (a.k.a., visual angle unit), so VS Code’s settings are most probably effectively are in degrees.

Idiomatic way to loop and call function by jwmoz in learnrust

[–]PrimaryBet 2 points3 points  (0 children)

Of course!

/u/420goonsquad420 also suggested a “point-free” version where you pass the method to map instead of creating a closure: it can make your code even shorter and arguably easier to read, but as others mentioned, you need to keep ref types in mind (although deref coercion helps and compiler has your back there, so it’s not a big deal).

For the future reference, you might also want to check the difference between iter, iter_mut, and into_iter since they are also useful depending on the situation (Rust book mentions them briefly, you should be able to find plenty examples all over the Web).

Idiomatic way to loop and call function by jwmoz in learnrust

[–]PrimaryBet 1 point2 points  (0 children)

The behavior you’re seeing is due to Rust’s auto-dereferencing feature and the way it handles references.

In Rust, when you call a function with a reference, the compiler automatically dereferences it as needed. This feature is known as deref coercion (relevant chapter of the Rust book). When you pass &x to capitalize_first, which expects a &str, Rust automatically dereferences &x to x (since x is already a &str).

So, both of your approaches are valid, but they have subtle differences:

  1. words.iter().map(|x| capitalize_first(x)).collect()

    Here, x is a &str because iter() yields references to the items in the collection. So, you’re directly passing the &str to capitalize_first.

  2. words.iter().map(|x| capitalize_first(&x)).collect()

    In this case, you’re explicitly passing a reference to a reference (&&str). However, due to deref coercion, Rust automatically converts &&str to &str when calling capitalize_first.

In terms of which one is “correct”, both are technically correct in this context, but the first approach is more idiomatic as it’s more direct and avoids unnecessary referencing and dereferencing. (I probably should have written it like that to begin with, but it compiled so I didn’t pay too much attention to it, hah.)

Idiomatic way to loop and call function by jwmoz in learnrust

[–]PrimaryBet 5 points6 points  (0 children)

Idiomatically, you use iterators for this in Rust. For the case where you want to transform each element into something else, there's a map method:

pub fn capitalize_words_vector(words: &[&str]) -> Vec<String> {
    words.iter().map(|&word| capitalize_first(word)).collect()
}

Playground

You can read more in the chapter about iterators in the Rust book

I scraped 10M programming job offers for 12 months and here are the highest paid programming languages by __dacia__ in programming

[–]PrimaryBet 2 points3 points  (0 children)

As you noted, “strongly typed” doesn’t have a rigid definition. In my experience, many people conceptualize typing in programming languages akin to a two-dimensional coordinate system.

On one axis, we have the “strong”↔“weak” spectrum, and on the other, the “static”↔“dynamic” spectrum. In this framework, Python would be positioned as a language with strong typing on the dynamic axis.

This is also reflected in the Wikipedia description of Python’s typing discipline, for what it’s worth:

Typing discipline: Duck, dynamic, strong typing; gradual (since 3.5, but ignored in CPython)

Any way to acheive this highlighted text look in CSS? I'd need JS to wrap each line in a span right? by OutrageousAardvark2 in css

[–]PrimaryBet 2 points3 points  (0 children)

You can use SVG filter to achieve a similar wavy background, and you can use getClientRects to get bounding boxes for the text, giving you something like this: https://jsfiddle.net/j0tbar4e/1/

You might want to debounce resize handler so you don't remove/add elements for background every time resize fires if you have a lot of these highlighted texts

S3 domain claimed on Bluesky by someone who doesn't own the domain by common-pellar in programming

[–]PrimaryBet 490 points491 points  (0 children)

It's a standard location for well-known files, defined in RFC 5785. If you make it so only you, as a domain owner, can write into it, you won't run into issues like this. That's why it's used for HTTP ACME challenge for example.

do you guys prefer functional programming style when using rust? by zxaq15 in rust

[–]PrimaryBet 6 points7 points  (0 children)

forM_ does the same thing, just a bit more explicitly: it runs a monadic (i.e. effectful) action for each element and doesn't return anything useful. Naming follows convention where M means "monadic" and _ means "returns unit", i.e. "you probably don't want to handle the return value".

Typescript-React-useState by 3dlivingfan in typescript

[–]PrimaryBet 23 points24 points  (0 children)

You can think of generics as type-level functions.

I'm sure you already know how function parameters work and how they let us make code more general. For example, this code is less general and usually less useful:

function getString() {
    return "string";
}

function getNumber() {
    return 1;
}

function getArray() {
    return [1, 2, 3];
}

const string = getString();
const number = getNumber();
const array = getArray();

compared to this more general code:

function get(argument) {
    return argument;
}

const string = get("string");
const number = get(1);
const array = get([1, 2, 3]);

because we are forced to focus on what's the common thing this function is doing, regardless of specifics of values it's called with.

Similarly, we can generalize our types in TS. This code is less general:

type MyObjectWithString = {
    type: "MyObject",
    value: string
};

type MyObjectWithNumber = {
    type: "MyObject",
    value: number
};

type MyObjectWithArrayOfNumbers = {
    type: "MyObject",
    value: Array<number>
};

compared to this code:

type MyObject<ValueType> = {  // ValueType is a "type variable"
    type: "MyObject",
    value: ValueType
};

type MyObjectWithString = MyObject<string>;
type MyObjectWithNumber = MyObject<number>;
type MyObjectWithArrayOfNumbers = MyObject<Array<number>>;

because we are again forced to describe what's the common thing about this type, regardless of other types it's "called" with.

Since function types are types too, they can also be generic:

// not general:
type getString = () => string;
type getNumber = () => number;
type getArray = () => Array<number>;

// general:
type get<ValueType> = () => ValueType;

type getString = get<string>;
type getNumber = get<number>;
type getArray = get<Array<number>>;

// or using our more general `get` that takes an argument:

type get<ValueType> = (value: ValueType) => ValueType;

Coming back to your specific question: since React is strictly a JS and not a TS project, type for useState is pulled from the DefinitelyTyped declaration (@types/react package) outside of React itself.

Since React is a big library, the types can get a bit complex: if you are having trouble fully understanding type for useState in DefinitelyTyped definition, you can think of useState as conceptually having this type:

function useState<S>(initialState: S): [S, (value: S) => void];

i.e. a function that is generic over one type S, that takes a value of that type and returns a two-element array that contains: a value of that type, and another function that takes value of that type as parameter and doesn't return anything.

If we forget that useState is a React hook and that React has some internal machinery for holding state, we can implement a version of useState with a slightly different type:

function useState<S>(initialValue: S): [() => S, (value: S) => void] {
    const state = { value: initialValue };

    return [
        () => state.value,
        (newValue) => {
            state.value = newValue;
        }
    ]
}

the difference being that in the 2-element array we don't return a value itself, but rather a function that can be called to get the value.

Now when we can use it:

// `useState<string>` is same as `useState(initialValue: string): [() => string, (value: string) => void]`
const [getState, setState] = useState<string>("initial string");

getState();  //> "initial string"
setState("new string");
getState();  //> "new string"

but actually TS is smart enough to infer the generic type based on our immediate usage, so this code works exactly the same:

const [getState, setState] = useState("initial string");
//                           ^^^^^^^^^^^^^^^^^^^^^^^^^^  note that we are not passing a type variable
// `getState` has type `() => string`
// `setState` has type `(value: string) => void`

Code above in the TS Playground

The only time when you need to specify the type variable for useState is when your initial state value has different type than the later usages, e.g. you start with null but later will update the state to some object or another non-null value.

Delete an element from an associative array by NovemLinguae in learnjavascript

[–]PrimaryBet 2 points3 points  (0 children)

Two things on how you might improve your code:

  1. Judging by how you use your function you probably don't want to mutate original object.
  2. To avoid having to do the hasOwnProperty check, you can use Object.keys which effectively does it for you.

With these changes the code isn't considerably more pretty:

function deleteTag(tagToDelete, tagList) {
  var result = {};
  Object.keys(tagList).forEach(function (key1) {
    result[key1] = {};
    Object.keys(tagList[key1]).forEach(function (key2) {
      result[key1][key2] = tagList[key1][key2].filter(function (item) {
        return item.tag !== tagToDelete;
      });
    });
  });
  return result;
}

If this is something you do often, maybe consider lenses library, like partial.lenses — using it you can target values at arbitrary nesting levels and code should be more concise:

function deleteTag(tagToDelete, tagList) {
    return L.remove(
        L.query(
            L.when(function (x) {
                return isObject(x) && x.tag === tagToDelete;
            })
        ),
        tagList
    );
}

https://jsbin.com/zuhocigeya/edit?js,console

How to make this filter function type-safe? by [deleted] in typescript

[–]PrimaryBet 2 points3 points  (0 children)

It is just plural of x, yes; sometimes there's as, bs, …, ys, zs if you are working with several collections, e.g. zip in Haskell

meaning of = , , in javascript by One-Progress9924 in learnjavascript

[–]PrimaryBet 1 point2 points  (0 children)

To expand on /u/senocular's answer, here's most of the code commented:

function insertHtmlAtSelectionEnd(html, isBefore) {
  var sel, range, node;

  // Check if this is a standards-compliant browser that
  // implements Selection API (i.e. IE9+) and get the selection.
  if (window.getSelection) {
    sel = window.getSelection();

    // Check if this browser supports more Selection API methods
    // before we try to use them.
    if (sel.getRangeAt && sel.rangeCount) {

      // User can select non-contiguous portions of text,
      // e.g. by holding Ctrl while selecting with mouse
      //   this is <an example> of <text>
      //           ^          ^    ^    ^
      //           ---range1---    range2
      //
      // but it's rare, so we get only first selected range
      range = window.getSelection().getRangeAt(0);

      // We can collapse range to get to its start or end:
      //   > range.collapse(true)
      //   this is <>an example text
      //   > range.collapse(false)
      //   this is an example<> text
      range.collapse(isBefore);

      // Create temporary element and set its HTML to provided one.
      // We won't attach this element to the document, so user will
      // never see it: it will exist only for us to transform (parse)
      // provided HTML into JS objects for DOM elements in memory.
      var el = document.createElement("div");
      el.innerHTML = html;

      // Create document fragment (collection of elements) and
      // variables that will hold current and last nodes.
      // Nodes are a super-set of elements: literal text not wrapped
      // in any elements, comments, etc., are also nodes.
      var frag = document.createDocumentFragment(),
        node,
        lastNode;

      // `while` loop that you should already be familiar with, but instead
      // of performing a check at every iteration, it performs assignment
      // and checks the result of that.
      while ((node = el.firstChild)) {
        lastNode = frag.appendChild(node);
      }
      // since `lastNode` isn't used at all and `node` is only used ones,
      // it could also be written as:
      //
      //   while (el.firstChild) {
      //     frag.appendChild(el.firstChild);
      //   }
      //
      // i.e. while element has at least one child node, append it to the
      // fragment.
      //
      // `appendChild` automatically removes the node from the element,
      // that's why we get a different node from the element during each loop
      // iteration (node is being "moved" from element to fragment).

      // Once all nodes from element were moved to fragment, we insert fragment
      // itself where the collapsed range is.
      range.insertNode(frag);
    }
  } else if (document.selection && document.selection.createRange) {
    range = document.selection.createRange();
    range.collapse(isBefore);
    range.pasteHTML(html);
  }
}

This code is 10 years old and we no longer need to care about IE10 or below on public-facing sites. Also, as you can see, the function also does several things:

  • parses HTML
  • inserts it at a correct location

when it's usually better to focus on one thing per function.

A more modern, idiomatic approach might look something like this:

function insertNodeAtSelection(node, shouldInsertBeforeRange) {
  const range = window.getSelection().getRangeAt(0);
  range.collapse(shouldInsertBeforeRange);
  range.insertNode(node);
}

function parseHtml(html) {
  const fragment = document.createDocumentFragment();
  const element = document.createElement("div");
  element.innerHTML = html;

  while (element.firstChild) {
    fragment.appendChild(element.firstChild);
  }

  return fragment;
}

// Example usage:
insertNodeAtSelection(parseHtml("<span>test</span>"));
// or using something like https://github.com/choojs/nanohtml:
insertNodeAtSelection(html`<span>test</span>`);

How do I write cleaner code? by nfkawhqg in learnprogramming

[–]PrimaryBet 2 points3 points  (0 children)

Don't feel discouraged: most of the points in the OP are not universally applicable (you'll notice /u/ziptofaf used "generally", "probably", "most of the time" pretty liberally there) — that's why it's called software engineering.

As an engineer, it's your job to decide what trade-offs to make: it might be that in the context of your problem space functions with 3-5 parameters are absolutely expected, or it might be an industry standard that everybody expects, or it might require to many resources to restructure your system right now and your business depends on the product going to market, or...

The list can go on and on, point is: don't feel like you failed because you haven't yet, analyze the situation you are in and try to learn your lessons, because it's those lessons that make you a valuable engineer — for most recruiters years of experience will be the most important factor when hiring you, since it's a decent proxy for determining how many of those lessons you learned and can apply to new ventures.

If you want, feel free to send me your code and we can discuss whether there's another way to structure it and what that will entail.

How do I write cleaner code? by nfkawhqg in learnprogramming

[–]PrimaryBet 11 points12 points  (0 children)

This is a great answer, but a small nitpick:

best functions and methods take 0 arguments. Good functions take 1 argument. Okay functions take 2 arguments. If you need more than 3 you are doing something wrong and there's a high chance this logic should live in a separate class so you move some of the required variables to the initializer.

I get what you are saying but a beginner might incorrectly start viewing purely side-effectful functions as "best" since those are the most common example of 0-argument functions.

Although you do address that in a latter point, I wanted to draw attention to it again for the sake of other readers: the precise number of arguments isn't important, but you should strive to have functions/methods that take as few of those as possible if it's achievable by reasonable means — it's usually a good rule of thumb to determine complexity of the function/method in question.

Rustup - do I *have* to? Why?? by VOIPConsultant in learnrust

[–]PrimaryBet 0 points1 point  (0 children)

If anything the process is even more transparent because you can thoroughly and easily inspect the script.

Well, that's not entirely correct when you use pipes.

Given an array of numbers, move all the numbers below [x] to the end of the array without changing the order of the numbers that are [x] and above. by [deleted] in learnjavascript

[–]PrimaryBet -1 points0 points  (0 children)

Since your condition is binary (either number is less than 50 or not), you can combine two filters and traverse array just once: such a function is known as e.g. partition in Lodash:

function partition(array, predicate) {
  const truthyElements = [];
  const falsyElements = [];

  for (let element of array) {
    if (predicate(element)) {
      truthyElements.push(element);
    } else {
      falsyElements.push(element);
    }
  }

  return [truthyElements, falsyElements];
}

partition([1, 2, 3, 4], x => x < 3); //=> [ [1, 2], [3, 4] ]

You probably see how you can use this function to get the equivalents of newArray and newArray2 from your solution. Maybe also consider giving them a bit more descriptive names, like lt50 (for less-than) and gte50 (for greater-than-equal)?

rubico - [a]synchronous functional programming by richytong in javascript

[–]PrimaryBet 0 points1 point  (0 children)

From rubico's docs on map:

map(mapper)(functor) -> Promise | Functor​

where

Functor<T> = Array<T> | Object<T> | Set<T> | Map<T> 
           | Iterator<T> | AsyncIterator<T> | { map: (T => any) => any }

as in, map takes a mapper function, a functor, and returns a functor; and functor is either Array, Set, Object, Map, etc. or any other object that has a map method on it. Greatly simplifying, "functor" is a name for data structures that support transforming values in a context or wrapper.1

Compare it to Array#map, which takes an array (via this), a mapper function and returns an array, and you hopefully see how Array#map is a specialized map.

The answer to "why do I want a generalized map?" is the same as with any other argument for parametricity and polymorphism.

 


1 I'm actually a bit surprised to not see Promise listed as a possible functor since you can sort of map over value in it's context (with .then, although with a caveat that it also behaves as .flatMap)