├── .gitignore ├── bsconfig.json ├── package.json ├── src ├── ffriends.js ├── friends_literal.js ├── friends.re └── friends.js ├── index.js ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /lib/ 2 | /node_modules/ 3 | -------------------------------------------------------------------------------- /bsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bucklescript-benchmark", 3 | "sources": [ 4 | { 5 | "dir": "src" 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bucklescript-benchmark", 3 | "version": "0.0.1", 4 | "description": "A small benchmark comparing Bucklescript to plain JavaScript", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js", 8 | "build": "bsb", 9 | "watch": "bsb -w" 10 | }, 11 | "author": "Jochen H. Schmidt", 12 | "license": "MIT", 13 | "devDependencies": { 14 | "bs-platform": "^1.6.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/ffriends.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const {makePerson} = require('./friends') 4 | 5 | function addFriend (friend, person) { 6 | person.friends.push(friend.name) 7 | return person; 8 | } 9 | 10 | function friends () { 11 | let tom = makePerson("Tom", 23, []); 12 | let mary = makePerson("Mary", 25, []); 13 | let john = makePerson("John", 27, []); 14 | let sara = makePerson("Sara", 21, []); 15 | let smiths = [tom, mary]; 16 | let millers = [john, sara]; 17 | 18 | millers = millers.map(p=>addFriend(tom, p)) 19 | smiths = smiths.map(p=>addFriend(john, p)) 20 | millers = millers.map(p=>addFriend(mary, p)) 21 | smiths = smiths.map(p=>addFriend(sara, p)) 22 | } 23 | 24 | module.exports = { 25 | friends 26 | } 27 | -------------------------------------------------------------------------------- /src/friends_literal.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const {makePerson} = require('./friends') 4 | 5 | let addFriend = (friend, {name, age, friends}) => 6 | ({name, age, friends: [friend.name, ...friends]}) 7 | 8 | function friends () { 9 | let tom = makePerson("Tom", 23, []); 10 | let mary = makePerson("Mary", 25, []); 11 | let john = makePerson("John", 27, []); 12 | let sara = makePerson("Sara", 21, []); 13 | let smiths = [tom, mary]; 14 | let millers = [john, sara]; 15 | millers = millers.map(p=>addFriend(tom, p)) 16 | smiths = smiths.map(p=>addFriend(john, p)) 17 | millers = millers.map(p=>addFriend(mary, p)) 18 | smiths = smiths.map(p=>addFriend(sara, p)) 19 | } 20 | 21 | module.exports = { 22 | friends 23 | } 24 | -------------------------------------------------------------------------------- /src/friends.re: -------------------------------------------------------------------------------- 1 | type person = {name: string, age: int, friends: list string}; 2 | 3 | let makePerson name age friends => {name, age, friends}; 4 | 5 | let addFriend friend person => { 6 | ...person, 7 | friends: [friend.name, ...person.friends] 8 | }; 9 | 10 | let friends () => { 11 | let tom = makePerson "Tom" 23 []; 12 | let mary = makePerson "Mary" 25 []; 13 | let john = makePerson "John" 27 []; 14 | let sara = makePerson "Sara" 21 []; 15 | let smiths = ref [tom, mary]; 16 | let millers = ref [john, sara]; 17 | millers := !millers |> List.map (addFriend tom); 18 | smiths := !smiths |> List.map (addFriend john); 19 | millers := !millers |> List.map (addFriend mary); 20 | smiths := !smiths |> List.map (addFriend sara); 21 | }; 22 | -------------------------------------------------------------------------------- /src/friends.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | let makePerson = (name, age, friends) => ({name,age,friends}) 4 | 5 | let addFriend = (friend, person) => { 6 | return Object.assign({}, person, { 7 | friends: [friend.name, ...person.friends] 8 | }); 9 | } 10 | 11 | function friends () { 12 | let tom = makePerson("Tom", 23, []); 13 | let mary = makePerson("Mary", 25, []); 14 | let john = makePerson("John", 27, []); 15 | let sara = makePerson("Sara", 21, []); 16 | let smiths = [tom, mary]; 17 | let millers = [john, sara]; 18 | millers = millers.map(p=>addFriend(tom, p)) 19 | smiths = smiths.map(p=>addFriend(john, p)) 20 | millers = millers.map(p=>addFriend(mary, p)) 21 | smiths = smiths.map(p=>addFriend(sara, p)) 22 | return millers.concat(smiths); 23 | } 24 | 25 | module.exports = { 26 | makePerson, friends 27 | } 28 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const FriendsRe = require('./lib/js/src/friends.js') 4 | const FriendsJS = require('./src/friends.js') 5 | const FriendsJS_literal = require('./src/friends_literal.js') 6 | const FriendsFJS = require('./src/ffriends.js') 7 | 8 | function bench (name, n, fn) { 9 | console.time(name) 10 | let result 11 | for (let i=0; i 102 | [1, [2, [3, [4, 0]]]] 103 | ``` 104 | 105 | This makes pushing a new element onto a list a constant timed operation (just allocate a new "CONS-Pair" with the new head item and the old list as tail). 106 | 107 | On the other side: If records and lists are structured this way, they 108 | are more difficult to handle in arbitrary JS code or within a 109 | debugging session. You lose the easy runtime introspectability of 110 | plain javascript objects. Blunt said: you do not directly see the 111 | names of the fields anymore. If you want to access such record 112 | instances from JavaScript you need to write accessor functions in 113 | BuckleScript. 114 | 115 | If you want to use idiomatic JS objects in [Bucklescript](https://github.com/bloomberg/bucklescript) (e.g. for 116 | interoperability with JS libs) - you can use the FFI (Foreign Function 117 | Interface) of BuckleScript. This FFI is what makes a big difference to 118 | languages like TypeScript: When writing pure BuckleScript 119 | (OCaml/Reason) code, the compiler is free to take any representation 120 | it likes, as all interoperability is restricted _within_ the Reason/OCaml language 121 | semantics. With the FFI one interfaces the pure written code with the 122 | JavaScript runtime. This is where BuckleScript has to play by the 123 | rules of its host language and accept the dynamic behaviour there. 124 | 125 | -- 126 | Jochen H. Schmidt 127 | 27. Mar. 2017 128 | --------------------------------------------------------------------------------