11
\$\begingroup\$

Standard ML (or golfier: SML) is a general-purpose, modular, functional programming language with compile-time type checking and type inference. (from Wikipedia)

Though you almost certainly will never win a code golf challenge with SML, (ab-) using it for golfing can nevertheless be quite fun (<- keyword for function declaration). So without further ado ...

What tips do you have for golfing in Standard ML?

Please only post tips which are somewhat unique to SML. General golfing tips belong to Tips for golfing in all languages.

\$\endgroup\$
1

4 Answers 4

9
\$\begingroup\$

Use symbolic identifiers

From The Definition of Standard Ml (revised) [PDF], Section 2.4:

An identifier is either alphanumeric: any sequence of letters, digits, primes (') and underbars (_) starting with a letter or prime, or symbolic: any non-empty sequence of the following symbols:

!  %  &  $  #  +  -  /  :  <  =  >  ?  @  \  ~  ‘  ^  |  * 

In either case, however, reserved words are excluded. This means that for example # and | are not identifiers, but ## and |=| are identifiers.

The important part (concerning golfing) is that you do not need white space between symbolic identifiers and alphanumeric identifiers or keywords.

Example

fun f a b c=if b then a else c

By replacing f by $ and b by !, we can save 6 bytes:

fun$a!c=if!then a else c

Note, however, that a symbolic identifier needs white space when next to other symbols. That's why we cannot replace a and c in the above example to get to the same byte count:

fun f$b!=if b then$else!    (* syntax error because != is parsed as one token *)
\$\endgroup\$
2
\$\begingroup\$

List functions

Lists are the standard data structure usually used recursively with :: constructor. Indexing must be done using nth.

Short and maybe useful functions are

  • @: append
  • hd: head, but also try pattern matching
  • tl: all but head
  • last: tail
  • take: first n elements
  • drop: drop first n elements and return
  • rev: reverse

Higher order functions:

  • map: map
  • foldr, foldl: fold and reverse fold
  • filter: filter
  • exists, all: exists, all bool cond
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Be aware that using functions from a structure requires either to open the structure (open List) or to qualify the functions (List.exists). However, the following list functions are also available at top level: @, app, foldl, foldr, hd, length, map, null, rev, tl. \$\endgroup\$
    – Laikoni
    Commented Jun 3, 2022 at 7:23
1
\$\begingroup\$

Pattern matching in functions

Concise way to extract the values and write cases for recursive functions. Case statements are probably too long.

Extracting values:

fn(x,y)=>x+y   (* lambda fn *)
fun f x y=x+y  (* curried bound function *)

Recursive function with base case (this basic list sum is equivalent to foldl op+ 0):

fun f(x::L)=x+f L|f _=0
\$\endgroup\$
1
\$\begingroup\$

Use wildcard matching instead of explicit matching

This broadly applies to any pattern matching construct with a fallthrough or wildcard: in some situations you can use the wildcard to match a pattern instead of an explicit pattern.

Empty list example (with formatting for clarity):

fun f([]) = 0
  | f(x::L) = x + f L

versus matching with wildcard saving a byte:

fun f(x::L) = x + f L
  | f(_) = 0
\$\endgroup\$
1
  • \$\begingroup\$ Also note that the wildcard does not need parentheses and only needs a space when preceded by an alphanumeric identifier. That is, the last line can be |f _=0 or also | $_=0 when f is renamed to $. Likewise, fun f _x=x works, but fun x_=x does not. \$\endgroup\$
    – Laikoni
    Commented Jun 3, 2022 at 7:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.