Math.min(Math.max(num, min), max) - <AUTHOR> https://twitter.com/jaffathecake/status/1296382880030044160 <comment><USER2> I find that the fact that the functions min and max have the same name as the variables min and max increases cognitive load which makes it harder to think about it.

I find the following easier to read :

      Math.min(Math.max(num, lower_bound), upper_bound)

<comment><USER3> Easy to remember, but may take some time to grasp:

      Arrays.sort( {lower_bound, num, upper_bound} )[1];

Next challenge: teach the optimizer to make that almost as fast as the min/max way ;-)

(You can't reduce it to the min/max call because it also works if you accidentally pass a lower bound that's larger than the upper bound. Worst- case, the above takes 3 comparisons, unless at least two of the inputs are constants)

<comment><USER4> > Next challenge: teach the optimizer to make that almost as fast as the > min/max way ;-)

I did _exactly_ this for my PhD!

[https://chrisseaton.com/phd/](https://chrisseaton.com/phd/)

<comment><USER5> Wait, how is that not trivial?

<comment><USER4> > how is that not trivial?

It could be trivial to implement an optimisation which does this for that exact code. But what are you going to do? Hand-code an optimisation for every similar thing people could write? I implemented a general solution.

So it also works through metaprogramming:

        [1, 2, 3].send(:sort).send(:[], 1)

Through user-defined sorting order:

        [1, 2, 3].sort_by { |a, b| b <=> a }[1]

When nested:

        [[1, 2].sort[1], 3].sort[0]

And so on.

Note that it also needs to be transparent to debuggers and profilers, it needs to handle multiple method redefinitions (for example what happens if someone redefines the sorting order for integers).

It's not a pattern-matching optimization - it's partial evaluation enabled by a new kind of polymorphic inline cache.

<comment><USER6> > But what are you going to do? Hand-code an optimisation for every similar > thing people could write?

While I appreciate that you solved the general problem, I wonder if there are legs here. Specifically, could one mine GitHub to find automatically common patterns that one could write specific optimizers for, or at minimum, leverage that to learn what semi-general cases are worth optimizing? To my knowledge optimizing compilers already do have effectively handlers for common operations, but I don't know if anyone has leveraged "big data" to help guide this.

IIRC, various tweaks and optimizations in Java were guided by Sun analyzing their own code based. GitHub is just so much bigger, and polyglot.

</comment></comment></comment></comment></comment></comment><comment><USER7> Luckily, this is a solved problem for go.

      func helper(a float64, c chan float64){
          time.Sleep(time.Duration(a) * time.Second)
          c <- a
      }

      func clamp(a float64, min float64, max float64) float64 {
          c := make(chan  float64, 3)
          go helper(a, c)
          go helper(min, c)
          go helper(max, c)
          _, out, _ := <-c, <-c, <-c
          return out
      }

<comment><USER8> That will give you the median value. What OP wants is the value `a` clamped within `min` and `max`.

<comment><USER7> Can you give an example where median([a, min, max]) is not equal to clamp(a, min, max), given max >= min?

<comment><USER9> If a < min or a > max, if I'm reading it right.

<comment><USER10> You can prove that this algorithm works for both of those cases. Assuming min <= max:

If a < min, then the sorted array is [a, min, max]. The median is min, which is a clamped to min.

If a > max, then the sorted array is [min, max, a]. The median is max, which is a clamped to max.

</comment></comment></comment></comment></comment><comment> Const-me In languages I use there's usually no need to write that code.

C++/17 has std::clamp() in <algorithm> header.

Modern C# has Math.Clamp() since .NET Core 2.0; too bad it's not available in desktop edition of the runtime.

HLSL has clamp() intrinsic function, and a special version saturate() to clamp into [ 0 .. +1 ] interval.

<comment><USER11> It gets a bit confusing when the order of arguments is different depending on the library. For instance, with std it's std::clamp(val, min, max), but with Qt it's qBound(min, val, max) (for some reason I think the order of arguments in qBound is more logical).

<comment><USER3> The expression _Math.min(Math.max(num, min), max)_ is symmetric in _min_ and _num_ , so it doesn't matter whether you interchange _min_ and _num_ (or, for that matter, _max_ and _num_ , but that is harder to see from that way to define the 'clamp' function)

<comment><USER11> Good point, thanks.

(Though I've just checked gcc's definition of std::clamp and it looks like

        __glibcxx_assert(!(__hi < __lo));
        return (__val < __lo) ? __lo : (__hi < __val) ? __hi : __val;

so order of arguments does matter there.)

</comment></comment></comment></comment><comment><USER12> Always good to know the underlying implementation, but for any Ruby readers check out clamp(). It's been available since 2.4.

      25.clamp(5, 10)
      => 10

      6.clamp(5, 10)
      => 6

      1.clamp(5, 10)
      => 5

<comment><USER4> I often see [a, b, c].sort[1] which I think is very neat.

<comment><USER13> If you are writing code that is clamping a lot of numbers, the GC churn from building a new array every time might be a problem.

<comment><USER4> Ideally the temporary array should optimise away.

<comment><USER13> Ideally, but so far my experiences with simple benchmarks and with ruby-prof have shown that CRuby doesn't make such optimizations:

[https://repl.it/repls/GargantuanThistleLink](https://repl.it/repls/GargantuanThistleLink)

        Result from sort: 3 in 0.9785124980007822s
        Allocated 3000001 object(s)
        Result from ternary: 3 in 0.3205206830025418s
        Allocated 1 object(s)
        Result from clamp: 3 in 0.5030354310001712s
        Allocated 2 object(s)

Interestingly the ternary comparison is faster than clamp.

</comment></comment></comment></comment></comment><comment><USER14> Stage 1 ECMAScript proposal to add Math.clamp (among others): [https://github.com/rwaldron/proposal-math- extensions](https://github.com/rwaldron/proposal-math-extensions)

But it looks dead: [https://github.com/rwaldron/proposal-math- extensions/issues/...](https://github.com/rwaldron/proposal-math- extensions/issues/16)

As someone mentioned in the thread, nested ternary is easier to interpret:

(a > max ? max : (a < min ? min : a))

<comment><USER15> To each his own but I disagree. Nested ternary's are hard to read and understand, and modifying them (by future devs) is tricky and error prone.

<comment><USER16> True, _nested_ ternaries can be hard to follow. And the excessive parentheses promote this way of looking at it.

OTOH I think _chained_ ternaries can be simple and easy to understand.

Yes, they are the exact same thing in this case, but getting rid of those nested parens really helps, at least for me.

sarah180's example is a good illustration. I would change the order of the tests because it makes more sense to me to check the min before the max. I'd also make one minor formatting change, because I code in a proportional font and can't line things up in columns:

      a < min ? min :
      a > max ? max :
      a

Maybe people think differently, but to me that is super easy to understand, and _much_ better than the confusing Math.min/max stuff.

I would also wrap the whole thing inside a function:

      function clamp( value, min, max ) {
          return(
              value < min ? min :
              value > max ? max :
              value
          );
      }

Now that it's inside a function, you could change the code to use if statements, or Math.min/max, or whatever suits your preferences.

</comment></comment></comment><comment><USER17> 68K assembly, no branches:

      # d0 = num, d1 = low, d2 = high, d3 = scratch
      sub.l   d1, d0
      subx.l  d3, d3
      or.l    d3, d0
      addx.l  d1, d0  # d0 = max(num,low)
      sub.l   d2, d0
      subx.l  d3, d3
      and.l   d3, d0
      add.l   d2, d0  # d0 = min(max(num,low),high)

Adapted from "Superoptimizer -- A Look at the Smallest Program" by Henry Massalin [1].

[1] [https://web.stanford.edu/class/cs343/resources/superoptimize...](https://web.stanford.edu/class/cs343/resources/superoptimizer.pdf)

<comment><USER18> Note that with modern branch predictors such optimizations may not actually be beneficial–ARM got rid of condition codes on all its instructions in the 64-bit version. (Plus, I assume they ran out of space to encode them.)

<comment><USER19> IEEE754 has defined min and max for quite some time. Nowadays almost all FPUs have min and max instructions built-in.

</comment></comment></comment><comment><USER20> OPs implementation requires 2 comparisons. I think this C expression is clearer, and will sometimes use 1 comparison:

        num < min ? min :
        num > max ? max :
        num

<comment><USER21> Incidentally, gcc and clang both compile this to two cmovs for me.

<comment><USER20> I don't speak x86. Do you mean that these compilers are evaluating both conditions, all the time? At what optimization level?

<comment><USER22> x86 has instructions that execute conditionally. Most conditionals in higher level languages get compiled to conditional jumps, but using conditional operations this isn't necessary. The same code path is taken in all cases, and the instructions effect is what is conditional.

In the case of cmov, it is either a nop or a mov dependent on the state of the conditional flags. Using this construct instead of a regular mov guarded by conditional jumps has better performance in some cases.

On my machine gcc is outputting a combination of conditional jumps and conditional movs at all optimization levels

</comment></comment></comment></comment><comment> V-2 Kotlin provides pretty nice syntax sugar for that:

       num.coerceIn(min..max)

That's it. This human reader finds it considerably more readable.

It also has

       coerceAtLeast

and

       coerceAtMost

<comment><USER13> Does kotlinc optimize away inline ranges like that, or does this result in a range object being constructed and discarded?

<comment><USER23> I haven't heard of any instances of Kotlin itself optimizing these things away, but the JVM may be able to do so during its various JIT passes. It's definitely not something you can necessarily rely on, though.

Luckily, these convenience methods are usually implemented as inline extension functions, so the whole thing will get inlined into the calling method, making JIT optimization more likely.

</comment></comment></comment><comment><USER24>
      [min, num, max].sort()[1]

<comment><AUTHOR> sort() on JavaScript arrays sorts alphabetically (unless you pass a compareFunction)

[https://stackoverflow.com/questions/21019902/why-cant- javasc...](https://stackoverflow.com/questions/21019902/why-cant-javascript- sort-5-10-1)

[https://developer.mozilla.org/en- US/docs/Web/JavaScript/Refe...](https://developer.mozilla.org/en- US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)

<comment><USER25> Good point, for those who need to implement a slick compareFunction for numbers, Math.sign is great:

      [min, num, max].sort((a, b) => Math.sign(a - b))[1]

An entirely different alternative is poor man's match:

      switch (true) {
      case num > max: return max;
      case num < min: return min;
      default: return num;
      }

<comment><USER26> Why sign though? I always write my sorts like this.

        .sort((a, b) => a - b)

<comment><USER18> Is there a better way to grab a reference to the subtraction operator?

<comment><USER26> I assume you're referring to a point-free reference.

Only by defining a `const subtract = (a, b) => a - b;`, which isn't really point-free.

Or by using a different language.

</comment></comment></comment></comment></comment></comment><comment><USER27> I think the main hurdle is that we need to read this inside-out, which is something we face regularly trying to read nested function calls. I seriously believe pipe-like operators solve this problem cleanly.

In Elixir which does have the pipe `|>` this could be.

        number = number |> max(lower_bound) |> min(upper_bound)

Which IMO is quite elegant.

<comment><USER27> Note: I don't really know Elixir, all I know is that this works in repl.it

<comment><USER28> I use Elixir day to day, and I agree, piping is one of the nicest things about it. And your code is the way I would have written it.

</comment></comment></comment><comment><USER29> It is simpler if you use the notation [x]_a^b (i.e. with a subscript and a superscript b) to mean x, clipped to the range a to b, and skip writing +/\- infinity if you don't intend clipping on one side.

Then you get a bunch of obvious identities like [x]^b = min(x, b) = [b]^x (x capped by b is the same as the smaller of x and b which is the same as b capped by x), [x]_a^b = [b]_a^x, and [x]_a^b = [[x]_a]^b. Putting these together you get [x]_a^b = [[x]_a]^b = min(max(x, a), b). But honestly it's just easier to stick to the notation most of the time.

A better write-up, for everyone who doesn't like reading new math notations inline: [https://imgur.com/gallery/593QEow](https://imgur.com/gallery/593QEow) (Imgur link with white background) [https://quicklatex.com/cache3/71/ql_46c49ac709b3789482d0736d...](https://quicklatex.com/cache3/71/ql_46c49ac709b3789482d0736d80481871_l3.png) (Original link - renders badly in Chrome due to PNG transparency)

<comment><USER30> Those are all valid C.

</comment></comment><comment><USER31> Very coincidental I see this post almost immediately after writing the same code:

        new_poll_rate = \
            min(
                max(
                    1 / messages_per_second,
                    constants.FASTEST_POLL_RATE
                ),
                constants.SLOWEST_POLL_RATE
            )

I agree with the sentiment, I had to re-read this several times to make sure I got it right.

<comment><USER32> If fastest poll rate > slowest poll rate, I think you've got them the wrong way around (or is that the joke?).

<comment><USER31> FASTEST_POLL_RATE is 1000hz, SLOWEST_POLL_RATE is 10hz. Thus, FASTEST_POLL_RATE is a smaller number on a per-second basis.

<comment><USER32> Ah, I see - for clarity I'd rename them FASTEST_POLL_RATE -> SHORTEST_POLL_PERIOD or store them in Hz rather than seconds, so everything was 1/ in that little snippet. Thanks for clearing up my confusion :)

<comment><USER31> Yeah that's a very good call, I will probably rename these. Thanks for the critique!

</comment></comment></comment></comment></comment><comment><USER33> Not as elegant, but way more readable:

if num > max: num = max

if num < min: num = min

</comment><comment><USER34> In Factor:

        : clamp ( x min max -- y ) [ max ] dip min ; inline

[https://docs.factorcode.org/content/word- clamp,math.order.ht...](https://docs.factorcode.org/content/word- clamp,math.order.html)

<comment><USER35> For casual readers, `dip` pops the top of the stack, executes a quotation, then pushes the top of the stack back on.

So this pops the max value off the stack, applies the quoted `max` word to the x and min stack values, then pops the max value back on the stack and applies the `min` word to the result and the max.

</comment></comment><comment><USER36> The basic function is simply defined as:

      function clamp(num, min, max) {
        return Math.max(min, Math.min(num, max));
      }

That is, if you don't try to do anything fancy and make any parameters optional. Lodash does and it makes the implementation much more complex.

      _.clamp(input: number, lower?: number, upper: number): number;

[https://github.com/lodash/lodash/blob/ddfd9b11a0126db2302cb7...](https://github.com/lodash/lodash/blob/ddfd9b11a0126db2302cb70ec9973b66baec0975/lodash.js#L13981)

<comment><USER37> Or to make sure it's crystal clear what's going on:

        function clamp(num, min, max) {
          if (num > max)
            return max;
          if (num < min)
            return min;
          return num;
        }

<comment> 52-6F-62 Speaking only to JS is there any reason to write it any other way outside of being clever or as a lambda for singular use? I definitely prefer this version. (Assuming any necessary runtime checks are included for a given project)

<comment><USER38> There are many reasons to forego readability, especially when writing a library: performance, compatibility, requirements, interpreter/compiler optimizations or even cyclomatic complexity.

In lodash's case it might even be all of the above, although I can't speak for the intentions of the authors since there are no comments to guide readers through the process.

Note GP's link points to what looks like the v3 branch. Check out the latest implementation of clamp, with a few less if statements, and what looks like a NaN check using strict equality if you want your mind blown. [https://github.com/lodash/lodash/blob/86a852fe763935bb64c125...](https://github.com/lodash/lodash/blob/86a852fe763935bb64c12589df5391fd7d3bb14d/clamp.js#L22-L23)

<comment><USER39> Reading that code it looks to me that:

clamp(null) returns 0

clamp(undefined) returns NaN

clamp(1, NaN, NaN) returns 0

clamp(1) returns 0

clamp(1, 5, NaN) returns 5

JavaScript is hard to write safe code for.

</comment></comment></comment></comment></comment><comment><USER40> There's an obvious solution to this:

        require('clamp')(num, min, max)

1 million monthly downloads

</comment><comment><USER41> Ideally I'd also want to throw an error when max < min.

</comment><comment><USER42> Kotlin implementation [1]:

        public fun Int.coerceIn(minimumValue: Int, maximumValue: Int): Int {
            if (minimumValue > maximumValue) throw IllegalArgumentException("Cannot coerce value to an empty range: maximum $maximumValue is less than minimum $minimumValue.")
            if (this < minimumValue) return minimumValue
            if (this > maximumValue) return maximumValue
            return this
        }

[1] [https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.ranges/c...](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.ranges/coerce- in.html)

</comment><comment><USER43> Most of the ternary implementations here are less correct than the original. You generally want min/max to satisfy the following:

1\. min/max of NaN and anything is NaN

2\. negative 0 is strictly smaller than positive 0

it's a fun exercise to implement clamp under these constraints.

</comment><comment><USER44> I'm not sure why the author isn't putting his preferred implementation into a clamp function then forgetting about it?

</comment><comment><USER45> An amusing anecdote ruined by the fact that everyone who can relate immediately starts thinking of a better way to rewrite it. Yes brain that might be better but that's not the joke.

</comment><comment><USER46> Fun seeing that pretty much everyone else finds that idiom confusing too. Half-serious, over breakfast:

        (case [(> n min) (< n max)]
          [true true] n
          [true false] max
          [false true] min)

(Side note: Clojure's `>` and `<` are kind of unreadable to begin with. Turning `if (> n min)` into "if n is greater than min" takes some work for me, still, after more than a year.)

<comment><USER47> However, prefix notation becomes much easier to read and reason about when you have more than two things to compare:

        (> 3 2 1 ...)

vs

        (3 > 2) && (2 > 1) && ...

</comment></comment><comment><USER48> Do people actually have trouble with this repeatedly, or just when they first learn about it? I started using this implementation of clamp a few years ago, and while it gave me some trouble when I first implemented it, the pattern is very simple, and I got used to it very quickly.

I use Common Lisp:

> (max min (min max n))

Is the difference my choice of language, my personal mental hardware, the amount of familiarity one has with the pattern, or none of the above?

</comment><comment><AUTHOR> in k:

      xs: 1 2 3 4 5
      max: 4
      min: 2

      max& min| xs
      2 2 3 4 4

works for scalar, vector, matrix

<comment><USER49> K made me realize that if you use the numbers 0 and 1 for booleans, `min()` is `&&` and `max()` is `||`. love that!

<comment><AUTHOR> same here, illuminating a-ha moment!

</comment></comment></comment><comment><USER50> I find the following easier to visualize. If L is the lower bound and U is the upper bound, and if you visualize L, U as two points on the real number line, then:

left_of_U ( right_of_L (num)) = right_of_L ( left_of_U (num)) = clamped version of num between L and U.

Here, left_of_U = Math.min(num, U) and right_of_L = Math.max(num, L).

</comment><comment><USER51> On the one hand, I've done this enough times that I can usually write it on auto-pilot without thinking about it. But on the other hand, whenever I make a mistake, the resulting bug is really hard to track down, because it's tough to just stare at the line and recognize that something wrong.

</comment><comment><USER52> In APL:

        lower⌈ upper⌊ numbers

See a stream of random numbers flowing from right to left. See the higher ones being pushed down ⌊ to the upper bound, and the lower ones being pushed up ⌈ to the lower bound, and the middle ones flowing through both guards unchanged.

</comment><comment><USER53> Excel has no clamp function but a neat alternative is

        =MEDIAN(min, num, max)

</comment><comment><USER54> I find the following much easier to read. It's certainly easier to maintain, deal with, for successive programmers, and likely has exactly the same compiled/interpreted operations for most common languages. Optionally replace t1 and t2 by overwriting num if needed.

Use full if else if you must.

If you're worried about speed, using built in min and max is not a good idea. There are many, many tricks to remove branches for certain datatypes, etc., as you need.

var t1 = num < min ? min : num; // clamp to min var t2 = max < t1 ? max : t1; // clamp to max return t2; // num clamped to [min,max]

</comment><comment><USER55> I like doing `Math.max(min, Math.min(num, max))` since it puts them in sort order.

</comment><comment><USER56> Slightly offtopic, but very practical use of a comparable algorithm is to determine to what extent a date ranges falls between a first and last date (e.g. first date of the year, last date of year). e.g. in Excel it would look like: MAX((MIN(end date range; last date) - MAX(Start date range;first date) + 1);0)/(last date - first date + 1). This results in 0 in case of no match, a fraction when only a part of the date range falls between the first and last date, and 1 in case it matches completely or even exceeds the first and last date.

</comment><comment> w-m I personally would find this much more straightforward:

      val - (sign(val - max) + 1) / 2 * (val - max) + (sign(min - val) + 1) / 2 * (min - val)

</comment><comment><USER57> I always used to get confused by the function names "min" and "max" because they return the minimum and maximum, but typically when you use them you are thinking in terms of _applying_ a minimum or maximum bound. Having a dedicated clamp function significantly helps although imo there is not a single correct order for the parameters to go in.

</comment><comment><USER58> For maximum readability, you could also go for

      (min + ((num + max - Math.abs(num - max)) / 2) + Math.abs(min - ((num + max - Math.abs(num - max)) / 2))) / 2

Since

      min(a, b) = (a + b - |a - b|) / 2

and

      max(a, b) = (a + b + |a - b|) / 2

</comment><comment><USER59>
      This is the TXR Lisp interactive listener of TXR 242.
      Quit with :quit or Ctrl-D on an empty line. Ctrl-X ? for  cheatsheet.
      1> (clamp 1 10 -1)
      1
      2> (clamp 1 10 15)
      10
      3> (clamp 1 10 5)
      5

Added on August 13, 2015 by commit f2e197dcd31d737bf23816107343f67e2bf6dd8e

</comment><comment><USER60> Talking about obscurity of code, in Forth you would write:

      5 9 7 min max .

This prints 7, as it's between 5 (lower bound) and 9 (upper bound).

Defining a _clamp_ "function" looks like this:

      : clamp ( min max n -- clamped_n )
        min max ;

</comment><comment><USER61> Python also doesn't have a built-in clamp function (I think there might be one in numpy), I usually use

        sorted((floor, x, ceiling))[1]

Throw it in a function with some asserts if you're worried about x not being a number and giving you weird results.

<comment><USER62> There is indeed one in numpy : [https://numpy.org/doc/stable/reference/generated/numpy.clip....](https://numpy.org/doc/stable/reference/generated/numpy.clip.html)

</comment></comment><comment><USER63> > it takes me ages to convince myself this implementation is correct.

So never use it in code.

</comment><comment><USER64> Here's clamp in idiomatic Elixir (using multi-clause functions and guards):

      def clamp(min, _max, n) when n<min, do: min
      def clamp(_min, max, n) when n>max, do: max
      def clamp(_min, _max, n), do: n

<comment><USER65> An Elixir convention I've seen is to put the thing you're operating on first, so that you can compose functions using the `|>` operator, which places the previous expression as the first argument of the function to the right.

Maybe something like this?

      defmodule Compare do
        def clamp(number, minimum, maximum) do
          number
          |> max(minimum)
          |> min(maximum)
        end
      end

      import Compare

      clamp(5, 1, 10) # 5
      clamp(1, 5, 10) # 5
      clamp(10, 1, 5) # 5

      some_number
      |> clamp(min, max)

As a side note, I think the Elixir |> operator is a stroke of genius that other languages should take a look at. Making the pipe operator append the _first_ argument has the following benefits

1.) It makes the most "important" argument of the function the first thing you read in function signatures

2.) If you need to add more arguments to a function signature later, they tend to be less important the original args, so they tend to make sense at the end

3.) It creates a convention for all libraries to follow so they can leverage the pipe operator. Its really jarring when the thing you want to put in a pipeline isn't the first argument (looking at you `Regex`[0] which puts the regular expression as the first arg and not the string)

[0] [https://hexdocs.pm/elixir/Regex.html#replace/4](https://hexdocs.pm/elixir/Regex.html#replace/4)

<comment><USER66> > It makes the most "important" argument of the function the first thing you > read in function signatures

Doesn't that make writing functions that can use partial application harder? e.g. If I was writing clamp i would want the signature to be

         (defn clamp [min max n] ,,,)

Then I can do:

        (map (partial clamp 1 11) [-14 2 5 8 11 15 18])

I know when I use Clojures threading macros I use thread last way more than any of the others. My next most common would be piping it into arbitrary locations, e.g.:

        ; pipe into an arbitrary spot (specified here as o)
        (as-> (range 1 10) o
              (map inc o)
              (filter even? o)
              (reduce + o))

I rarely use thread-first.

<comment><USER65> Elixir has an anonymous function short hand that makes the "partial application" use case pretty easy for me.

      &Compare.clamp(&1, some_min, some_max)

The above creates an arity one function which puts the arg into the first position in the original function.

I've never felt pain around partial application because I use the anonymous function short hand a good deal

</comment></comment></comment></comment><comment><USER67> [https://twitter.com/ben_a_adams/status/1296463312780251136](https://twitter.com/ben_a_adams/status/1296463312780251136)

</comment><comment><USER68> Numpy has `np.clip`.

In pure Python `statistics.median([min, max, num])` also works.

</comment><comment><USER69> In Python, I usually put the following aliases:

      upperbound = min
      lowerbound = max

Use:

      a = upperbound(a, 10)
      b = lowerbound(-10, b)

</comment><comment><USER70> > it takes me ages to convince myself this implementation is correct.

> Googler

Then this is another proof that google doesnt only hire on mathematical puzzle tricks

</comment><comment><USER71> Math.min(a, x) == at_most_a(x)

Math.max(b, x) == at_least_b(x)

at_most_b(at_least_a(x))

A similar kind of thing is really common in measure theory (limsup, liminf) and option payoffs.

</comment><comment><USER72> When making glsl shaders, there's clamp().

</comment><comment><USER73> I made a simple clamp function based on this const clamp = (num, min=0,max=100) => Math.min(Math.max(num, min), max)

</comment><comment><USER74> This is a great example of how haskell makes these things obvious ;)

        clamped = num `max` min' `min` max'

<comment><USER75> no idea what's going on there, I know some of those variables are actually functions but the whole thing is unreadable unless you have experience in haskell imo

<comment><USER76> The backticks turn regular functions into left-associative operators of the highest priority (by default).

So

        a `foo` b `bar` c

is

        (bar (foo a b) c)

<comment><USER27> Oohh nice. So kinda like a pipe.

I really think we deserve more syntax that allowed something like this, because otherwise one needs to read `(bar (foo a b) c)` inside-out.

<comment><USER76> > Oohh nice. So kinda like a pipe.

I never thought of it that way, but it is true that it can be used as a pipe.

Fundamentally it's just the dual of (): Haskell lets you use operators as infix functions by wrapping them in () so

        (+) 1 2

is the same as

        1 + 2

and conversely lets you use prefix (binary) functions as operators by wrapping them in backticks.

You can even combine those through _sections_ , which serve to partially apply infix operators: [https://wiki.haskell.org/Section_of_an_infix_operator](https://wiki.haskell.org/Section_of_an_infix_operator)

</comment></comment></comment></comment></comment><comment><USER77> The fact that you need to type 33 characters to define something so simple as clamp() really does not make sense

</comment><comment><USER78> This is something that upon seeing I would sketch out. It's way easier for me to understand visually

</comment><comment><USER79> This one doesn't bother me much. What's harder and worse, IMO, is doing saturating _math_.

</comment><comment><USER80> Once you've seen this a few dozen times, you instantly parse it as "clamp(num, min, max)"

<comment><USER81> Did a bunch of coding bootcamps just begin session or something? I don't understand the comments here treating it like it's so hard to write and verify that it needs a completely different, slower, less direct, cutesy implementation.

<comment><USER80> I don't understand the explosion of comments here either. I was just saying for myself, it's a trivial construct and very commonly encountered.

</comment></comment></comment><comment><USER82> Is this a problem that comes up often? What kind of situation would make you want to calculate this?

<comment><USER83> It's pretty common in data science or financial applications to restrict the range of data in this way.

There are probably SQL devs reading this and wondering what the fuss is about.

</comment></comment><comment><USER84> Wrap it in a function, verify the implementation once, then henceforth use clamp(x, min, max).

</comment><comment><USER85> I would make it more confusing to read by using the 100 and 0 percentiles.

</comment><comment><USER27> I always though pipe operators are under-rated and under-used.

In elixer that could be

</comment><comment><USER86> > _it takes me ages to convince myself this implementation is correct_

It would take them less time to convince themself if they switched min and num to put the values in proper semantic order: min < num < max.

Math.min(Math.max(min, num), max)

<comment><USER87> That still leaves the order of Math.min and Math.max undecided and will probably not help much if you get easily confused by the visuals of this code.

I never thought about it but of course there must be code tongue twisters (or more correctly, brain twisters).

Thinking about it, I would probably go with a less confusing implementation. Terse code is hard to read and the compiler is likely clever enough to choose the best implementation anyway.

<comment><USER88> > and the compiler is likely clever enough to choose the best implementation > anyway.

Not in my experience. The compiler is likely to be able to do something decent to it, but it'll probably be different.

Consider the following snippets. For unsigned integers they're all equivalent (and return the max of x and m), but gcc with a wide range of flags can't recognize them as identical.

      (x<m) * m + (x>=m) * x

      (x<m) * (m-x) + x

      x<m ? m : x

<comment><USER87> There can always be things that trip the compiler. Without looking at the actual assembler, you never know that.

Interestingly in your example, clang is able to resolve the first and the third line to the same assembler code.

[https://godbolt.org/z/navMEc](https://godbolt.org/z/navMEc)

I do wonder why it then isn't able to do that for the second line. Possibly because the CPU might have different flags set after processing the substraction?

But I'm not sure if your example is a good argument after I said I prefer less confusing code and you present an example which even confuses the compiler. ;-)

</comment></comment></comment></comment><comment><USER89> >[...] it takes me ages to convince myself this implementation is correct.

Is that supposed to be difficult?

Not trying to be snarky, I'm honestly surprised, do people actually struggle with this? Googlers in particular?

<comment><USER90> This whole discussion feels like I'm not getting an obvious joke.

</comment></comment><comment><USER91> Just write a isBetween(low,middle,high)

<comment><USER92> Your method name and the signature are misleading. First, it implies that it returns a boolean, not a number. Second, the argument names look like they have to be already sorted, which defeats the purpose.</comment></comment>


Improve Facebook or Leave It - <AUTHOR> http://smallblog.desandro.com/2016/improve-facebook-leave-it <comment><USER2> I'm not a fan of Trump or the way this election played out (or even facebook, really), but this article is absurd.

>Because Facebook has multiple figures in leadership positions that supported Trump. Thiel vocally, Luckey surreptitiously.

Thiel isn't in a leadership position at facebook (de facto or de jure - he's a board member who doesn't take a day-to-day role) and Luckey is about as marginalized as you can be within a company while maintaining contractual agreements. The real leadership of facebook seems genuinely progressive. Also, I'm not sure some employees supporting a mainstream politician is grounds for the company to be shaken up or disbanded (49% of voters supported Trump!).

>Because Zuckerberg believes the fake news his platform elevates played no part in the election ... Because Facebook's core product promotes the distribution of false information

Nate Silver largely agrees: [https://twitter.com/NateSilver538/status/802272157954781185](https://twitter.com/NateSilver538/status/802272157954781185). And sure maybe it had some impact, but so did 50 other things going on. I'm not going to defend fake news and I think it's harmful to the election process and facebook, but this isn't a strong argument against facebook as a company.

>Because Facebook shipped a racist feature in its core advertising product.

A huge amount of advertising is targeted racially in a non-controversial way. This is a reality of advertising and I don't consider it racist. Facebook has made it clear it does not tolerate the illegal or discriminatory use of this feature.

<comment><USER3> > (49% of voters supported Trump!).

No. Facts still matter. As of today, Trump has received just 46.6% of the vote.

</comment></comment><comment><USER4> I hope one day I'm so wealthy that I can use my source of livelihood to make a sociopolitical statement.

Until that day, I'd much rather ensure that my children are safe and happy than to stand up against my employer's wrongdoings.

(I don't work for Facebook. But I thought about how practically impossible it would be for me to do the "right thing" if it were my company)

<comment><USER5> Where do you live and what do you do for a living? If it's the SF Bay area and software, you have no excuse. Or any first world country doing a professional job for that matter.

<comment><USER4> Canada.

I'm not saying I would turn a blind eye if my company was doing something dangerous or illegal. But in that fuzzy zone of unethical, maybe illegal but maybe not... As awful as it sounds, my household has one income and it's not silicon valley amounts of money and it feels instinctive to protect my own above all else.

<comment><USER5> I understand where you are coming from, as I'm part of a single income household with two children that is barely above water month to month. But I've actively made a choice to struggle a bit more financially rather than making potentially twice the salary at a less ethical company. It hurts sometimes, but for me personally, my mental health is much better and I enjoy my entire work day. I don't feel awkward in conversations when discussing what I do. I feel better looking my children in the eye and telling them to do the right thing. And in the end everyone is well fed and has a roof over their head and getting a proper education, so if I'm not keeping up with the other technorati in my supposed group, then so be it.

</comment></comment></comment></comment><comment><USER6> Note that Facebook operates and has a similar influence in many more countries.

Just like in the U.S., elections in many countries are affected by the 'quality' of the information being shared and distributed through Facebook.

So Facebook - the people who work at Facebook - should promptly acknowledge its impact on public opinion and public perception (with the dangers that that implies) and immediately focus on finding solutions to these unexpected side- effects of social networks.

Things like echo chambers, fear vortexes, fake news, calls to (useless) protest and so on.

Social networks have the potential to generate serious unrest - as has been the case in many countries already, so these things should be taken very seriously - more than what Facebook is doing now.

<comment><USER7> FYI the quality of information is defined by the minds that consume it. Information has zero value and rating until it comes face to face with the human mind. We need to stop blaming something of no value for the entities that are unwilling to study it.

Time for The Kardashians? Check! Think about what I just read? Oh sorry. That's FB's fault?

Really? We're advocating for mass ignorance and laziness? What's next? Blaming the super market because I buy soda, chips and processed food? Even when real food is right in front of me? Really?

<comment><USER6> > That's FB's fault?

Since Facebook makes this communication possible (and profits greatly from it), it should also assume the responsibility for the side-effects of such communication.

These effects exist and have consequences in the real world (sometimes violent) and if left unchecked things can quickly spiral out of control and lead to war.

Yes, people should be smarter and not believe the memes on Facebook, but they aren't and there is no time to wait for everyone to get enlightened, so a more practical and constructive solution is needed.

One such feature could be to provide 'alternative views' for posts - a sort of forced advertising - in which the views of the 'other' side are offered.

A nice and interesting AI project, could save the world..

There's no one else who can do it, only Facebook.

</comment></comment></comment><comment><USER8> One day, I hope to live in a world where people can disagree politically and not think the other side is the evil incarnate.

</comment><comment><USER9> People still using facebook ? :-)

Its end is nigh, the era of socialising will come to an end when people realize its not what we wanted.

I will actually go as far as saying its one great app/idea away from going down. If someone made a proper app for creating events and it spread like wildfire attracting all the "kids", I think it would be game over for FB.com

I dont think theres anything else holding me back. Events and messenger...

</comment><comment><USER10> Blaming Facebook for the election result is like blaming the ocean for drownings.

<comment><USER7> +1

</comment></comment><comment><USER11> I'm reading news about security/programming languages/new technologies here, but I don't know who is this guy. So, maybe someone can explain to me who is this guy and why I see this post on HN?

</comment><comment><USER12> Every time I read something this Manichean - something implying that the "good people" must climb over the barricades and vanquish the land of evil - Ride of the Valkyries plays in my head.

</comment><comment><USER7> Pro Nanny State nonsense. People need to be responsible and accountable. There's no room for mindlessness in a Democracy. Yes, FB needs to raise its bar. But that doesn't absolve the responsibilities of those who use it. This blame X for the decisions of Y is a false god. It needs to stop.

</comment><comment><USER13> There are many reasons to leave facebook (as a user, at least, but arguably for employees too), but these have to be among the dumbest I've ever read. Ooh, let's boycott eachother for political opinions. Get a grip.

<comment><USER14> For what it's worth, aren't political opinions about what the practical applications of justice and goodness are? If you were going to boycott someone over anything, wouldn't it be those? If someone else's opinion falls within a reasonable spectrum from our own, it's fine to accept them. When the difference becomes great enough, you're obligated to reject those views.

Where you draw the line is up to you, though there is often a societal consensus on what a reasonable Overton window is like. The problem with your argument is that you want everyone to get along, but you want them to do it regardless of extreme differences in how different people want to shape the good life. It's hard to cooperate with someone that fundamentally opposes everything you stand for at your core and, importantly(!), wants to impose their views on you. This is important because it is far easier to tolerate differences between groups that do not impose their views on each other, which is the situation in which I agree with you more often than not [1].

If you want everyone to get along, you need to show why on particular issues, or for overarching reasons, it's not worth rejecting each other. Otherwise, I find what you say hard to accept when examined below the merest surface.

[1] A counter example would be a group that is murdering or mutilating its own members, and those members ask for help. That would be a clearly justified case for external intervention.</comment></comment>


The surprising ways that metaphors shape your world - <AUTHOR> http://www.boston.com/bostonglobe/ideas/articles/2009/09/27/thinking_literally/ <comment><USER2> "The result has been a torrent of research testing the links between metaphors and their physical roots, with many of the papers reading as if they were commissioned by Amelia Bedelia, the implacably literal-minded children's book hero."

That's a great simile in the article. Linguists who study translation (for example Peter Newmark) have been studying metaphor for a long time. What's interesting about metaphor is how automatically writers and speakers use metaphor in communication, and how much a reader or listener with a different linguistic background may not recognize a metaphor.</comment>


Graylog 1.1 released - <AUTHOR> https://www.graylog.org/graylog-1-1-is-now-generally-available

<comment><USER2> I've been loving the beta for a while now. Very pleased with the continuous progress they're making.</comment>


Women, Tech Conferences and the Bullshit Surrounding It - <AUTHOR> https://sugarrae.com/rants-in-bitchland/women-tech-conferences-and-bs/ <comment><USER3> Why aren't conference proposals blind anyway? Seems to have worked for orchestras.

<comment><USER4> Because individual speakers draw crowds; individual orchestra members do not. Could you see Linus Torvalds' speaker application getting denied because it was a blind proposal from "some hothead"?

Edit: missed the meaning of "blind".

<comment><USER5> If it were a blind proposal, you wouldn't know it was from "yet another white male".

Individual speakers draw crowds, yes. But conferences are also a way for people to share their ideas and establish their names in the first place. A conference that optimizes for crowd draw is enforcing a preexisting hierarchy to the detriment of the community.

A solution is to use the keynote address and invited speakers to draw crowds, while taking blind proposals for most of the actual content.

"What is the goal of X?" is a good question to ask in any social endeavor.

<comment><USER4> Whoops, edited.

> _A solution is to use the keynote address and invited speakers to draw > crowds_

Ok, but nothing's solved, just pushed up a level.

<comment><USER6> It gives women, along with other frequently disadvantaged groups, such as minorities, the obese, seniors, and physically challenged persons, a more equitable chance to be heard in the first place. It means that the speakers who are chosen have met a minimum professional relevance level. This is a good short term win.

Will it mean those people have equitable chances to do keynotes today - <USER2> more so than the current systems.

Will it mean they have a chance to build a professional reputation that may result in invitations to do keynotes tomorrow - yes. This is a good long term win.

</comment></comment></comment></comment></comment><comment><USER7> In my opinion we should judge people solely on the relevance and quality of their presentations at conferences. Why should anything else matter? I think everyone agrees with this for the most part. It's just unfortunate that some people feel the need to supply unequal treatment to certain genders/races by creating quotas.

<comment><USER8> I think a lot of people on HN and reddit agrees with your opinion. We should judge people on quality and merit. Unfortunately, studies have shown the people who claim this tend to be even more biased.

See bottom of this page. [http://managingbias.fb.com/](http://managingbias.fb.com/) It's kind of like when people say "I don't see race."

<comment><USER9> That's a bit... ad-hominum. Maybe I'm mis-reading it, but for me it parsed more or less as "I'm not saying you're a racist, but people who say what you're saying are racists...."

If that interpretation is wrong, please do correct me.

I'd like it if arguments could stand on their own, not be dismissed because someone falls into a particular category.

>I have a dream that my four little children will one day live in a nation where they will not be judged by the color of their skin, but by the content of their character.

and all that.

<comment><USER5> Useful reading: [http://laurencetennant.com/bonds/adhominem.html](http://laurencetennant.com/bonds/adhominem.html)

The post you're responding to is making the argument "Claiming that you aren't unbiased does not make you unbiased. Trying to be unbiased does not necessarily make you unbiased."

That's certainly not ad hominem at all.

<comment><USER10> _The post you 're responding to is making the argument "Claiming that you aren't unbiased does not make you unbiased. Trying to be unbiased does not necessarily make you unbiased."_

No, it goes farther and very clearly says it actually mskes you _more_ biased.

<comment><USER5> That's fair, I misparaphrased. Still, not an ad hominem because its argument appeals to studies. That could be fallacious, but it's not an ad hominem fallacy.

<comment><USER11> Not to be pedantic, but its logically invalid; no fallacy is needed.

</comment></comment></comment></comment></comment></comment></comment><comment><USER12> Similar to the putative attitude of the organizers of these conferences, colleges have bent over backwards to get more female enrollment (indeed, there are now more females going to college than males). However,

 _" A new report from the National Student Clearinghouse looks at degrees in STEM fields (science, technology, engineering and math) and finds that the share of STEM bachelor's degrees going to women ticked down over the past decade. The biggest decline was in computer science, where women received 23 percent of bachelor's degrees awarded in 2004 and just 18 percent in 2014. On the bright side — at least for career prospects — both men and women are slightly more likely to be majoring in STEM fields today than they were in 2004; it's just that men have shown more growth than women."_[0]

The opportunities are there for those females who want it. Maybe most of them simply don't want to go into the computer field---individual men and women have different things they want out of life and out of their careers, which is ok! Why should everyone be a computer science major? The world would be a pretty dull place.

The author's points are quite valid; I would add that you don't want to push people into a field they have no interest (or aptitude) in. It makes the person miserable and cheapens the degrees of others (a smaller consideration in tech, I'll grant you, since it's more meritocratic than some other fields).

The smallest minority is the individual. If 95% of individuals who happened to be men gave the best auditions, they should probably be given the spots. I say "probably" because if it's a private conference, the organizers can do whatever they want, and people need not attend if they don't like the speaker choices. Ultimately, if women are dissatisfied with the "boys club", they can organize their own conference across the street.

[0][https://www.washingtonpost.com/news/rampage/wp/2015/01/27/wo...](https://www.washingtonpost.com/news/rampage/wp/2015/01/27/women- falling-behind-in-stem-bachelors-degrees/)

<comment><USER13> _The opportunities are there for those females who want it. Maybe most of them simply don 't want to go into the computer field_

You seem to take that as a law of nature... as though it's natural for there to be a truly _massive_ gender bias in computing, a gender bias that was far less 20 years ago and has gotten egregiously worse since roughly 2000.

The real question should be: why the hell aren't women enrolling into and graduating from CS programs?

The answer is probably _enormous_ and _systemic_ , but the current situation should not be seen as acceptable, IMO.

Incidentally, the same questions could (and should) be asked of, say, men in nursing. And, again, the answers are certainly enormous and systemic, starting from childhood socialization, running through peer group issues, and on and on.

</comment></comment><comment><USER14> How can one lament the lack of women in a conference panel but make no mention of how lily white it is?

Is it just me or do most of these underepresentation conversations seem to focus on gender more than race? How the heck does that make any kind of sense?

If anything racial disadvantages have even broader economic consequences than gender. How is race not an intrinsic, automatic part of every conversation on representation in tech alongside gender? Why is it "women in tech" instead of "women and minorities in tech"?

<comment><USER15> >How can one lament the lack of women in a conference panel but make no mention of how lily white it is?

Maybe it is related to how the mismatch from base rate in prison populations in regards to race is a sign of systematic racism against the over-represented groups, but the same doesn't seem to be reported in regards to sex.

<comment><USER16> So, commute all prison sentences to STEM scholarships, and problem solved?

<comment><USER15> If prison offered good job training (and we got people to be willing to employ felons), I think recidivism rates would take a significant dip. But oddly enough, such a solution would only further solidify the gender gap in tech as such scholarships would be going to far more men than women.

</comment></comment></comment></comment><comment><USER17> The gender imbalance in tech will remain self-reinforcing unless we actively work to change it. Right now the gender balance is so bad that we're effectively giving up on half the population. How does anyone think that is a _good_ thing? Other high-skill fields like medicine & law aren't anywhere near as imbalanced as tech.

Changing the status quo requires outreach and making the culture more inclusive. Most appeals to meritocracy in tech boil down to "but I really like the way things are now".

<comment><USER18> That change in culture has to start at high school and college levels, if not sooner, in educational terms for any meaningful changes to happen. Plus the culture that needs to work to change isn't necessarily just the tech culture.

<comment><USER19> Exactly. Pop-culture in the US (and high-school/college kids are drowning in it) is very anti-intellectual in general. And getting worse every year (reality shows, etc).

But a lot of discrimination comes from female peer-pressure, not males. My daughter kept repeating "math is hard" because her female friends kept saying so, until I had none of it. She ended up being very good in math, but chose chem+biology as her major in college :-)

</comment></comment></comment><comment><USER20> > There's also no African Americans on the Edge Conference's roster. I don't > see any people of (obvious) Hispanic descent. Why is no one up in arms over > that?

Because people who care don't get nearly as much press as people who talk about women being excluded.

Because the men who work in tech don't care so much about race, but they do care about the obvious lack of women.

Because it's easier to go "we have 40% asians and indians" and ignore the issue than to find a way around "we have 95% males".

</comment><comment><USER21> The lack of representation of women at these sorts of conferences is _in and of itself_ something that turns women off participating in them and ultimately off the profession. It's a self-perpetuating problem. Until you get that essential fact, you just don't get the overall problem.

"For all they know, 95% of speaker pitches came from men and thus why they ended up with a 95% male speaker line up once they whittled down the list to the best pitches." Shouldn't the very next thought be: "gee, why would 95% of speaker pitches come from men?" Why might that be the case?

To me, the "women just aren't interested in tech" explanation is ridiculous on its face. "Women just don't want to be in a high-profile, financially rewarding career with tons of growth potential, because ____." What goes in the blank? I'm dying to know.

<comment><USER22> I didn't choose to be an engineer because it was high profile, financially rewarding with tons of growth potential. I chose it because I absolutely love designing and building things. If you've ever been completely captivated by the sight, sound, and smell of a steam locomotive's moving parts, or sheer awesome thrill of a top fuel dragster or P51 at full throttle as it "digs in", or building something nobody has made before, you are not really an engineer.

If you can't use a piece of machinery, look at software, read about Fukushima, and not always be thinking about how you'd design it better, you are not really an engineer.

If you wouldn't work on cool engineering projects for free just because they are cool, you are not really an engineer.

If you just want to do engineering to make a pile of money and retire, you are not really an engineer.

If you want to present at conferences for the fame and recognition, you are not really an engineer. If you present because you cannot resist telling everyone about this totally awesome piece of engineering, you are likely a real engineer.

<comment><USER23> Same here. I wouldn't even be interested in tech jobs other than programming. I don't care about the money. Two years ago I even turned down a promotion to the manager because all I wanted to do was (and is) coding. Also, the original commenter implies that the average man and woman have the same (tech) interests, which is simply wrong. The average man and the average woman are _not_ the same.

</comment></comment></comment><comment><USER24> For the record, I agree with the points made. But, I've flagged this, as it will (and has started to) produce the usual firestorm.

<comment><USER25> Then so be it. We shouldn't _not_ talk about it.

</comment></comment><comment><USER25> Brilliant article. Unfortunately, Rae's perspective does not fit the narrative of most HN readers.

</comment><comment><USER26> When say you chose people solely on relevance and quality, but you only have men as speakers.. Then it's laughable that your system for choosing speakers isn't biased.

Percentages shouldn't be the reason why you hire or don't hire someone but they should be a measure of how much bias is in your system for choosing persons of varying classes. If your percent of xyz participants in the majority class is way higher than the distribution in the possible applicants then there is some sort of class bias(economic, race, socio) in either how you choose applicants, or in how you get applicants.

<comment><USER7> Wouldn't this only be true if there was a perfect 50/50 split of qualified speakers based on gender? Percentages can be positioned to show that bias exists only when the input doesn't match the result. It is unknown whether the field of applicants had an "acceptable" amount of diversity to begin with.

<comment><USER26> The percent ratio based on class of participants should be in range of the percent ratio of possible people qualified by class.

And as I stated.. The failure of not being near this percent is either because how you chose your participants from applicants or how you chose to get people to be applicants.

<comment><USER27> > how you chose to get people to be applicants

Applicants are self-selecting. Your argument attempts to shift responsibility (and agency) away from speakers and practitioners.

<comment><USER26> I'm not shifting anything.

How can one have agency if they don't know that there is an opportunity?

i.e.

If an opportunity is open to all; but is only presented to one class then you are in general only going to get applicants from the class that you presented the opportunity too.

</comment></comment></comment></comment></comment><comment><USER28> that's a very long way to say "I don't understand / like affirmative action"

<comment><USER9> It's a long way of saying "I don't like affirmative action" because they're explaining why they think affirmative action is bad.

>I earned my way onto that list. And here is someone telling me people who didn't should be added simply so I wasn't the lone female on it?

>In three words? That's some bullshit.

It's only a long way to say it if you're already committed to ignoring their arguments. Because in reality their arguments have a bit more nuance then just "I don't like affirmative action".

<comment><USER28> Frankly, I think they make one and only one point with a lot of different examples that make the same point in basically the exact same way: "as a woman in tech who has succeeded despite roadblocks, I feel like any amount of affirmative action will make others doubt the extent of my achievements".

I am not committed to ignoring their arguments -- I used to hold similar positions. Then I talked with people who disagreed with me, grappled with their positions, and changed my mind. The author here shows no semblance of any such depth of thought, just repeated invocations of "if I made it, it must be possible! if we help others who are worse than me, then that lessens my achievement!" At its core, it's a selfish argument[1], which is why I changed my mind.

[1]: to be clear, there are quite a few non-personally-selfish arguments against affirmative action. "it'll make others doubt how much better i am than most other women" is not one of them.

</comment></comment></comment><comment><USER29> Kids (and people that didn't grow up) will try for a long time to avoid this discussion. But I have to say to you: you lost. You can leave, or you can adapt. But you can't stop it.

</comment><comment><USER30> This article is kinda insulting. Panels and conferences suck when they're homogenous. They're banal and uninspiring because the perspectives are all too similar.

The reality is that they didn't work hard enough to find good quality presenters that represent the actual world we live and work in - one where people approach problem solving in myriad different ways that stem from their own history and experience.

tl;dr - if you can't find women, POC for your conference, you didn't look hard enough.

<comment><USER31> Does diversity of gender/race equate directly to diversity of content? Painting a conference as uninspiring solely based on what percentage of the panel are $demographic seems wrong. Are you suggesting that white males somehow all produce the same content?

<comment><USER32> Bias favoring white males creates a culture of entitlement. Ever went to these mediocre conferences with mediocre talks? What unimaginative blokes organize them?

Then take one considered magically good, like Strange Loop. Their excellence translations into excellent diversity work too: ([http://bridgetconsulting.com/?p=131](http://bridgetconsulting.com/?p=131))</comment></comment></comment>


TFS is destroying your development capacity - <AUTHOR> http://www.derekhammer.com/2011/09/11/tfs-is-destroying-your-development-capacity.html <comment><USER2> I have significant experience with CSV, SVN, Perforce, Source Depot (Microsoft's internal Perforce fork), Team Foundation Server, Mercurial, and Git. Roughly in that order of exposure.

I safely say that TFS is easily the slowest, least scriptable, most confusing, obnoxious piece of crap software that I have ever had the displeasure of using. The Microsoft-internal hate for TFS was astonishing, but political pressures forced us to use "dogfood" it.

Personally, I used to keep all of my source code at Microsoft in a local Mercurial repository (this was before Git had decent Windows support). I only interacted with TFS when I absolutely had to.

<comment><USER3> How recent was your experience with TFS? It's been around for 6 years and shipped 3 versions, that should be enough time for it to be good enough for dogfood.

<comment><USER2> You'd think that right? But I left Microsoft in spring of 2010.

</comment></comment></comment><comment><USER4> TFS truly is awful.

I am amazed that the cost is not mentioned in the article though.

Forced to use it where I work, because management wanted the reporting capabilities that it provides and like the turnkey solution. My back of napkin calculations came up with that for the cost of TFS we could have kept our existing SVN/Jira/CruiseControl solution (or migrated to a hosted solution) and hired someone at 60k a year to just write reports for the existing system, or paid Atlassian to come up with them for us.

Add in everything mentioned in the article, the cost and that basic functionality such as "get latest" doesn't and you have an impedance to developer productivity.

These days I tend get the TFS code, check into mercurial/git and work that way.

</comment><comment><USER3> > TFVC is a centralized-server model that requires constant and active > communication between a client (read: developer) machine and the server. If, > for example, the network goes down for 1 hour, development grinds to a halt. > The reason here is that TFS will mark all files as read-only on the > filesystem until you have asked the server to check them out for you.

Perforce works the same way, causing much frustration for me whenever I have to work with a slow and unreliable p4 server (and, despite Perforce marketing, those exist). You can override p4 and make writable the files you want to edit without telling the server. But when you want to check in a changeset, you have to tell the server you edited the files, otherwise they will get left out of the changeset. Worse yet, if you try to get too clever with your local copy's settings, the p4 utility might overwrite your changes with a newly checked-in version the next time you update your local copy.

When I worked at Microsoft in the early part of the last decade, we used a Perforce fork called Source Depot. (Internet mentions of sd are rare, but here is one: <http://stackoverflow.com/questions/491295>). I have no experience with TFS version control, but it looks to have taken a lot of inspiration from sd, which was a fresh breath after the previous revision control tool which didn't even support branches.

<comment><USER5> Editing of local files "behind the back" of the P4 server is not that bad. When you reconnect to the server, just ask your P4 client to "synchronize offline changes" (in P4V, I think) or just checkout your entire clientspec and ask your P4 client to revert unchanged files. I'm sure these operations could be easily scripted, too.

Clearly not ideal, but workable. I'm surprised Perforce has not created offline changelists (like git or Mercurial's Patch Queue). The feature could probably be implemented entirely in P4 client code. Perforce has implement server-assisted "shelving" of changelists, but I don't find that as helpful as local branches or changelists would be.

<comment><USER3> > When you reconnect to the server, just ask your P4 client to "synchronize > offline changes" (in P4V, I think)... I'm sure these operations could be > easily scripted, too.

p4v does have a lot of added features and conveniences. Maybe I'm an old fart, or maybe I'm just too used to sd (which didn't have an official GUI client app when I used it) but I don't actually like to use p4v, preferring to use the p4 command-line tool. So, yes, I've gotten used to automating certain operations via shell scripts that wrap p4.

> ... or just checkout your entire clientspec and ask your P4 client to revert > unchanged files...

If you do that, though, the server will tell everyone else that checks out any file that you have it opened for edit too. This can be really misleading when they want to delete or integrate to the file. I don't like that Perforce implicitly discourages merging branches through "who else has opened this file" notifications, but that's how it is and I'd rather not abuse the system.

</comment></comment></comment><comment><USER6> I'm sure there are lots of frustrating things in daily TFS workflow but some points in the article are quite wrong.

> TFVC is a centralized-server model that requires constant and active > communication between a client (read: developer) machine and the server. If, > for example, the network goes down for 1 hour, development grinds to a halt. > The reason here is that TFS will mark all files as read-only on the file > system until you have asked the server to check them out for you.

You can switch to offline mode, and it will sync when you're reconnecting to the server.

> TFVC wants you to do everything inside of Visual Studio.

Yes, but it's easily extendable, and there's a power tool integrating Tortoise like functionality to Explorer Shell. And there's always the command line tool, here's the syntax for "add", for example:

<http://msdn.microsoft.com/en-us/library/f9yw4ea0.aspx>

      tf add itemspec [/lock:(none|checkin|checkout)] [/type:filetype] [/noprompt] [/recursive] [/login:username,[password]]

> In order to create this bug work item, you need to use either Team Explorer > (through Visual Studio, most likely) or the TFS 2010 Web Interface. The > obvious problem for the first scenario is that developers are the only ones > likely to have Visual Studio and are only one of several groups of people > that could log a bug

...and Excel and MS Project, by default. Web + Excel + MS Project should cover almost all "several groups of people". And there's always this api, available through libraries or web services.

> TFS as Agile Project Management ...

All project and work item templates are customizable, either via XML definitions or through a power tools interface. And when you do, all the external interfaces display your customizations without any additional work, be it Excel or TFS Web Access or the others. And they're instantly reportable too.

> TFS as Build System ...

It can build MSBuild scripts, Ant and Maven builds natively. Constructing builds is always hard, MSBuild or workflow style build introduced in 2010 are no different. Normally, any sln file governing the project can be built without any modifications. I find gated check-ins or nightly builds quite easy to setup, his mileage seams varying.

<comment><USER2> The command line tool is much nicer than the GUI, but there is still no way to get easily machine parseable output. Unlike Git, all of the `tf` commands are porcelain. If you want plumbing, you need to code to the COM/C# APIs.

</comment></comment><comment><USER7> I initially read this as "Team Fortress is ruining your development capacity." and I agree. I play too many games.

<comment><USER8> I can write an article on this topic. I rationalize the time wasted by playing as Engineer. I also work for a Gamification startup so I can call it 'research' :)

</comment></comment><comment><USER9> Obligatory link to git-tfs: <https://github.com/spraints/git-tfs>

</comment><comment><USER10> When set up and used properly, TFS is a decent source control / bug tracking system, especially if you use Visual Studio for day to day development.

The problems with TFS come from a few areas. First, it's easy to set it up in some sub-optimal configuration, by putting it on insufficient hardware, for example. There's a very real and very high cost to doing that aspect right, of course. Second, if you're doing development with a small team and a limited number of branches, TFS is probably overkill, and the way the tradeoffs are balanced for TFS is probably way off from the actual tradeoffs your team needs. Third, if writing code in the VS IDE isn't the norm then you might be going against the TFS grain enough to cause serious pain. Fourth, if you don't use the bug/work item tracking parts of TFS then it'll have less value to you, obviously.

Finally, the biggest problem with TFS is the competition. People apply the label "distributed version control systems" to Mercurial and Git but that hides the important aspect that these systems are not _just_ capable of decentralization but they are also extremely fully featured and highly advanced modern VCSes. If you are deciding ab initio which VCS to use it'd be silly to not choose Hg or Git for almost any project. They are free, there is tons of support, they are scalable, and they are extremely good.

</comment><comment><USER11> Can't really recognize these problems. I've no problem with working offline for example. You get the latest version from the repository, do your stuff and check-in when your done. Conflicts are pretty easy too. I don't know this 3 pane "standard" merge view that the guy is ranting about, but the 2 pane (local and remote version) view in TFS works just fine for me.

Bug and work items, sure, not very good. Usable, but still prefer to keep issue tracking outside TFS.

I've only used SVN apart from TFS, and while it does the job, I mainly used it because it's free. Really disliked the hidden .svn files cluttering up folders though.

I've never really gotten Git or Mercurial. They seem to be for linux command- line type of coders. But I really wouldn't know, as I haven't used them.

TFS works just fine. If you are doing MS development, it's probably the best tool for the job.

The majority of these kinds of rants come from people who are used to something else, then proceed to proclaim certain software "stupid", because it does not work like their favorite choice of similar software.

A bit silly really - Use what you like, but don't engage in bouts of mud throwing. You'll just be as much of a "factionist" as the author implicitly claims he is not.

</comment><comment><USER12> Although I agree with the overall sentiment, there are a few inaccuracies with this article. I am not defending TFS, just correcting.

To address the point about losing connectivity, VS prompts you to "Go offline" which removes all the readonly flags from every file and folder (I know...) and does a folder scan like a regular basic VCC would do upon reconnection. I haven't had a problem with this (as long as your copy is very close to the server copy).

To address the point about multiple merges, you can select multiple conflicts and perform bulk operations on them (accept server, accept client etc) and I'm pretty sure automerge is one of the options.

Also yes the merging tool is horrendous. I use p4merge instead for both TFS and git. Much easier to see what has changed and also easier to cherry pick.

<comment><AUTHOR> Re: offline mode.

I've had to deal with this a few times. I make a brief mention of it in my article but gloss over the details because I wanted to get on to more important topics.

In general, offline mode has been a terrible experience for me. It is handled differently in different versions of TFS. In one version (2008?), you go to File -> Offline Mode. In another, you need to either reopen the solution and get prompted project by project to Temporarily Work Offline or unbind TFS manually.

In both solutions, I've had difficulty reconnecting to TFS. In a complex set of steps that were probably "dumb" but seemed like my only options, I have lost changes made on my local file system.

My experience may vary from others, granted. Though, after talking to some colleagues about their experience, mine has been easy.

<comment><USER12> Fair enough. I guess the overall impression we both share of the offline process can be summed up by the word "unintuitive".

Also funnily enough, I've just come back after lunch to find something has killed SQL Server, which has affected TFS, forcing me to experience all the joy that is offline mode. I'll no doubt be swearing and cursing MS in a few minutes.

</comment></comment></comment><comment><USER13> My understanding of TFS is that the only reason it exists is to sell more SQL Server licenses.

<comment><USER14> It was more about getting the Developer Division to be a $1 billion in revenue department. My guess is that TFS is a drop in the bucket for SQL Server revenue.

</comment></comment><comment><USER15> Agree entirely with the article.

TFS is one of those products that you feel like you should be using what with being an ENTERPRISE, but after a couple of stand-offs with it, you feel like you've been thoroughly well and truly raped by the vendor. This is unless you were using VSS before at which point you are scarred for life.

I made a fair bit of cash between '03-'07 saving people from botched, painful VSS and TFS environments. If people pay you lots of money and worship the ground you walk on for getting rid of TFS, then it's probably a bad product.

I replaced them with a simple scripted virtual Debian/Trac/SVN appliance with Active Directory integration via LDAP. I let them design and build their own processes and workflows with Trac workflow. I do the same but with Trac and Mercurial now.

<comment><USER16> TFS is a below average source control system in an age when there are many better choices. VSS, on the other hand, is an active threat to all of your code.

At a previous employer, I was delighted by the switch to TFS, because it meant we no longer had to worry about the VSS file store getting corrupted and losing data. Now I'm on contract with another employer still using VSS, and we should be cutting over to TFS soon. Once again, I will be delighted. Because the below average is a welcome change from the flatly unacceptable.

<comment><USER15> Agree. I illustrated VSS to someone once by printing the source out and throwing it in the bin. That got the point through.</comment></comment></comment>


Tornado Web Framework/Server hits 1.0 - <AUTHOR> http://groups.google.com/group/python-tornado/browse_thread/thread/6040b860b74444e0

<comment><USER2> Sweeeet. I've been wondering for a while about doing Comet style realtime stuff in Django and wondered if Tornado would work. This post inspired me to search the Tornado mailing list and, sure enough, there's a great thread with a full example explaining how to do it. Very awesome, I love the internet.

For others wondering about how to do realtime in django, here's the thread: [http://groups.google.com/group/python- tornado/browse_thread/...](http://groups.google.com/group/python- tornado/browse_thread/thread/a76c14cacaa303b8/e004d1f265030694?lnk=gst&q=django#e004d1f265030694)

<comment><USER3> Wow, that's awesome. Thanks for sharing :)

</comment></comment><comment><USER4> I've been using Tornado for the past few months, and it's great. The code is straightforward and easy to read. It does what it does very well.

See <http://www.tornadoweb.org/> for an intro.</comment>


On code quality: rewrite once - <AUTHOR> http://blog.tetrack.com/2009/01/on-code-quality-rewrite-once/ All you have to do is delete your first implementation and rewrite all the code from scratch. The main reason for this is that you can focus on code quality without being constrained by the existing implementation. <comment><USER2> I find rewriting is more necessary in some languages than others. In Java, a rewrite was common. In Lisp, I don't think I've ever rewritten: the first dumbest prototype is just one continuous refactoring away from the final product. Python and Ruby were somewhere in between.

I kind of have a vague feeling for why this would be true, but I can't quite put it into words. Maybe it has to do with how much structural stuff I have to write, or how directly I can express my program in the first place. Thoughts?

<comment><USER3> I've noticed that python seems to stay cleaner than php would, but I'm not sure if it's the framework that's keeping things neat or the fact that php made it easier for the code to get dirty. It's also easy clean up a few parts of python without effecting too much where php might need a rewrite.

</comment></comment><comment><USER4> Isn't this what refactoring is ? As you mature as a coder, you will be able to write good code for certain standards which need not be thrown away. So having a look at the code and fixing the crappy portion will be more productive than throwing away the whole implementation. I think whole rewrite rule is useful when you start working on a new technology... but if you are using a stack for considerable amount of time, then refactoring is the way to improve the code quality.

<comment><USER5> Well, maybe. I think it depends on the project.

At the moment, I'm working interfacing a handheld device with a networking device. I quickly wrote a prototype to work out implementation details (since connectivity required using a particular protocol). That's not to say I didn't write parts of the prototype to be refactored or pulled out, but given that I had to do a fair amount of exploratory programming to determine the best implementation, much of the prototype code will be thrown away.

<comment><USER4> So you are working with a new technology stack and exploring new things... throwaway prototype is good when youa re doing something new. If you were versed witht he particular protocol, would you need to write to throwaway prototype ? I dont think so...

</comment></comment></comment><comment><USER6> Beware of the dreaded _Second System_ Effect. As in your second system is assured to be a disaster because you think you know enough but never really do. The practice of rewriting everything once assures that you will eternally experience the _Second System_ Effect.

OK to rewrite the really bad stuff that has a high density of bugs. OK to adapt your architecture if it really doesn't fit the problem domain you are discovering and you really can make it simpler. OK to clean up basically ugly code that neither you nor others can easily understand. The important thing is to have a good reason to rewrite besides "I always do it that way."

Always rewrite from scratch on principle? This is the path to madness, failure, project overruns, and downright disasters. That is unless you are very very lucky. Luck helps but good software is not produced by luck.

<comment><USER7> Not entirely true, even Brooks on "The Mythical Man Month" suggests to _Plan to throw one away_.

So the suggestion isn't "the path to madness". The way to avoid the _Second System Effect_ is simply to make a commitment not to develop new features on the rewrite. This second system will do the same as the first one except the code will be better.

An example of a successful project that did this is _Subversion_ they pretty clearly said that they wanted to Create a CVS equivalent with certain annoyances corrected. That clear purpose and definition helped them avoid feature creep.

</comment></comment><comment><USER8> I use this technique all the time, a quick throwaway prototype to get something working and the basics figured out, then sit back think about how it should be done properly and redo it bearing in mind the possible traps you missed the first time.

</comment><comment><USER9> Yes, I entirely agree with doing this, especially if you get requirements while you're working. In college, I was working on a site that I received piecewise requirements, and one requirement would cause me to rewrite one module that would cause conflicts with others. Once I was satisfied that I had all of the requirements, I simply rewrote everything almost entirely from scratch.

So yes, its best to try to write it correctly the first time, but its ok to rewrite it a second. After that, you should probably look as to what you're doing wrong.

</comment><comment><USER10> I think its best to write once to get the tests done right and to make sure the design works, then rewrite to get the code more readable. That way the tests will save you if you screw up the rewrite.

</comment><comment><USER11> IMHO there's some code that deserves more than 1 rewrite.

For example the library Powerplant (Metrowerks' mac equivalent to MFC) was rewritten a dozen times before it was released, as its design patterns needed a lot of fishing out to get them right.</comment>


Should Parents Post Pictures of Their Kids on Facebook? - <AUTHOR> http://healthland.time.com/2013/09/06/should-parents-post-pictures-of-their-kids-on-facebook/?iid=hl-main-lead

<comment><USER2> I think the article raises a good question, but the way they argue that point strikes me as a bit of a stretch:

> There was plenty of admonishing following Miley Cyrus's shenanigans at the > Video Music Awards about the ill effects of constant exposure and living in > the spotlight from a young age. Well in a way, that's what is happening to > this generation of kids, albeit on a smaller scale.

I'd argue that this is beyond just "a smaller scale". Or if it is merely a smaller scale, it's about as much smaller as the non-digital fact that your kids will be seen by your friends and family IRL.

There's something asymmetrical about Miley Cyrus-level fame that doesn't happen with your kids' photos on Facebook. I personally know most of the people who view my Facebook page, and they know me. I don't have screaming fans. When I go out in public, strangers don't ask me for an autograph. Paparazzi doesn't try to photograph me. There's no idolization (or criticism) by millions of strangers.

Saying it's the same thing, but on "a smaller scale" downplays the fact that many behaviors--I would argue the most problematic ones--don't even EXIST until you reach a larger scale.

</comment><comment><USER3> Nobody should post anything on Facebook.</comment>


Kindle Subscribers Will Be Able to Access NYTimes.com for Free - <AUTHOR> http://techcrunch.com/2011/03/28/kindle-subscribers-will-be-able-to-access-nytimes-com-for-free/

<comment><USER2> As far as I've been reading on the internet, everybody will be able to access NYTimes.com for free.</comment>


Show HN: List of available domains - <AUTHOR> https://assafmo.gitlab.io/available-domains/ <comment><AUTHOR> A while ago I made for myself a list of available domains, and here it is.

There were a lot more, but I've filtered it to show only ones with appraisal value >= 100$.

I'm posting this only to get HN feedback. (Although I've added affiliates, so if I'll start making some cents from open sourcing this list I'll know I've helped some of you guys. :-))

Cheers, assafmo.</comment>


Ask HN : Apache Airflow vs. Celery - <AUTHOR> I see many common features between airflow and celery. Airflow uses Celery as an Executor. A DAG in airflow is similar to a chain in celery. What are the specific cases airflow is better and which one is good for production? <comment><USER2> Both have a place but are generally used differently. Below is my opinion of the two, though you could in theory use these systems differently.

Airflow executes repeatable processes, usually on a schedule. You probably won't want to use airflow to kick off a process per user - an airflow run is "heavy". Within a run you would usually run Spark or the like to move and transform large heaps of data. Airflow makes for a good orchestrator that makes sure all the jobs are run in the right order. Airflow is best used as a better structured version of shell scripts to create reporting and data science pipelines once an hour.

Celery is more of a task executor. I don't have as much experience with celery specifically, but generally background work systems like celery are built as a way to reliably do work asynchronously from a user request. Think async api calls - e.g. sending emails. You could just do in another thread (or just don't await in node and let it happen somewhere), but you want something to monitor that these things are done even in the face of kill -9. Systems like Celery tend to perform better when there aren't dependencies between messages, and messages are small - e.g. dealing with a single user. Usage of celery-like systems also tends to be real-time - you want it done asynchronously, but "sooner than tomorrow."</comment>