13
\$\begingroup\$

For many code golf questions, we allow functions as answers. What exactly does it mean for some code to be a valid submission as a function?

This question came up during a discussion on built-ins, but is a separate discussion from that one.

Here are some examples in Python, where I'm not sure which should be allowed.

Cases that seem clearly allowed:

  • Defining a wholly new function, where defining means giving the function a name by which it can be later called:

    limit = 10
    def func(a):
        for i in range(limit):
            if a[i % len(a)]:
                return i
    
  • An expression which evaluates to a function:

    lambda a:a.count(a[0])/len(a)
    

Cases that seem like they shouldn't be allowed:

  • Causing a function to exist and be usable, but without interacting with it directly:

    import math
    

    This causes the function math.gcd to exist, without directly interacting with it.

    This case is particularly problematic, because a golfing language could be defined to cause literally every possible function to become defined when given a 1 (or 0) character command, which defeats the purpose.

  • Causing a very large number of functions to be defined, where the function in question is one of them:

    for index, code in enumerate(all_possible_strings):
        eval("func" + str(index) + "=" + code)
    

    Assume that all_possible_strings is a generator which yields all possible strings. Somewhere in that sequence, the string lambda a:a.count(a[0])/len(a) must have occurred, so the function func<very large number> is now defined as that function. This also seems problematic and like a loophole.

Cases I'm not sure about/what the consensus is:

  • Submissions that contain an expression that evaluates to the desired function, as well as other code:

    A = [1]
    for i in range(50):
         A.append(sum(A) * i)
    A.count
    

    Supposing A.count solved the challenge, would this be valid?

Given these cases, what should our standard of a valid function submission be?

\$\endgroup\$
  • \$\begingroup\$ Related. \$\endgroup\$ – Martin Ender Apr 26 '16 at 9:20
  • 4
    \$\begingroup\$ Very good point on the function generator though, that does indeed seem problematic. \$\endgroup\$ – Martin Ender Apr 26 '16 at 9:21
  • \$\begingroup\$ Also related. \$\endgroup\$ – FryAmTheEggman Apr 26 '16 at 13:42
  • \$\begingroup\$ I think it should be eval("func"+str(i)+"="+index)? \$\endgroup\$ – justhalf Apr 26 '16 at 17:50
  • \$\begingroup\$ @justhalf Thanks, I fixed it. \$\endgroup\$ – isaacg Apr 26 '16 at 20:12
17
\$\begingroup\$

Here's what I (and the majority of the community) have been going by, which I think works well:

  • Named functions/lambdas are acceptable (def foo(n): n+1, foo = lambda n: n+1, int foo(int n) { return n+1; }, auto foo = [](int n){ return n+1; }).
  • Unnamed functions/lambdas are acceptable (lambda n: n+1, [](int n){ return n+1; }).
  • Any expression which evaluates to a (named or unnamed) function is acceptable (pow).
  • Additional "helper" functions may be defined in addition to the primary solution function (f=lambda x:abs(x);lambda n:f(n)+n).
  • Any imports/includes/requires/whatever may be imported/included/required/whatever outside of the function (import math;math.gcd).

In general, so long as the code defines at least one function, named or unnamed, and the solution function performs consistently regardless of how many times it has been called previously, the submission is acceptable. The only exception is import-only submissions - though they bring functions into the global scope, they neither define new functions nor evaluate to a function that can be captured and/or called. Thus, from math import* is not valid, but from math import*;gcd is.

(note: that wording seems less than ideal, but I can't think of a way to improve it right now)

As for the code that generates all possible functions, that would be technically valid by these rules, but should be added as a standard loophole.

\$\endgroup\$
  • \$\begingroup\$ Now that you've phrased it like that, this is pretty much exactly the consensus we have. If you think I can improve the wording on that to unambiguously rule out answers that generate "all" functions, let me know (then I think this would be a duplicate). \$\endgroup\$ – Martin Ender Apr 26 '16 at 11:53
  • \$\begingroup\$ @MartinBüttner I think the wording on your answer is fine. Like I said, I think forbidding generating all functions would be better as a standard loophole. \$\endgroup\$ – Mego Apr 26 '16 at 19:33
  • \$\begingroup\$ Why is the last expression the one that has to do it? In a language like Pyth with variable introduction, it might well be shorter to define the helper function second. \$\endgroup\$ – isaacg Apr 26 '16 at 20:15
  • \$\begingroup\$ @isaacg Maybe if we define the "last expression" to mean "last evaluated expression". As such, you could do the equivalent of rest of code <break> var f = <last evaluated expression>. I don't know too much about languages like Pyth personally, but it seems that if the submission either 1. can be assigned to a variable and used like and/or can be used itself as a typically defined function, or 2. contains a delimited expression that fulfills 1 after the rest of the code runs, that it should be an acceptable answer. \$\endgroup\$ – CAD97 Apr 26 '16 at 20:25
  • \$\begingroup\$ @isaacg Admittedly, I know much less about Pyth than I should. That said, CAD97's solution seems reasonable. That said, the solution function doesn't have to be the last one defined. \$\endgroup\$ – Mego Apr 26 '16 at 20:25
  • \$\begingroup\$ That was poorly worded but maybe someone more familiar with the workings of non-traditionally-linear languages can phrase it better. \$\endgroup\$ – CAD97 Apr 26 '16 at 20:26
  • \$\begingroup\$ @CAD97 An example in python of what I'm talking about is def a(): return b() + 2; def b(): return 3, where ; is a newline and the challenge is return 5. Is a a valid function for this challenge? \$\endgroup\$ – isaacg Apr 27 '16 at 2:06
  • \$\begingroup\$ @isaacg I would count that (though in this trivial example you could reverse them). My guess for good start to wording: 3. Causes a function to be defined after running that was not defined before. Unfortunately then it's again butting up against import math -- there might not be a good simple way to define an answer after all... \$\endgroup\$ – CAD97 Apr 27 '16 at 2:10
-1
\$\begingroup\$

I would say that you should have to specify how to call it and have the constant part count towards the byte count.

For your example about defining every possible function, you would have to specify the code to create the generator, and the function's number, and everything would count towards the byte count.

For import math, you would also have to count math.gcd (plus () to avoid loopholes?).

Etc.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .