These are chat archives for ramda/ramda

21st
Apr 2015
Raine Virta
@raine
Apr 21 2015 07:08
@TheLudd why is it that ap should run in parallel, part of the spec or?
Ludwig Magnusson
@TheLudd
Apr 21 2015 07:59
Not part of of the spec no
But consider you have a database, you want to make two independent queries and call some function with both. You can do this with lift. If ap supports parallel execution the two database requests will be done in parallel. Otherwise they will be done sequentially.
Scott Sauyet
@CrossEye
Apr 21 2015 10:35
@TheLudd: I think there is a problem with trying to find a parallel between Promise.then and Future.fork. They're really not related. The parallel for Promise.then is Future.map, right?
Ludwig Magnusson
@TheLudd
Apr 21 2015 10:36
@CrossEye Not really. The share some features but Promise.then does other stuff as well.
Promises lack the feature of giving you control over when to execute the underlying function.
So I guess that is one of the reasons for the gap between Promise and Future
Scott Sauyet
@CrossEye
Apr 21 2015 10:39
Yes, but I think that is the closest analogy one would find. It's the basis for all the "Promises are Functors" discussions around.
In some sense you can think of a Promise as though it were the public API of a Future.
And some Promise implementations make this explicit, using also a Deferred object which does control execution.
But then exposing only a Promise gloss on it.
Scott Sauyet
@CrossEye
Apr 21 2015 10:44
If I'm not mistaken, it was the Promise community's lack of interest in exploring this connection which lead to the Fantasyland spec.
Ludwig Magnusson
@TheLudd
Apr 21 2015 10:51
Interesting, had no idea
I do see Futures as essentially different. Migrating will be a non trivial task. I am just trying to find any real big issues and be aware of them if there are any.
Scott Sauyet
@CrossEye
Apr 21 2015 10:57
There are clearly big differences. Futures are defined in terms of common algebraic laws. Promises instead are specified by process flow.
Scott Sauyet
@CrossEye
Apr 21 2015 11:03
The biggest difference I see is that Futues don't generally supply the same read-only gloss that Deferreds do when they expose Promises.
You can still map multiple functions over a Future, but you do have to control it to be sure it's invoked only one time.
Scott Sauyet
@CrossEye
Apr 21 2015 11:14
Reference: promises-aplus/promises-spec#94
Hardy Jones
@joneshf
Apr 21 2015 11:19
do all futures re-execute when you call fork?
meaning, is that what makes a future a future?
it seems like you should be able to cache the result and still have the same semantics
or maybe it's too early for me to be thinking about this...
Ludwig Magnusson
@TheLudd
Apr 21 2015 11:21
@joneshf I guess so. I don't know if there is some standard definition for futures, I just know what drboolean has said. But when you create a new promise, you do supply the fork function. Calling fork is just calling the function you created the promise with. I suppose you can wrap that function in R.once.
This message was deleted
Ludwig Magnusson
@TheLudd
Apr 21 2015 11:27
Hmm that wont really work. The future will only be forkable once. But perhaps there is a similar solution
Ludwig Magnusson
@TheLudd
Apr 21 2015 11:39
@CrossEye Is this where the name fantasy land comes from? =)
https://github.com/promises-aplus/promises-spec/issues/94#issuecomment-16176966
Scott Sauyet
@CrossEye
Apr 21 2015 11:49
I'm guessing so. I don't know the history exactly, but I'm pretty sure that this thread was what lead to the spec. That comment looks likely to have inspired the name.
Ludwig Magnusson
@TheLudd
Apr 21 2015 11:51
Yes. Brian announces fantasy land further down
Seems to be a lot of hostility right away in the conversation. Wonder if I am missing some context...
Raine Virta
@raine
Apr 21 2015 11:54
data.future was renamed to data.task because it removed memoization of the computation
Scott Sauyet
@CrossEye
Apr 21 2015 12:06
I think the person who started the thread has a bit of a reputation for trolling.
Brandon Wilhite
@JediMindtrick
Apr 21 2015 13:57
can you memoize the actual call, so that when fork is called again it just gets the cached value?
Scott Sauyet
@CrossEye
Apr 21 2015 14:27
@JediMindtrick I don't see any obstacle to that.
Ludwig Magnusson
@TheLudd
Apr 21 2015 14:33

I think it is hard to do in a generic way that conforms to functional programming paradigms. Here is an example that mutates state (there may be bugs and perhaps it can be improved):

function Future(f) {
  var self = this;
  this.isForked = false;
  this.rejection;
  this.resolution;
  this.fork = function(reject, resolve) {
    if (isForked) {
      if (this.rejection != null) {
        reject(this.rejection);
      } else {
        resolve(this.resolution);
      }   
    } else {
      isForked = true;
      f(function(e) {
        self.rejection = e;
        reject(e);
      }, function(val) {
        self.resolution = val;
        resolve(val);
      }); 
    }   
  }
}

I am leaning against letting other parts of the code take care of this.

I believe this responsibility lies outside Future. Less is more =)
Brandon Wilhite
@JediMindtrick
Apr 21 2015 14:43
so is it part of the definition that Future.fork should act this way? @raine 's comment seems to imply this
Ludwig Magnusson
@TheLudd
Apr 21 2015 14:44
Is there such a thing as the defenition of Future?
Brandon Wilhite
@JediMindtrick
Apr 21 2015 14:44
heck if I know, I'm still quite new to a lot of this stuff :)
Ludwig Magnusson
@TheLudd
Apr 21 2015 14:45
the constructor should look like this IMHO:
function Future(f) {
  this.fork = f;
}
when you call myFuture.fork() you call the exact function you passed in.
Brandon Wilhite
@JediMindtrick
Apr 21 2015 14:52

so

var myFuture = Future( _ => /*run some ajax*/);

?

Ludwig Magnusson
@TheLudd
Apr 21 2015 14:53
yes
and handle the result in a correct way
Scott Sauyet
@CrossEye
Apr 21 2015 14:58
Don't you want to be able to pass handlers into fork?
Ludwig Magnusson
@TheLudd
Apr 21 2015 14:58
that is what you do when you fork it.
myFuture.fork(errorHandler, successHandler)
Ludwig Magnusson
@TheLudd
Apr 21 2015 15:06
@CrossEye sorry, I perhaps misunderstood you. Some of my code here is pseudo without me stating it =)
explicitly doing myFuture.fork() would be incorrect yes. You need to pass in handlers
Brandon Wilhite
@JediMindtrick
Apr 21 2015 15:08
I would think you'd want to implement in such a way that is agnostic to how f in Future(f) behaves, right? This would be a difference from the first definition, I think. Understanding you put some caveats when you posted it :)
Scott Sauyet
@CrossEye
Apr 21 2015 15:08
Right, but the point was that would you want to have to pass in to the Futire constructor a function which dealt with those handlers itself?
Brandon Wilhite
@JediMindtrick
Apr 21 2015 15:08
sorry...I really meant in the parameters that 'f' accepts
var fut1 = Future( (a, b) => return a + b;)

OR

var fut2 = Future( _ => return angular.$http.get('some/url') );

right?

Ludwig Magnusson
@TheLudd
Apr 21 2015 15:11
@JediMindtrick no, the fork does not return, it should call callbacks
Brandon Wilhite
@JediMindtrick
Apr 21 2015 15:12
so f has to accept two functions then, reject and resolve
Ludwig Magnusson
@TheLudd
Apr 21 2015 15:12
the typical way to create a function that returns a Future would look like this (if we are in node land with their callback conventions)
var getFromDb = function(id) {
  return new Future(function(reject, resolve) {
     someDbFunction.get(id, function(err, result) {
       if(err != null) {
          reject(err)
       } else {
          resolve(result)
       }
     })
  }
}
Scott Sauyet
@CrossEye
Apr 21 2015 15:12
My thought is that Future determines how fork, map, and the result of f () interact. They don't do so directly.
Brandon Wilhite
@JediMindtrick
Apr 21 2015 15:14
I see...I guess the thought is that if we are using a future we're inherently doing something async and would need to have some kind of callback for success and failure...sorry, forgot that bit
Ludwig Magnusson
@TheLudd
Apr 21 2015 15:16
@JediMindtrick Yes, especially if you are creating a Future with the constructor.
Hardy Jones
@joneshf
Apr 21 2015 16:27
:point_up: April 21 2015 7:33 AM you can do impure things internally (like mutate state) and still have a pure interface. If you can ensure that nobody from outside can observe the mutation within, then you really have no way of telling whether or not someone is mutating right? In your example in particular, it should be pure so long as you can't modify rejection or resolution from outside the function.
Hardy Jones
@joneshf
Apr 21 2015 16:34
It's still pure because what changes is the amount of time the computation might take, not the actual value being computed.
Brandon Wilhite
@JediMindtrick
Apr 21 2015 16:36
obviously I'm noob...but if the impure operation you are doing sometimes fails and sometimes does not and that changes whether you call reject or resolve...doesn't that make the function impure? or is the definition not that strict
Hardy Jones
@joneshf
Apr 21 2015 16:37
well sure, if you have a pure function, and use it in an impure setting the whole thing is still impure
but that's not dependent on any particular implementation of any function
But if what you're doing is pure (and just might take a long time to complete) then making it a future is viable, and doesn't change the purity of things
Brandon Wilhite
@JediMindtrick
Apr 21 2015 16:41
that makes sense
Jethro Larson
@jethrolarson
Apr 21 2015 19:38
What method should I use to turn an array-like object (nodeList) into an array?
nm, I can just use anything like map(R.I)