npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@explorablegraph/exlang

v0.0.2-d

Published

Expression evaluation built with explorable graphs

Downloads

2

Readme

Explorable functions could form the organizing information model of a programming language.

Consider a language with Lisp syntax based on explorable functions (exfns).

(exfn a b c)

A C-style language (including an evolved JavaScript) would write this as

exfn(a, b, c);

These both mean to ask explorable function exfn for the object with key (a b c). In current JavaScript, this project expresses the C-style call as:

exfn[apply]([a b, c ]);

The rest of this page considers a hypothetical programming language based on exfns.

Note: The syntax here is just noodling, and something of a mess. The underlying concept feels extremely sound, however.

Declaration

The language needs a syntax for defining the following elements for an explorable function:

  • Name (exfn, above): the key that will be used to register the exfn in an explorable namespace (graph) of defined functions. This makes the defined exfn available to other functions.
  • A graph that declares the exfn's keys/members:
    • Public keys, if any, and their implementation.
    • A public key which returns the exfn's public keys.
    • Hidden keys, if any, and their implementation.

Map

Defining an exfn to map lowercase letters to uppercase letters might look like:

lowerToUpper = {
  a: "A",
  b: "B",
  c: "C",
};

This defines an exfn with the name lowerToUpper with the public keys ['a', 'b', 'c'].

The language needs some syntax for unique symbols as a key. Perhaps we introduce #keys to mean such a unique symbol. In this language, we can get the public keys for an object:

lowerToUpper.#keys; // Returns ['a', 'b', 'c']

Who defines #keys? The exfn definition above is implicitly composed with a definition for the base explorable function object/class/definition.

Functions

Defining an exfn to add numbers in a C-style language might look like:

add = {
  (a, b) => a + b,
};

This defines a graph with no public keys. The #keys key returns an exfn [] (always returns undefined, no public keys itself).

Public keys

An exfn can explicitly define keys using the #keys symbol.

The following function converts letters to uppercase:

lowerToUpper = (lower) => lower.toUpperCase();

This implicitly has an empty #keys exfn. The function can also provide examples of the values it will accept:

lowerToUpper = {
  a: "A",
  b: "B",
  c: "C"
} + (lower) => lower.toUpperCase()

This can be useful for math functions too:

fibo = {
  #keys: { { 0, 1 }, { 1, 1 } }
} + (a, b) => // Do the math

This fibonacci function can do the math, as well as provide examples of the tuples it accepts.

Hidden keys

An exfn can define a hidden key X with [X]. These will not be included in the exfn's publicly-inspectable #keys.

lowerToUpper = {
  a: "A",
  b: "B",
  c: "C",
  [secret]: "You have found the secret value!",
};

lowerToUpper.a; // "A"
lowerToUpper.#keys; // { a, b, c}
lowerToUpper.secret; // You have found the secret value

Invocation equals traversal

Invoking a method on an exfn — or, alternatively, traversing the graph it defines — is a matter of traversing the graph expressed by the exfn.

Using the example add definitions above, the invocation add(1, 2) or (add 1 2) means: traverse theadd graph with a tuple(1, 2). The add` definition responds with the sum of the numbers.

Data structures

Many common data structures can be represented as explorable functions: arrays, lists, trees, strings.

The language must provide an intrinsic exfn definition that provides a way to modify a graph at runtime.

Object-oriented programming

Object-oriented concepts can be expressed by composition of declaration graphs: nodes in the declaration graph for exfn A can point to other declaration graphs. If A incorporate's exfn B's graph, A can be said to inherit from B.

A common pattern is to have a key represent a tuple (method ...args).

A String class as an explorable function:

String = {
  append: (s) => { /* Calculate value + s, set that as new value. */ },
  length: () => { /* get length */ },
  value: null,
})

Given this representation, a variable of type string is an exfn that composes the definitions of String.

message =
  {
    value: "Hello",
  } + String;

Here, the + operator returns a new graph that composes subgraphs a and b. The resulting exfn will search in graph a for key first, and if not found will look in graph b. The compose operation also composes the #keys of the subgraphs.

One can then make invocations such as:

message.value; // "Hello"
message.length; // 5
message.definition; // Returns message's definitions, including those of String

Operations

The package of Explorable intrinsics in this project are written in JavaScript, but the algorithms behind them are universal and inherently portable to explorable functions implemented in any language. That is, any language built around explorable functions would also pick up a well-defined set of useful operations.

Intrinsics

Lisp

The concept could also be easily represented with a Lisp-like syntax. The add example earlier:

(define add
  (lambda
    (a b) (+ a b)
  )
)