The tricks from the JS wiki apply to Civet as well.

Special variables

#

# by itself is an alias to this.length. It's useful as a variable pre-initialized to undefined, as well as a loop variable (as explained below).

# is more generally a shortcut to .length

string#
array#
//instead of
string.length
array.length

& and .

& and . can be used as argument placeholders, allowing short syntax for creating functions. They differ in that . lifts outside a function call while & does not.

[99..1].map console.log .,"beers on the wall"
[99..1].map &+" beers on the wall"
//instead of
[99..1].map (x)=>console.log x,"beers on the wall"
[99..1].map (x)=>x+" beers on the wall"

If you want to access a property of ., you can't follow it with ., as it fails to parse. Instead, ? (which compiles to ?. in JS) or ! (which compiles to . in JS) can be used:

args.map console.log ..X   //fails
args.map console.log .?X   //okay
args.map console.log .!X   //okay

@

@ is shorthand for this and @X is shorthand for this.X.

Looping

The traditional for-loop

for(i=0;i++<10;)console.log i

can be shortened in Civet to

for$=0;$++<10;console.log $
for$ of[1..10]console.log $
for[i=1..10]console.log i++
for;#^10;console.log #=-~#
[1..10].map console.log .

These are not always interchangeable, so which is shortest will depend on the rest of the code. Note that # can also be used in place of $.

Also try postfix loop, sometimes it could be shorter.

This is a bit cursed, but if you are using eval, you can access the loop variable without ever assigning it directly:

for[0..9]eval "console.log(i)"

Late Assignment

a&&(b=3)
a&&b=3   //-2 bytes

i=1/(i+3)
i=1/i+=3 //-1 byte

Multiple Assignment

c=c*2+1
c++*=2   //-1 byte

Operators

Civet introduces a number of new operators that can help shorten your code.

Pipe operator

Sometimes using |> can avoid an intermediate variable to save a byte.

s=a+b,console.log s*s
a+b|>console.log .*.  //-1 byte

It can also be used to help lift the placeholder variable . through multiple function calls.

args.map console.log f .      //fails
console.log f $ for$ of args  //use a for-loop
args.map console.log(.|>f)    //or pipe into the inner function

Concat operator

The ++ operator is a shorter alternative to the concat method.

[1,2,3]++[4,5,6] // [1,2,3,4,5,6]

Modulo operator

%% always returns positive values.

-5%3  // -2 (remainder)
-5%%3 // 1 (modulo)

Other operators

"abc"<?"string"  // typeof "abc" === "string"
"abc"!<?"string" // typeof "abc" !== "string"

a^^b // a xor b
a!^b // a xnor b

a^^=b // a = a xor b
a!^=b // a = a xnor b

a?=b // a??=b

a%/b // floor division: Math.floor(a/b)

a∈b // b.contains(a)

a?b   //a?.b   (optional chaining property access)
a?(b) //a?.(b) (optional chaining function call)
a? b  //a?.(b), same as above

Chained comparisons

s<2&&console.log i
s<2<console.log i   // -1 byte

Node.js features

Civet runs on Node.js, which makes additional functions available compared to pure JavaScript.

Buffer

Consider Buffer as a way of accessing code points of an ASCII string or bytes of a Unicode string.

Buffer("Hello, World!").map console.log "Char code = ",.

It also can work in reverse, as an alternative to String.fromCharCode.

console.log ""+Buffer [103,111,108,102]

write

If you need write, you can still use it in Node with process.stdout.write.

Chars golfing

Operators

There are Unicode alternatives for many operators. ∈\∉\∋\∌ could be useful even in bytes scoring.

Packing

eval runs JavaScript code, not Civet code, so you'll need to edit your code accordingly before packing.

//To pack,
(Buffer.from "my source").toString "ucs2"

//Unpack & run
eval ""+Buffer "packed","ucs2"

If you have an odd number of characters in your source, then you can prepend ; to it before packing, and use

eval 0+Buffer "packed","ucs2"