<commit_before>#+TITLE:     μLithp
#+AUTHOR:    Fogus
#+EMAIL:     <EMAIL>
#+LANGUAGE:  en
#+OPTIONS:   H:3 num:nil toc:nil \n:nil @:t ::t |:t ^:t -:t f:t *:t <:t
#+OPTIONS:   TeX:t LaTeX:t skip:nil d:nil todo:t pri:nil tags:not-in-toc
#+INFOJS_OPT: view:nil toc:nil ltoc:t mouse:underline buttons:0 path:http://orgmode.org/org-info.js
#+EXPORT_SELECT_TAGS: export
#+EXPORT_EXCLUDE_TAGS: noexport

#+INCLUDE: header/header.org org

* In the beginning was a fancy

This is a line-by-line deconstruction of how μLithp works, including commentary on extending the base language.

** The primordial functions and forms

#+name: ur
#+begin_src ruby :tangle ../src/lithp.rb :noweb yes 
class Lisp
#+end_src

Ruby is one of [[http://c2.com/cgi/wiki?ArgumentsAgainstOop][those]] kinds of languages, so everything starts with a class declaration. Kidding aside, I thought it would be cool to encapsulate Lispiness in a class a provide extension via inheritance, but never got around to trying it. 

#+name: ur
#+begin_src ruby :tangle ../src/lithp.rb :noweb yes 
  def initialize(ext={})
#+end_src

The constructor seems like as good a place as any to declare the basic functionality.  Every minimal Lisp requires a basic set of features, including, but not limited to the following functions and special forms:

 - ~label~ : a way to bind a value to a name
 - ~quote~ : avoids evaluation of an expression
 - ~car~   : retrieves the first element in a list
 - ~cdr~   : retrieves all but the first element in a list
 - ~cons~  : constructs a new list from some element appended to the front of some list
 - ~eq~    : checks the equality of two values
 - ~if~    : checks the truthiness of an expression and evaluates one of two branches depending on the result
 - ~atom~  : checks if a value is a base value (i.e. not a composition type like a list)
 - ~λ~     : creates a function

I'll give more detail about each below.

#+name: ur
#+begin_src ruby :tangle ../src/lithp.rb :noweb yes 
    @env = { :label => proc { |(name,val), _| @env[name] = eval(val, @env) },
#+end_src

Every Lisp evaluation takes place in the context of some environment.  In μLithp the environment is a simple Hash instance and represents a global evaluation context.  The ~:label~ symbol is bound to a ~lambda~ that takes two things, an Array with a symbol representing a name and a value and also a context (that is ignored).  The name is then inserted into the global environment with the given value.  As you can see, all bindings are created explicitly in ~@env~.  You'll notice that I created the ~:if~ logic with the ~proc~ form.  Doing so signals to the evaluator that the thing defined should receive its arguments unevaluated.

You'll notice that all of the callable's take an array as the first argument and a context as the second.  This is key for future expansion.  Additionally, I like to use Ruby's destructuring format to unwrap the actual arguments hidden in the passed array.

#+name: ur<commit_msg>Fix minor typo<commit_after>#+TITLE:     μLithp
#+AUTHOR:    Fogus
#+EMAIL:     <EMAIL>
#+LANGUAGE:  en
#+OPTIONS:   H:3 num:nil toc:nil \n:nil @:t ::t |:t ^:t -:t f:t *:t <:t
#+OPTIONS:   TeX:t LaTeX:t skip:nil d:nil todo:t pri:nil tags:not-in-toc
#+INFOJS_OPT: view:nil toc:nil ltoc:t mouse:underline buttons:0 path:http://orgmode.org/org-info.js
#+EXPORT_SELECT_TAGS: export
#+EXPORT_EXCLUDE_TAGS: noexport

#+INCLUDE: header/header.org org

* In the beginning was a fancy

This is a line-by-line deconstruction of how μLithp works, including commentary on extending the base language.

** The primordial functions and forms

#+name: ur
#+begin_src ruby :tangle ../src/lithp.rb :noweb yes 
class Lisp
#+end_src

Ruby is one of [[http://c2.com/cgi/wiki?ArgumentsAgainstOop][those]] kinds of languages, so everything starts with a class declaration. Kidding aside, I thought it would be cool to encapsulate Lispiness in a class a provide extension via inheritance, but never got around to trying it. 

#+name: ur
#+begin_src ruby :tangle ../src/lithp.rb :noweb yes 
  def initialize(ext={})
#+end_src

The constructor seems like as good a place as any to declare the basic functionality.  Every minimal Lisp requires a basic set of features, including, but not limited to the following functions and special forms:

 - ~label~ : a way to bind a value to a name
 - ~quote~ : avoids evaluation of an expression
 - ~car~   : retrieves the first element in a list
 - ~cdr~   : retrieves all but the first element in a list
 - ~cons~  : constructs a new list from some element appended to the front of some list
 - ~eq~    : checks the equality of two values
 - ~if~    : checks the truthiness of an expression and evaluates one of two branches depending on the result
 - ~atom~  : checks if a value is a base value (i.e. not a composition type like a list)
 - ~λ~     : creates a function

I'll give more detail about each below.

#+name: ur
#+begin_src ruby :tangle ../src/lithp.rb :noweb yes 
    @env = { :label => proc { |(name,val), _| @env[name] = eval(val, @env) },
#+end_src

Every Lisp evaluation takes place in the context of some environment.  In μLithp the environment is a simple Hash instance and represents a global evaluation context.  The ~:label~ symbol is bound to a ~lambda~ that takes two things, an Array with a symbol representing a name and a value and also a context (that is ignored).  The name is then inserted into the global environment with the given value.  As you can see, all bindings are created explicitly in ~@env~.  You'll notice that I created the ~:if~ logic with the ~proc~ form.  Doing so signals to the evaluator that the thing defined should receive its arguments unevaluated.

You'll notice that all of the callables take an array as the first argument and a context as the second.  This is key for future expansion.  Additionally, I like to use Ruby's destructuring format to unwrap the actual arguments hidden in the passed array.

#+name: ur
{'fraction_non_alphanumeric': 0.08525963149078727, 'fraction_numerical': 0.0010050251256281408, 'mean_word_length': 3.979983319432861, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7608784', 'n_tokens_mistral': 1862, 'n_tokens_neox': 1770, 'n_words': 877}