question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

One thing that functional languages like PureScript do is generate curried functions. This appears to be a blocker for Closure. For example,

(function(){

  var Show_string = { show: function(s){ return s; } };

  function print(d,v){
    console.log(d.show(v));
  }

  function greet(d,v){
    return print(d,v + "!");
  }

  return greet(Show_string, "Mary");
})();

Closure outputs,

console.log("Mary!");

Excellent result. It did pretty straight-forward transformations here. Including removing the overhead of generic functions, which are achieved via dictionary (argument) passing in Haskell-like languages. However, in languages like Haskell/PureScript, functions are all single-argument chains of functions, like this:

(function(){

  var Show_string = { show: function(s){ return s; } };

  function print(d) {
    return function(v){
      console.log(d.show(v));
    }
  }

  function greet(d){
    return function(v){
      return print(d)(v + "!");
    }
  }

  return greet(Show_string)("Mary");
})();

Unfortunately, Closure outputs the following:

(function() {
  function c(a) {
    return function(b) {
      console.log(a.show(b));
    };
  }
  return function(a) {
    return function(b) {
      return c(a)(b + "!");
    };
  }({show:function(a) {
    return a;
  }})("Mary");
})();

This means that PureScript’s output is both large and slow – this example is small, but imagine large codebases with nested levels of this.

So it seems that “uncurrying” is not a process that Closure currently does. I’m not sure whether this was decided against, simply because it’s not normal in JS to have functions like this, or whether it’s an oversight, or whether there’s a good reason that makes reducing these in the general case difficult.

Could someone fill me in?

If it’s simply not something considered, how difficult would it be to add? Is it something I could implement myself in Closure? I’m discussing with the PureScript community and considering whether to add it to the compiler output, but on the other hand, this kind of thing feels like Closure’s bread and butter, so I’m attempting to do it the Right Way before going off and patching something further up the chain.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:15
  • Comments:13 (2 by maintainers)

github_iconTop GitHub Comments

8reactions
krkcommented, Dec 21, 2021

Tried setting assumeClosuresOnlyCaptureReferences = true and it worked:

On commit 2809700cd70d76b6212cd45540151b90c8d003ba, diff:

diff --git a/src/com/google/javascript/jscomp/CompilationLevel.java b/src/com/google/javascript/jscomp/CompilationLevel.java
index 02ec99aee..0211a6cc1 100644
--- a/src/com/google/javascript/jscomp/CompilationLevel.java
+++ b/src/com/google/javascript/jscomp/CompilationLevel.java
@@ -181,7 +181,7 @@ public enum CompilationLevel {
     options.setSmartNameRemoval(true);
     options.setInlineConstantVars(true);
     options.setInlineFunctions(Reach.ALL);
-    options.setAssumeClosuresOnlyCaptureReferences(false);
+    options.setAssumeClosuresOnlyCaptureReferences(true);
     options.setInlineVariables(Reach.ALL);
     options.setComputeFunctionSideEffects(true);
     options.setAssumeStrictThis(true);

Command:

java -jar bazel-bin/compiler_unshaded_deploy.jar -O ADVANCED --js ps.js --js_output_file minps.js

Input:

(function(){

  var Show_string = { show: function(s){ return s; } };

  function print(d) {
    return function(v){
      console.log(d.show(v));
    }
  }

  function greet(d){
    return function(v){
      return print(d)(v + "!");
    }
  }

  return greet(Show_string)("Mary");
})();

Output:

console.log("Mary!");
5reactions
chrisdonecommented, Dec 31, 2021

Thanks a bunch @krk! I’ve eyeballed the Dockerfile and can’t see where my attempt diverged from yours, but no matter, I’m sure it was something subtle and trivial.

Happy new year! 🎊

EDIT: I was able to reproduce the result. ✔️

Read more comments on GitHub >

github_iconTop Results From Across the Web

Currying and Uncurrying in JavaScript and Flow - Medium
The isomorphism described by currying and uncurrying is a property of functions in general, which transcends any particular language. In ...
Read more >
Currying - Wikipedia
In mathematics and computer science, currying is the technique of translating the evaluation ... Uncurrying is the dual transformation to currying, and can...
Read more >
Definitions of curry and uncurry : r/haskell - Reddit
curry's first argument must be a function which accepts a pair. It applies that function to its next two arguments. uncurry is the...
Read more >
A verified framework for higher-order uncurrying optimizations
Abstract Function uncurrying is an important optimization for the efficient execution of functional programming languages.
Read more >
Currying and Uncurrying - Learn Functional Programming in ...
Learn how to transform functions into their curried or uncurried forms. ... Currying functions with more arguments; The functions curry and uncurry ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found