Hy Lisp

Examples of Lisp, and discussion of video of final project

How does Common Lisp differ from Scheme? Typically:

  • Lisp often has Dynamic Scope vs. Scheme always has Lexical Scope
  • Syntax differences (Lisp has defn vs. Scheme's define ... (lambda ...))
  • Lisp is large and unwieldy
  • Scheme is and elegant
  • Lisp is practical
  • Scheme is beautiful
  • Lisp uses nil for "empty list"; it is also false
  • Scheme uses '() for "empty list"; only #f is false
  • Lisp uses different scopes for variables and functions !?

How does Hy Lisp differ from Common Lisp?

  • Hy Lisp has Python's scoping rules, lexically scoped ... sorta
  • Hy Lisp is really just Python with different syntax
  • Hy Lisp uses Python's stack for function calls --- no trampoline, or Tail Call Elimination, etc.
  • Hy Lisp has Lisp-if and Python-if

Videos and Blogs

  1. http://technicae.cogitat.io/2014/11/scientific-computing-with-hy.html - Hy computing
  2. http://nbviewer.ipython.org/github/bollwyvl/hy_kernel/blob/master/notebooks/Tutorial.ipynb - Hy notebook
  3. https://www.youtube.com/watch?v=E7hTimGmGBs - Hy video
  4. https://www.youtube.com/watch?v=P76Vbsk_3J0 - Clojure video
  5. https://www.youtube.com/watch?v=0Vq2rcjWbTc - Animvs video

Final Project + Video Rubric

  • Quality - 20%
  • Programming Languages integration - connection to PL ideas, such as scope, continuations, internals, closures, parser, lexer, interpreter, etc. - 20%
  • Introduction to new language - 20%
  • Code and documentation effort - 20%
  • Conversation on videos - 20%

Bonus: up to 10%, examples:

  • creativity
  • effective use of media (eg, animations, varied video sequences)
  • extensive docs, code integration

Due: Monday, Dec 15, 2014 8am

Notebook on Hy Lisp:

http://nbviewer.ipython.org/github/bollwyvl/hy_kernel/blob/master/notebooks/Tutorial.ipynb

In [1]:
%%file ~/.ipython/kernels/hy/kernel.json

{
  "argv": ["python", "-m", "hy_kernel.hy_kernel", "-f", "{connection_file}"],
  "display_name": "Hy Lisp",
  "language": "hy",
  "codemirror_mode": "hy",
  "language_info": {
    "name": "hy",
    "codemirror_mode": {
      "name": "hy"
    },
    "mimetype": "text/x-hylang",
    "pygments_lexer": "ipython3"
  },
  "help_links": [
    {
      "text": "Hy Documentation",
      "link": "http://docs.hylang.org/"
    },
    {
      "text": "Hy Google Group",
      "link": "https://groups.google.com/forum/#!forum/hylang-discuss"
    },
    {
      "text": "Hy Github",
      "link": "https://github.com/hylang/hy"
    }
  ]
}
Created file '/home/dblank/.ipython/kernels/hy/kernel.json'.

Lisp

In [ ]:
(defn simple-conversation ()
   (print "Hello!  I'd like to get to know you.  Tell me about yourself!")
   (setv name (raw_input "What is your name? "))
   (setv age (raw_input "What is your age? "))
   (print (+ "Hello " name "!  I see you are "
             age " years old."))
   None)

(simple-conversation)
In [1]:
(defn fact (n)
    (if (= n 1)
        1
        (* n (fact (- n 1)))))
In [2]:
(fact 5)
Out[2]:
120L
In [17]:
((let [[x 5]] 
   (lambda () (+ x 1))))
Out[17]:
6L
In [33]:
(defn display (v) (print v) 'ok)
(try
    (display (fact 900))
    (catch [e Exception] 'ok)
;;    (else (print "no errors"))
    (finally 'ok)
  )
67526802209645841583879061361800814224269427869589384312198268703685091643180416969132446952698303794226010370578672908593198347699886928591906501031587651846976759681112609524787093848004428636186893395272784450630354080243217646658024696659065951793757223520229235577548653833681102170973893746054649126415909143150172860721156685810655759230011450132992176454983227538696340112610447029002337004887877266387704586077293585433151612518800147764461182680822867092786694982831838641800997499819339206579415325649748486265233918911087114592440896594062675914294925816719862178374679272092637524786939036290035924271782253738059886933923447877769583003016705363339031413069155837518524761078342052635475632113169618774549275701480106933362990003732589370593557325299434734459295866728988740794174654391479926000848846686708729736713207285203712732201272410830836913052635365082888725171636081587151603468291106754640398232146673627370895934090777828827549554232436190464827998683927179246029919443251026464452337939599198528297828591122689960620361238248313158071643395848405047261412680039877733761849874447323867911712630023171745968278465780558568067035013885275080292137360491875164947724464221693533755035300065350065137490832039523382963747026185653050331832380991844842560750923543775188582096487476950254418365198999674684417286265442786651594404781622946901879166382930714196908227460133027605817864877377712193142137625430353718448269390732615776645283198828602917680224041088993892610506802195917247838900106910698057030379190571057605849323113308634452008179881165616449767648354161225066967961297609698742737923389391615207441152319392845687673311899247085327703421862972871644495409572259985563215471482083325653231777113271326579970310755604973969708949477374254974480294652427022436705380184064008853457214518515270985563195412993145274057688634448812449445800617631162768243125606424844709372022149908463572254912654907763445758543980999149122998104378965626781898655221443263601405152073199706585080288735040205417371277253096243200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
In [34]:
(defn display (v) (print v) 'ok)
(try
    (display (fact 1000))
    (catch [e Exception] 'ok)
;;    (else (print "no errors"))
    (finally 'ok)
  )

Cool Macro tricks

"Threading Macro" from Clojure

sh is a Python library that wraps up shell commands as Python functions.

  • cat - concatenate
  • grep - search
  • wc - word/character/line count

In Python, you would write:

from sh import cat, grep, wc

wc(grep(cat("/usr/share/dict/words"), "-E", "^hy"), "-l")

In Hy Lisp:

In [29]:
(import [sh [cat grep wc]])
In [31]:
(wc (grep (cat "/usr/share/dict/words") "-E" "^hy") "-l")
Out[31]:
210
In [2]:
(-> (cat "/usr/share/dict/words") (grep "-E" "^hy") (wc "-l"))
Out[2]:
210

How is Hy implemented?

From hy_kernel.py:

class HyKernel(IPythonKernel):
   def do_execute(self, code, *args, **kwargs):
        '''                                                                     
        Generate python code, and have IPythonKernel run it, or show why we     
        couldn't have python code.                                              
        '''
        try:
            tokens = tokenize(code)
            _ast = hy_compile(tokens, '__console__', root=ast.Interactive)
            _ast_for_print = ast.Module()
            _ast_for_print.body = _ast.body
            code = astor.codegen.to_source(_ast_for_print)
        except Exception as err:
            if (not hasattr(err, 'source')) or not err.source:
                err.source = code
            # shell will find the last exception                                
            self.shell.showsyntaxerror()
            # an empty code cell is basically a no-op                           
            code = ''
        return super(HyKernel, self).do_execute(code, *args, **kwargs)

Macros

Hy Philosophy:

(defmacro -> [head &rest rest]
  (setv ret head)
  (for* [node rest]
    (if (not (isinstance node HyExpression))
      (setv node `(~node)))
    (.insert node 1 ret)
    (setv ret node))
  ret)

Scheme Philosophy

  (define-syntax ->
   [(-> ?a) ?a]     
   [(-> ?a (?b . ?args) . ?rest)
    (-> (?b ?a . ?args) . ?rest)])
In [6]:
(-> '"hello"  (+ "!") .upper str)
Out[6]:
'HELLO!'