These are chat archives for ramda/ramda

21st
Feb 2017
Matthew Willhite
@miwillhite
Feb 21 2017 02:28
@jonahx normally when you go from a list to an object you’d want to think in terms of reduce, so maybe something more like:
const rawInputs = reduce((acc, k) => assoc(k, stream(‘’), acc), {}, keys)
Jonah
@jonahx
Feb 21 2017 02:35
@miwillhite i prefer my version to that. in general, i am not a fan of reduce.
Matthew Willhite
@miwillhite
Feb 21 2017 02:35
I’m curious why you don’t like reduce…
Also, the reduce version has only one iteration over keys, whereas your version has two…
Jonah
@jonahx
Feb 21 2017 02:37
@miwillhite eh, big O is the same, so i’ll take the readability until it matters. re: reduce, it’s a thin veneer over a temporary variable being mutated inside a loop.
Matthew Willhite
@miwillhite
Feb 21 2017 02:38
ah yeah…well if you are looking for a more imperitive approach, then why not just use a for loop?
Jonah
@jonahx
Feb 21 2017 02:38
the point is i’m not looking for an imperative approach.
reduce is imo imperative programming in sheep’s clothes
Brad Compton (he/him)
@Bradcomp
Feb 21 2017 02:40
I would argue that reduce is an essential building block for functional programming, not just borrowed from imperative languages
Gabe Johnson
@gabejohnson
Feb 21 2017 02:40
@jonahx all the abstractions are a veneer
Jonah
@jonahx
Feb 21 2017 02:40
@Bradcomp I rarely have a use for it. I’d caveat my earlier statement thought by saying point-free versions of reduce are fine.
Brad Compton (he/him)
@Bradcomp
Feb 21 2017 02:41
It's lower level than map and filter, in the sense that you can build map and filter out of reduce.
But a lot of functional abstractions can be expressed as folds.
It's funny I hear the same complaint often against map: it's just a different way of writing a for loop
Jonah
@jonahx
Feb 21 2017 02:44
@Bradcomp I have no issue with map. To me it expresses a distilled natural concept — “take all this stuff, do this to each one”. the problem with the for loop is not what it’s doing, it’s that it exposes all this unnecessary machinery to do it — the boilerplate syntax, the temporary index variable, etc.
Matthew Willhite
@miwillhite
Feb 21 2017 02:44
That's why folds are, along with maps and filters, one of the most useful types of functions in functional programming.
— learnyouahaskell.com
Jonah
@jonahx
Feb 21 2017 02:45
@miwillhite I am aware that a fold is a basic concept of fucntional programming. I am arguing that if you can rewrite a non-point-free reduce using a construct that is a pure transformation without an intermediate temporary variable being mutated, your code will be easier to read.
Brian McKenna
@puffnfresh
Feb 21 2017 02:49
:+1: folds suck
if you're using fold, you're probably reimplementing something
Brad Compton (he/him)
@Bradcomp
Feb 21 2017 02:49
... that was implemented originally with a fold
Matthew Willhite
@miwillhite
Feb 21 2017 02:50
const rawInputs = reduce(flip(assoc(__, stream(''), __)), {}) point free :joy:
Brad Compton (he/him)
@Bradcomp
Feb 21 2017 02:50
@miwillhite while that is point free, it will also assign the same stream to each key
Matthew Willhite
@miwillhite
Feb 21 2017 02:51
oof
I’m done, I like the reduce solution, but I’m pretty new at this stuff still
Jonah
@jonahx
Feb 21 2017 02:52
@Bradcomp I don’t understand why that’s a counterargument. we’re trying to write expressive, high-level code. so it’s actually an argument in favor if what @puffnfresh and I are saying.
Brad Compton (he/him)
@Bradcomp
Feb 21 2017 02:52
I like the reduce solution too
Matthew Willhite
@miwillhite
Feb 21 2017 02:52
@jonahx Please post something that you are satisfied with when you find it!
Jonah
@jonahx
Feb 21 2017 02:54
@miwillhite I think my original is fine, but still a little long for what i’m doing. I’m not sure there is a ramda funtion to express it even more compactly, thouhg (why I asked). I suppose the solution I’d be satisfied with is make a new utility that expresses the concept, lock up the implementation in a closet I don’t have to look at, and then just call that
Matthew Willhite
@miwillhite
Feb 21 2017 02:54
;)
Brad Compton (he/him)
@Bradcomp
Feb 21 2017 02:55

reduce is imo imperative programming in sheep’s clothes

This is what got me riled up.

I am arguing that if you can rewrite a non-point-free reduce using a construct that is a pure transformation without an intermediate temporary variable being mutated, your code will be easier to read.

This too. reduce does not mutate a variable, and the reduce solution imposed was immutable.

It's lower level than map and filter

I agree here that it's lower level, but that doesn't mean it's imperative or shouldn't be used. It's a foundational concept in FP and when you are trying to get a single value out of a list then you should be looking at reduce or a function that is built from a fold.

'imposed'.replace('im', 'pro')
:stuck_out_tongue:
Rick Medina
@rickmed
Feb 21 2017 02:58

if you're using fold, you're probably reimplementing something

could someone explain this?

Brad Compton (he/him)
@Bradcomp
Feb 21 2017 03:00
mergeAll(map((k) => ({[k]: stream('')}), keys))
Jonah
@jonahx
Feb 21 2017 03:00
@Bradcomp I stand by the riling statement :), even though technically you are correct the ramda version returns a new object on each iteration. But I consider that an implementation detail. Eg, most code constructing objects using that native JS reduce will mutate the same object, building it up. But again, whether you do it that way or the cleaner way ramda does it, conceptually you are doing mutation imo.
Brad Compton (he/him)
@Bradcomp
Feb 21 2017 03:01
:point_up: There's my non-fold version ;)
Jonah
@jonahx
Feb 21 2017 03:01
@Bradcomp I like it
I think you’ve just won my argument for me though :P
Matthew Willhite
@miwillhite
Feb 21 2017 03:02
that is nice! I had one more go, trying to avoid reduce:
into({}, map(flip(objOf)(stream(''))), ks);
but not very legible imho
I get the argument now too, was being a bit dense at the start of the conversation ;P
Brad Compton (he/him)
@Bradcomp
Feb 21 2017 03:04
I use reduce a lot, and it isn't just in a mutative way that you imply. It's useful for reducing a list to a single value. Often that means taking a binary operation of a -> a -> a and applying it to an [a] which is really a different case.
It is lower level, but it doesn't really come from an imperative place. It has a clear semantic meaning that can point you toward how you're supposed to read a function, which can help readability once you know the patterns
Jonah
@jonahx
Feb 21 2017 03:06
@Bradcomp I think those cases fall into my “point-free” exception. eg, arr.reduce(:+) in ruby is nice
Brad Compton (he/him)
@Bradcomp
Feb 21 2017 03:07
Rather than viewing the immutability of the Ramda version as an implementation detail, I would suggest that the imperative mutation is really more of the implementation detail while the concept is an immutable function from a list to a single value.
Jonah
@jonahx
Feb 21 2017 03:07
again, to me it comes down to if your specifying a concept (“take all these things, sum them up”) versus spelling out the details of how the summing should take place
arr.reduce(:+) is the former, arr.reduce(0) {|m, x| m + x} is the latter, and it’s not just because it’s more verbose
Brad Compton (he/him)
@Bradcomp
Feb 21 2017 03:16
@rickmed I think he means that most of the time there are functions built on folds you can usually use instead of using reduce in the raw.
Rick Medina
@rickmed
Feb 21 2017 03:18
@Bradcomp thanks. Maybe I'm not seeing something, but personally I much rather implement a reduce in one line than having to memorize hundreds of functions for each specific case
also, I really don't get why reduce is mutative
Jonah
@jonahx
Feb 21 2017 03:19
@rickmed in practice you’re looking at memorizing 10-20 that will vastly improve readability
ofc you can keep going forever, but i agree there is a balance between the cognitive load of your “vocabulary” and expressiveness
the argument is where to draw to the line, which is probably a different answer for most people but not as different as you’d think (meaning our shared brains causes the answers to be pretty similar, same way there’s a concensus that a particular apps UI is untuitive, etc)
Brad Compton (he/him)
@Bradcomp
Feb 21 2017 03:28
@rickmed I agree. While I use a lot of Ramda's functions, reduce can often be the most understandable solution.
Brian McKenna
@puffnfresh
Feb 21 2017 03:28
@rickmed code duplication sucks
@rickmed do you use .map?
Rick Medina
@rickmed
Feb 21 2017 03:31
My personal view is that is that there would be much more than 10-20. Also, I actually argue that is more readable since when I see a reduce I know the function is folding into a structure. Otherwise I would have to remember is it "merge", "mergeBy", "mergeAll", "mergeWith"? who knows exactly what all of those do

@rickmed do you use .map?

yeap

Jonah
@jonahx
Feb 21 2017 03:37
@rickmed I think merge and mergeAll are pretty well-named and self-explanatory. I don’t see a mergeBy. as for mergeWith, there are a handful of xxxWith functions, like the zipWith, in all cases it means do the thing, and then apply a function after it. so the “with” means “with a function”. So you’ve only had to remember 1 new thing, and you’ve gained a bunch of expressive power
Rick Medina
@rickmed
Feb 21 2017 03:42
@jonahx assuming you are using ramda. What about if you use a different library or language?
Matthew Willhite
@miwillhite
Feb 21 2017 03:43
@rickmed That would be like saying “I’m moving from underscore to ramda, so I’m going to only use what I learned in the former"
Jonah
@jonahx
Feb 21 2017 03:46
@rickmed it’s always the same dilemma. one of the costs of learning a new language is becoming familiar with it’s idioms and finding and learning it’s libraries. that’s the reason people are more productive in languages they know. so sure, if you’re programming in a new language you may not have time to find the best solution, so you just write some code which reimplements a solved problem. that’s what makes your code worse than an expert’s.
Rick Medina
@rickmed
Feb 21 2017 03:47
@miwillhite my point is that it would be limiting yourself of taking advantage of all these generic functional interfaces that work in different contexts instead of memorizing specific APIs
Matthew Willhite
@miwillhite
Feb 21 2017 03:50

I wouldn’t call it limiting at all. Each new library is a different take, so in fact by looking at how different libraries do things you gain perspective and are better able to solve problems.

For example, I have found several functions in Ramda that I’d love to see in the little bit of Ruby work I do…and I think about how I could improve my Ruby code just by thinking about it differently. I am a better Ruby developer for the JS that I write. I am a better JS developer for the Objective-C code that I have written…

Brian McKenna
@puffnfresh
Feb 21 2017 03:53
@rickmed why don't you use .reduce instead of .map?
instead of using .map you could write it each time using .reduce, right?
Brad Compton (he/him)
@Bradcomp
Feb 21 2017 03:55
I would say there's a large leap from 'use map instead of reduce' to 'folds suck'
Rick Medina
@rickmed
Feb 21 2017 03:55
@puffnfresh sure, but map is not specific to lists isn't it? I can't apply merge to lists, objects or futures
Brian McKenna
@puffnfresh
Feb 21 2017 04:03
@rickmed no, map works on lists and futures
and either, and maybe, and ...
and functions :)
Rick Medina
@rickmed
Feb 21 2017 04:04
that's what I'm saying! :)
@miwillhite is just that I see so many times in the gitter or whatnot people asking for the ramda function that solves their super specific case, and I feel they're missing an important benefit of what, imho, fp provides. Mostly bc they're coming from an imperative environment using something like underscore/lodash
Matthew Willhite
@miwillhite
Feb 21 2017 04:09
I agree that it is a balance. For you AND for your team. I use reduce a lot, but for example I found mergeWith the other day and found it was a perfect fit for what I needed. It is a new term in my vocabulary and I’m excited to share it with my teammates!
reduce can feel a bit verbose at times…and maybe that is a good time to look for a better abstraction
we are a small team and wear lot’s of hats, so often times reduce is a great way to communicate my intent to a person less involved in “my” part of the codebase. But I make those judgements based on a lot of factors.
Brian McKenna
@puffnfresh
Feb 21 2017 04:15
@rickmed so you use .map when abstract but .reduce when specific?
if you want to .map just a list, what do you do?
Rick Medina
@rickmed
Feb 21 2017 04:27
@puffnfresh for me, if I feel I can implement in terms of fold in a 1-2 liner in less time than looking for the specific api (IF it exists), I do it.
Rick Medina
@rickmed
Feb 21 2017 04:39
with the exceptions of the generic functional interfaces provided by the type (eg: map)
Brian McKenna
@puffnfresh
Feb 21 2017 04:42
@rickmed given type search, are you still quicker at implementing functions than finding them?
Stefano Vozza
@svozza
Feb 21 2017 07:08
it's interesting, for me reduce is a veener over recursion not a for loop. if you think of it that way, it's a beautiful abstraction
foldl :: (b -> a -> b) -> b -> [a] ->  b
foldl f z []     = z
foldl f z (x:xs) = foldl (f z x) xs
The fact that ther type signature basically writes the function for you is particularly nice
Keith Alexander
@kwijibo
Feb 21 2017 08:45
@puffnfresh what type search do you use for javascript functions? (I think @raine did one for Ramda?)
Bernhard Wang
@zwc
Feb 21 2017 08:57

It is possible to use Evolve to use constants instead of a function?

const turnIntoCucumber = { type: 'Cucumber' };
const tomato = { type: 'Tomato' };
const cucumber = R.evolve(turnIntoCucumber, tomato);

But it's still a Tomato :)

Keith Alexander
@kwijibo
Feb 21 2017 08:58
@zwc wrap the constant values with always
Bernhard Wang
@zwc
Feb 21 2017 08:58
Oh, thanks!
Worked like a charm
Keith Alexander
@kwijibo
Feb 21 2017 08:59
i guess you could also do it in two steps with something like flip(merge)({type: 'Cucumber'})
I like your examples :)
Bernhard Wang
@zwc
Feb 21 2017 09:01
I liked that I got to use Always :)
Keith Alexander
@kwijibo
Feb 21 2017 09:11
My take: reduce is useful, and functional, but it is a fairly low level abstraction (a step above recursion, as @svozza said). I share @rickmed's tendency to revert to reduce over higher level abstractions, more than I need to I think, because it can be hard to find the right higher level abstractions.
Keith Alexander
@kwijibo
Feb 21 2017 09:17
I had a nice experience with ramda yesterday when I thought I'd need a custom fold, but quickly banged out a composition (pipe(values, map(pipe(values, sum)), reduce(max, 0))) of functions I figured would exist in ramda, and it all worked the way I expected
Sudarsan Balaji
@artfuldev
Feb 21 2017 09:18
@kwijibo :+1:
Keith Alexander
@kwijibo
Feb 21 2017 09:21
But I do side with @Bradcomp in that, if the API of existing functions doesn't quite fit what you're trying to do, a 2 line custom fold can be more readable than a contorted composition
Bravi
@Bravilogy
Feb 21 2017 10:27
@gabejohnson ok so I played around with crocks and it's good in a sense that it's got a lot of stuff in there. but one and major problem is that it doesn't use prototype for methods and therefore we can't overwrite stuff. For example, I wanted to add a little extra functionality to traverse method on the List and I cannot, because the constructor just returns an object with methods on it..
James Forbes
@JAForbes
Feb 21 2017 11:22
the filter can become R.reject( R.either(R.isNil, R.isEmpty) )
ah its gone :O
Keith Alexander
@kwijibo
Feb 21 2017 11:37
@Bravilogy can you decorate the constructor?
Denis Stoyanov
@xgrommx
Feb 21 2017 11:41
reject(converge(or, [isNil, isEmpty]))
or reject(liftN(2, or)(isNil, isEmpty))
Bravi
@Bravilogy
Feb 21 2017 11:51
@kwijibo can u give me an example please?
Keith Alexander
@kwijibo
Feb 21 2017 11:53
const makeList = (...args) => 
    R.merge(List(...args), {traverse: betterListTraverse })
Bravi
@Bravilogy
Feb 21 2017 12:03
ah I see. and then use makeList instead. Yeah I suppose I could
thanks
Bravi
@Bravilogy
Feb 21 2017 13:01
what's the equivalent to foldMap in ramda?
is it chain ?
Bravi
@Bravilogy
Feb 21 2017 13:10
nvm, wrote my own version
Drew
@dtipson
Feb 21 2017 14:33
my sense is that direct folds are harder to generalize. folding Identity and folding Maybe require different type signatures, for instance. "Folding" a Future also requires a different type signature, and indeed, is very deliberately not called .fold because that would give people the wrong intuition (that is, despite Either[].fold and Future[].fork looking very similar initially, their full type signatures are not the same and they act very differently)
Alexander Doroshenko
@aledoroshenko
Feb 21 2017 14:35
Guys hey! I have this in Lodash/fp. What's the way to do this with Ramda?
const diffById = _.spread(_.differenceBy('id'));
diffById([notesA, notesB])
Matthew Willhite
@miwillhite
Feb 21 2017 14:36
@aledoroshenko can you post an example of what that does?
Adam Szaraniec
@mimol91
Feb 21 2017 14:36
I've not used lodash
Maybe you are searching http://ramdajs.com/docs/#groupBy
Alexander Doroshenko
@aledoroshenko
Feb 21 2017 14:37
Give me a sec, making an example
Drew
@dtipson
Feb 21 2017 14:37
The other thing about folds/reduce is that it can cater to a desire to "get values back out" of types, which is often unnecessary/the wrong direction
Alexander Doroshenko
@aledoroshenko
Feb 21 2017 14:40

From lodash docs, differenceBy:

_.differenceBy('x', [{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }]);
// => [{ 'x': 2 }]

So it looks two collections by prop, and returns difference. In my expample it's curried, so waiting for two objects to inspect. And spread takes array of arguments and call passed function with them, like apply does.

Drew
@dtipson
Feb 21 2017 14:40
especially if you're going to just put those values back into another type anyhow, there's probably a better abstraction between types (like traverse) that preserves their logic/structure throughout
Brad Compton (he/him)
@Bradcomp
Feb 21 2017 16:21
R.differenceWith
Brad Compton (he/him)
@Bradcomp
Feb 21 2017 16:21
R.apply
Brad Compton (he/him)
@Bradcomp
Feb 21 2017 16:21
R.eqProps
Brad Compton (he/him)
@Bradcomp
Feb 21 2017 16:22
apply(differenceWith(eqProps('id')))([a, b])
Galileo Sanchez
@galileopy
Feb 21 2017 17:41
is Bacon.flatMap like .chain???
If so, how can I avoid repeating the elem.asEventStream in the inner map??
const listToClickStream = (linkList) => Bacon.mergeAll(R.map((elem) =>  elem.asEventStream('click'), linkList));
const clickedProps = (linkList) => Bacon.mergeAll(R.map((elem) =>  elem.asEventStream('click').toProperty(false), linkList));
const clickStream = liStream.flatMap(listToClickStream);
const selected = liStream.flatMap(clickedProps);
Rick Medina
@rickmed
Feb 21 2017 17:49
flatmap/bind/chain, should all convey the same intuition -flattening and mapping a type. Haven't used bacon but iirc rxjs flatmap is something equivalent to .map( x => observable).mergeAll
Denis Stoyanov
@xgrommx
Feb 21 2017 17:51
general => chain = join + map or join = chain + id or map = chain + of
Galileo Sanchez
@galileopy
Feb 21 2017 17:51
ok, what's making this hard to understand for me is that IDK if I can do streamOfArrays.mergeAll()
Rick Medina
@rickmed
Feb 21 2017 18:14
that shouldn't work. it would be flattening two different types (if you are trying to get to the array values)
Denis Stoyanov
@xgrommx
Feb 21 2017 18:24
for map/ap/foldMap/traverse u can use a Compose but for monad we need a monad transformer (because controlled effects)
Markus Pfundstein
@MarkusPfundstein
Feb 21 2017 18:58
is there a lisp-like let equalivent available?
then I could get rid of a lot of { } and return statements :-)
Rick Medina
@rickmed
Feb 21 2017 19:22
@MarkusPfundstein are you taking about functions (like why not use arrow fns)?
Galileo Sanchez
@galileopy
Feb 21 2017 19:42
@rickmed
const eventList = liStream.map(R.map((elem) =>  elem.asEventStream('click')));
const clickStream = eventList.flatMap(Bacon.mergeAll);
const selected = eventList.map(R.map(x => x.toProperty(false))).flatMap(Bacon.mergeAll);
I solved it that way
it's a bit clearer
Galileo Sanchez
@galileopy
Feb 21 2017 19:55
so from most, kefir, RxJS and Bacon, only most is fantasyLand compatible?
Markus Pfundstein
@MarkusPfundstein
Feb 21 2017 20:00

@rickmed
well instead of

const f = x => {
    const y = x * x;
    const z = x / x ;
    return new Task(( … ) ..
}

It would be cool to do something like

const f = x => 
    let(‘y’, x * x, 
        ‘z’, x / x,
        (x, y) => new Task)
syntax sucks though and using strings for naming also :(
Brad Compton (he/him)
@Bradcomp
Feb 21 2017 20:02
I know it's not the same, but I often handle that sort of thing with converge
and useWith
Markus Pfundstein
@MarkusPfundstein
Feb 21 2017 20:02
if you refer to me: care to explain with an example ? 😇
Brad Compton (he/him)
@Bradcomp
Feb 21 2017 20:04
converge((y, z) => new Task(...), [(x) => x * x, (x) => x / 2])(x)
Also yes, I do refer to you, sorry :)
Markus Pfundstein
@MarkusPfundstein
Feb 21 2017 20:05
thats quite cool
const f = (x, y) => 
    converge((x, y) => Promise.resolve(x + y), [K, K])(x, y)
not really awesome.. but a starting point
Galileo Sanchez
@galileopy
Feb 21 2017 20:10
@MarkusPfundstein that starts to look lispy :)
the let snippet
Markus Pfundstein
@MarkusPfundstein
Feb 21 2017 20:11
haha, all new js code looks lispy
const getFileTextFromPublication = publicationId =>
    sqlQuery(`select id from files where publication_id = ${publicationId} limit 1`)
        .map(R.pipe(safeHead, R.map(R.prop('id'))))
        .chain(f => f.cata({
            Nothing : () => ReaderTask(_ => Task.of('')),
            Just : id => sqlQuery(`select txt from files_text where file_id = ${id} limit 1`)
                .map(R.pipe(safeHead, R.map(R.prop('txt'))))
                .chain(ft => ft.cata({
                    Nothing : () => ReaderTask(_ => Task.of('')),
                    Just : text => ReaderTask(_ => Task.of(text))
                }))
        }));

const wait = delay => ReaderTask(env =>
    new Task((rej, res) => setTimeout(res, delay)));

const uploadPubsWithDelay = delay =>
    R.reduce((result, next) =>
        result.chain(xs =>
            wait(delay)
                .map(R.tap(e => log('upload next batch')))
                .chain(_ =>
                    R.traverse(ReaderTask.of, putPublicationToElastic, next).map(ys => [...xs, ...ys]))),
        ReaderTask(_ => Task.of([])))
its just paranthesis at wrong places
and no macros ;-)
Galileo Sanchez
@galileopy
Feb 21 2017 20:12
certainly js is a good place to start before delving into lisp
that's actually why started learning it
Markus Pfundstein
@MarkusPfundstein
Feb 21 2017 20:12
i think js is the perfect way to learn fp thanks to ramda and fantasy-land
but only since ES6 tbh
Galileo Sanchez
@galileopy
Feb 21 2017 20:13
what exactly did ES6 brought to the table?
Markus Pfundstein
@MarkusPfundstein
Feb 21 2017 20:13
arrow functions and destructing
Galileo Sanchez
@galileopy
Feb 21 2017 20:13
I just started last year, so I am not familiar with old js
Markus Pfundstein
@MarkusPfundstein
Feb 21 2017 20:13
without them I wouldn’t want to code in js
just imagine the pain of
R.map(function (el) { return el * 2; }, [1,2,3])
Galileo Sanchez
@galileopy
Feb 21 2017 20:14
yep although I like old functions for multiliners
it is too odd to write (x,y,z) =>{ ...; ...; return}
Markus Pfundstein
@MarkusPfundstein
Feb 21 2017 20:14
yeah thats why I need a let
:P
Gabe Johnson
@gabejohnson
Feb 21 2017 20:15
functions are useful for hoisting and this shenanigans
Markus Pfundstein
@MarkusPfundstein
Feb 21 2017 20:15
psst
don’t say the th… word
Galileo Sanchez
@galileopy
Feb 21 2017 20:15
^^ hoisting is one cool feature
I don't rely on this anymore
Gabe Johnson
@gabejohnson
Feb 21 2017 20:16
I love this! But not for it’s common usage.
Markus Pfundstein
@MarkusPfundstein
Feb 21 2017 20:16
i don’t know… I used it a lot, and it just overcomplicates stuff
Gabe Johnson
@gabejohnson
Feb 21 2017 20:16
definitely complicates things
Galileo Sanchez
@galileopy
Feb 21 2017 20:16
it would be interesting to see where this provides a better solution for certain patterns
Markus Pfundstein
@MarkusPfundstein
Feb 21 2017 20:17
its quite cool if you in a continuation, and the this is actually the evoking object
like in mocha
but
this is dangerous (!)
Gabe Johnson
@gabejohnson
Feb 21 2017 20:17
i use if for dynamic scopes
usually w/ call
Markus Pfundstein
@MarkusPfundstein
Feb 21 2017 20:18
btw Gabe, the do is not really what I was looking for
though its quite interesting
Gabe Johnson
@gabejohnson
Feb 21 2017 20:21
I had an idea for a lisp-like let form:
const f = x => 
    let(y= x * x, 
        z= x / x) { … }
very similar to yours
as a macro it would just desugar to
const f = x =>
  ((y=x*x, z=x/x) => {…})()
@MarkusPfundstein ^
Markus Pfundstein
@MarkusPfundstein
Feb 21 2017 20:25
would be awesome
wait
Gabe Johnson
@gabejohnson
Feb 21 2017 20:25
with a return on the last expression statement
in the block
Markus Pfundstein
@MarkusPfundstein
Feb 21 2017 20:26
((y = x * x, is nice
i need to check this
Gabe Johnson
@gabejohnson
Feb 21 2017 20:26
@ram-bot
const f = x => ((y=x*x,z=x/x) => y*z)();
ram-bot
@ram-bot
Feb 21 2017 20:26
Unexpected token =
Gabe Johnson
@gabejohnson
Feb 21 2017 20:27
what version is ram-bot on?
of node
Rick Medina
@rickmed
Feb 21 2017 20:27
@MarkusPfundstein I just create closures with lambdas honestly and I don't mind a few const here and there. Converge et al are cool but I personally don't like that reverses the reading flow
@galileopy definitely not rxjs. Checkout flyd
Markus Pfundstein
@MarkusPfundstein
Feb 21 2017 20:27
no the reverse is no good
problem with const is
you need { }
and then also returns
let must be an expression
Rick Medina
@rickmed
Feb 21 2017 20:28
I don't mind a few here and there :)
Gabe Johnson
@gabejohnson
Feb 21 2017 20:29
works in chrome 56
Markus Pfundstein
@MarkusPfundstein
Feb 21 2017 20:29
const g = (x) => 
    (y = x + x, z = x / x) => Promise.resolve(y + z)()
returns a function
Gabe Johnson
@gabejohnson
Feb 21 2017 20:30
need to wrap the inner arrow function in parens
Markus Pfundstein
@MarkusPfundstein
Feb 21 2017 20:30
const g = (x) => 
    ((y = x + x, z = x / x) => Promise.resolve(y + z))();
that works
Gabe Johnson
@gabejohnson
Feb 21 2017 20:30
yep
Markus Pfundstein
@MarkusPfundstein
Feb 21 2017 20:30
ok, thats a good start
:-)
now how to write a macro
Gabe Johnson
@gabejohnson
Feb 21 2017 20:30
hahaha
Markus Pfundstein
@MarkusPfundstein
Feb 21 2017 20:31
there was some js project that could do macros
Gabe Johnson
@gabejohnson
Feb 21 2017 20:32
it’s on v2 (almost v3) but still experimental
Markus Pfundstein
@MarkusPfundstein
Feb 21 2017 20:35
thanks
Gabe Johnson
@gabejohnson
Feb 21 2017 20:35
:thumbsup:
Markus Pfundstein
@MarkusPfundstein
Feb 21 2017 20:36
wow
sweet is sweet
Gabe Johnson
@gabejohnson
Feb 21 2017 20:42
@xgrommx cool!
Rick Medina
@rickmed
Feb 21 2017 20:59
@xgrommx wow that's just abuse! :smile: you got a new follower though
Denis Stoyanov
@xgrommx
Feb 21 2017 21:06
sometime I tweet some interesting material @rickmed :smile:
Markus Pfundstein
@MarkusPfundstein
Feb 21 2017 21:39
thats cool
Brian McKenna
@puffnfresh
Feb 21 2017 22:24
@svozza foldl is a for-loop, foldr is constructor replacement
@kwijibo I don't use type-search in JavaScript, I search Haskell and if I can't find it in JS then I write it myself and move on