Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Jan 31 2019 18:12
    ArturAralin closed #312
  • Jan 31 2019 18:12
    ArturAralin commented #312
  • Jan 31 2019 12:57
    codecov[bot] commented #313
  • Jan 31 2019 12:57
    codecov[bot] commented #313
  • Jan 31 2019 12:56
    codecov[bot] commented #313
  • Jan 31 2019 12:56
    codecov[bot] commented #313
  • Jan 31 2019 12:56
    codecov[bot] commented #313
  • Jan 31 2019 12:56
    codecov[bot] commented #313
  • Jan 31 2019 12:55
    codecov[bot] commented #313
  • Jan 31 2019 12:55
    codecov[bot] commented #313
  • Jan 31 2019 12:54
    codecov[bot] commented #313
  • Jan 31 2019 12:54
    codecov[bot] commented #313
  • Jan 31 2019 12:46
    Avaq review_requested #313
  • Jan 31 2019 12:46
    Avaq opened #313
  • Jan 31 2019 12:45

    Avaq on types

    Add misisng type definition for… Add missing type defintion for … (compare)

  • Jan 31 2019 12:38
    Avaq assigned #312
  • Jan 31 2019 12:38
    Avaq commented #312
  • Jan 31 2019 12:16
    kherdier starred fluture-js/Fluture
  • Jan 31 2019 10:45
    ArturAralin commented #312
  • Jan 31 2019 10:35
    Avaq commented #312
Diego Ceresuela
@dicearr
I tweaked the example and I can confirm that both approaches, chain (sequence) and traverse are concurrent as we expected. The chain (parallel) and the one using ConcurrentFuture are parallel.
Vladimir Kapustin
@kapooostin
Great! I yet have no intuition about using traverse. Thank you for bringing it up.
Aldwin Vlasblom
@Avaq
You can use 'traverse (Par) (Par)' instead of 'sequence' to make the traversal in parallel.
Vladimir Kapustin
@kapooostin
I guessed, looking at seq docs, that there should be something like that, but I still have very vague understanding of traverse and Concurrent Future.
Vladimir Kapustin
@kapooostin
@Avaq I just made my second module with fluture instead of Promises or Streams. And it was extremly satisfying experience! The last one was very small (I needed to create a bunch of vcards, encode them as qrcodes and save to svg) but still the process made me feel happy. Everything is a pipe now :)
Aldwin Vlasblom
@Avaq
Excellent! :D
Vladimir Kapustin
@kapooostin
Hi, all! Does anybody here have an experience of using Fluture with gulp tasks?
Aldwin Vlasblom
@Avaq
I don't, but I am curious what the challenge is.
Vladimir Kapustin
@kapooostin
I’m still digging into it, but BrowserSync now throws an odd error. I converted one task: now it returns a Future consumed by promise instead of a Stream. I’m not sure where the problem is because I had to do a lot of changes to make it work. The task itself runs without any problems. But BrowserSync hiccups right from the start trying to re-run it. And promise returns a regular Promise so it shouldn’t be the cause.
Vladimir Kapustin
@kapooostin
Well, the issue I bumped into was complitely Fluture-unrelated: logging utils package I imported modified the system console.log function which was unexpected by another logging package used by BrowserSync. Fluture itself works inside a gulp task without a hitch.
Aldwin Vlasblom
@Avaq
Oh, that must've been a pain to uncover. Good that Fluture works fine though! :)
Vladimir Kapustin
@kapooostin
Took me half a day. And no help from google though the package in question has 1M downloads a month, and BrowserSync—2.5M. Modifying console.log looked quite unnecessary, I removed it and the package worked just fine.
Henrique Barcelos
@hbarcelos

Hey guys, I need some help here. I have a Future returning function which receives data from cache as parameter.
I need to fetch the fresh data (with another Future returning function) and return both in a tuple.

cached => {
   return F.parallel(2)([F.resolved(cached), getFresh(cached)]);
}

Is there a better way to write this?

I guess this is somewhat common, so there might be a way to write this point-free style, but I can't think of how
Aldwin Vlasblom
@Avaq
@hbarcelos Instead of parallel(2), you could use both(): cached => both(resolve(cached)) (getFresh(cached))
Then, from there, to make it point free, you just need one combinator. See if you can spot it: https://gist.github.com/Avaq/1f0636ec5c8d6aed2e45
Vladimir Kapustin
@kapooostin
Hi, all! I needed a way to ensure the a certain step is done before continuing. Something like a tap but with Future-returning function. So I've come up with this:
// before :: ( a -> Future ? ) -> a -> Future a
const before = beforeFn => value => and( resolve( value ) )( beforeFn( value ) );

// ensureDirExists :: [ [ String ], String ] -> Future [ [ String ], String ]
const ensureDirExists = before(
  ( [ images, dest ] ) => attemptP( () => mkdirp( dest ) )
);
Maybe it is a common case ant there is some idiomatic solution?
Aldwin Vlasblom
@Avaq
@kapooostin I believe you are looking for apFirst, apSecond, or chainFirst. They are common functions to derive from ap and chain, and some (if not all) of them are available in Sanctuary.

Hm, the app does not do multi-line messages.
const mkdir = encaseP (mkdirp) 

pipe ([
  mkdir ('it'), 
  apSecond (stuffWithDir), 
])
in this example, stuffWithDir is also a Future
Vladimir Kapustin
@kapooostin
@Avaq Thank you, I’ll check it!
John Goza
@spexican924

Hi all! I'm attempting to use encase to wrap a method that creates a readstream but I think I might be misunderstanding something. When the readstream is created successfully I get a Uncaught TypeError: encase() expects its first argument to be a Function.thrown back. Code example:

        const ssh2sftp = require("ssh2").Client;
        const {reject, resolve, encase} = require("fluture");
        // try {
        // resolve(ssh2sftp.createReadStream("myfile.txt");
          encase(ssh2sftp.createReadStream("myfile.txt"));
        // } catch (err) {
        //   reject(err);
        // }

I've also tried using attempt instead of encase. Just wondering where my gap is here or what I'm missing

Commented code is my try/catch that works for my use case. Figured it might be helpful to include it for reference
Diego Ceresuela
@dicearr
encase requires its first argument to be a function. You can try encase (ssh2sftp.createReadStream.bind (ssh2sftp)) ("myfile.txt"). Similar thing happens with attempt (() => ssh2sftp.createReadStream ("myfile.txt")).
Vladimir Kapustin
@kapooostin
John Goza
@spexican924
Thank you guys! I actually use fluture-node in this project as well. Great library.
voxbono
@voxbono
Hey, I'm trying to find a way to use mongodb and Fluture together. I found a chat in the history here, but I couldn't get it to work. So I need to ask some questions instead.
I have an express server that should connect to mongoDb on startup. I want to be able to reference that connection at every query I make to the database. (I don't want to close the connection between each query). How can this be done with Futures? Or can it even be done with Future? The connect method is a promise. And I want to see if I can avoid promises in my application altogether. I also want to avoid having this connection stored as a global variable if possible. Does my question make sense?
Diego Ceresuela
@dicearr
Hi @voxbono. You can take a look at Booture (https://github.com/fluture-js/booture/). It is a tool for bootstrapping applications, the example in the README is a web server with multiple databases.
voxbono
@voxbono
@dicearr Thank you for the feedback! Question: won't this lib open and close the connection for every request?
Diego Ceresuela
@dicearr
Well. It is up to you. If in your acquiring function you acquire a connection and in your disposing function you close it, yes it will create a connection for every request. But you can also acquire a Pool, and reuse the connections from the pool in your application.
Actually, if you do the first thing, it is not going to create a connection per request but re-use the same connection for every request.
Diego Ceresuela
@dicearr
I've checked the mongodb docs and I couldn't find any Pooling reference. I guess it is internally done in the MongoClient.
voxbono
@voxbono
All I know is that I found a few posts on stack overflow saying that closing connection between each query is bad practice. The connection should be open as long as the Node app is alive, and close once the Node app shuts down. And I struggle to figure out a way to do this without storing a global reference to the connection. I only do it once, but still, my autism hates it! :D
Diego Ceresuela
@dicearr
That is exactly what you can do with Booture. Acquire a connection, reuse it in your application, and finally dispose it when the application is closed.
voxbono
@voxbono

@dicearr Sorry if I ask some silly questions. Now I'm looking at the last part of the sample:

const program = withServices (({app}) => Future ((rej, res) => {
  const conn = app.listen (3000);
  conn.once ('error', rej);
  process.once ('SIGINT', res);
}));

fork (console.error) (console.log) (program);

How can I get this to work with an express app?
How can I do something like this in all of this?

const app = express();
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
Diego Ceresuela
@dicearr

You could use the application bootstrapper like in the example:

const acquireApp = (mongo, config) => (
  attempt (() => require ('./imaginary-app').create (mongo, config))
);

const bootstrapApp = {
  name: 'app',
  needs: ['config', 'mongo'],
  bootstrap: ({mongo, config}) => acquire (acquireApp (mongo, config)),
};

And the imaginary application would be your Express app and could look like this:

const express = require ('express');
const users = require ('./controllers/users');

module.exports.create = (config, mongo) => {
  const app = express ();

  app.use (logger (config.logger));
  app.use (express.json ());
  app.use (express.urlencoded ({ extended: false }));

  app.get ('/users', users.list (mongo));
  app.post ('/users', users.add (mongo));

  return app;
}
Fabiano Taioli
@ftaiolivista_gitlab
Hi All. I created a data structure based on Fluture and Knex to works with query in a more lazy way, if can be useful to anyone the code is here: https://github.com/FbN/iodio
Aldwin Vlasblom
@Avaq
Cool stuff @ftaiolivista_gitlab!
Fabiano Taioli
@ftaiolivista_gitlab
@Avaq Thank you very much :)
Oler
@rodrigooler
How would you convert this to Fluture?
const [x, y] = await Promise.all([getX(), getY()])
I saw the parallel in the documentation but I'm confused
Oler
@rodrigooler
?
Diego Ceresuela
@dicearr
Assuming that both getX and getY return promises, you could do const eventualValues = Future.both (Future.attemptP (getX)) (Future.attemptP (getY)), and then you can run the computation by forking it Future.fork (console.error) (console.log) (eventualValues). If you also want to use do-notation then you can check https://github.com/fluture-js/fluture#go.
2 replies
Stefano Vozza
@svozza
has anyone tried to use Fluture with the Crocks ReaderT (https://crocks.dev/docs/crocks/ReaderT.html) monad transformer? i thought it would work with any fantasyland compliant Future but i’m getting errors that look like it depends on Crocks specific stuff
Sebastian
@hellos3b
Love the library so far, but not enjoying trying to combine multiple futures in typescript. Maybe this is the only , but wondering if someone can give me a better suggestion
So I have two interfaces, a User and an Activity, and I need to get User first to get an oauth token to then fetch Activity, but I need both for my output
type User = {
  name: string;
  refreshCode: string;
}

type Activity = {
  title: string;
}

const getUserById: (id: string) => Future<Error, User>;
const getActivityById: (id: string) => (code: string) => Future<Error, Activity>;

// Get userId and activityId from a webhook, and I want to fetch the data and return a tuple of both
const getData = (userId: string, activityId: string) => Future<Error, [User, Activity]>
Here are the 3 ways that I've thought of handling it, first is how I've handled it, second is as promises, third is with go
// This feels hard to read/follow as there's not a lot of implicit casting
const getData = (userId: string, activityId: string) => R.pipe(
  getUserById,
  F.chain (
    (user: User) => R.pipe(
      getActivityById(activityId),
      F.map ((activity: Activity): [User, Activity] => [user, activity])
    )(user.refreshCode)
  )
)(userId)

// Promises are easier
const getData = async (userId: string, activityId: string) => {
  const user = await getUserById(userId);
  const activity = await getActivityById(activityId)(user.refreshCode);
  return [user, activity];
}

// Using `go` gets close, but the typing is weak
const getData = (userId: string, activityId: string) => F.go (function*() {
  const user: User = yield getUserById(userId)
  const activity: Activity = yield getActivityById(activityId)(user.refreshCode);
  return [user, activity] as [User, Activity]
})
lambdaydoty
@lambdaydoty

@hellos3b if you could change the signature of getActivityById:

const getActivityById: (id: string) => (code: string) => Future<Error, Activity>

into:

const getUserActivityById: (id: string) => (user: User)=> Future<Error, [User, Activity]>

, then the getData could be defined as a simple pipe:

const getUserById = id => F.resolve ({ name: 'Alice', refreshCode: '*:+*:+*:+' })
const getUserActivityById = id => user => F.resolve ([user, { title: 'Good Actitivy', code: user.refreshCode }])

const getData = (userId, activityId) => getUserById (userId)
  .pipe (F.chain (getUserActivityById (activityId)))

const app = getData (123, 456)
F.fork (console.error) (console.log) (app)