Skip to content

Instantly share code, notes, and snippets.

@tokland
Created February 22, 2012 19:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tokland/1886744 to your computer and use it in GitHub Desktop.
Save tokland/1886744 to your computer and use it in GitHub Desktop.
Design notes for Blynx, a functional programming language.

Blynx

Blynx is a functional and statically-typed programming language.

It generates Javascript code, so it can be used both client-side (in a browser) or server-side (with node.js).

State: in development

Features

  • Functional (mostly, impure side effects allowed).
  • Basic built-in types: integer, float, string, tuple, array, record, hash.
  • Statically typed.
  • Polymorphic types.
  • Algebraic data types.
  • Type-classes (traits).
  • Automatic type-inference.
  • Pattern-matching.
  • Eager/strict evaluation.
  • Whitespace-relevant syntax.
  • Syntactic sugar for asynchronous calls.
$ cat >publications.txt <<EOF
book | 9781560273332 | Standard AMT Logbook
book | 9780760331749 | How to Weld
magazine | 1748-7188 | Algorithms for molecular biology
EOF
$ blynx validate-publications.bl publications.txt
Book 'Standard AMT Logbook' (9781560273332) -- valid
Book 'How to Weld' (9780760331749) -- invalid
Magazine 'Algorithms for molecular biology' (1748-7188) -- valid
#!/usr/bin/blynx
# Scenario: we have a text file with lines describing a book or magazine
# with its title and ISBN code. Example:
#
# $ cat >publications.txt <<EOF
# book | 9781560273332 | Standard AMT Logbook
# book | 9780760331749 | How to Weld
# magazine | 1748-7188 | Algorithms for molecular biology
# EOF
#
# The script would validate these publication codes:
#
# $ blynx validate-publications.bl publications.txt
# Book 'Standard AMT Logbook' (9781560273332) -- valid
# Book 'How to Weld' (9780760331749) -- invalid
# Magazine 'Algorithms for molecular biology' (1748-7188) -- valid
export(Publication, valid?)
import fs
import re
import sys
type Publication traits(Eq) =
Book(title: String, isbn: String) |
Magazine(name: String, issn: String)
interface Show of Publication
str(publication: Publication): String =
match publication
Book as book -> "Book <#{book$title}> (#{book$isbn})"
Magazine as magazine -> "Magazine <#{magazine$name}> (#{magazine$issn})"
valid?(publication: Publication): Bool =
match publication
Book(title=title, isbn=isbn) -> title.present? && isbn.validIsbn13?
Magazine(name=name, issn=issn) -> name.present? && issn.validIssn?
validIsbn13?(isbn13: String): Bool =
# An ISBN-13 has 12 digits and a check digit:
#
# x13 = (10 - (x1 + 3*x2 + x3 + 3*x4 + ... + x11 + 3*x12) mod 10) mod 10
match isbn13
/^\d{13}$/ ->
xs = isbn13.map(int)
factors = [1, 3].cycle(6)
terms = [x*factor for (x, factor) in xs[0...12].zip(factors)]
expected_x13 = (10 - (terms.sum % 10)) % 10
xs.get(12) == expected_x13
_ -> False
validIssn?(issn: String): Bool =
# An ISSN number is an eight digit number (divided by a hyphen into
# two four-digit numbers), being the last one the check_digit:
#
# x8 = 11 - ((x1*8 + x2*7 + x3*6 + ... + x7*2) mod 11)
match issn
/^(\d{4})-(\d{4})$/ captures [xs1, xs2] ->
xs = (xs1 ++ xs2).map(int)
terms = [x*idx for (x, idx) in xs[0..6].zip([8..2,-1])]
check_digit = 11 - (terms.sum % 11)
expected_x8 = match check_digit
11 -> "0"
10 -> "X"
other -> other.str
issn.get(7) == expected_x8
_ -> False
getPublicationsFromFile(path: FilePath): impure [Publication] =
parseLine(line: String): Maybe(Publication) =
fields = line.split("|", 3).map(strip)
match fields
["book", isbn13, title] -> Just(Book(title=title, isbn13=isb13))
["magazine", issn, name] -> Just(Magazine(name=name, issn=issn))
other -> Nothing
fs@readFileSync(path).lines.map(parseLine).compact
main() =
match sys@args
[] ->
stderr("validate-publications.bl FILE1 [FILE2 ...]")
sys@exit(1)
paths ->
paths.each(path ->
getPublicationsFromFile(path).each(publication ->
state = if publication.valid? then "valid" else "invalid"
print("#{publication} -- #{state}")
)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment