g | x | w | all
Bytes Lang Time Link
016Uiua240919T000025Znyxbird
043Clojure240917T203406ZMartin P
036PowerShell Core210803T023912ZJulian
042R210801T153748ZDominic
022Haskell210801T014142ZUnrelate
046tinylisp210801T012736ZDLosc
057Racket210731T231852ZD. Ben K
007Jelly210730T223631ZNick Ken
042Python 3.8 prerelease210730T013754Zhyper-ne
045Perl 5210730T111721ZKjetil S
029APL Dyalog Unicode210730T012508ZAdá
022K ngn/k210730T060501ZRazetime
027J210730T051357ZJonah
037JavaScript210730T014237Ztsh
026Wolfram Language Mathematica210730T023433Zatt
036Factor210730T012953ZBubbler

Uiua, 16 bytes

◌⍢(^!°⊂⊂|±⧻):[]¤

Try it!

◌⍢(^!°⊂⊂|±⧻):[]¤
              :[]¤  # s -> [s] []
 ⍢(      |±⧻)      # repeat while the top isn't []:
      °⊂⊂          #   [s r?] [r1 r2...] -> s [r? r1 r2...]
    ^!              #   s [...] -> f(s) [...]
◌                   # [] [...] -> [...]

I initially tried to do something with catching an error from °⊟, but this ended up being shorter.

Clojure, 43 bytes

#(seq(iteration %2 :initk % :vf :v :kf :s))

Call with state and function. Function has to return either nil or hash-map with keys :s (new state) and :v (value). Example:

(#(seq(iteration %2 :initk % :vf :v :kf :s))
  137
  #(when-not (zero? %)
     (let [digit (mod % 5)
           next-state (int (/ % 5))]
       {:s next-state :v digit})))

=> (2 2 0 1)

PowerShell Core, 36 bytes

for($k,$a=$args;$a){$a,$u=&$k $a;$u}

Try it online!

Takes two parameters, a function $k and the initial value $a

-1 byte thanks to mazzy!

R, 43 42 bytes

u=function(s,l=f(s))if(1/l)c(l[2],u(l[1]))

Try it online!

Recursive function using helper function f to to the unfolding.

f must output the fixed non-integer value Inf to represent that the list has ended (a more natural value in R would be NULL or NA, but the functions is.null() and is.na() are each much less golfy than the simple test 1/x [truthy for all integers, falsy only for Inf])

Haskell, 22 bytes

f#x=do(s,v)<-f x;v:f#s

Try it online!

Function is expected to return a list [(state, value)] or an empty list. (Footer converts from the conventional/expected use of Maybe.)

f#x=                      Define a function (#) on arguments f and x, returning
    do     <-f x;         the concatenation for each element of f called on x
      (s,v)               providing the new state and value
                 v:       of the value prepended to
                   f#s    (f#) called on the new state.

Was this before I remembered MonadFail is a thing (never mind I'm not even using it anymore):

Haskell, 26 bytes

f#x|s:v<-f x=v++f#s|1>0=[]

Try it online!

Function is expected to return a list [state, value] or an empty list.

tinylisp, 46 bytes

(d U(q((S F)(i(F S)(c(h(t(F S)))(U(h(F S))F))(

Try it online!

Ungolfed

Implements the spec directly:

(load library)

(def unfold
  (lambda (val func)
    (if (func val)
      (cons
        (head (tail (func val)))
        (unfold (head (func val)) func))
      nil)))

This approach is pretty inelegant: it's not tail-recursive, and it calls the function three times at each step. If I were going to implement unfold for the standard library, it would look more like this (using a helper function _unfold):

(def _unfold
  (lambda (func return-val accum)
    (if return-val
      (_unfold func
        (func (head return-val))
        (cons (head (tail return-val)) accum))
      (reverse accum))))

(def unfold
  (lambda (func val)
    (_unfold func (func val) nil)))

Racket, #lang racket, 57 bytes

(define(u s f)(match(f s)[`(,z,x)(cons x(u z f))][_'()]))

Try it online!

The function f can return anything other than a list of two values to indicate stop.


Not the most interesting racket solution: no tail-call recursion, so is bounded by memory usage. It would be more fun (and not difficult) to write a #lang that supplies unfold as part of its runtime—then there would be a 0-byte solution :)

We (unexpectedly?) save a few bytes by eliminating spaces between ,z,x and _'() in match clauses. I expected each to coalesce into a single identifier, but (un)quoting took precedence. The remaining whitespace (6 spaces, by my count) is required.

Jelly, 7 bytes

Ṫv@¥ƬFḊ

Try it online!

A dyadic link taking the start value as its left argument and the Jelly code for the relevant function to unfold as its right. It expects the return value of this link to be an empty list if we’re done, otherwise a list of [next value for result, next value for function]. Returns a list of integers.

Python 3.8 (pre-release), 42 bytes

u=lambda f,x:(r:=f(x))and[r[1],*u(f,r[0])]

Try it online!

-1 byte thanks to Noodle9
-4 bytes thanks to Shaggy

Assumes falsy output for the end case and a pair otherwise (any subscriptable value with at least two elements). Since a list of falsy values is still truthy, this works perfectly fine.

Perl 5, 45 bytes

sub u{@f=$_[1]->(@_);@f?(pop@f,u(@f,pop)):()}

Try it online!

APL (Dyalog Unicode), 32 29 bytes

Full program, prompting for s and then for f.

¯1↓r⊣⎕{1↓r,∘⊃←⍺⍺⍵}⍣{⍬≡⍺}⎕⊣r←⍬

Try it online!

r←⍬ initialise the result variable to the empty list

⎕⊣ dismiss that in favour of s from stdin

⎕{}⍣{⍬≡⍺} get f from std and use it as follows until the result is the empty list:

⍺⍺⍵ apply f to the current s (returning [e,t] or [])

r,∘⊃← extend r with the first value from that (e or 0)

1↓ drop the first value from that (leaving [t] or [])

r⊣ discard that (i.e. the last computed value, i.e. []) in favour of r

¯1↓ drop the last value (0)

K (ngn/k), 22 bytes

{-1_1_*'|'{x}(y@*:)\x}

Try it online!

call with f[n,s].

s should return an array (nextState;digit) and return a falsy value when it's supposed to end.

I can remove {x} but that would make the function stop on a repeated state. Although that is unlikely, it doesn't seem right to reject that.

Explanation

{-1_1_*'|'{x}(y@*:)\x}
                   \x
                       iterate on first arg, producing array
             (y@*:)    apply second arg(function) to the first elem of the iteration
          {x}          stop if the iteration is falsy
        |'             reverse each array
      *'               take first element of each
 -1_1_                 remove first and last element

J, 27 bytes

1 :'[:(#~2|i.@#)(,u@{:)^:_'

Try it online!

This is J adverb, which modifies a verb returning (new element, new state) to create the required unfold verb.

JavaScript, 37 bytes

f=>g=s=>(a=f(s))?[a[1],...g(a[0])]:[]

Try it online!

((state: T) => [next_state: T, val: S]?) => (state: T) => S[]

Wolfram Language (Mathematica), 26 bytes

f=#@#2/.{a_,b_}:>b<>#~f~a&

Try it online!

Input [f, s]. Returns a StringJoin of elements. Expects an empty list to indicate the list has ended.

To output a list, +6 bytes:

f=#@#2/.{a_,b_}:>{b,##&@@#~f~a}&

Try it online!

Factor, 37 36 bytes

[ collector [ follow ] dip 1 head* ]

Try it online!

-1 byte thanks to @chunes

Takes initial-value and quotation on the stack, and returns a vector. The input quotation should return next-state next-value on the stack, or f f to terminate.

some-quot collector [ high-order-func ] dip is a pattern to snatch the top of the stack of every call of some-quot into a vector. Unfortunately, it collects the top of the stack before follow can detect that the loop has ended, so the resulting vector has a dummy element at the end. 1 head* removes it.