Background

Inspired by Octave's (and, by extension, MATL's) very convenient interpretation of truthy/falsy matrices, Jelly got the Ȧ (Octave-style all) atom.

Ȧ takes an array as input and returns 1 if the array is non-empty and does not contain the number 0 (integer, float, or complex) anywhere in the tree structure; otherwise, it returns 0.

For example, the array [[]] is truthy because it is non-empty and contains no zeroes, but [[0]] is falsy because it contains a 0 at the innermost level.

In a programming language of your choice, write a full program or a function that takes a possibly empty, possibly jagged array of integers as input and prints or returns a truthy or falsy value that indicates if Ȧ would return 1 or 0, respectively.

Your submission must abide to the following rules.

• The truthy and falsy values must be consistent for all inputs, i.e, all arrays for which Ȧ returns 1 must map to the same truthy value, and all arrays for which Ȧ returns 0 must map to the same falsy value.

• Since full programs can only take string representations of arrays as input, this is allowed. However, you must use the canocical representation of your language, as returned by repr or similar.

In particular you cannot assume that the first element of the array will be preceded by a space.

• If (and only if) your language cannot represent jagged arrays natively, you may take a string representation of the input, using the canonical syntax of any pre-existing programming language.

• If your language has several ways of representing jagged arrays (e.g., lists and tuples), you only have to support one of them.

• If your language has a built-in that is itself a valid submission to this challenge, you may not use it in your answer. All other built-ins are allowed.

• You are encouraged to post answers using both array and string manipulation, even if one is significantly shorter than the other.

• All standard rules apply.

May the shortest code in bytes win!

Truthy test cases

[1]
[10]
[[]]
[[[[1]]]]
[[], [1], [1, 2]]
[[1], [1, [2]], [1, [2, [3]]]]
[[8], [8, [9]], [8, [9, [10]]]]


Falsy test cases

[]
[0]
[0, -1]
[-1, 0]
[[[[0]]]]
[[0], [1, 2], [3, 4, 5]]
[[8], [8, [9]], [8, [9, [1, 0]]]]
[-1, 0, 0, 0]

• Based on the test cases, do you mean "contain the number 0" to mean anywhere in the tree structure? That's not what I have guessed it meant. – xnor Mar 18 '17 at 17:35
• Yes, anywhere. I'll try to clarify that. – Dennis Mar 18 '17 at 17:36
• What exactly do you mean "you cannot assume that the string representation will have a particular format"? – Dada Mar 18 '17 at 17:40
• These are not jagged arrays - jagged arrays would have all numbers at the same depth, because only sizes vary, not element types. – Ørjan Johansen Mar 18 '17 at 18:41
• @Qwertiy Right, "most" languages where "everything" is an Object... my favorite is Haskell, where it isn't. Nor in C, at least not in a way that allows you to mix arrays and ints safely. Both of those languages are perfectly capable of jagged arrays, but still cannot use them for this problem. – Ørjan Johansen Mar 18 '17 at 23:41

Jelly, 3 bytes

ṭFẠ


F flattens the input list.

ṭ tacks on the original input list as an element, which is falsy if and only if it is empty.

Ạ then checks if any element in the flattened list, or the original list itself, is falsy.

FẠ^Ṇ


Thanks to Dennis for encouraging finding a solution matching his.

FẠ gives 0 if the input contains a falsy value at any depth, else 1. This is what Ȧ does, except for empty lists.

Ṇ gives 1 if the input is a falsy value, else 0. The only falsy list is the empty list.

XOR-ing the two gives the answer.

F;WẠ


This is much in the same spirit as Dennis's F;LẠ, but instead of using L to put a zero in the list when the list is empty, it uses W to put the empty list into itself (producing [[]]), making it contain a falsy element.

• Outgolfed in my own challenge and my own language... Well done! – Dennis Mar 19 '17 at 23:08

Retina, 10 bytes

A\b0
^...


Try it online!

First we remove the input if it contains a zero. The we try to match at least three characters from the beginning of the string (to ensure that the input hasn't been eliminated in the previous stage, or was only [] to begin with).

Ruby, 25242318 16 bytes

p$_!~/\D0|^..$/


Requires the -n flag on the command line (+1 byte, -e -> -ne).

Try it online!

This is a full program that takes input in Ruby's canonical array format on STDIN and outputs true or false on STDOUT.

 $_ # line of input that was read automatically (-n) !~/ / # does not match the regex... \D0 # a non-digit followed by a 0 | # or... ^..$   #   a 2-length string (which must be [], the empty array)
p                # output the result


23 byte function version:

->a{"#{a}"!~/\D0|^..$/}  This is a proc that takes one argument, the array to be tested. Thanks to Martin Ender for a byte and to Ventero for two bytes! • You could save two more bytes by using p$_!~/\D0|^..$/ (or p ! ~/\D0|^..$/, yay significant whitespace) together with the -n flag. – Ventero Mar 19 '17 at 14:16

Jelly, 4 bytes

FẠ_Ṇ


Try it online!

Ȧ yields 0 if the input is empty or contains a 0, otherwise it is 1.

FẠ yields 0 if the flattened input contains a 0, leaving only the edge case of an empty array (since the input is guaranteed to be an array).

Ṇ is a non-vectorising logical not monad, and hence returns 0 for any non-empty list and 1 for the empty list. As such this can simply be subtraced from the result of FẠ using _.

• One down, at least one more to go. – Dennis Mar 19 '17 at 0:07
• @Dennis It isn't FẠạṆ, right? – Erik the Outgolfer Mar 19 '17 at 8:01
• @EriktheOutgolfer No, it is not. The answer I have in mind deals different with the edge case of an empty array and would produce a different result for non-arrays. – Dennis Mar 19 '17 at 14:48
• @Dennis Like returning A for True, B for false, C for empty and D for non-array? That would be non-competing. What I did is use absolute difference instead of difference because there are no negative booleans. – Erik the Outgolfer Mar 19 '17 at 14:56
• @EriktheOutgolfer B must equal C to comply with the challenge spec, but D can be anything as the input is guaranteed to be an array. – Dennis Mar 19 '17 at 14:59

05AB1E, 9 8 bytes

-1 bytes thanks to Emigna

)Q¹˜0å~_


Explanation:

)Q        Is the length of the input 0?
~    _  ... NOR ... (just for you, Dennis)
¹˜     Input deep flattened
0å   Contains 0


Try it online!

• Seems to fail for [[]]. – Dennis Mar 18 '17 at 17:45
• Is 0 really truthy in 05AB1E? – Dennis Mar 18 '17 at 17:46
• all arrays for which Ȧ returns 1 must map to the same truthy value, and all arrays for which Ȧ returns 0 must map to the same falsy value (emphasis mine) – Dennis Mar 18 '17 at 17:53
• @Dennis Alright, chucked in a logical negation byte there. – Okx Mar 18 '17 at 17:55
• Aw, just for me. :P – Dennis Mar 18 '17 at 17:56

Mathematica, 17 bytes

#!={}&&#~FreeQ~0&


FreeQ does the check against 0 for us, but of course it would return True for input {}, so we need to check that case separately.

APL (Dyalog), 2112 7 bytes

Golfed 5 bytes thanks to Adám by using forks

⍬∘≡⍱0∊∊


Try it online!

This is my first try at Dyalog. Golfing tips are welcome!

Explanation

⍬∘≡                   Fork; Is the argument a null set
⍱                  Nor
0∊∊               0 belongs to the enlisted form of the argument
For example, (1 (2 (3 (0)))) would become
1 2 3 0 using the ∊ monad
Then we check if zero belongs to this vector

• +1 Note that you are combining the results of two tests. This is perfect for a fork. ⍬∘≡ is the left test (empty-set bound-to identical-to), and 0∊∊ is the right test (itself a fork; zero member-of enlisted-form). Put it together: ⍬∘≡⍱0∊∊. Try it online! – Adám Mar 18 '17 at 21:42
• Also, you may want to use the name "APL (Dyalog)" so people can find what it is you are using. – Adám Mar 18 '17 at 21:43
• @Adám Thanks for the tips! – Kritixi Lithos Mar 19 '17 at 7:10

Operation Flashpoint scripting language, 199 188 bytes

A={f={private["_i","_r"];_r=1;_i=0;while{_i<count _this}do{o=_this select _i;if(o in [o])then{if(o==0)then{_r=0}}else{_r=o call f};_i=_i+1};_r};if(count _this==0)then{0}else{_this call f}}


Call with:

[3,6,4,[4,6],[3,6,[],[2,4,[0],3]]] call A


or with:

hint format["%1", [3,6,4,[4,6],[3,6,[],[2,4,[0],3]]] call A]


Explanation:

In the game's scripting language, any string containing code can be called. The curly braces {} denote the beginning and the end of a string. (Quotation marks work too, but that gets messy when they are nested.) So, A={...} assigns a string to variable A, and the variable can then be called like a function with: <argument> call A. Basically any string can be treated as a block of code.

Then, inside the "function" A, we define another function f. private declares the two variables _i and _r local to function f. A local variable's name has to start with an underscore.

while {} do {} is a loop, where the first string (denoted by {}) contains the code for the loop condition and the second one for the loop body.

_this is the argument that was passed with the call function. _this can be of any type, but here we assume it is an array.

In the loop, o=_this select _i accesses the _i:th element of the array and assigns it to variable o. if (o in [o]) is a trick to determine if the o is another array or not. If o is a number (or anything other than an array), o in [o] will evaluate to true, because the in function finds a value matching o from the array [o]. If o is an array, the expression yields false, because the in refuses to compare arrays.

If o is not an array, we check if it equals zero, and if it does, we'll set the variable _r, which we'll use as the return value, to zero. Otherwise, if o is an array, we assign to _r the return value of the recursive call to f with the new array o as the argument.

After the loop, at the end of function f, we evaluate the expression _r, which yields the value of _r, and as this is the last expression to be evaluated, this is what the call to function f returns.

Now that we have defined f (f need not be inside A, but this way we could have declared it a local variable/function (no difference really) of A if we didn't want to save some bytes), let's get back A. if (count _this == 0) checks if A's input array is empty, and if it is, A returns 0. Otherwise the function f is called and its return value will be A's return value.

One might notice that it seems that a semicolon would be missing from a few of places, but this is not the case, because a semicolon is only needed after a statement if another statement follows it inside the same block of code (i.e. string).

• Wait, what?! Operation Flashpoint? – Brain Guider Mar 20 '17 at 13:23
• wat how? what??? confuzed – Christopher Mar 20 '17 at 15:30
• @DownChristopher Added an explanation. – Steadybox Mar 20 '17 at 16:24
• @AnderBiguri Yep, why not? The game's scripting language fits the definition of programming language given in the meta post linked in the question. – Steadybox Mar 20 '17 at 16:25
• @Steadybox I am confused about the existence of the thing, not its validity!! – Brain Guider Mar 20 '17 at 16:35

Perl 5, 15 bytes

Saved 2 bytes by using the same technique as Doorknob's Ruby answer.

14 bytes of code + -p flag

$_=!/\b0|^..$/


Try it online!

/.../ ensures that the array isn't empty (it will match on any array but [].
/\b0/ will only match if there is a 0 in the array. (the \b ensures that the 0 isn't a part of another number but a whole number).

f x=or[elem c"[,"|c:'0':_<-scanr(:)[]x]<(x<"[]")


Try it online!

Thanks to Lynn for the test cases and the x<"[]" trick.

The outer inequality requires (x<"[]") to be True (nonempty list) and or[elem c"[,"|c:'0':_<-scanr(:)[]x] to be False (no zeroes).

Characters of 0 are detected as following a , or [, as opposed to a number like 20. The expression scanr(:)[]x generates all suffices of l, and c:'0':_<- captures those whose second character is '0'. Then, elem c"[," checks whether the first character is , or [.

I assume here that Haskell-style lists don't have spaces, but if so ',' can just be replaced by ' '.

Here's a more direct 48-byte method, though it produces 0's and 1's which aren't Truthy/Falsey in Haskell.

f"[]"=0
f(c:'0':_)|elem c"[,"=0
f(_:t)=f t
f _=1


Jelly, 4 bytes

F;LẠ


Try it online!

How it works

F;LẠ  Main link. Argument: A (array)

F     Flatten A.
L   Yield A's length.
;    Concatenate.
Ạ  All; Tell if all elements of the resulting 1D array are truthy.


Note that the Ạ atom behaves like Python's all and thus is rather different from the banned Ȧ.

• Heads-up: This isn't the only 4-byte solution Jelly, apart from the obvious L;FẠ. Who can find another one? – Dennis Mar 18 '17 at 19:54

JavaScript (ES6), 34 bytes

a=>a.length&&+!~,${a}.search,0  Test cases let f = a=>a.length&&+!~,${a}.search,0

console.log('Truthy:')
console.log(f([1]))
console.log(f([10]))
console.log(f([[]]))
console.log(f([[[[1]]]]))
console.log(f([[], [1], [1, 2]]))
console.log(f([[1], [1, [2]], [1, [2, [3]]]]))
console.log(f([[8], [8, [9]], [8, [9, [10]]]]))

console.log('Falsy:')
console.log(f([]))
console.log(f([0]))
console.log(f([0, -1]))
console.log(f([-1, 0]))
console.log(f([[[[0]]]]))
console.log(f([[0], [1, 2], [3, 4, 5]]))
console.log(f([[8], [8, [9]], [8, [9, [1, 0]]]]))

• You can probably use !!a[0] instead of a.length. (You don't have to worry about a[0] being zero as the result must be false in this case anyway.) – Neil Mar 18 '17 at 23:54
• Never mind, I saw Qwerty already got there. – Neil Mar 18 '17 at 23:57

Julia, 45 bytes

a(x)=all(a,x);a(x::Int)=x!=0;g(x)=x!=[]&&a(x)


This creates a function g that indicates whether Ȧ would be 1 or 0 by calling a recursive function a. To make a suitable a, we use multiple dispatch:

# A method for scalar values
a(x::Int) = x != 0

# A recursive fallback for arrays
a(x) = all(a, x)


The function all takes a function argument, so we're calling a on each element of the input. Then we simply define the function for the submission as

g(x) = x != [] && a(x)


Basically we just need a but with a check to correctly handle [].

Try it online!

• can you define the function a(x) or g(x) as !x instead? – Cyoce Mar 20 '17 at 18:24

Grime, 1614 11 bytes

Thanks to Zgarb for saving 5 bytes.

es\0v#|!..


Try it online!

The e tells Grime to try and match the entire input and print 0 or 1 depending on whether that's possible.

The |! is effectively a "neither" operator, because x|!y is shorthand for (x|y)!. So we make sure that the input neither contains a zero preceded by a symbol nor is a string of only two characters ([]).

A note about the second half: P# matches a rectangle that contains at least one match of P. However, in our case P consists of both s and \0 so that would normally require parentheses: (s\0)# (because the precedence of # is too high). But Grime has a really neat feature where you can modify the precedence of operators with ^ and v. So by using v# we lower #'s precedence so that it's lower than that of any other operator (including concatenation), which lets us save a byte on the parentheses.

Pip, 12 bytes

#Va&\b0NIa


Takes the array as a command-line argument in Pip's repr form, like [1;[2;3]]. Returns 1 for truthy, 0 for falsey. Try it online or verify all test cases.

Explanation

              a is 1st cmdline arg (implicit)
Va            Eval a (converting from a string to a list)
#              Take the length (0 if empty, nonzero if nonempty)
&          Logical AND
\b0      Regex pattern: word boundary followed by 0 (avoids things like 10)
NIa   Not in a (0 if \b0 matches in a, 1 if it doesn't)
Autoprint


Here's a function that takes a list instead:

#_>0=0N_Js^s

#_            Len(arg)
>0          is greater than 0
=         which also equals the following (comparison operators chain like Python's):
0N       Count of 0's in
_Js^s  arg, joined on space and then split on space (a hacky way to flatten)


TIO

Röda, 59 44 bytes

f a{[1]if{g(a)[[]!=a]}}g a{[a!=0];try a|g _}


Try it online!

f takes the input from its stream as a list that can contain other lists and integers. It returns 1 if a is truthy and nothing otherwise. The helper function g checks if a contains zeros.

Explanation:

f a{[1]if{g(a)[[]!=a]}}
f a{                  } /* Function declaration */
g(a)          /* Call g -> pushes some booleans to the stream */
[[]!=a]   /* Push value []!=a to the stream */
if{           }  /* If all booleans in the stream are true: */
[1]                 /*   Push 1 to the stream */
/* Otherwise return nothing */

g a{[a!=0];try a|g _}   /* Helper function */
g a{                }   /* Function declaration */
[a!=0];             /* Push value a!=0 to the output stream */
try          /* Ignore errors in the following if a is not a list */
a        /* Push values in a to the stream */
|g _    /* Pull values from the stream and */
/*   call g for each of them */
/*   (pushes boolean values to the output stream) */


A solution that makes use of regexes could very likely be shorter.

This answer could have been shorter if it were allowed to return multiple values. This has been discussed in one of my answers before, and it was concluded that it is allowed in the default rules to return different truthy and falsy values for different inputs, but for some reason OP forbid it here and there. :(

Wonder, 15 bytes

@&#0! iO0flat#0


Usage:

(@&#0! iO0flat#0)[1;2;3;[8;9;0]]


Flatten input, get all occurrences of 0, logical NOT, logical AND with input.

import Data.List
(%)=isInfixOf
f x=not(",0"%x||"[0"%x)&&x<"[]"


Try it online!

This is a function String -> Bool. Haskell’s lists are heterogenous, so there’s no built-in way to represent lists like [0, [0]].

• Based on the re-worded rules, the inputs should not have spaces because Haskell arrays don't by default. At least, I think that's the interpretation even though Haskell doesn't allow jagged arrays. But it looks like your code would work the same with , for  . – xnor Mar 18 '17 at 18:40
• As I'm quibbling up in the question comments, Haskell does have jagged arrays (and lists) - it's just that it's not really enough for what this question requires. – Ørjan Johansen Mar 18 '17 at 23:44

Python 2, 45 39 38 bytes

lambda a:(a>[])^(' 0'inaor'[0'ina)


Try it online!

-6 thanks to @BenFrankel

previous version, without converting list to string repr, 68 bytes:

lambda a:(len(a)and g(a))*1
g=lambda b:all(map(g,b))if b>[]else b!=0

• This gives a false positive on []. The following saves 6 bytes and succeeds on []: lambda a:bool(a)^(' 0'inaor'[0'ina) – Ben Frankel Mar 18 '17 at 23:30

MATLAB, 49 bytes

As MATLAB (as well as Octave) does not allow these kind of nested arrays, we interpret it as a string.

First we replace all non-digit characters with a space. Then we use str2num to convert it to an (1D) array, on which we can apply all (which is allowed, as it does not completely solve this task by itself.)

s=input('');s(s<45|s>57)=32;disp(all(str2num(s)))


egrep, 7+3=10 bytes

\<0|^.]


+3 bytes for the required -v flag to invert the result.

Grep doesn't have any concept of arrays, so this uses a string representation as given in the question. Takes input on one line from stdin, returns via the exit code (ignore stdout).

(Now using a version which doesn't account for 01 and similar, since word-of-god is that it's OK)

Original bash/grep entry:

grep -Ev '\<0+\>|^.]'


Finds 0s anywhere (using the word boundary checks \< and \> to discount things like 10 or a1), or a whole string matching [], then inverts the match.

Breakdown:

grep
-E \    # extended regular expression syntax
-v \    # invert match
\<0+\>  # a number of 0s with alphanumeric boundaries on both sides
|^.\]   # or ']' as the second character (implies '[]')

• Not cheating, just good golfing. :) Btw, grep is capable for primality testing, so it is a programming language as far as PPCG is concerned. \<0\|^.] plus -v would count as an 11 byte solution. – Dennis Mar 18 '17 at 21:44
• @Dennis cool, thanks! (I switched to egrep rather than grep to save an additional byte; language name doesn't count towards byte-count!) – Dave Mar 18 '17 at 22:09

Javascript ES6, 24 chars

Works with array, returns 1 or 0:

a=>!!a[0]&!/\b0/.test(a)


Test:

f=a=>!!a[0]&!/\b0/.test(a)

console.log([
[1],
[10],
[[]],
[[[[1]]]],
[[], [1], [1, 2]],
[[1], [1, [2]], [1, [2, [3]]]],
[[8], [8, [9]], [8, [9, [10]]]],
].every(x => f(x)===1))

console.log([
[],
[0],
[0, -1],
[-1, 0],
[[[[0]]]],
[[0], [1, 2], [3, 4, 5]],
[[8], [8, [9]], [8, [9, [1, 0]]]],
].every(x => f(x)===0))

• Since the return value can be truthy/falsy, you can drop the !! (though then you must change & to &&). Saves one byte. – Brian McCutchon Mar 21 '17 at 3:19
• @BrianMcCutchon, no as there is a binary &. In case of && without !! consistent output will be broken: undefined for [],0 for [0] and [0,1,2] and false for others. – Qwertiy Mar 21 '17 at 4:30
• I don't see how breaking consistent output is bad in this challenge. My point with switching to && is that you would need to if you take my first suggestion, since 2 & 1 == 0. – Brian McCutchon Mar 21 '17 at 4:41
• @BrianMcCutchon, the first point of the question: "The truthy and falsy values must be consistent for all inputs, i.e, all arrays for which Ȧ returns 1 must map to the same truthy value, and all arrays for which Ȧ returns 0 must map to the same falsy value." – Qwertiy Mar 21 '17 at 4:44
• Ah, I skimmed that too quickly. Never mind. – Brian McCutchon Mar 21 '17 at 4:45

√ å ı ¥ ® Ï Ø ¿ , 12 4 bytes

i0Bu


Explanation

i            › Take input as a list and automatically flatten it. If empty, push 0.
0           › Push 0 to the stack
B          › Pop 0 and push the number of times it appears
u         › convert top value to its boolean


If result needs to be outputted ...

i0Buo        › same as above; o outputs the top value on the stack


Previous solution

I had posted this before realising that stack based languages could leave the value on the stack as a form of output

i0B¿0oP?!¿o?


Explanation

i            › Take input as a list and automatically flatten it. If empty, push 0.
0           › Push 0 to the stack
B          › Pop 0 and push the number of times it appears
¿         › If the top value is true ...
0        › Push 0
o       › Output the top value on the stack
P      › Pop the top value from the stack
?     › End if statement
!    › Boolean opposite of top value
¿   › If the top value is true ...
o  › Output the top value
? › End if statement


As Lynn and xnor remarked, Haskell does not come with a heterogeneously-nested list type. But it's easy to add them as a custom data type and let the function operate on that type, and this is much preferrable to operating on (urgh!) strings.

data L=L Int|T[L]
f(L n)=n/=0
f(T l)=all f l


To actually be able to write out such lists as literals with [1, [2]] syntax, you also need some typeclass fu. Full test case:

{-# LANGUAGE OverloadedLists, TypeFamilies #-}
import GHC.Exts (IsList(..))

instance Num L where
fromInteger = L . fromInteger
negate (L n) = L $negate n instance IsList L where type Item L = L fromList = T main = mapM_ (print . f) ( [ [1] , [[[[0]]]] , [[8], [8, [9]], [8, [9, [1, 0]]]] ] :: [L])  Try it online! Vim, 23 bytes :g/0\|^..$/d
:s/.\+/1/<CR>


Try it online!

Outputs an empty string for false, or 1 for true. This could be shorter if I can output an empty string or [] for false (both of which are falsy values in vim).

Stacked, 20 bytes

:size\flat,0 eq none


Try it online!

Alternatively, using a string:

:tostr'\d+'match'0'has¬\size¬>


Try it online!

Lithp, 74 bytes

(def f #L::((foldl(flatten L)(?(>(length L)0)1 0)#N,A::((?(== N 0)0 A)))))


Try it online!

Well, this turned out longer than I'd hoped. The [] case tripped me up and added a few bytes. It simply flattens the list and does a fold left over it, and if it finds a 0 it sets the accumulator to 0.

Ruby, 24 22 bytes

->a{a[0]&&a*?!!~/\b0/}


Try it online!

Yes I know there's a better solution in Ruby but I wanted to find one taking the array in input instead of a string.

tinylisp, 70 64 bytes

(load library
(d _(q((X)(i(c()X)(all(map _ X))X
(q((L)(i L(_ L)0


The last line is an unnamed lambda function that takes a list and returns 1 for "truthy-under-Ȧ" and 0 for falsey. Try it online!

Ungolfed

(load library)

(def _Ȧ
(lambda (val)
(if (equal? (type val) List)
(all (map _Ȧ val))
val)))

(def Ȧ
(lambda (ls)
(if ls
(_Ȧ ls)
0)))


The recursive helper function _Ȧ does most of the work. If its argument is a list, we map _Ȧ to its elements and return 1 if they are all truthy, 0 if any are falsey. (Conveniently, all returns 1 when given the empty list.) Otherwise, the argument must be an integer; we return it as-is (0 is falsey and all other integers are truthy in tinylisp).

The main function Ȧ checks if the list is nonempty. If so, it calls _Ȧ; if not, it returns 0.

The golfed version takes advantage of some undefined behavior: rather than using (e(type X)List) to test whether X is an integer or a list, it does (c()X), which attempts to cons (prepend) the empty list onto X. If X is a list, this results in a nonempty list, which is truthy. If X is an integer, tinylisp outputs an error message and returns an empty list, which is falsey. Since stderr is ignored, this approach is valid.

PHP, 63 54 bytes

9 bytes saved by @user63956

function a($a){return$a&&!strpos(print_r($a,1)," 0");}  takes an array as input; returns true or false: If $a is not empty,
check if print_r output contains a 0 value.

array solution, 83 bytes

function b($a,$r=0){$r|=$a;foreach($a as$v)$r|=is_array($v)?b($v,1):!!$v;return$r;}  recursive function returns 1 or 0. breakdown function b($a,$r=0) {$r|=$a; # if$a is not empty, set $r (no effect in recursion) foreach($a as$v) # loop through elements:$r&=is_array($v) # 2. if test failed, clear$r
?b($v,1) # 1. if array, recurse :!!$v;          #    else test element <>0
return$r; # return$r
}

• You can save a few bytes with strpos(print_r(\$a,1)," 0") instead of preg_match(...). – user63956 Mar 19 '17 at 12:03
• @user63956 ... and it also solves the 0-index problem. I wasn´t aware of the second print_r parameter. Great! – Titus Mar 20 '17 at 12:06