1641442128
This package provides utility functions for Ethereum dapps and other web3.js packages.
A Bloom filter is a probabilistic, space-efficient data structure used for fast checks of set membership. That probably doesn’t mean much to you yet, and so let’s explore how bloom filters might be used.
Imagine that we have some large set of data, and we want to be able to quickly test if some element is currently in that set. The naive way of checking might be to query the set to see if our element is in there. That’s probably fine if our data set is relatively small. Unfortunately, if our data set is really big, this search might take a while. Luckily, we have tricks to speed things up in the ethereum world!
A bloom filter is one of these tricks. The basic idea behind the Bloom filter is to hash each new element that goes into the data set, take certain bits from this hash, and then use those bits to fill in parts of a fixed-size bit array (e.g. set certain bits to 1). This bit array is called a bloom filter.
Later, when we want to check if an element is in the set, we simply hash the element and check that the right bits are in the bloom filter. If at least one of the bits is 0, then the element definitely isn’t in our data set! If all of the bits are 1, then the element might be in the data set, but we need to actually query the database to be sure. So we might have false positives, but we’ll never have false negatives. This can greatly reduce the number of database queries we have to make.
Real Life Example
An ethereum real life example in where this is useful is if you want to update a users balance on every new block so it stays as close to real time as possible. Without using a bloom filter on every new block you would have to force the balances even if that user may not of had any activity within that block. But if you use the logBlooms from the block you can test the bloom filter against the users ethereum address before you do any more slow operations, this will dramatically decrease the amount of calls you do as you will only be doing those extra operations if that ethereum address is within that block (minus the false positives outcome which will be negligible). This will be highly performant for your app.
Note
Please raise any issues here
web3.utils.randomHex(size)
The randomHex library to generate cryptographically strong pseudo-random HEX strings from a given byte size.
size
- Number
: The byte size for the HEX string, e.g. 32
will result in a 32 bytes HEX string with 64 characters preficed with “0x”.String
: The generated random HEX string.
web3.utils.randomHex(32)
> "0xa5b9d60f32436310afebcfda832817a68921beb782fabf7915cc0460b443116a"
web3.utils.randomHex(4)
> "0x6892ffc6"
web3.utils.randomHex(2)
> "0x99d6"
web3.utils.randomHex(1)
> "0x9a"
web3.utils.randomHex(0)
> "0x"
web3.utils._()
The underscore library for many convenience JavaScript functions.
See the underscore API reference for details.
var _ = web3.utils._;
_.union([1,2],[3]);
> [1,2,3]
_.each({my: 'object'}, function(value, key){ ... })
...
web3.utils.BN(mixed)
The BN.js library for calculating with big numbers in JavaScript. See the BN.js documentation for details.
Note
For safe conversion of many types, incl BigNumber.js use utils.toBN
mixed
- String|Number
: A number, number string or HEX string to convert to a BN object.Object
: The BN.js instance.
var BN = web3.utils.BN;
new BN(1234).toString();
> "1234"
new BN('1234').add(new BN('1')).toString();
> "1235"
new BN('0xea').toString();
> "234"
web3.utils.isBN(bn)
Checks if a given value is a BN.js instance.
bn
- Object
: An BN.js instance.Boolean
var number = new BN(10);
web3.utils.isBN(number);
> true
web3.utils.isBigNumber(bignumber)
Checks if a given value is a BigNumber.js instance.
bignumber
- Object
: A BigNumber.js instance.Boolean
var number = new BigNumber(10);
web3.utils.isBigNumber(number);
> true
web3.utils.sha3(string)
web3.utils.keccak256(string) // ALIAS
Will calculate the sha3 of the input.
Note
To mimic the sha3 behaviour of solidity use soliditySha3
string
- String
: A string to hash.String
: the result hash.
web3.utils.sha3('234'); // taken as string
> "0xc1912fee45d61c87cc5ea59dae311904cd86b84fee17cc96966216f811ce6a79"
web3.utils.sha3(new BN('234'));
> "0xbc36789e7a1e281436464229828f817d6612f7b477d66591ff96a9e064bcc98a"
web3.utils.sha3(234);
> null // can't calculate the hash of a number
web3.utils.sha3(0xea); // same as above, just the HEX representation of the number
> null
web3.utils.sha3('0xea'); // will be converted to a byte array first, and then hashed
> "0x2f20677459120677484f7104c76deb6846a2c071f9b3152c103bb12cd54d1a4a"
web3.utils.sha3Raw(string)
Will calculate the sha3 of the input but does return the hash value instead of null
if for example a empty string is passed.
Note
Further details about this function can be seen here sha3
web3.utils.soliditySha3(param1 [, param2, ...])
Will calculate the sha3 of given input parameters in the same way solidity would. This means arguments will be ABI converted and tightly packed before being hashed.
Warning
This method poses a security risk where multiple inputs can compute to the same hash. Provided in the example code are multiple cases of this security risk
paramX
- Mixed
: Any type, or an object with {type: 'uint', value: '123456'}
or {t: 'bytes', v: '0xfff456'}
. Basic types are autodetected as follows:
String
non numerical UTF-8 string is interpreted asstring
.String|Number|BN|HEX
positive number is interpreted asuint256
.String|Number|BN
negative number is interpreted asint256
.Boolean
asbool
.String
HEX string with leading0x
is interpreted asbytes
.HEX
HEX number representation is interpreted asuint256
.
String
: the result hash.
// As a short example of the non-distinguished nature of
// Solidity tight-packing (which is why it is inappropriate
// for many things from a security point of view), consider
// the following examples are all equal, despite representing
// very different values and layouts.
web3.utils.soliditySha3('hello','world01')
// "0xfb0a9d38c4dc568cbd105866540986fabf3c08c1bfb78299ce21aa0e5c0c586b"
web3.utils.soliditySha3({type: 'string', value: 'helloworld'},{type: 'string', value: '01'})
// "0xfb0a9d38c4dc568cbd105866540986fabf3c08c1bfb78299ce21aa0e5c0c586b"
web3.utils.soliditySha3({type: 'string', value: 'hell'},{type: 'string', value: 'oworld'},{type: 'uint16', value: 0x3031})
// "0xfb0a9d38c4dc568cbd105866540986fabf3c08c1bfb78299ce21aa0e5c0c586b"
web3.utils.soliditySha3({type: 'uint96', value: '32309054545061485574011236401'})
// "0xfb0a9d38c4dc568cbd105866540986fabf3c08c1bfb78299ce21aa0e5c0c586b"
web3.utils.soliditySha3('234564535', '0xfff23243', true, -10);
// auto detects: uint256, bytes, bool, int256
> "0x3e27a893dc40ef8a7f0841d96639de2f58a132be5ae466d40087a2cfa83b7179"
web3.utils.soliditySha3('Hello!%'); // auto detects: string
> "0x661136a4267dba9ccdf6bfddb7c00e714de936674c4bdb065a531cf1cb15c7fc"
web3.utils.soliditySha3('234'); // auto detects: uint256
> "0x61c831beab28d67d1bb40b5ae1a11e2757fa842f031a2d0bc94a7867bc5d26c2"
web3.utils.soliditySha3(0xea); // same as above
> "0x61c831beab28d67d1bb40b5ae1a11e2757fa842f031a2d0bc94a7867bc5d26c2"
web3.utils.soliditySha3(new BN('234')); // same as above
> "0x61c831beab28d67d1bb40b5ae1a11e2757fa842f031a2d0bc94a7867bc5d26c2"
web3.utils.soliditySha3({type: 'uint256', value: '234'})); // same as above
> "0x61c831beab28d67d1bb40b5ae1a11e2757fa842f031a2d0bc94a7867bc5d26c2"
web3.utils.soliditySha3({t: 'uint', v: new BN('234')})); // same as above
> "0x61c831beab28d67d1bb40b5ae1a11e2757fa842f031a2d0bc94a7867bc5d26c2"
web3.utils.soliditySha3('0x407D73d8a49eeb85D32Cf465507dd71d507100c1');
> "0x4e8ebbefa452077428f93c9520d3edd60594ff452a29ac7d2ccc11d47f3ab95b"
web3.utils.soliditySha3({t: 'bytes', v: '0x407D73d8a49eeb85D32Cf465507dd71d507100c1'});
> "0x4e8ebbefa452077428f93c9520d3edd60594ff452a29ac7d2ccc11d47f3ab95b" // same result as above
web3.utils.soliditySha3({t: 'address', v: '0x407D73d8a49eeb85D32Cf465507dd71d507100c1'});
> "0x4e8ebbefa452077428f93c9520d3edd60594ff452a29ac7d2ccc11d47f3ab95b" // same as above, but will do a checksum check, if its multi case
web3.utils.soliditySha3({t: 'bytes32', v: '0x407D73d8a49eeb85D32Cf465507dd71d507100c1'});
> "0x3c69a194aaf415ba5d6afca734660d0a3d45acdc05d54cd1ca89a8988e7625b4" // different result as above
web3.utils.soliditySha3({t: 'string', v: 'Hello!%'}, {t: 'int8', v:-23}, {t: 'address', v: '0x85F43D8a49eeB85d32Cf465507DD71d507100C1d'});
> "0xa13b31627c1ed7aaded5aecec71baf02fe123797fffd45e662eac8e06fbe4955"
web3.utils.soliditySha3Raw(param1 [, param2, ...])
Will calculate the sha3 of given input parameters in the same way solidity would. This means arguments will be ABI converted and tightly packed before being hashed. The difference between this function and the soliditySha3
function is that it will return the hash value instead of null
if for example a empty string is given.
Note
Further details about this function can be seen here soliditySha3
web3.utils.isHex(hex)
Checks if a given string is a HEX string.
hex
- String|HEX
: The given HEX string.Boolean
web3.utils.isHex('0xc1912');
> true
web3.utils.isHex(0xc1912);
> true
web3.utils.isHex('c1912');
> true
web3.utils.isHex(345);
> true // this is tricky, as 345 can be a a HEX representation or a number, be careful when not having a 0x in front!
web3.utils.isHex('0xZ1912');
> false
web3.utils.isHex('Hello');
> false
web3.utils.isHexStrict(hex)
Checks if a given string is a HEX string. Difference to web3.utils.isHex()
is that it expects HEX to be prefixed with 0x
.
hex
- String|HEX
: The given HEX string.Boolean
web3.utils.isHexStrict('0xc1912');
> true
web3.utils.isHexStrict(0xc1912);
> false
web3.utils.isHexStrict('c1912');
> false
web3.utils.isHexStrict(345);
> false // this is tricky, as 345 can be a a HEX representation or a number, be careful when not having a 0x in front!
web3.utils.isHexStrict('0xZ1912');
> false
web3.utils.isHex('Hello');
> false
web3.utils.isAddress(address)
Checks if a given string is a valid Ethereum address. It will also check the checksum, if the address has upper and lowercase letters.
address
- String
: An address string.Boolean
web3.utils.isAddress('0xc1912fee45d61c87cc5ea59dae31190fffff232d');
> true
web3.utils.isAddress('c1912fee45d61c87cc5ea59dae31190fffff232d');
> true
web3.utils.isAddress('0XC1912FEE45D61C87CC5EA59DAE31190FFFFF232D');
> true // as all is uppercase, no checksum will be checked
web3.utils.isAddress('0xc1912fEE45d61C87Cc5EA59DaE31190FFFFf232d');
> true
web3.utils.isAddress('0xC1912fEE45d61C87Cc5EA59DaE31190FFFFf232d');
> false // wrong checksum
web3.utils.toChecksumAddress(address)
Will convert an upper or lowercase Ethereum address to a checksum address.
address
- String
: An address string.String
: The checksum address.
web3.utils.toChecksumAddress('0xc1912fee45d61c87cc5ea59dae31190fffff232d');
> "0xc1912fEE45d61C87Cc5EA59DaE31190FFFFf232d"
web3.utils.toChecksumAddress('0XC1912FEE45D61C87CC5EA59DAE31190FFFFF232D');
> "0xc1912fEE45d61C87Cc5EA59DaE31190FFFFf232d" // same as above
web3.utils.checkAddressChecksum(address)
Checks the checksum of a given address. Will also return false on non-checksum addresses.
address
- String
: An address string.Boolean
: true
when the checksum of the address is valid, false
if its not a checksum address, or the checksum is invalid.
web3.utils.checkAddressChecksum('0xc1912fEE45d61C87Cc5EA59DaE31190FFFFf232d');
> true
web3.utils.toHex(mixed)
Will auto convert any given value to HEX. Number strings will interpreted as numbers. Text strings will be interpreted as UTF-8 strings.
mixed
- String|Number|BN|BigNumber
: The input to convert to HEX.String
: The resulting HEX string.
web3.utils.toHex('234');
> "0xea"
web3.utils.toHex(234);
> "0xea"
web3.utils.toHex(new BN('234'));
> "0xea"
web3.utils.toHex(new BigNumber('234'));
> "0xea"
web3.utils.toHex('I have 100€');
> "0x49206861766520313030e282ac"
Returns provided string without 0x prefix.
str
- string
: Input stringString
: The input string without 0x prefix.
web3.utils.stripHexPrefix('234');
> "234"
web3.utils.stripHexPrefix('0x234');
> "234"
web3.utils.stripHexPrefix(42);
> 42
web3.utils.toBN(number)
Will safely convert any given value (including BigNumber.js instances) into a BN.js instance, for handling big numbers in JavaScript.
Note
For just the BN.js class use utils.BN
number
- String|Number|HEX
: Number to convert to a big number.Object
: The BN.js instance.
web3.utils.toBN(1234).toString();
> "1234"
web3.utils.toBN('1234').add(web3.utils.toBN('1')).toString();
> "1235"
web3.utils.toBN('0xea').toString();
> "234"
web3.utils.hexToNumberString(hex)
Returns the number representation of a given HEX value as a string.
hexString
- String|HEX
: A string to hash.String
: The number as a string.
web3.utils.hexToNumberString('0xea');
> "234"
web3.utils.hexToNumber(hex)
web3.utils.toDecimal(hex) // ALIAS, deprecated
Returns the number representation of a given HEX value.
Note
This is not useful for big numbers, rather use utils.toBN instead.
hexString
- String|HEX
: A string to hash.Number
web3.utils.hexToNumber('0xea');
> 234
web3.utils.numberToHex(number)
web3.utils.fromDecimal(number) // ALIAS, deprecated
Returns the HEX representation of a given number value.
number
- String|Number|BN|BigNumber
: A number as string or number.String
: The HEX value of the given number.
web3.utils.numberToHex('234');
> '0xea'
web3.utils.hexToUtf8(hex)
web3.utils.hexToString(hex) // ALIAS
web3.utils.toUtf8(hex) // ALIAS, deprecated
Returns the UTF-8 string representation of a given HEX value.
hex
- String
: A HEX string to convert to a UTF-8 string.String
: The UTF-8 string.
web3.utils.hexToUtf8('0x49206861766520313030e282ac');
> "I have 100€"
web3.utils.hexToAscii(hex)
web3.utils.toAscii(hex) // ALIAS, deprecated
Returns the ASCII string representation of a given HEX value.
hex
- String
: A HEX string to convert to a ASCII string.String
: The ASCII string.
web3.utils.hexToAscii('0x4920686176652031303021');
> "I have 100!"
web3.utils.utf8ToHex(string)
web3.utils.stringToHex(string) // ALIAS
web3.utils.fromUtf8(string) // ALIAS, deprecated
Returns the HEX representation of a given UTF-8 string.
string
- String
: A UTF-8 string to convert to a HEX string.String
: The HEX string.
web3.utils.utf8ToHex('I have 100€');
> "0x49206861766520313030e282ac"
web3.utils.asciiToHex(string)
web3.utils.fromAscii(string) // ALIAS, deprecated
Returns the HEX representation of a given ASCII string.
string
- String
: A ASCII string to convert to a HEX string.String
: The HEX string.
web3.utils.asciiToHex('I have 100!');
> "0x4920686176652031303021"
web3.utils.hexToBytes(hex)
Returns a byte array from the given HEX string.
hex
- String|HEX
: A HEX to convert.Array
: The byte array.
web3.utils.hexToBytes('0x000000ea');
> [ 0, 0, 0, 234 ]
web3.utils.hexToBytes(0x000000ea);
> [ 234 ]
web3.utils.bytesToHex(byteArray)
Returns a HEX string from a byte array.
byteArray
- Array
: A byte array to convert.String
: The HEX string.
web3.utils.bytesToHex([ 72, 101, 108, 108, 111, 33, 36 ]);
> "0x48656c6c6f2125"
web3.utils.toWei(number [, unit])
Converts any ether value value into wei.
Note
“wei” are the smallest ether unit, and you should always make calculations in wei and convert only for display reasons.
number
- String|BN
: The value.unit
- String
(optional, defaults to "ether"
): The ether to convert from. Possible units are:
noether
: ‘0’wei
: ‘1’kwei
: ‘1000’Kwei
: ‘1000’babbage
: ‘1000’femtoether
: ‘1000’mwei
: ‘1000000’Mwei
: ‘1000000’lovelace
: ‘1000000’picoether
: ‘1000000’gwei
: ‘1000000000’Gwei
: ‘1000000000’shannon
: ‘1000000000’nanoether
: ‘1000000000’nano
: ‘1000000000’szabo
: ‘1000000000000’microether
: ‘1000000000000’micro
: ‘1000000000000’finney
: ‘1000000000000000’milliether
: ‘1000000000000000’milli
: ‘1000000000000000’ether
: ‘1000000000000000000’kether
: ‘1000000000000000000000’grand
: ‘1000000000000000000000’mether
: ‘1000000000000000000000000’gether
: ‘1000000000000000000000000000’tether
: ‘1000000000000000000000000000000’String|BN
: If a string is given it returns a number string, otherwise a BN.js instance.
web3.utils.toWei('1', 'ether');
> "1000000000000000000"
web3.utils.toWei('1', 'finney');
> "1000000000000000"
web3.utils.toWei('1', 'szabo');
> "1000000000000"
web3.utils.toWei('1', 'shannon');
> "1000000000"
web3.utils.fromWei(number [, unit])
Converts any wei value into a ether value.
Note
“wei” are the smallest ether unit, and you should always make calculations in wei and convert only for display reasons.
number
- String|BN
: The value in wei.unit
- String
(optional, defaults to "ether"
): The ether to convert to. Possible units are:
noether
: ‘0’wei
: ‘1’kwei
: ‘1000’Kwei
: ‘1000’babbage
: ‘1000’femtoether
: ‘1000’mwei
: ‘1000000’Mwei
: ‘1000000’lovelace
: ‘1000000’picoether
: ‘1000000’gwei
: ‘1000000000’Gwei
: ‘1000000000’shannon
: ‘1000000000’nanoether
: ‘1000000000’nano
: ‘1000000000’szabo
: ‘1000000000000’microether
: ‘1000000000000’micro
: ‘1000000000000’finney
: ‘1000000000000000’milliether
: ‘1000000000000000’milli
: ‘1000000000000000’ether
: ‘1000000000000000000’kether
: ‘1000000000000000000000’grand
: ‘1000000000000000000000’mether
: ‘1000000000000000000000000’gether
: ‘1000000000000000000000000000’tether
: ‘1000000000000000000000000000000’String
: It always returns a string number.
web3.utils.fromWei('1', 'ether');
> "0.000000000000000001"
web3.utils.fromWei('1', 'finney');
> "0.000000000000001"
web3.utils.fromWei('1', 'szabo');
> "0.000000000001"
web3.utils.fromWei('1', 'shannon');
> "0.000000001"
web3.utils.unitMap
Shows all possible ether value and their amount in wei.
Object
with the following properties:
noether
: ‘0’wei
: ‘1’kwei
: ‘1000’Kwei
: ‘1000’babbage
: ‘1000’femtoether
: ‘1000’mwei
: ‘1000000’Mwei
: ‘1000000’lovelace
: ‘1000000’picoether
: ‘1000000’gwei
: ‘1000000000’Gwei
: ‘1000000000’shannon
: ‘1000000000’nanoether
: ‘1000000000’nano
: ‘1000000000’szabo
: ‘1000000000000’microether
: ‘1000000000000’micro
: ‘1000000000000’finney
: ‘1000000000000000’milliether
: ‘1000000000000000’milli
: ‘1000000000000000’ether
: ‘1000000000000000000’kether
: ‘1000000000000000000000’grand
: ‘1000000000000000000000’mether
: ‘1000000000000000000000000’gether
: ‘1000000000000000000000000000’tether
: ‘1000000000000000000000000000000’web3.utils.unitMap
> {
noether: '0',
wei: '1',
kwei: '1000',
Kwei: '1000',
babbage: '1000',
femtoether: '1000',
mwei: '1000000',
Mwei: '1000000',
lovelace: '1000000',
picoether: '1000000',
gwei: '1000000000',
Gwei: '1000000000',
shannon: '1000000000',
nanoether: '1000000000',
nano: '1000000000',
szabo: '1000000000000',
microether: '1000000000000',
micro: '1000000000000',
finney: '1000000000000000',
milliether: '1000000000000000',
milli: '1000000000000000',
ether: '1000000000000000000',
kether: '1000000000000000000000',
grand: '1000000000000000000000',
mether: '1000000000000000000000000',
gether: '1000000000000000000000000000',
tether: '1000000000000000000000000000000'
}
web3.utils.padLeft(string, characterAmount [, sign])
web3.utils.leftPad(string, characterAmount [, sign]) // ALIAS
Adds a padding on the left of a string, Useful for adding paddings to HEX strings.
string
- String
: The string to add padding on the left.characterAmount
- Number
: The number of characters the total string should have.sign
- String
(optional): The character sign to use, defaults to "0"
.String
: The padded string.
web3.utils.padLeft('0x3456ff', 20);
> "0x000000000000003456ff"
web3.utils.padLeft(0x3456ff, 20);
> "0x000000000000003456ff"
web3.utils.padLeft('Hello', 20, 'x');
> "xxxxxxxxxxxxxxxHello"
web3.utils.padRight(string, characterAmount [, sign])
web3.utils.rightPad(string, characterAmount [, sign]) // ALIAS
Adds a padding on the right of a string, Useful for adding paddings to HEX strings.
string
- String
: The string to add padding on the right.characterAmount
- Number
: The number of characters the total string should have.sign
- String
(optional): The character sign to use, defaults to "0"
.String
: The padded string.
web3.utils.padRight('0x3456ff', 20);
> "0x3456ff00000000000000"
web3.utils.padRight(0x3456ff, 20);
> "0x3456ff00000000000000"
web3.utils.padRight('Hello', 20, 'x');
> "Helloxxxxxxxxxxxxxxx"
web3.utils.toTwosComplement(number)
Converts a negative numer into a two’s complement.
number
- Number|String|BigNumber
: The number to convert.String
: The converted hex string.
web3.utils.toTwosComplement('-1');
> "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
web3.utils.toTwosComplement(-1);
> "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
web3.utils.toTwosComplement('0x1');
> "0x0000000000000000000000000000000000000000000000000000000000000001"
web3.utils.toTwosComplement(-15);
> "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1"
web3.utils.toTwosComplement('-0x1');
> "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
Original article source at https://web3js.readthedocs.io
#web3 #blockchain #javascript #ethereum
1632537859
Not babashka. Node.js babashka!?
Ad-hoc CLJS scripting on Node.js.
Experimental. Please report issues here.
Nbb's main goal is to make it easy to get started with ad hoc CLJS scripting on Node.js.
Additional goals and features are:
Nbb requires Node.js v12 or newer.
CLJS code is evaluated through SCI, the same interpreter that powers babashka. Because SCI works with advanced compilation, the bundle size, especially when combined with other dependencies, is smaller than what you get with self-hosted CLJS. That makes startup faster. The trade-off is that execution is less performant and that only a subset of CLJS is available (e.g. no deftype, yet).
Install nbb
from NPM:
$ npm install nbb -g
Omit -g
for a local install.
Try out an expression:
$ nbb -e '(+ 1 2 3)'
6
And then install some other NPM libraries to use in the script. E.g.:
$ npm install csv-parse shelljs zx
Create a script which uses the NPM libraries:
(ns script
(:require ["csv-parse/lib/sync$default" :as csv-parse]
["fs" :as fs]
["path" :as path]
["shelljs$default" :as sh]
["term-size$default" :as term-size]
["zx$default" :as zx]
["zx$fs" :as zxfs]
[nbb.core :refer [*file*]]))
(prn (path/resolve "."))
(prn (term-size))
(println (count (str (fs/readFileSync *file*))))
(prn (sh/ls "."))
(prn (csv-parse "foo,bar"))
(prn (zxfs/existsSync *file*))
(zx/$ #js ["ls"])
Call the script:
$ nbb script.cljs
"/private/tmp/test-script"
#js {:columns 216, :rows 47}
510
#js ["node_modules" "package-lock.json" "package.json" "script.cljs"]
#js [#js ["foo" "bar"]]
true
$ ls
node_modules
package-lock.json
package.json
script.cljs
Nbb has first class support for macros: you can define them right inside your .cljs
file, like you are used to from JVM Clojure. Consider the plet
macro to make working with promises more palatable:
(defmacro plet
[bindings & body]
(let [binding-pairs (reverse (partition 2 bindings))
body (cons 'do body)]
(reduce (fn [body [sym expr]]
(let [expr (list '.resolve 'js/Promise expr)]
(list '.then expr (list 'clojure.core/fn (vector sym)
body))))
body
binding-pairs)))
Using this macro we can look async code more like sync code. Consider this puppeteer example:
(-> (.launch puppeteer)
(.then (fn [browser]
(-> (.newPage browser)
(.then (fn [page]
(-> (.goto page "https://clojure.org")
(.then #(.screenshot page #js{:path "screenshot.png"}))
(.catch #(js/console.log %))
(.then #(.close browser)))))))))
Using plet
this becomes:
(plet [browser (.launch puppeteer)
page (.newPage browser)
_ (.goto page "https://clojure.org")
_ (-> (.screenshot page #js{:path "screenshot.png"})
(.catch #(js/console.log %)))]
(.close browser))
See the puppeteer example for the full code.
Since v0.0.36, nbb includes promesa which is a library to deal with promises. The above plet
macro is similar to promesa.core/let
.
$ time nbb -e '(+ 1 2 3)'
6
nbb -e '(+ 1 2 3)' 0.17s user 0.02s system 109% cpu 0.168 total
The baseline startup time for a script is about 170ms seconds on my laptop. When invoked via npx
this adds another 300ms or so, so for faster startup, either use a globally installed nbb
or use $(npm bin)/nbb script.cljs
to bypass npx
.
Nbb does not depend on any NPM dependencies. All NPM libraries loaded by a script are resolved relative to that script. When using the Reagent module, React is resolved in the same way as any other NPM library.
To load .cljs
files from local paths or dependencies, you can use the --classpath
argument. The current dir is added to the classpath automatically. So if there is a file foo/bar.cljs
relative to your current dir, then you can load it via (:require [foo.bar :as fb])
. Note that nbb
uses the same naming conventions for namespaces and directories as other Clojure tools: foo-bar
in the namespace name becomes foo_bar
in the directory name.
To load dependencies from the Clojure ecosystem, you can use the Clojure CLI or babashka to download them and produce a classpath:
$ classpath="$(clojure -A:nbb -Spath -Sdeps '{:aliases {:nbb {:replace-deps {com.github.seancorfield/honeysql {:git/tag "v2.0.0-rc5" :git/sha "01c3a55"}}}}}')"
and then feed it to the --classpath
argument:
$ nbb --classpath "$classpath" -e "(require '[honey.sql :as sql]) (sql/format {:select :foo :from :bar :where [:= :baz 2]})"
["SELECT foo FROM bar WHERE baz = ?" 2]
Currently nbb
only reads from directories, not jar files, so you are encouraged to use git libs. Support for .jar
files will be added later.
The name of the file that is currently being executed is available via nbb.core/*file*
or on the metadata of vars:
(ns foo
(:require [nbb.core :refer [*file*]]))
(prn *file*) ;; "/private/tmp/foo.cljs"
(defn f [])
(prn (:file (meta #'f))) ;; "/private/tmp/foo.cljs"
Nbb includes reagent.core
which will be lazily loaded when required. You can use this together with ink to create a TUI application:
$ npm install ink
ink-demo.cljs
:
(ns ink-demo
(:require ["ink" :refer [render Text]]
[reagent.core :as r]))
(defonce state (r/atom 0))
(doseq [n (range 1 11)]
(js/setTimeout #(swap! state inc) (* n 500)))
(defn hello []
[:> Text {:color "green"} "Hello, world! " @state])
(render (r/as-element [hello]))
Working with callbacks and promises can become tedious. Since nbb v0.0.36 the promesa.core
namespace is included with the let
and do!
macros. An example:
(ns prom
(:require [promesa.core :as p]))
(defn sleep [ms]
(js/Promise.
(fn [resolve _]
(js/setTimeout resolve ms))))
(defn do-stuff
[]
(p/do!
(println "Doing stuff which takes a while")
(sleep 1000)
1))
(p/let [a (do-stuff)
b (inc a)
c (do-stuff)
d (+ b c)]
(prn d))
$ nbb prom.cljs
Doing stuff which takes a while
Doing stuff which takes a while
3
Also see API docs.
Since nbb v0.0.75 applied-science/js-interop is available:
(ns example
(:require [applied-science.js-interop :as j]))
(def o (j/lit {:a 1 :b 2 :c {:d 1}}))
(prn (j/select-keys o [:a :b])) ;; #js {:a 1, :b 2}
(prn (j/get-in o [:c :d])) ;; 1
Most of this library is supported in nbb, except the following:
:syms
.-x
notation. In nbb, you must use keywords.See the example of what is currently supported.
See the examples directory for small examples.
Also check out these projects built with nbb:
See API documentation.
See this gist on how to convert an nbb script or project to shadow-cljs.
Prequisites:
To build:
bb release
Run bb tasks
for more project-related tasks.
Download Details:
Author: borkdude
Download Link: Download The Source Code
Official Website: https://github.com/borkdude/nbb
License: EPL-1.0
#node #javascript
1599097440
A famous general is thought to have said, “A good sketch is better than a long speech.” That advice may have come from the battlefield, but it’s applicable in lots of other areas — including data science. “Sketching” out our data by visualizing it using ggplot2 in R is more impactful than simply describing the trends we find.
This is why we visualize data. We visualize data because it’s easier to learn from something that we can see rather than read. And thankfully for data analysts and data scientists who use R, there’s a tidyverse package called ggplot2 that makes data visualization a snap!
In this blog post, we’ll learn how to take some data and produce a visualization using R. To work through it, it’s best if you already have an understanding of R programming syntax, but you don’t need to be an expert or have any prior experience working with ggplot2
#data science tutorials #beginner #ggplot2 #r #r tutorial #r tutorials #rstats #tutorial #tutorials
1596728880
In this tutorial we’ll learn how to begin programming with R using RStudio. We’ll install R, and RStudio RStudio, an extremely popular development environment for R. We’ll learn the key RStudio features in order to start programming in R on our own.
If you already know how to use RStudio and want to learn some tips, tricks, and shortcuts, check out this Dataquest blog post.
[tidyverse](https://www.dataquest.io/blog/tutorial-getting-started-with-r-and-rstudio/#tve-jump-173bb26184b)
Packages[tidyverse](https://www.dataquest.io/blog/tutorial-getting-started-with-r-and-rstudio/#tve-jump-173bb264c2b)
Packages into Memory#data science tutorials #beginner #r tutorial #r tutorials #rstats #tutorial #tutorials
1596513720
What exactly is clean data? Clean data is accurate, complete, and in a format that is ready to analyze. Characteristics of clean data include data that are:
Common symptoms of messy data include data that contain:
In this blog post, we will work with five property-sales datasets that are publicly available on the New York City Department of Finance Rolling Sales Data website. We encourage you to download the datasets and follow along! Each file contains one year of real estate sales data for one of New York City’s five boroughs. We will work with the following Microsoft Excel files:
As we work through this blog post, imagine that you are helping a friend launch their home-inspection business in New York City. You offer to help them by analyzing the data to better understand the real-estate market. But you realize that before you can analyze the data in R, you will need to diagnose and clean it first. And before you can diagnose the data, you will need to load it into R!
Benefits of using tidyverse tools are often evident in the data-loading process. In many cases, the tidyverse package readxl
will clean some data for you as Microsoft Excel data is loaded into R. If you are working with CSV data, the tidyverse readr
package function read_csv()
is the function to use (we’ll cover that later).
Let’s look at an example. Here’s how the Excel file for the Brooklyn borough looks:
The Brooklyn Excel file
Now let’s load the Brooklyn dataset into R from an Excel file. We’ll use the readxl
package. We specify the function argument skip = 4
because the row that we want to use as the header (i.e. column names) is actually row 5. We can ignore the first four rows entirely and load the data into R beginning at row 5. Here’s the code:
library(readxl) # Load Excel files
brooklyn <- read_excel("rollingsales_brooklyn.xls", skip = 4)
Note we saved this dataset with the variable name brooklyn
for future use.
The tidyverse offers a user-friendly way to view this data with the glimpse()
function that is part of the tibble
package. To use this package, we will need to load it for use in our current session. But rather than loading this package alone, we can load many of the tidyverse packages at one time. If you do not have the tidyverse collection of packages, install it on your machine using the following command in your R or R Studio session:
install.packages("tidyverse")
Once the package is installed, load it to memory:
library(tidyverse)
Now that tidyverse
is loaded into memory, take a “glimpse” of the Brooklyn dataset:
glimpse(brooklyn)
## Observations: 20,185
## Variables: 21
## $ BOROUGH <chr> "3", "3", "3", "3", "3", "3", "…
## $ NEIGHBORHOOD <chr> "BATH BEACH", "BATH BEACH", "BA…
## $ `BUILDING CLASS CATEGORY` <chr> "01 ONE FAMILY DWELLINGS", "01 …
## $ `TAX CLASS AT PRESENT` <chr> "1", "1", "1", "1", "1", "1", "…
## $ BLOCK <dbl> 6359, 6360, 6364, 6367, 6371, 6…
## $ LOT <dbl> 70, 48, 74, 24, 19, 32, 65, 20,…
## $ `EASE-MENT` <lgl> NA, NA, NA, NA, NA, NA, NA, NA,…
## $ `BUILDING CLASS AT PRESENT` <chr> "S1", "A5", "A5", "A9", "A9", "…
## $ ADDRESS <chr> "8684 15TH AVENUE", "14 BAY 10T…
## $ `APARTMENT NUMBER` <chr> NA, NA, NA, NA, NA, NA, NA, NA,…
## $ `ZIP CODE` <dbl> 11228, 11228, 11214, 11214, 112…
## $ `RESIDENTIAL UNITS` <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1…
## $ `COMMERCIAL UNITS` <dbl> 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ `TOTAL UNITS` <dbl> 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1…
## $ `LAND SQUARE FEET` <dbl> 1933, 2513, 2492, 1571, 2320, 3…
## $ `GROSS SQUARE FEET` <dbl> 4080, 1428, 972, 1456, 1566, 22…
## $ `YEAR BUILT` <dbl> 1930, 1930, 1950, 1935, 1930, 1…
## $ `TAX CLASS AT TIME OF SALE` <chr> "1", "1", "1", "1", "1", "1", "…
## $ `BUILDING CLASS AT TIME OF SALE` <chr> "S1", "A5", "A5", "A9", "A9", "…
## $ `SALE PRICE` <dbl> 1300000, 849000, 0, 830000, 0, …
## $ `SALE DATE` <dttm> 2020-04-28, 2020-03-18, 2019-0…
The glimpse()
function provides a user-friendly way to view the column names and data types for all columns, or variables, in the data frame. With this function, we are also able to view the first few observations in the data frame. This data frame has 20,185 observations, or property sales records. And there are 21 variables, or columns.
#data science tutorials #beginner #r #r tutorial #r tutorials #rstats #tidyverse #tutorial #tutorials
1615346451
#laravel 8 vue js #laravel vue js #laravel vue js tutorial #laravel 8 vue js tutorial