These are chat archives for ramda/ramda

29th
Jul 2015
Hardy Jones
@joneshf
Jul 29 2015 01:52
@algesten I'd argue that it is the types where we all slip up. The problem is, the vast majority of languages don't allow expressive enough types.
And the ones that do don't necessarily make it easy to maintain/refactor.
As a hint, swift and java are definitely not powerful enough.
purescript approaches the level of power we need for lots of things, but it's still young and needs more development to make it the defacto.
Scott Sauyet
@CrossEye
Jul 29 2015 03:28
Just so everyone knows, if you need something from me, ask soon. I leave on a two-week vacation early Sunday morning.
No computers, no internet. Beach, books, volleyball, campfires, and absolutely no defect resolution or production problems!
Hardy Jones
@joneshf
Jul 29 2015 03:40
Two vacations in just as many months?
how do I get a job like that?
that's what I need from you :)
Scott Christopher
@scott-christopher
Jul 29 2015 03:41
I need to get more experience with vacations too.
Martin Algesten
@algesten
Jul 29 2015 06:22

@joneshf i disagree. these statements "types is where we all slip up" i'd argue is an university academic point of view and not pragmatic programmer. so far i never mistaken my array of ints to be an array of objects.

it only becomes a problem in languages like swift, where time hasn't really moved on since the 70s and I still have to chose Int8, Int32, Int64 (and UInt8, UInt32 etc) combined with a compiler that doesn't help me with "a < b" when a and b are different integer types (and don't get me started on nil and Optional types).

javascript on the other hand doesn't have this problem mainly because it reduces the complexity by not even differentiating between float and integers combined with some (mostly non surprising) type inference (for example, truthy falsey is a great thing).

i'd say that part of javascript's success on the server is to do with productivity. less code and more done. and a big part of that is writing less type expressions to satisfy some over zealous compiler.

Simon Friis Vindum
@paldepind
Jul 29 2015 06:28
@algesten You've never had a null pointer exception either? An adequate type system can prevent such errors.
Oh, and that is not type inference. That is coercion.
Simon Friis Vindum
@paldepind
Jul 29 2015 06:37
IMHO falsey and truthy are sad concepts. I can't understand how some JS programmers are happy with such awful semantics inherited from a language (C) that didn't even have booleans. 0 is false, -1 is true, empty string is false, empty array is true. Arbitrary complexity is the worst type of complexity.
Martin Algesten
@algesten
Jul 29 2015 06:41
@paldepind coercion. sorry. too early. i do coffeescript. so my NPE woes are alleviated by a?.foo?(b?[0]) style syntax
@paldepind and no, an adequate type system can't prevent NPE since we are working in a world that is full of null. a network request may very well return nothing. same for reading a file. and we can wish for non-nil as much as we want – but we are working with computers.
Scott Christopher
@scott-christopher
Jul 29 2015 06:44
A type system can enforce those nullable types to be handled safely.
Martin Algesten
@algesten
Jul 29 2015 06:46
@scott-christopher oh you mean like swift's optionals. that's the worst kind of solution. endless amount of syntax to spell out for something so silly.
Scott Christopher
@scott-christopher
Jul 29 2015 06:47
So you’re saying we have a world full of null types, but we shouldn’t have to worry if it’s null?
The coffeescript example you gave of a?.foo?(b?[0]) is effectively syntactic sugar for a monadic chain of optional/null types.
Martin Algesten
@algesten
Jul 29 2015 06:51
no. i'm saying this is one of the key things you have to be aware of as a programmer. many times you have to expect null and many times you don't. swift's optionals makes the compiler treat more cases than necessary as expecting null resulting in endless amount of fluff to satisfy the compiler.
yes. i'm new to functional programming, so i expect there to be interesting solutions to that kind of chaining i haven't seen yet.
nomosyn
@nomosyn
Jul 29 2015 08:35

@CrossEye @paldepind Hi! Little summary:
Backus showed good reasons to use point free style,
which matches the endless and necessary quest to do more with less and ramda in some ways.

This these (2005)
describes "a mechanism to translate classic pointwise code into the point-free
style. This mechanism can be applied to a λ-calculus rich enough to represent
the core functionality of a real functional programming language."

Do you know (or anybody else that might be interested) some papers on the
subject?

Scott Sauyet
@CrossEye
Jul 29 2015 11:00
@joneshf: I'm trying to work my way up to one 1 -2 week vacation every month. One obstacle: my boss.
Hardy Jones
@joneshf
Jul 29 2015 11:47
@algesten it seems like an academic point of view because the vast majority of languages have such non-expressive type systems that the vast majority of "pragmatic programmers" don't even realize that problems like NPE, out of bounds indexing, invalid comparisons, implicit type coercion, and whatever other common issues (which are type errors!) simply don't have to exist.
also note that there are different levels of type errors
mistaking an array of ints for an array of objects is one level that most static analysis can catch: type checker, unit tests, linter maybe?
and there are higher levels of type errors that most static analysis can't catch: array indexing, demeter violations, LSP.
Using swift as the basis of a comparison is not good. Like you said, it's stuck in the 70's with one or two more recent features
Hardy Jones
@joneshf
Jul 29 2015 11:56
null is not something we HAVE to deal with. It's something we deal with because we made poor decisions in the past, and continue to make them now.
Also, i don't see much difference in what swift asks of you and what coffeescript asks of you. You're still forced to write unnecessary syntax to combat the issue.
All those question marks are something you shouldn't have to worry about.
Hardy Jones
@joneshf
Jul 29 2015 12:10
The solution has nothing to do with FP, but it has a whole lot to do with programming languages. And the solution is quite simple: don't put null in the language. Anything else is an attempt to mitigate the problem, not a solution. Yes, that means we can't actually "fix" the current languages that have null (without breaking changes). Yes, that means this problem won't go away so long as we continue to use these languages (read: many many decades if not centuries). But that's what happens when an industry is young. We made mistakes, we just need to educate ourselves and move on.
Martin Algesten
@algesten
Jul 29 2015 12:11

@joneshf true. the whole problem may be say cocoa, stdlib, etc etc. a entire libraries that have null returns. however this is reality.

the big difference with swift and coffescript is to do with said libraries. working with swift is impossible without a big IDE that helps me show the return type, with javascript/coffee i use emacs. Example:

let cell = uitableview.dequeueReusableCellWithIdentifier("sectioncell")
cell = uitableview.dequeueReusableCellWithIdentifier("sectioncell”)

with swift, at this point, i have absolutely no idea what cell contains. could be a UITableViewCell or perhaps UITableViewCell? who knows? it’s actually AnyObject for some reason. which means I must downcast it first. but since i can’t know that, or whether it’s an optional or not, i can’t just get on with it reading any property of it. cell!.prop (perhaps if-let?) or cell.prop. the only way to know is letting the compiler run and litter my IDE with angry red errors telling me that i didn’t deal with the type properly.

for javascript this just wouldn’t be a problem. cell would be an object (or null). period. maybe a prototyped object, but i don’t care. cell?.prop would suffice in coffee.

Hardy Jones
@joneshf
Jul 29 2015 12:12
Also, I guess we should be clear when talking about swift being stuck in the 70's, it's stuck in the algol-based 70's not the 70's that had actually solved many issues already. Considering sml and similar languages didn't even have null to begin with at that time.
Martin Algesten
@algesten
Jul 29 2015 12:13
true that. i mean that having to worry about the bit-size of an int really isn’t that meaningful for most stuff today.
Hardy Jones
@joneshf
Jul 29 2015 12:15
Oh sure, libraries that embrace poor decisions just exacerbate the issue. And like you said, this is our reality.
It's quite unfortunate.
Thomas Reggi
@reggi
Jul 29 2015 15:28
Hello all, I've learning how to write better promise chains using Ramda. I came up with my first in an answer to my own question Writing promises without opening then calls. I would love it if someone from the Ramda community could talk a look at my answer and offer any suggestions.
Shane Keulen
@SeeThruHead
Jul 29 2015 15:47
compose(times(jsonGenerator)), Maybe, Number);
am i just trying to use maybe the wrong way here?
Jethro Larson
@jethrolarson
Jul 29 2015 15:49
You might just need a map around times
Thomas Reggi
@reggi
Jul 29 2015 15:52
Also just put in a feature request for R.throw ramda/ramda#1317 I'd love to hear someones thoughts.
Shane Keulen
@SeeThruHead
Jul 29 2015 15:54
switched it to defaultTo but realize that it doesn't catch NaN
is there a built in for NaN guarding?
Shane Keulen
@SeeThruHead
Jul 29 2015 16:08
anyone have a solution? or advise on which ramda utility to use for checking NaN
Shane Keulen
@SeeThruHead
Jul 29 2015 16:13
i feel silly isNaN
lol
David Chambers
@davidchambers
Jul 29 2015 16:16
@SeeThruHead, we did have R.isNaN briefly. You now have two options: Number.isNaN (if your environment defines it) or R.equals(NaN).
@reggi, promises don’t compose. I’d like to write a post explaining why I think in 5–10 years the JavaScript community may be as dissatisfied with promises as it currently is with callbacks. You should have a look at plaid/async-problem if you’re interested in alternatives.
Shane Keulen
@SeeThruHead
Jul 29 2015 16:23
thanks @davidchambers, I'm trying hard to get up to speed with using this library. if anyone could point out what's wrong with this i would be immensely grateful const responseGen = compose(times(jsonGenerator), defaultTo(20), not(Number.isNaN), Number);
oh i think i know what i'm doing wrong here
is there a good way of wrapping NaN like you would null/undefined with Maybe?
Thomas Reggi
@reggi
Jul 29 2015 16:31
@davidchambers Hello again. I took a look at that repo. What is your recommended alternative? Do you have any hope that async / await will be a solution to the problem?
Martin Algesten
@algesten
Jul 29 2015 16:43
@davidchambers looking forward to that post :)
David Chambers
@davidchambers
Jul 29 2015 16:46
@reggi, async/await may improve the situation for imperative JavaScript programming, but I want composability rather than more keywords for control flow. Of the approaches in the async-problem repo, futures come out ahead based on the requirements. Here is the main function:
const main = () => {
  concatFiles(process.argv[2])
  .fork(write(process.stderr), write(process.stdout));
};
Note that concatFiles(process.argv[2]) returns a value, so we don’t actually trigger side effects (ignoring the reading of command-line arguments) until we .fork().
This is impressive. We’ve isolated side effects to .fork(write(process.stderr), write(process.stdout)).
Here’s the main function from promises.js:
const main = () => {
  const dir = process.argv[2];
  readFile({encoding: 'utf8'}, path.join(dir, 'index.txt'))
  .then(data => Promise.all(
    data
    .match(/^.*(?=\n)/gm)
    .map(file => readFile({encoding: 'utf8'}, path.join(dir, file)))
  ))
  .then(data => process.stdout.write(data.join('')))
  .catch(err => {
    process.stderr.write(err.message);
    process.exit(1);
  });
};
Thomas Reggi
@reggi
Jul 29 2015 16:52
It's like all I've been told about promises is a lie! @davidchambers you might have just contributed to my structure of reality crumbling. I'm gonna go study up on futures a bit. This seems to be the lib you're using https://github.com/folktale/data.task, any reason why they call them Task and you call them Future?
David Chambers
@davidchambers
Jul 29 2015 16:53
The problem is that the Promise-based readFile is not a pure function, because applying it triggers a side effect (reading from the file system). The Future-based readFile, on the other hand, is a pure function because no side effects occur until we .fork(). So with futures we can compose pure functions whereas with promises we end up with sequences of effectful computations which contaminate the small bits of code which could be pure functions. Basically we’re left with one big main.
blup
@blup
Jul 29 2015 16:54
i'm having a hard time with writing functional style as i feel sometimes its a bit too contrived and underperformant. For example, in pointfree style, although the code is DRY, the execution isn't necessarily as there aren't any tmp vars and some things might need to be calculated multiple times. Am I just being paranoid?
David Chambers
@davidchambers
Jul 29 2015 16:54
I’m pleased you’ve found this enlightening, @reggi. I’m not sure why the Folktale team decided to name (or rename) the type Task. I believe it was named Future at one point.
Thomas Reggi
@reggi
Jul 29 2015 16:55
@davidchambers thanks for the explanation!
David Chambers
@davidchambers
Jul 29 2015 16:57
@blup, unless you’re actually seeing your application load slowly or scrolling is laggy, I think you’re being paranoid. Ask yourself is it fast enough? rather than is it as fast as it could be? We could, after all, write assembly if the goal is to write code that’s as fast as possible. ;)
No problem, @reggi. Welcome to the wonderful world of functional programming!
Martin Algesten
@algesten
Jul 29 2015 16:58
@davidchambers this looks a bit like baconjs. do you see a big difference between functional reactive programming and this? (I know the definition of "functional rx" is not clear)
blup
@blup
Jul 29 2015 17:03
@davidchambers i'm sure this is a bit contrived, but i was trying it out as an exercise: https://gist.github.com/blup/6cb835d64a6771931bea
David Chambers
@davidchambers
Jul 29 2015 17:06
@algesten, I haven’t yet used Bacon.js. I really should. And to be honest I still don’t know what FRP is. ;)
@blup, I absolutely prefer the latter. When dealing with expressions I prefer x * y to R.multiply(x, y). It’s when one wants to write a “double” function that R.multiply becomes useful: R.map(R.multiply(2), xs) versus R.map(x => 2 * x, xs). Now that we have => using lambdas isn’t bad. R.map(function(x) { return 2 * x; }, xs) was pretty noisy.
blup
@blup
Jul 29 2015 17:13
davidchambers: thanks, i guess i'll keep FP for the higher level stuff then. i was hesitating at where to draw the line.
David Chambers
@davidchambers
Jul 29 2015 17:14
It’s good to push things to the extreme, as in your gist, then dial it back a bit.
Jethro Larson
@jethrolarson
Jul 29 2015 18:40
I've been getting the feeling while reading about generators that they're kind of low level and harder to reason about than necessary. Anyone else feel that way?
David Chambers
@davidchambers
Jul 29 2015 18:45
I find them very difficult to reason about.
Thomas Reggi
@reggi
Jul 29 2015 19:54
Theres a syntax that @davidchambers and others have been using to express how Ramda methods work something like (a -> [b]) -> [a] -> [b] the documentation, coding examples, github issues, and even comments in code all have it. I'm completely unfamiliar with this notation. I've been learning it (erh* ignoring it) slowly enough to pickup that an arrow is a returned value and the values are object types? Can anyone point me in the direction of some documentation / a name for this notation?
David Chase
@davidchase
Jul 29 2015 19:57
@reggi this is a good resource https://github.com/DrBoolean/mostly-adequate-guide/blob/master/ch7.md specifically that chapter
Thomas Reggi
@reggi
Jul 29 2015 19:58
Thanks!
David Chambers
@davidchambers
Jul 29 2015 20:33
David Chase
@davidchase
Jul 29 2015 21:12
:thumbsup:
Jethro Larson
@jethrolarson
Jul 29 2015 22:14
I'm writing this talk on point-free programming and I'm choosing to write all the helpers on the fly, and make all of them unary to drive home currying. Also so I don't have to explain how ramda's curry and compose works. I have a module on converge and I remember hearing that you could use compose in place of converge. How you'd do that isn't occurring to me though.
    var includeAges = map((person) => assoc('age')(calcAge(person))(person))
    var includeAges = map((person) => compose(assoc('age'),calcAge)(person)(person))
Is there a way to make this point-free without converge and identity?
to be clear, compose in this case is binary and not curried
Jethro Larson
@jethrolarson
Jul 29 2015 22:39

I can make a new helper like

//:: (a -> a -> b) -> (a -> b)
var duplex = (fn) => (a) => fn(a)(a)

then

var includeAges = map(duplex(compose(set('age'), calcAge)))

I feel like I'm missing some secret sauce though

David Chambers
@davidchambers
Jul 29 2015 23:46
I don’t know of the secret sauce.
On another note, these examples could probably be written nicely using lenses. ;)