HN user

markov_twain

23 karma
Posts0
Comments15
View on HN
No posts found.

Github keeps the refs for pull requests separate from branches and tags. For example, you can fetch pull request #123 into a local branch called pull-123 with: `git fetch origin refs/pull/123/head:pull-123`.

When you open a pull request from a branch, Github creates the separate pull request refs to track changes to that branch. I'm assuming they have some kind of after-receive hook that updates the ref whenever you push.

However, if you close the pull request (or delete the branch, which automatically closes the pull request), then rebase the branch locally and force push your branch, the pull request will not be updated, and you still see all the comments and historical data.

You can then open a new pull request from that branch, and go through the code review process again. If you mention #123 in the description of the new pull request, it'll create a link at the bottom of the discussion on the original, closed one. This helps keep the separate discussions tied together if you're coming back later and want to see all revisions of this branch.

Thanks for this--I mentioned finagle to jcoglan on twitter yesterday after I read his blog post, and I don't think he was aware of the similarities.

I actually didn't know about futures until I learned about scala and finagle. I watched a talk on twitter's service stack given by marius eriksen and was blown away. My coworkers heard me rambling on about futures for weeks afterwards, and I found that it was difficult to explain what was so great about them. So I'm not surprised at the negative reactions in the comments here (although jcoglan did a much better job of exlaining them than I ever did).

Even worse, he lists "brainfuck" as a technology that's easier to use outside of the big-company matrix. There is no such thing as "brainfuck". There are various dialects and derivative languages. There is the object-oriented programming language which solves its problem excellently and whose limitations are well-known and sometimes very painful, especially when dealing with huge amounts (multi-node) of data. There are other models of computation with different trade-offs. There is no such thing as "brainfuck". It is not a technology or skill or anything else. There's Toadskin and Smallfuck and Doublefuck and various others, but there isn't a "BrainFuck". I can't type "brainfuck start" at the command line and get anything useful to happen.

Sorry, I had to do that.

AFAIK, to use the brightbox packages on heroku you'd have to write a buildpack that either downloads all the dependencies and runs through the same build process that brightbox uses, or use something like heroku-buildpack-fakesu to create a fakeroot type of environment where you can install debs.

Another issue with using the brightbox packages is that if you happen to run into a bug, you'll have to figure out if the bug was caused by something non-standard in your ruby installation or if it's actually a bug in ruby.

One last thing to note is that it looks like the latest brightbox release targets patchlevel 327, while ruby core is at 392 (not counting 2.0.0-p0), so you're missing a lot bug fixes until the brightbox team gets around to building against the latest release.

Unfortunately, Ruby 1.9.x is not copy-on-write friendly, mainly due to the garbage collection strategy. I would venture to guess that most Rails apps these days are running on some version of Ruby in the 1.9 series. So siong1987 is generally correct in the assumption that forking a Rails process n times will consume about n times the amount of memory as a single process. However, Ruby 2.0 has a new garbage collector (called bitmap-marking) that promises to be copy-on-write friendly, so as adoption of that increases your suggestions will become more important.

This bit of ruby should take care of it

    HashMap = HashTable = Map = Table = Dictionary = Hash
And if you're feeling adventurous,
    Object.send :remove_const, :Hash

Why has arithmetic become the universal example of currying and partial function application?

Examples: "Currying", Section 9.3 of Programming in Scala (addition); Ruby 1.9.3 documentation for Proc#curry http://www.ruby-doc.org/core-1.9.3/Proc.html#method-i-curry (addition); "Currying" at the Haskell Wiki http://www.haskell.org/haskellwiki/Currying (division); "Currying" at Wikipedia http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_... (division); "Currying" at c2 wiki http://c2.com/cgi/wiki?CurryingSchonfinkelling (addition, multiplication); PEP 0309 for adding curry to Python http://www.python.org/dev/peps/pep-0309/ (addition); this StackExchange post; etc.

Surprisingly, searching for currying in JavaScript returns this John Resig post with actually useful examples: http://ejohn.org/blog/partial-functions-in-javascript/ although they still have no advantage over doing partial application by just defining a new function.

The only situation in which I've ever thought to myself "I know, I'll use curried functions," was in passing a set of data through a bunch of filters with different arities.

To take an example from HN's front page today, say you want to take some map of key value pairs, grab all the keys, convert them to strings, reject duplicates, sort them alphabetically, and finally concatenate them separated by commas.

Let's assume you have the following functions available (in pseudocode):

  keys(map) -> vector
  flatmap(func, vector) -> vector
  tostring(anything) -> string
  sort(sort-func, vector) -> vector
  compare-strings(string, string) -> first-is-greater, theyre-equal, or last-is-greater
  unique(compare-func, vector) -> vector
  concat(separator, vector) -> vector
and assume you have some way of connecting a list of these filter functions together like pipes, where the output of each function becomes the input of the next:
  reduce(composing-func, list-of-filter-functions, initial-input) -> final-result
Here, the composing-func takes two arguments: input, which is the output of the last iteration (or initial-input); and filter, which represents each function that will be applied in turn to produce some output. Notice that each filter function must take exactly one argument, which matches the return type of the previous filter-function in the pipeline.
  composing-func = (previous-result, filter) -> {
    apply(filter, previous-result)
  }
Now looking at our available functions, we can use currying and partial function application to pre-fill-in some arguments needed so that their input and output types line up:
  list-of-filter-functions = [
    flatmap(keys),
    map(tostring),
    unique(compare-strings),
    sort(compare-strings),
    concat(",")
  ]
And actually, we're now done. All of our filter functions have been partially applied as a sort of initialization for a complicated pipeline.

I'm guessing that currying and partial function application are useful in building parsers (like haskell & scala's parser combinators) but I don't know.

well, I hate to beat a dead horse, but here's a one-liner (ruby):

  (map1.keys | map2.keys).map(&:to_s).sort.join(", ").instance_eval { empty? ? "<none>" : self }

so this is horribly non-idiomatic ruby, but it was fun

  p ->(*_) {
    _.reduce({}, :merge).tap { |_| return "<none>" if _.empty? }.keys.uniq.map(&:to_s).sort.join(", ")
  }.({c:3,d:4,b:2}, {f:5,e:4,a:1})
  
  p ->(*_) {
    _.reduce({}, :merge).tap { |_| return "<none>" if _.empty? }.keys.uniq.map(&:to_s).sort.join(", ")
  }.({}, {})
  
  # "a, b, c, d, e, f"
  # "<none>"
edit: a little bit better.
  func = ->(*_) {
    return "<none>" if _.all?(&:empty?)
    _.flat_map(&:keys).uniq.map(&:to_s).sort.join(", ")
  }
  
  func.({c:3,d:4,b:2}, {f:5,e:4,a:1})
  #=> "a, b, c, d, e, f"
  func.({}, {})
  #=> "<none>"
https://gist.github.com/66b45e765a2aa6a97143