Довільна довжина каррінгу


53

Написати функцію, f яка приймає додатне ціле число і повертає функцію.

Нова повернута функція повинна бути ідентичною f. Однак, коли "виклик припинення" відбувається,f замість цього слід повернути суму всіх пропущених цілих чисел.

Наприклад, g=f(4)(якщо fце перша функція) слід встановити gіншу функцію. h=g(3)зробимо те саме. Однак, якщо ви телефонуєте hбез аргументів (детальніше див. Нижче), він повинен вивести 7, оскільки це сума попередніх аргументів функції. Іншими словами, f(3)(4)() == 7.

Зверніть увагу, це не те саме, що f(3,4)().

"Виклик припинення" - це один із наступних варіантів (на ваш вибір):

  • викликати без аргументів
  • null як аргумент
  • будь-яке непозитивне значення

Довільна кількість функціональних викликів повинна підтримуватися, заздалегідь не визначений ліміт.

Гарантується, що загальна сума не буде більше 1 000.

Можна припустити, що щонайменше один дзвінок проводиться до "виклику припинення".

Ваш код не повинен використовувати статичні змінні за програмою, тому слід мати можливість запускати експеримент кілька разів за один і той же час виконання та спостерігати точно таку ж поведінку.

Приклади:

f(1)() == 1
f(4)(2)(7)() == 13
f(4)(2)(7)(5)(2)() == 20

4
@LuisMendo Це загалом означає, що f(4)повертає нову функцію. Якщо ця нова функція викликається без аргументів, вона повертається 4, але якщо вона викликається з іншим аргументом, вона знову поверне нову функцію з тією ж семантикою, але з новим аргументом, доданим до 4і так далі.
Мартін Ендер

6
@LuisMendo Це дійсно до Євгена, але я думаю, що дозволити повторні дзвінки значно відіб'ється від виклику, адже цікава частина полягає не в тому, щоб зробити функціональний стан, а зробити функцію вищого порядку.
Мартін Ендер

6
@MartinEnder Це має багато сенсу. Євгеній, якщо це є наміром, будь ласка, змініть формулювання виклику. Написати функцію, яку можна нескінченно викликати, зовсім не говорить про те, що функція повинна повертати функцію
Луїс Мендо,

4
Чи можна припустити, що одночасно буде лише один екземпляр ланцюга викликів? Наприклад, ні q = f(2)(3); b = f(1)(2)(3); q(); b()?
Conor O'Brien

3
Щойно нещодавно підібравши Haskell, я зацікавився, чи можливо це в Haskell. Система сильного типу змушує мене думати, що цього не може бути.
CAD97

Відповіді:



21

Хаскелл (GHC), 118 байт

Це 98 байт для коду і 20 байт для прапора компілятора GHC -XFlexibleInstances, що дозволяє розширити тип системи.

class F a where f::Int->a
instance F(()->Int)where f n()=n
instance F a=>F(Int->a)where f=(f.).(+)

Це визначає "функцію" f, яку можна викликати з довільною кількістю цілих чисел, за якою слідує одиниця (), після чого вона повертає ціле число. Потрібні анотації типу. Спробуйте в Інтернеті!

Пояснення

Примушення системи суворого типу Haskell дозволити це вимагає певної магії, а саме: розширення GHC для гнучких екземплярів типу. Як це працює, fце параметрично поліморфна функція, обмежена обмеженням класу типу: її тип є F a => Int -> a. Це означає, що fприймає ціле число і повертає значення типу aдля будь-якого типу, aщо належить до класу typec F. F- це лише назва класу типу, який забезпечує функціюf ; це оголошено на першому рядку.

Наступні два рядки - це два екземпляри Fдля різних типів a. Другий рядок зазначає, що належить тип функцій від ()до цілих чисел F(де ()тип одиниці, єдиним членом якого є значення ()), і реалізація f n () = n; функція повертає свій перший аргумент. В останньому рядку зазначено, що якщо aналежить F, то так же і тип функцій від цілих чисел до a: з функції f :: Int -> aми можемо генерувати іншу функцію f :: Int -> Int -> a. Реалізація є f m n = f (m+n)(код використовує комбінатори, щоб скоротити її), де fліворуч - новий, а fправоруч - старий. Це по суті даєf новий цілий аргумент, який додається до наступного. Кілька аргументів підсумовуються разом так:

  f  a1   a2   a3   a4   a5  ()
= f (a1 + a2)  a3   a4   a5  ()
= f (a1 + a2 + a3)  a4   a5  ()
= f (a1 + a2 + a3 + a4)  a5  ()
= f (a1 + a2 + a3 + a4 + a5) ()
=    a1 + a2 + a3 + a4 + a5

fНа кожній лінії має інший тип.

Функції Haskell прокручуються автоматично, тому якщо ви даєте fлише цілі числа, ви отримуєте функцію.


1
Можливо, я випиваю, але це не зовсім те, що вимагає виклик. Ви визначаєте дві (!) Функції, обидві викликані f, а не одну функцію, яка виконує завдання. Однак це так близько, як ви можете дістатися в Haskell. Я не думаю, що неможливо вирішити завдання за допомогою однієї функції через сувору систему типу.
німі

3
@nimi Це визначає не дві функції, що викликаються f, але нескінченно багато функцій, що викликаються f. (Один для кожної можливої ​​кількості аргументів.) Ці функції (з цієї нескінченної родини) мають два різновиди визначення, один сортування, коли кількість аргументів дорівнює нулю, а інший, коли його немає.
ShreevatsaR

@ShreevatsaR: Я бачу два визначення, f n()=nі f=(f.).(+)тому я би назвав це визначенням двох функцій.
німі

7
@nimi Є два визначення, але не дві функції. Кількість визначень не повинна бути кількістю функцій. Наприклад, ви можете визначити факторіальну функцію за допомогою двох визначень g 0 = 1і g n = g (n-1) * nтам, де є два визначення, але лише одна функція. Тут ми маємо два визначення, але нескінченно багато функцій. (Кожен різного типу.)
ShreevatsaR

1
@nimi BTW ghciзавантажте вищезгадане і спробуйте :t f- воно скаже f :: F a => Int -> a(мається на увазі, що якщо aце екземпляр класу f, то fце функція Int -> a). Таким чином, ми могли б розглядати це як одну функцію або нескінченно багато, але хоча вона має два різновиди визначення (як і факторіальна функція), я не бачу жодної хорошої основи вважати це двома функціями.
ShreevatsaR

15

Python 2, 42 41 36 байт

Це рішення ніколи не матиме переповнення, оскільки Python підтримує цілі числа довільної точності. Нуль - це «особлива цінність».

f=lambda n:lambda m:m and f(m+n)or n

Спробуйте в Інтернеті

Безголівки:

def f(n):
    def g(m=''):
        return f(m+n)if m<''else n
    return g

14

C, 62 58 байт, прикордонна конкуренція

Збережено 4 байти завдяки Кевіну! (Ще не видаляючи typedef, оскільки це потрібно щось для того, щоб викликати його.)

typedef(*(*B)(_))(_);q;f(x,o,_){x=x?(q+=x,f):(x=q,q=0,x);}

Функція викликати f; ви припиняєте його називати і отримуєте результат, називаючи його непозитивним числом 0. Спробуйте тестовий джгут онлайн!

Отже, наскільки я можу сказати, єдиний спосіб "зависнути" функції, які мають кілька типів повернення, - це зробити одне з наступного:

  1. Передайте результат функції, щоб повідомити компілятору, який ви хочете знову викликати результат;
  2. або створити union/ structтип, який має intпідтипи та функціонування / самореференції.

Я намагався робити (2), але це здавалося трохи проти духу питання і, відверто кажучи, майже не піддається. Таким чином, відповідаючи духу виклику, я вибрав варіант (1). Для цього потрібно ввести кожну повернуту функцію у функцію, щоб вона могла бути використана.

Цей синтаксис "каррі" виглядає дещо дивним, але досить схожим. Щоб наслідувати f(21)(1), треба було б написати ((B)((B)f(21))(1))(0). Я визначив Bтип як функцію, яка приймає ціле число і повертає покажчик на функцію, яка приймає ціле число. Розширено, це виглядає так:

   ( (B)( (B) f(21) )(1) )(0)
//            f(21)            - call f with 21
//        (B)                  - cast to B, a function pointer
//      (           )(1)       - call with 1
//   (B)                       - cast to a function pointer
// (                     )(0)  - call with 0

Якщо ви скажете, що він закінчується лише на 0, ви вимагатимете кастингу (що ви робите в C, оскільки C не може правильно визначити функцію, яка сама повертається), і ви залишаєте очищення глобального між запусками до абонента (який Я думаю, що це цілком розумно), ви можете спростити всю справу q;f(x){return x?(q+=x,f):q;}.
Кевін


1
@Kevin поки що, згідно з правилами сайту, функція повинна бути багаторазовою. Якби я не робив нуль qпісля кожного запуску, то ця функція більше не була б корисною
Conor O'Brien

Можливо, покажчики функцій? Вам потрібно буде посилатися кожен раз, але, можливо, варто перевірити
Пуховик

1
@ ConorO'Brien Я щойно реалізував ваш підхід до союзу. Це довше, ніж це, але це не за горами.
Якоб

13

Математика, 25 байт

f[x_]@y_=f[x+y]
f[x_][]=x

Спробуйте в Інтернеті! (Використання математики.)

Можна зробити три байти менше, перенісши відповідь на JavaScript, але я хотів представити більш ідіоматичне рішення Mathematica. Це @лише трохи синтаксичного цукру, що робить рішення еквівалентним:

f[x_][y_]=f[x+y]
f[x_][]=x

Так що так, ідея полягає в тому, що в Mathematica ви не можете просто визначити функцію, f[x_]але можете безпосередньо приєднати значення до складнішого виразу, що містить f, наприклад f[x_], переданий інший аргумент. Встановивши для цього два визначення, ми можемо отримати бажану поведінку:

  • Перше визначення згортає один f[x][y]виклик f[x+y], тим самим використовуючи один "виклик" і додаючи аргументи всередині. Це правило діє, поки ми не залишимося f[sum][].
  • Друге визначення розпаковує цей остаточний випадок, визначаючи всю оцінку, яку слід оцінити sum.

1
<3 символічного програмування
Джуліан Вольф

8

C ++, 72 байти

#define O(P)operator()(P){return{P+a};}int
struct F{F O(int(m))O()a;}f;

Це визначає тип, Fякий виступає як запитувана функція, і змінну fцього типу для виклику. Він дійсний з C ++ 11 і працює з онлайн-версіями GCC, clang, icc та VC ++.

Використання:

int main() {
  return f(1)(2)(3)(); // returns 6
}

Пояснення:

Після попередньої обробки та переформатування це виглядає так:

struct F {
  F operator()(int(m)) { return{int(m)+a}; }
  int operator()() { return {+a}; }
  int a;
} f;

Це зазвичай пишеться:

struct F {
  F operator()(int m) { return {m+a}; }
  int operator()() { return a; }
  int a;
} f;

return a;і return {+a};робимо те ж саме, оскільки унар +не змінює значення, а зайві дужки навколо повернутого значення дозволені. int mі int(m)зробіть те ж саме, оскільки зайві дужки навколо імені змінної дозволяються, включаючи параметри функції. return {m+a};і return {int(m)+a};зробити те ж саме, як кидання mвід intдо intне змінює свого значення. Ці зміни operator()зближують два синтаксиси перевантаження в синтаксисі, що дозволяє двічі викликати одне визначення макросу. Вибір правильного порядку для трьох членів дозволяє також intвключити перше слово наступного рядка ( ) у визначення макросу.


1
Гарний. І не тільки рішення про гольф ... перевантаження, operator()щоб зробити цю роботу було особливо класно.
Рей Тол


6

C, 104 96 байт

#define a(i)s(i)|b
#define b(i)u(i)|c
#define c(i)u(i)|b
b,c,d;s(i){b=c=i;i=d;}u(i){c=b+=i;i=d;}

Використовує метод за посиланням, яким поділився @JulianWolf. Останній аргумент повинен бути 0.

Спробуйте в Інтернеті!


Коментарі не для розширеного обговорення; ця розмова переміщена до чату .
Денніс

4

Math.JS, 38 байт

f(x)=i(x,0)
i(x,y)=x<0?y:j(z)=i(z,y+x)

Телефонуйте за допомогою f(number_a)(number_b)(...)(negative_number)

Якщо нам дозволяється вказати початковий виклик, 12 байт ( f(x)=i(x,0)\n) можна скинути, і його можна викликати за допомогоюi(number_one,0)(number_two)(...)(negative_number)

Спробуй це!

Роз'яснення

LaTeX!

Як показано у наведеному вище LaTex, f(x)просто викликає i(x,0), тоді i(x,y)повертає значення yif xменше 0, або функцію j(z)=i(z,x+y), яка приймає один аргумент, який циклічно. Додавання до значення y.


4

C, 232 206 байт

#include<string.h>
#include<stdlib.h>
#define f(X)s(""#X)?0:g
#define g(X)u(""#X)?0:h
#define h(X)u(""#X)?0:g
g=0,h=0;s(char*s){g=h=atoi(s);return 0;}u(char*s){char*a=strlen(s)?s:"0";g=h+=atoi(a);return 0;}

Це, ймовірно, може бути значно полегшене, але це повинно слугувати доказом концепції, що C може використовуватися без будь-яких розширень мови * для вирішення цієї проблеми, викликаючи без аргументів, а не з магічним значенням.

* @hvd зауважив, що, хоча це працює з поля, використовуючи gcc, деяка поведінка не визначена у стандарті C, тобто це може бути не портативно. Використовуйте на свій страх і ризик!

Безголівки:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define f(X) start("" #X) ? 0 : f0
#define f0(X) update("" #X) ? 0 : f1
#define f1(X) update("" #X) ? 0 : f0

long f0 = 0;
long f1 = 0;

int start(const char *s) {
    f0 = f1 = strtol(s, NULL, 10);

    return 0;
}

int update(const char *s) {
    const char *a = strlen(s) ? s : "0";
    f0 = f1 += strtol(a, NULL, 10);

    return 0;
}

int main() {
    printf("f(1)()          -> %ld\n", f(1)());
    printf("f(1)(2)(0)(3)() -> %ld\n", f(1)(2)(0)(3)());
    printf("f(1)(-2)(3)()   -> %ld\n", f(1)(-2)(3)());
    printf("f()             -> %ld\n", f());

    return 0;
}

Компіляція та запуск з gcc arbitrary-length-currying.c -o arbitrary-length-currying && ./arbitrary-length-curryingрезультатами (після деяких попереджень)

f(1)()          -> 1
f(1)(2)(3)(0)() -> 6
f(1)(-2)(3)()   -> 2
f()             -> 0

"без будь-яких розширень мови" - фокус чергування gта hпродовження ланцюга макровикликів не гарантовано спрацьовує, оскільки не визначено, чи gз'явиться наступне в контексті розширення першого g. C11 додає приклад до 6.10.3.4, щоб уточнити, що це не визначено. (IIRC, препроцесор TenDRA - це той, який не розширить його так, як вам хочеться.) Окрім цього, жодна версія мови не підтримує порожні макроаргументи та неявний int, тому дійсна програма C не може використовувати обидва. :) Все-таки приємна відповідь. Шукаєте далі гольфу?
hvd

@hvd: так, напевно, я повернуся до нього через пару днів і побачу, чи зможу я покататися на ньому. Ви, безумовно, праві, що це невказана поведінка, але я думаю, що стандартне лікування тут полягає в тому, що мови визначаються їх реалізацією, тому, поки це працює з gcc, я задоволений.
Джуліан Вольф

Я просто звертався до коментаря, який ви включили у свою відповідь, що він не покладається на будь-які мовні розширення. Так, навіть з мовними розширеннями, це цілком справедливо як відповідь тут, не означало підказувати інакше.
hvd

Ах, це безумовно справедливо. Ви маєте рацію, що я повинен зазначити, що, хоча додаткові прапори не потрібні, це може бути не портативним.
Джуліан Вольф

Ви можете протестувати порожній рядок, *sа не strlen(s). Струни C мають неявну довжину, закінчуються charзначенням 0. Хороший макро-хакер, що дозволяє телефонувати з / без аргументу!
Пітер Кордес

4

8086 машинного коду, 27 байт

00000000  bb 00 00 85 c0 74 13 01  d8 be 00 01 89 e7 47 47  |.....t........GG|
00000010  57 b9 1b 00 f3 a4 5b 89  47 01 c3                 |W.....[.G..|
0000001b

Цей машинний код повинен бути за адресою 0x100 і передбачає крихітну модель коду (cs = ds = es = ss). Місце розташування функції можна змінити, не витрачаючи зайвих байтів. Якщо розмістити його на компенсації, це 0дозволить зберегти байт ( xor si,siзамість mov si, 0x100)

Обов’язковий режим виклику

Це передбачає, що абонент попередньо виділив щонайменше 27 байт. Він приймає число в axі повертає вказівник функції в bx. Виклик цього вказівника за допомогою ax=0завершує ланцюг і повертає суму в bx.
Тож для першого дзвінка:

mov bp, sp
sub sp, 28
mov ax, number_to_add
call function
; new function pointer in bx

Потім для кожного наступного дзвінка:

sub sp, 28
mov ax, number_to_add
call bx
; new function pointer in bx

Для припинення:

mov ax, 0
call bx
; result in bx
mov sp, bp

Ungolfed (прокоментував розбирання машинного коду):

00000000  BB0000            mov bx,0x0      ; 0 is replaced after copying
00000003  85C0              test ax,ax
00000005  7413              jz 0x1a         ; if(ax==0) ret (with value in bx)
00000007  01D8              add ax,bx       ; arg += total
00000009  BE0001            mov si,0x100    ; address of the original: ds:0x100
0000000C  89E7              mov di,sp
0000000E  47                inc di
0000000F  47                inc di          ; dst = sp+2 = above return address
00000010  57                push di
00000011  B91B00            mov cx,0x1b
00000014  F3A4              rep movsb         ; copy the function code.
00000016  5B                pop bx            ; bx = start of copy destination
00000017  894701            mov [bx+0x1],ax   ; update total in the copied code
0000001A  C3                ret               ; with bx = function pointer

Після виклику цього з ненульовим AX, bx = spі буфер заповнюється модифікованою копією машинного коду з function. 16-бітний безпосередньо в першій інструкції містить загальну суму. (Це написано останньою інструкцією перед ret.)

push di/ pop bxможе бути замінено на mov bx, di(раніше rep movsb), що спростить, але без економії.

Вимагаючи, щоб абонент передавав вказівник на буфер dst di, врятував би 4 байти проти обчислення його відносно sp.

Зробити початкову адресу функції таким же, як розмір функції, збереже байт ( mov cx, si).


Це буде кращою відповіддю, якщо ви включили розбирання байтів машинного коду. відповіді на машинні коди, безумовно, потребують версії, що не має волі. наприклад, використовувати objdump -b binaryзамістьhexdump -C
Пітер Кордес

Оновлено коментовану розбирання. Можлива економія: вимагайте, щоб абонент передав покажчик dst у di(4 байти). Зробіть стартову адресу функції = розмір: mov cx, siзамість mov cx, 0x1b.
Пітер Кордес

2

C #, 62 байти

dynamic f(int n)=>(System.Func<int,dynamic>)(m=>m<0?n:f(n+m));

Для завершення дзвінка передайте негативну кількість, наприклад

f(1)(2)(3)(-1) == 6

Я хотів би змусити його працювати, передаючи nullабо не параметри до кінця. Однак усі способи, які я спробував, були набагато довші
TheLethalCoder

Чи можете ви використовувати !mзамість m<0і пропустити nullабо 0як останній параметр?
betseg

@betseg Ні в C # тільки а Booleanможе бути використаний як Boolean... Я намагався, nullале це просто стало довше. Я хотів використати, ??що означає, якщо LHS є недійсним RHS, але як мені потрібно, якщо LHS не є нульовим, це робити ще RHS, я не зміг.
TheLethalCoder

2

Скала, 58 чол

case class f(n:Int){def apply(m:Int)=f(n+m)
def apply()=n}

Спробуйте в Інтернеті

Безголівки:

case class f(n:Int){
  def apply(m:Int)=f(n+m)
  def apply()=n
}

Пояснення:

Цей код визначає case classвиклик f з конструктором, що приймає int. Визначте клас регістру, який буде генерувати рівні, хеш-код, toString та методи копіювання, а також супутний об’єкт з тим самим іменем, щоб увімкнути створення об'єкта безnew ключового слова.

Цей клас має перевантажений метод застосування: один бере інше ціле число, щоб додати та створює новий об’єкт із оновленою сумою, і один без аргументів для отримання суми.

У Scala будь-який об'єкт із методом застосування може бути названий як метод, тобто o.apply(x)може бути записаний як o(x). Це використовується в стандартній бібліотеці для масивів, списків, карт та Function1ознак, реалізованих анонімними функціями



2

Perl 5, 36 байт

sub f{my$n=pop;sub{@_?f($n+pop):$n}}

say f(1)->(); # 1
say f(1)->(2)->(3)->(); # 6

Що для цього потрібно -M5.016? Здається, ви повинні мати можливість кинути, -M5.016а потім також скинути myі зберегти пару байтів. Якщо це просто say, ви можете використовувати прапор -Eзамість цього, який не активується use strict, тому ви все одно можете скинути його my.
Кріс

@Chris Ви праві, він не потребує 5.16, мою первинну редакцію зробив (використовував __SUB__), але я змінив це, перш ніж подати, і не видалив біт про 5.16. Я зніму це. Я не думаю, що скидання myбуло б правильним.
панно

(і ні, я не вважаю це sayчастиною коду, це лише для ілюстративних цілей)
hobbs

1
Якщо ви видалите myбез use strict, $nнеявно є глобальною змінною. Це погана форма у правильних сценаріях Perl, але вона досить часто зустрічається в одностроях, і тут, здається, працює.
Кріс

2

Мозок-Флак , 6 байт

Насправді я щойно помітив, що оскільки ToS - це дійсний формат повернення, що з'являється, 0 не дуже потрібен, що зберігає 2 байти:

({{}})

Спробуйте в Інтернеті!

Оригінальне подання, 8 байт

Використовує 0як особливе значення:

({{}}{})

Спробуйте в Інтернеті!

Пояснення

З огляду на аргументи 1 , 2 , ..., п , 0 стек спочатку виглядає наступним чином :

                                                       а н

                                                       

                                                       a 2

                                                       a 1

                                                       0

Потім код йде, з'являється кожен в I , накопичує їх, виштовхує 0 складає їх і поміщає результат:

(      )  -- push the following value:
 {  }     --   while ToS ≠ 0 (sums the runs):
  {}      --     pop 1 element
     {}   --   pop the remaining 0 & add it

Альтернативні рішення, 8 байт

Замість того, щоб вискакувати 0 і додати його до суми, ми також можемо поміняти стеки, оскільки правильний спочатку порожній:

({{}}<>)

Спробуйте в Інтернеті!

Використовуючи -rпрапор, 0 знаходиться у верхній частині стеку, тому ми можемо викласти його першим:

({}{{}})

Спробуйте в Інтернеті!

{}({{}})

Спробуйте в Інтернеті!


О боже мій ... Чудовий!
Євген Д. Губенков

2

C (GCC), 83 байти

Мій перший C гольф! Є кілька інших C-рішень, але це дещо інше. Передпроцесорне використання суто косметичне. Цей підхід вперше був обговорений у відповіді Конора О'Браєна тут .

#define r union r
t=0;r{int v;r(*f)();};r e;r f(a){t+=a;e.v=a?f:t;t*=a>0;return e;}

Кінцеве значення дорівнює нулю. Повернене значення - це об'єднання, тому для виклику результату, поля використання fта доступу до кінцевого значення використовуйте поле використання v, наприклад

f(1).f(2).f(3).f(0).v

Спробуйте це в Інтернеті

Обмеження

Глобальна змінна містить загальний обсяг. Незважаючи на те, що це прямо заборонено, подання підтримує повторні виклики (загальна сума скидається в термінальному дзвінку), що, здається, є причиною заборони глобального стану.

Покажчик на файл fзберігається на поверненому об'єднанні через intчлен, тому це очевидно не є портативним. Я не впевнений, чи працює це на GCC на всіх платформах або просто на Linux або просто на x86 або просто на ELF або ... Якщо хтось знає якісь деталі про це, будь ласка, прокоментуйте або надішліть повідомлення!


2

APL (Dyalog Classic) , 48 47 46 44 32 байт

r←(a f)x
r←⍎'(a+x)f'↓⍨-0=x

0f

Спробуйте в Інтернеті!

Припиняється, проходячи в нуль. Синтаксис виклику:((0 f 1) 2) 0

-15 байт завдяки @ngn

Вимагає ⎕IO←0

Будь-які поради щодо гольфу вітаються!


якщо ви можете використовувати 0 як значення термінатора, перейдіть :If x<0на :If×xта замініть пункти "якщо" та "інше"
ngn

Дерп. Я не бачив, щоб це сказало "
непозитивно

ти знаєш цю хитрість? r←⍎condition⊃'else' 'then'
ngn


Думав, що сказав 22 ...> _ <
Zacharý


1

Dyvil , 34 байти

infix int apply(i:int,j:int=0)=i+j

Використання :

0() // = 0
0(1)() // = 1
0(1)(2)() // = 3

Слід ()можна опустити.

Пояснення :

Визначає оператор поєднання, який бере дві вставки та додає їх. Параметр jмає значення за замовчуванням 0для підтримки виклику без аргументів. У 0наведених вище прикладах не назва, а буквальне.


1

Джулія v0.5 +, 52 байти

type F n end
F()=0
(f::F)()=f.n
(f::F)(x)=(f.n+=x;f)

Телефонувати як F. Це, мабуть, може бути набагато коротше, застосувавши менший метод OO, але мені завжди подобається отримати можливість використовувати цю ідіому.

Якщо можна припустити, що "принаймні один виклик буде здійснений до виклику припинення", другий рядок можна видалити, щоб зберегти 6 байт.



1

R, 40 байт

f=function(x)function(y)`if`(y,f(x+y),x)

Тут діє значення стоп. Ще два байти ми можемо опустити його.

Проблема полягає в тому, що R не вистачає стислої вбудованої лямбда. Але якщо додати його , ми можемо отримати код до 26 байт :

f=x->(y->`if`(y,f(x+y),x))

(Так, це дійсно R. Це просто потрібно імпортувати.)


1

PHP, 44 байт

Ідея від @ user63956

Виклик припинення 0

function f($i){return[$_GET[0]+=$i][$i]?:f;}

Інтернет-версія

Припинення викликом з NULLнеобхідний гіпсом [$i]на[+$i]

PHP, 47 байт

function f($i){global$s;return$i?f.!$s+=$i:$s;}

Інтернет-версія

PHP, 52 байти

Виклик припинення NULLабо будь-яке інше значення, яке не відповідає PHP

function f($i){global$s;$i?$s+=$i:print$s;return f;}

якщо програма повинна припинитися після заміни виводу print$sна die("$s")+ 2 байти

Інтернет-версія


1
Я думаю, функція повинна повертатися (не друкувати) $s. тож ви могли зробити щось на кшталт return$i?f:$sнаприкінці
Конор О'Браєн

@ ConorO'Brien Я не впевнений, але якщо ваше мислення буде правильним, це могло б врятувати 5 байт. Дякую
Jörg Hülsermann,

1
Кілька байт можуть бути збережені з суперглобального змінними function f($i){return[$_GET[0]+=$i][$i]?:f;}.
user63956

@ user63956 дуже приємна ідея
Jörg Hülsermann

1

PowerShell, 86 байт

$f={$n=$args[0];$f=(gv f).value;{if($args){&$f($args[0]+$n)}else{$n}}.getnewclosure()}

Спробуйте в Інтернеті!

Код тесту:

&(&(&(&(&(&$f 4)2)7)5)2)

Вихід: 20


Дуже хороша. Ласкаво просимо до PPCG! Ви можете зберегти байт, виконуючи $n="$args"замість цього $n=$args[0]. $args[0]Однак це не буде працювати з іншого , тому що тоді ви отримаєте конкатенацію рядків, а не додавання.
AdmBorkBork


1

Пітон, 69 байт

def f(a=0,s=[]):
    if a:
        return lambda b=0:f(b,s+[a])
    return sum(s)

1
Я припускаю, що це пітон? Ви повинні вказати мову, що використовується у вашій відповіді.
corvus_192

Чи можете ви спробувати пограти у відповідь більше? На сьогоднішній день це не дуже добре гольф.
Rɪᴋᴇʀ


1

R, 54 52 байти

f=function(x){g=function(y='')'if'(y>'',f(x+y),x);g}

Збережено 2 байти завдяки MickyT!

Подібно до однієї з відповідей пітона. Безголівки:

f=function(x){
  g=function(y=''){
    if(y>''){
      f(y+x)
      }
      else{x}
  }
  g
}

Виконує як

> f(1)(2)(4)()
[1] 7

1
Хороша робота. Ви можете позбутися внутрішніх дужок навколо пункту if. f=function(x){g=function(y='')'if'(y>'',f(x+y),x);g}
MickyT

Я трохи спантеличений, чому у вашій версії "невольф" return. returnв R не такий, як в інших мовах, він робить передчасний переривання. Не використовувати return- ідіоматично. З іншого боку, у вашої версії все ще є гольф if.
Конрад Рудольф

@KonradRudolph У гольфів ifбув лінь, але returnце лише для читабельності - він дає такий же результат з або без return.
BLT

@BLT Гм. Я сильно відчуваю, що безоплатно в R return знижує читабельність, оскільки це сигналізує про неправильну річ (передчасний вихід) і є прикладом програмування культового культу .
Конрад Рудольф

Класно, я знову дізнався щось нове. Це одна з причин, що я продовжую повертатися. Дякую @KonradRudolph, цікаво також питання про переповнення стека: stackoverflow.com/questions/11738823/…
BLT

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.