======= INPUT ======
VEC `map` FN =
(VEC rest `map` FN) conj: (VEC first FN)
FOO goodNumber? =
FOO `<` 5 i: true f: false
BAR =
[X 1, Y 2] let: X `*` Y
N snakeOfAge =
{ :name :sam :age N }
SNAKE birthday =
SNAKE as: :age soc: (SNAKE `get` :age) `+` 1
APP main: ARGS =
[1 2 3 4.89 5] `map` sqrt `map` snakeOfAge `map` birthday
======= OUTPUT ======
((clojure.core/defn
map
[VEC FN]
(conj (map (rest VEC) FN) (FN (first VEC))))
(clojure.core/defn goodNumber? [FOO] (if (< FOO 5) true false))
(def BAR (let [X 1 Y 2] (* X Y)))
(clojure.core/defn snakeOfAge [N] {:age N, :name :sam})
(clojure.core/defn
birthday
[SNAKE]
(assoc SNAKE :age (+ (get SNAKE :age) 1)))
(clojure.core/defn
main
[APP ARGS]
(map (map (map [1 2 3 4.89 5] sqrt) snakeOfAge) birthday)))
Last active
December 19, 2015 10:09
-
-
Save ympbyc/5938797 to your computer and use it in GitHub Desktop.
FP with message-passing syntax
map :: [a] * (a -> b) -> [b]
VEC map: FN =
(FN value: VEC fst) consOnto: (VEC rest map: FN)
:xx
:y
:zazaza
1
2
3
"hello"
"hi"
[1 2 3 4]
['a' 'b' 'c']
{:x 5 :y 'hi' [1] 7}
One thing I like about Lisp, Smalltalk and concatenative languages is that they do not have implicit priorities in application of procedures. Smalltalk's unary, binary and keyword messages varying in priority is a good balance I think.
{:age 5 :name "Sam"} birthday
2 + 3
{:x 1 :y 2} assoc: :x with: 8
VEC map: FN =
(VEC fst FN) consOnto: (VEC rest map: FN)
Type system should not be that decent. Primitive types and aliasing should be enough. Letting users to form a hierarchy of types is undesirable. Type inference is essential.
snake :: {:age number :name string}
birthday :: snake -> snake
SNAKE birthday =
SNAKE assoc: :age with: (SNAKE 's :age + 1)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns smallfp.smallparser | |
(:require [instaparse.core :as insta])) | |
(def parser | |
(insta/parser " | |
<program> = <OSP> def (<NEWLINE>+ def)* <OSP> | |
<expr> = token | wrappedMessage | keywordMessage | binaryMessage | unaryMessage | compounddata | |
<strongExpr> = token | wrappedMessage | binaryMessage | unaryMessage | compounddata | |
<strongestExpr> = token | wrappedMessage | unaryMessage | compounddata | |
<token> = string | keyword | parameter | symbol | number | |
<message> = keywordMessage | binaryMessage | unaryMessage | |
<wrappedMessage> = <OPENPAREN> message <CLOSEPAREN> | |
keywordMessage = (strongExpr (<SP> kselector <SP> strongExpr)+) | |
binaryMessage = strongExpr <SP> bselector <SP> strongestExpr | |
unaryMessage =(expr <SP> (uselector | parameter)) | |
<def> = definition | defconst | |
definition = message <SP> <EQUAL> <SP> expr <OSP> <END> | |
defconst = parameter <SP> <EQUAL> <SP> expr <OSP> <END> | |
<compounddata> = vector | map | |
vector = <'['> <OSP> expr? (<SEP> expr)* <OSP> <']'> | |
map = <'{'> <OSP> (mapkey <SP> mapvalue)? (<SEP> mapkey <SP> mapvalue)* <OSP> <'}'> | |
<mapkey> = expr | |
<mapvalue> = expr | |
kselector = ALPHANUMANIC <COLON> | |
bselector = <'`'> ALPHANUMANIC <'`'> | |
uselector = symbol | |
string = #'\"(.*)*\"' | |
keyword = <COLON> ALPHANUMANIC | |
number = (digit+) | (digit+ DECIMALP digit+) | |
symbol = ALPHA ALPHANUMERIC* | |
parameter = CAPITALPHA ALPHANUMERIC* | |
<digit> = #'[0-9]' | |
<ALPHA> = #'[a-z]' | |
<CAPITALPHA> = #'[A-Z]' | |
<ALPHANUMERIC> = #'[a-zA-Z0-9_?!$-+*<>]' | |
<ALPHANUMANIC> = ALPHANUMERIC+ | |
<COLON> = ':' | |
OPENPAREN = '(' | |
CLOSEPAREN = ')' | |
EQUAL = '=' | |
SP = #'\\s+' | |
OSP = SP? | |
SEP = <OSP> <','> <OSP> | SP | |
NEWLINE = #'\n' | |
END = (NEWLINE NEWLINE | 'end') | |
<DECIMALP> = '.' | |
")) | |
(defn unary-message-transformer | |
[receiver selector] | |
`(~selector ~receiver)) | |
(defn keyword-message-transformer | |
[receiver & mes] | |
(let [pairs (apply array-map mes) | |
fnname (->> (keys pairs) | |
(clojure.string/join "") | |
symbol)] | |
(cons fnname (cons receiver (vals pairs))))) | |
(defn binary-message-transformer | |
[receiver op arg] | |
(list op receiver arg)) | |
(defn map-transformer | |
[& kvs] | |
(apply hash-map kvs)) | |
(defn definition-transfoter | |
[[form & args] expr] | |
`(defn ~form [~@args] ~expr)) | |
(defn defconst-transformer | |
[param expr] | |
`(def ~param ~expr)) | |
(defn smallparser [x] | |
(println "======= INPUT ======") | |
(println x) | |
(println "======= OUTPUT ====== | |
") | |
(insta/transform | |
{:string read-string | |
:symbol `~(comp symbol str) | |
:keyword (comp keyword str) | |
:parameter (comp symbol str) | |
:number (comp read-string str) | |
:kselector (comp symbol str) | |
:bselector (comp symbol str) | |
:uselector (comp symbol str) | |
:unaryMessage unary-message-transformer | |
:keywordMessage keyword-message-transformer | |
:binaryMessage binary-message-transformer | |
:map map-transformer | |
:vector vector | |
:definition definition-transfoter | |
:defconst defconst-transformer} | |
(parser x))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment