Skip to content

Instantly share code, notes, and snippets.

@branneman branneman/philosophy.md
Last active Dec 20, 2018

Embed
What would you like to do?
Hogget language specification - https://hogget.org/

Hogget: Philosophy

Elevator pitch

  • Functional programming language
  • Strong typed
  • Dense syntax, everything is an expression
  • Compiles to JavaScript

The Name

A Hogget is a sheep between one and two years of age. Inspired by Ramda, we also like sheep. It's a unique and rememberable name, a short one, it's not yet taken, easily pronounceable, and there's not too many languages that start with an H yet.

Facts

  • Implemented in JavaScript for Node.js
  • File extension: .hgg
  • British English

Hogget: language specification

Types

  • null
  • bool (true or false)
  • int (signed)
  • dec (signed)
  • str (utf-8)
  • enum
  • list (int indexed)
  • obj (string indexed)
  • func

Program

All hogget programs are started by calling the main function, which must be implemented by the user. Example:

let main = => {
  log('the answer is' add(12 30) '\n');
  exit(0);
}

Expressions & Statements

Expressions are language constructs that evaluate into a value and can be nested. Statements are language constructs that don't evaluate into a value and must stand on their own, they are separated with ;.

Comments

// single line comment
let myVar = 42; // inline comment
/* multi
line
comment */

Variables

All variables are immutable. Declare a variable with the let statement, which receives an expression or value.

let myVar = 42;
let myResults = getResults();

Numbers

The rule is simple: if there's a . involved in a number, it's a dec, otherwise it's an int. Whether it's positive or negative doesn't matter.

let answer = 42;
let pi = 3.14;
let cold = -3;

Strings

Strings are delimited with a single quote ('), and are interpolated with ${varName}. Example:

let question = 'What is the answer to everything?';
let answer = 'The answer is ${toStr(42)}';

Enums

let PaymentCardType = enum { MasterCard Maestro Visa };
let myPayment1 = enum(PaymentCardType Visa); // functional access
let myPayment0 = PaymentCardType.Maestro;    // operator access

Lists

let constants = [1.41 2.71 3.14];

Objects

Comma's (,) are fully optional, though they may increase readability when using single line syntax. The formatter will put objects on a single line wih comma's if the line does not exeed 80 characters.

let position = obj { lat: 123.456, lng: 789.321 };
let mapConfig = obj {
  center: obj {
    lat: 123.456
    lng: 789.321
  }
  ratio: "4:3"
  zoom: getDefaultZoom()
};
log(prop("lat" position)); // functional access
log(position.lat);         // operator access

Functions

All functions are expressions and must have an return value (null is valid).

Functions can be defined as one-liners without curly brackets, or as multi line with curly brackets. The last line is the return statement. Specifying arguments is optional.

let myAdd0 = => 12 30;
let myAdd1 = (a b) => add(a b);
let myAdd2 = (a b) => {
  let result = add(a b);
  result;
};

All functions are curried, enabling this kind of programming:

let arr = map(add(12.0) [-27.29 -26.86]);

Hogget: Standard library

Generic

  • log(* ...) -> null - Output a string to the terminal or console. Calls the toStr() function if given anything but a string. Multiple strings are added together, newlines are not automatically inserted.
  • exit(int) -> null: Immediately exits the program, with an exit code.

Logic & Conditionals

  • not(bool) -> bool: Returns the not of it's argument.
  • and(bool bool) -> bool
  • or(bool bool) -> bool
  • xor(bool bool) -> bool
  • if(func func func) -> *: Will call and return either the second or third argument depending on the result of the first.
  • identity(*) -> *: Returns the given argument.
  • eq(* *) -> bool
  • identical(* *) -> bool: Returns true of both arguments are strictly equal.
  • lt() and lte()
  • gt() and gte()

Types

  • type(*) -> string
  • isNull(*) -> bool
  • isBool(*) -> bool
  • isInt(*) -> bool
  • isDec(*) -> bool
  • isStr(*) -> bool
  • isEnum(*) -> bool
  • isOfEnum(enum *) -> bool
  • isList(*) -> bool
  • isObj(*) -> bool
  • isFunc(*) -> bool

Type conversions

  • toBool(*) -> bool
  • toStr(*) -> str
  • toInt(*) -> int
  • toDec(*) -> dec

Numbers

All the arithmetic functions work with either int values or dec values, and will then return the same type. num is used to denote either int or dec.

  • add(num num) -> num
  • subtract(num num) -> num
  • multiply(num num) -> num
  • divide(num num) -> num
  • modulo(num num) -> num: Returns the remainder of the division.
  • pow(num num) -> num
  • product([num]) -> num, implemented as: foldl(multiply, 1)
  • sum([num]) -> num, implemented as: foldl(add, 0))

Strings

  • len(str) -> int: Return length.
  • includes(str) -> bool
  • add(str str) -> str: Add two strings together.
  • capitalise(str) -> str: Uppercase the first character of a string.
  • upper(str) -> str: Uppercase the string.
  • lower(str) -> str: Lowercase the string.
  • slice(int int str) -> str: Slices a string into a subset, given a start index and length (also known as substring).

Lists

  • map(fn list) -> list
  • filter(fn list) -> list
  • foldl(fn * list) -> *: Recursive left-to-right fold (also known as reduce).
  • foldr(fn * list) -> *: Recursive right-to-left fold (also known as reduceRight).
  • chain(fn list) -> list (also known as flatMap).
  • len(list) -> int: Returns the number of items in the list.
  • index(int list) -> *: Returns an item located at given index.
  • find(func list) -> *: Returns an item for which the predicate function returned true.
  • indexOf(* list) -> int: Returns the index for the given item.
  • includes(* list) -> bool: Returns whether the list includes the given item.
  • concat(list list) -> list: Returns the result of concatenating the given lists.
  • flatten(list) -> list: Returns a new list by pulling every item out of it and it's sub-lists.
  • split(str str) -> list
  • join(str list) -> str
  • slice(int int list) -> list: Slices a list into a subset, given a start index and length.
  • fill(int *) -> list
  • sort(func list) -> list
  • cloneShallow(list) -> list
  • cloneDeep(list) -> list

Objects

  • prop(str obj) -> *
  • assoc(str * obj) -> obj
  • cloneShallow(obj) -> obj
  • cloneDeep(obj) -> obj

Functions

  • compose(func func) -> func and compose([func]) -> func: right-to-left function composition.
  • pipe(func func) -> func and pipe([func]) -> func: left-to-right function composition.
  • flip(func) -> func: Returns a new function with it's first two arguments' order reversed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.